PDFium VCL siunčia RFC 3161 laiko žymėjimo užklausas per libcurl ne Windows tikslams, dinamiškai susietas su aštuoniais simboliais, kartodamas Windows posistemės, susijusios su WinHTTP, formą. Dvi parinkčių reikšmės nusprendžia, ar transportas patikimas apkrovoje, ir visas modulis buvo patikrintas mašinoje, negalėjusioje jo sukompiliuoti jo tikslinei platformai
Laiko žymėjimas yra tai, kas pavercia parašą į kažką, išgyvenantį sertifikato galiojimo pabaigą, ir tai tinklo operacija, sėdinti pasirašymo operacijos viduje. Tas derinys daro transporto pasirinkimą reikšmingą taip, kaip paprastai nebūna: jis bėga darbinėje gijoje, jis kalba su serveriu, kurio nekontroliuojate, ir pakibimas ten sustabdo pasirašymo konvejerį, o ne puslapio pakrovimą
Kodėl libcurl, o ne FPC HTTP klientas?
Nes alternatyva įtempia TLS krūvą į saugyklą ir tada priverčia jus prižiūrėti jos versijų aptikimą. Akivaizdus kelias Free Pascal yra fphttpclient su OpenSSL lizdo sluoksniu, ir jis klysta detalėse: FPC 3.2.2 OpenSSL susiejimai nepatikimai aptinka OpenSSL 3.x daugumoje dabartinių distribucijų, o macOS prideda LibreSSL skirtumus viršuje. Kas prasideda kaip mažas HTTP iškvietimas tampa nuolatine kažkieno kito TLS ABI priežiūra
libcurl išsprendžia savąjį TLS posistemę ir tikrina grandines prieš platformos pasitikėjimo saugyklą, tad Pascal pusei to nereikia nieko. Susiejimo sluoksnis yra aštuoni simboliai. Tas skaičius yra argumentas: mažesnis paviršius tarp jūsų kodo ir judančios priklausomybės reiškia mažiau vietų, kur distribucijos atnaujinimas gali jus sulaužyti, ir jis atitinka esamą Windows posistemę, kuri taip pat susieja saują WinHTTP įėjimo taškų
uses
FPdfTsaFpc;
var
ReqDer, RespDer: TBytes;
begin
if not TsaHttpAvailable then
raise Exception.Create('no HTTP transport for timestamping');
Writeln('TSA transport: ', TsaHttpBackendName);
ReqDer := BuildTimeStampQuery(DocumentDigest);
if PostTimeStampQuery('https://tsa.example.org/tsr', ReqDer, RespDer) then
AttachTimeStampToken(RespDer)
else
raise Exception.Create('timestamp request failed');
end;
C kintamo argumentų skaičiaus funkcijos deklaravimas Pascal
curl_easy_setopt ir curl_easy_getinfo C pusėje yra kintamo argumentų skaičiaus, ir Object Pascal neturi būdo tai išreikšti. Kelias, kuris veikia, yra deklaruoti kelis fiksuotus prototipus, po vieną argumentų klasei, visus rodančius į tą patį eksportuotą simbolį: long imanti perkraja, rodyklę imanti perkraja ir tą toliau, pasirenkami iškvietimo vietoje pagal tai, ką iš tikrųjų perduodate
Tai saugu dėl konkrečios priežasties, vertos suprasti, o ne kopijuoti. Kiekvienas tų argumentų tipų perduodamas sveikojo skaičiaus registre pagal veikiančias platformos iškvietimo konvencijas, kas yra tiksliai ta vieta, iš kurios C realizacija va_arg jį skaito. Triukas todėl galioja sveikiesiems skaičiams, rodyklėms ir rankenoms, ir jis ne galioja slankiojo kablelio argumentams, kurie keliauja kitais registrais. Nepridėkite double imančios perkrajos manydami, kad šablonas apibendrėja
// Vienas eksportuotas simbolis, keli fiksuoti prototipai. Kiekviena
// perkraja perduoda savo argumentą sveikojo skaičiaus registre, kur ir
// skaito C pusė. Slankiojo kablelio perkrajos neveiktų ir jos nededamos
type
TCurlSetOptLong = function(Handle: Pointer; Option: Integer;
Value: NativeInt): Integer; cdecl;
TCurlSetOptPtr = function(Handle: Pointer; Option: Integer;
Value: Pointer): Integer; cdecl;
var
curl_easy_setopt_long: TCurlSetOptLong;
curl_easy_setopt_ptr: TCurlSetOptPtr;
Du nustatymai, lemiantys, ar užklausa pasibaigia
Pirmasis yra aiški tuščia Expect: antraštė. libcurl įjungia HTTP 100-continue pasisveikinimą užklausos kūnams virš maždaug kilobaito, ir laiko žymėjimo užklausa su sertifikato užklausa paprastai peržengia tą ribą. Kai kurie TSA serveriai niekada neatsako į tęsinį, tad klientas laukia pilną outą prieš siųsdamas kūną, kurį serveris būtų priėmęs nedelsdamas. Tuščios Expect: antraštės siuntimas slopina pasisveikinimą, ir užklausa praeina vienu apsukimu
Antrasis yra CURLOPT_NOSIGNAL, kuris turi būti nustatytas. Be jo libcurl realizuoja savo vardų išskyrimo outą naudodamas SIGALRM, o tas mechanizmas nėra gijų saugus. Pasirašymas bėga darbinėje gijoje, tad numatytasis elgesys yra latentinis užstrigimas, pasirodantis lygiagrečiai ir niekada viengijame teste. Vėliavos nustatymas išjungia signalu pagrįstą kelią ir kainuoja tik rezolverio outo smulkumą
Abu defektai dalijasi profiliu, darančiu juos brangiais vėlesniam radimui. Nė vienas nepasirodo funkciniam teste prieš gerai besielgiantį serverį viena gija. Abu pasirodo gamyboje, prieš vieną konkretų TSA, apkrovoje. Kai susiejate tinklo biblioteką, perskaitykite, ką jos numatytosios reikšmės mano apie jūsų procesą, prieš manydami, kad jos tinka
Kaip patikrinti kodą, kurio jūsų kompiliatorius niekada nematys?
Padarydami, kad kompiliatorius jį vis tiek matytų, per kontroliuojamą kopiją. Ši kūrimo mašina neturi Linux ar macOS cross-kompiliatoriaus, tad laiko žymėjimo modulio ne Windows šakos normalios statybos metu niekada nepasiekia kodo generatoriaus. Kodas, kuris niekada nekompiliuojamas, yra kodas, tyliai pūvantis: pervadinimas bendrame tipe, pakeistas parametrų sąrašas, pridėta modulio priklausomybė, ir nė kas nepastebi mėnesių mėnesius
Technika yra mechaninė. Nukopijuokite modulį į laikiną katalogą, pervadinkite jį ir pakeiskite kiekvieną Windows sąlygą, tiek {$IFDEF MSWINDOWS} formą, tiek {$IF DEFINED(MSWINDOWS) formą, simboliu, kuris niekada neapibrėžtas. Tada kompiliuokite kopiją. Kai visos 3,828 eilutės kompiliuojasi, jūs įrodėte, kad ne Windows kelias naudoja modulius, kurie egzistuoja, kviečia posistemės funkcijas sutampančiais parašais ir nurodo tipus, esančius apimtyje. Tai ne įrodymas, kad transportas veikia, ir niekas, išskyrus pačią tikslinę platformą, jums to neduos. Tai įrodymas, kad šaka dar nesulaužyta, o būtent tas nesėkmės režimas realiai kaupiasi
Lydraudžio įprotis yra palikti patį libcurl modulį laisvą nuo platformos sargų, tad jis dalyvauja įprastoje Windows statyboje, nors niekas ten jo nenurodo. Kasdienė statyba tada toliau nemokamai saugo jo sintaksę ir tipus. Modulis, kompiliuojantis tik platformoje, kurios neturite, yra modulis be jokio kompiliatoriaus, jo tikrinančio, ir ta pati logika galioja visame cross-kompiliatorių darbe, aprašytame straipsnyje Delphi ir FPC cross-kompiliatorių spąstai
Ribojimas to, kas grįžta
Laiko žymės atsakymas yra maža DER struktūra, ir niekas transporte to nesaugo. Serveris, kompromituotas, sukonfigūruotas blogai ar tiesiog nukreiptas į neteisingą URL, gali grąžinti atsitiktinį srautą, o klientas, skaitantis iki jungties uždarymo, mielai jį sukaups. Abu transportai todėl riboja atsakymą, kas yra teisinga ribos vieta: atsisakymas transporte neleidžia per dideliam kūnui kada bet būti alokuotam, kol analizatoriaus lygio patikra suveikia tik po to, kai atmintis jau įsipareigota
Ta pati logika galioja URL. Posistemė priima tik schemas, kuriomis prasmingai moka kalbėti, tad konfigūracijos klaida nepajėgia nedelsiant su aiškiu pranešimu, vietoj to, kad būtų atiduota libcurl interpretuoti kokiaip tik jo protokolų palaikymas leidžia
Kur transportas sėdi pasirašymo istorijoje
Laiko žymėjimas yra pirmasis ilgalaikės validacijos istorijos žingsnis, o ne visa ji. Žetonas turi būti pritvirtintas prie parašo, validacijos medžiaga turi būti užrašyta dokumento saugumo saugykloje, ir archyvo laiko žymės turi būti atnaujintos, kol dabartinė nesuspjausta. Visas tas lankas padengtas straipsnyje ilgalaikiai PDF parašai su RFC 3161 laiko žymėmis ir DSS
Transportas taip pat yra viena platesnės perkeliamumo pozicijos dalis: gimtosios bibliotekos pakrovėjas, aprašytas straipsnyje gimtosios bibliotekos pakrovimas bet kuriame tikslas, tvarko tos pačios klasės problemą pačiam PDFium dvinariniam failui. Abiem atvejais šablonas identiškas: susiekite saują simbolių dinamiškai, praneškite tiksliai, kas nepajėgė susirišti, ir niekada neleiskite dingusiai priklausomybei tapti susiejimo metu klaida, sustabdanti programos paleidimą
Windows ir ne Windows laiko žymių posistemės abu keliauja su PDFium Delphi komponentu, parenkami pagal tikslą, o ne pagal konfigūraciją, tad Lazarus programa Linux ir Delphi programa Windows pagamina tą patį laiku pažymėtą parašą per skirtingą santechniką