2012-11-27 10 views
5

Ho setacciato Internet e non ho trovato una soluzione o un metodo su come verificare il certificato durante la connessione su HTTPS utilizzando TIdHTTP.Delphi Indy verifica certificato server SSL

ho collegato un componente IdSSLIOHandlerSocketOpenSSL come IOHandler, impostare le SSLModes, ecc, ma quando navigo a https://s3.amazonaws.com non si può verificare il certificato.

OpenSSL (Indy) dà

"Errore di connessione con SSL SSL3_GET_SERVER_CERTIFICATE:. Certificato verifica fallita"

Le librerie OpenSSL hanno successo caricato (verificato con WhichFailedToLoad). L'evento OnStatusInfo scrive quanto segue:

stato SSL: "prima/collegare l'inizializzazione" status

SSL: "prima/collegare l'inizializzazione" status

SSL: "SSLv2/v3 cliente scrittura ciao A"

stato SSL: "SSLv3 leggere Server ciao uno" status

SSL: "SSLv3 leggere certificato del server B"

SSL s tato: "SSLv3 leggere certificato del server B"

stato SSL: "SSLv3 leggere certificato del server B"

E OnVerifyPeer, AOK = False.

Come posso verificarlo correttamente. Cosa sta succedendo?

Grazie per la lettura, Adrian

risposta

7

è necessario implementare un gestore di eventi per l'evento OnVerifyPeer del componente TIdSSLIOHandlerSocketOpenSSL.

Da IdSSLOpenSSL.pas:

Nota che realmente dovrebbe sempre implementare OnVerifyPeer, in caso contrario il certificato del peer si sono connessione a NON è controllata per assicurarsi che sia valido.

Se si desidera solo per considerare validi gli stessi certificati Biblioteca ritiene valida anche, basta implementare in questo modo:

function TForm1.IdSSLIOHandlerSocketOpenSSL1VerifyPeer(Certificate: TIdX509; 
    AOk: Boolean; ADepth, AError: Integer): Boolean; 
begin 
    Result := AOk; 
end; 

Come Indy primi controlli per la validità del certificato e passa tu se è Ok o meno nel parametro AOk. L'ultima parola è nel codice, poiché potresti voler passare alcuni tipi di errori di validazione minori, come non essere aggiornati, o anche chiedere all'utente se il certificato è accettato o meno in caso di errore (minore o non).

Per capire perché funziona in questo modo, si consiglia inoltre di leggere tutti i commenti nella parte superiore della IdSSLOpenSSL.pas File:

{

indicazioni importanti per l'OnVerifyPeer: Rev 1.39 del febbraio 2005 deliberatamente rotto l'interfaccia OnVerifyPeer, che (ovviamente?) riguarda solo i programmi che hanno realizzato che callback come parte del SSL negoziazione. Nota che dovresti davvero sempre implementare OnVerifyPeer, altrimenti il ​​certificato del peer che stai connettendo a NON è controllato per assicurarti che sia valido.

Prima di questo, se la libreria SSL rilevato un problema con un certificato o la profondità era insufficiente (cioè il parametro "Ok" in VerifyCallback è 0/FALSE), quindi indipendentemente dal fatto che il tuo OnVerifyPeer restituito Vero o Falso, la connessione SSL sarebbe deliberatamente fallita.

Questo ha creato un problema in quanto, anche se c'era solo una minore problema con uno dei certificati della catena (OnVerifyPeer viene chiamato una volta per ogni certificato nella catena di certificati), che l'utente può essere felice di accettare, la negoziazione SSL sarebbe fallita. Tuttavia, cambiare il codice per consentire la connessione SSL quando un utente restituito Vero per OnVerifyPeer avrebbe fatto sì che il codice esistente che dipendeva rifiuto automatico di certificati non validi sarebbe poi accettare certificati non validi, che sarebbe stato un titolo inaccettabile modificare.

Di conseguenza, OnVerifyPeer è stato modificato per interrompere deliberatamente il codice esistente aggiungendo un parametro AOk. Per preservare la funzionalità precedente, l'evento OnVerifyPeer dovrebbe eseguire "Risultato: = AOk;". Se si desidera considerare accettando i certificati ritenuti non validi dalla libreria SSL, quindi in OnVerifyPeer, assicurarsi che il certificato sia realmente valido e quindi impostare Risultato su Vero. In realtà, oltre allo che controlla AOk, devi sempre implementare il codice che garantisce che tu sia solo accettando certificati validi (almeno dal tuo punto di vista).

Ciaran Costelloe, ccostelloe [_a_t_] flogas.ie

}

{

RLebeau 1/12/2011: evento Rompere OnVerifyPeer di nuovo, questa volta per aggiungere un parametro aggiuntivo AERROR (patch di cortesia di "jvlad", [email protected]). Questo consente al codice utente di distinguere tra certificati non firmati e non validi.

}

1

Se si ottiene un errore come SSL3_GET_SERVER_CERTIFICATE:certificate verify failed, allora continuate a leggere:

Sembra a Indy 10, che se si imposta un VerifyDepth di 0, il 0 significa in realtà all.Purtroppo, Indy sembra solo di conoscere le CA radice, così al fine di verificare solo le radici, provare la OnVerify seguente metodo:

function TForm1.IdSSLIOHandlerSocketOpenSSL1VerifyPeer(Certificate: TIdX509; 
    AOk: Boolean; ADepth, AError: Integer): Boolean; 
begin 
    if ADepth = 0 then 
    begin 
    Result := AOk; 
    end 
    else 
    begin 
    Result := True; 
    end; 
end; 
+1

Questo è sbagliato. Indy non conosce certificati radice per impostazione predefinita. Questo ti rende vulnerabile agli attacchi MitM. È necessario impostare almeno 'VerifyMode',' VerifyDepth' e 'RootCertFile' per avere una connessione sicura. Dopodiché puoi semplicemente restituire 'AOk' per qualsiasi profondità dato che OpenSSL fa la cosa giusta per te. – TobiX

1

So che questo è un antico posto, ma è tutto quello che potevo trovare per risolvere il problema. Quindi vorrei aggiungere alla risposta di Marcus per gli altri con lo stesso problema: Quando OpenSSL non riesce a trovare il certificato di root sul PC, AError restituirà # 19 (X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) e AOK sarà falso per il certificato di root. Quando si carica manualmente il certificato radice da file, AOK dovrebbe sempre restituire true (e si ha raggiunto pinning certificato di qualche tipo troppo):

FSSLIOHandlerSocketOpenSSL.SSLOptions.RootCertFile: 'MyRoot.cer';