Sono alle prese con un problema con il certificato del cliente e spero che qualcuno qui possa aiutarmi. Sto sviluppando una coppia client/server usando boost asio ma cercherò di essere non specifico. Sono su Windows e uso openssl 1.0.1eIl client OpenSSL non invia il certificato client
Fondamentalmente, voglio avere l'autenticazione del client usando i certificati client. Il server accetta solo i clienti che hanno un certificato firmato dalla mia CA. Quindi ho configurato una CA autofirmata. Questo ha emesso altri due certificati. Uno per il client e uno per il server. Entrambi firmati dalla CA. L'ho fatto diverse volte e sono sicuro di averlo capito.
Anche il lato server funziona correttamente. Richiede i certificati client e se sto usando s_client e do quei certificati tutto funziona. Inoltre, se sto utilizzando un browser e ho installato la mia CA radice come attendibile, quindi importare i certificati client.
L'unica cosa che non riesco a far funzionare è il client libssl. Non riesce sempre durante la stretta di mano e, per quanto posso vedere non invierà il certificato client:
$ openssl.exe s_server -servername localhost -bugs -CAfile myca.crt -cert server.crt
-cert2 server.crt -key private/server.key -key2 private/server.key -accept 8887 -www
-state -Verify 5
verify depth is 5, must return a certificate
Setting secondary ctx parameters
Using default temp DH parameters
Using default temp ECDH parameters
ACCEPT
SSL_accept:before/accept initialization
SSL_accept:SSLv3 read client hello A
SSL_accept:SSLv3 write server hello A
SSL_accept:SSLv3 write certificate A
SSL_accept:SSLv3 write key exchange A
SSL_accept:SSLv3 write certificate request A
SSL_accept:SSLv3 flush data
SSL3 alert read:warning:no certificate
SSL3 alert write:fatal:handshake failure
SSL_accept:error in SSLv3 read client certificate B
SSL_accept:error in SSLv3 read client certificate B
2675716:error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a
certificate:s3_srvr.c:3193:
ACCEPT
Sto usando questo s_server come strumento di debug, ma contro la mia server reale si verifica la stessa cosa. s_client funzionerà correttamente con gli stessi certificati. Inoltre, se disattivo "-Verificare" nel server la connessione funziona. Quindi sembra proprio che il cliente si rifiuti di inviare il suo certificato. Quale può essere la ragione per questo?
Dal momento che sto usando spinta ASIO come SSL wrapper codice simile a questo:
m_ssl_context.set_verify_mode(asio::ssl::context::verify_peer);
m_ssl_context.load_verify_file("myca.crt");
m_ssl_context.use_certificate_file("testclient.crt", asio::ssl::context::pem);
m_ssl_context.use_private_key_file("testclient.key", asio::ssl::context::pem);
Ho anche cercato di bypassare ASIO e accedere al contesto SSL direttamente dicendo:
SSL_CTX *ctx = m_ssl_context.impl();
SSL *ssl = m_ssl_socket.impl()->ssl;
int res = 0;
res = SSL_CTX_use_certificate_chain_file(ctx, "myca.crt");
if (res <= 0) {
// handle error
}
res = SSL_CTX_use_certificate_file(ctx, "testclient.crt", SSL_FILETYPE_PEM);
if (res <= 0) {
// handle error
}
res = SSL_CTX_use_PrivateKey_file(ctx, "testclient.key", SSL_FILETYPE_PEM);
if (res <= 0) {
// handle error
}
Non riesco a vedere alcuna differenza di comportamento. Va detto che sto usando un boost molto vecchio 1.43 che non posso aggiornare, ma suppongo che tutte le chiamate rilevanti vadano più o meno direttamente a OpenSSL e il server funziona bene con quella versione, quindi penso di poterlo escludere.
Se inizio a forzare client e server a versioni specifiche, i messaggi di errore cambiano ma non funziona mai e funziona sempre sempre con il test s_client. Attualmente è impostato su TLSv1
Se posso passare al TLSv1 per esempio c'è più chiacchiere tra client e server e alla fine ottengo l'errore:
...
SSL_accept:SSLv3 read client key exchange A
<<< TLS 1.0 ChangeCipherSpec [length 0001]
01
<<< TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c f4 71 28 4d ab e3 dd f2 46 e8 8b ed
>>> TLS 1.0 Alert [length 0002], fatal unexpected_message
02 0a
SSL3 alert write:fatal:unexpected_message
SSL_accept:failed in SSLv3 read certificate verify B
2675716:error:140880AE:SSL routines:SSL3_GET_CERT_VERIFY:missing verify
message:s3_srvr.c:2951:
2675716:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure:s3_pkt.c:989:
ACCEPT
ho trovato una voce bug vecchio pubblicato sul mailing list di openssl che ha fatto riferimento a questo. Apparentemente un CRLF sbagliato nella stretta di mano che è stato corretto due anni fa. O ce l'ha?
Ho eseguito il debugging per quasi una settimana e sono davvero bloccato. Qualcuno ha un suggerimento su cosa provare? Sono fuori di idee ...
Cheers, Stephan
PS: Ecco ciò che il sopra s_server di debug fuori sarebbe con s_client e lo stesso certficate:
$ openssl s_client -CAfile ca.crt -cert testclient.crt -key private/testclient.key -verify 2 -connect myhost:8887
ACCEPT
SSL_accept:before/accept initialization
SSL_accept:SSLv3 read client hello A
SSL_accept:SSLv3 write server hello A
SSL_accept:SSLv3 write certificate A
SSL_accept:SSLv3 write key exchange A
SSL_accept:SSLv3 write certificate request A
SSL_accept:SSLv3 flush data
depth=1 C = DE, // further info
verify return:1
depth=0 C = DE, // further info
verify return:1
SSL_accept:SSLv3 read client certificate A
SSL_accept:SSLv3 read client key exchange A
SSL_accept:SSLv3 read certificate verify A
SSL_accept:SSLv3 read finished A
SSL_accept:SSLv3 write session ticket A
SSL_accept:SSLv3 write change cipher spec A
SSL_accept:SSLv3 write finished A
SSL_accept:SSLv3 flush data
ACCEPT
... l'handshake viene completato e i dati vengono trasferiti.
Purtroppo ho provato tutte le combinazioni che potrei trovare già. Compreso questo. Inutilmente. Sembra che il cliente non si fidi del proprio certificato cliente e non lo invii. Se utilizzo questa combinazione, il client non invia alcun certificato, Se utilizzo il file di catena, sembra che manda la CA di root invece che la sua. –
Se invia la CA radice, è perché si sta chiamando SSL_CTX_use_certificate_chain_file() con solo il certificato CA al suo interno. Potresti provare a passare il file contenente solo il tuo certificato client a SSL_CTX_use_certificate_chain_file()? –
Grazie ragazzi per tutto il vostro contributo! Molto apprezzato! @Remi: quando faccio questo, il client non invia alcun certificato. Questo è il primo caso che ho descritto. Che tra l'altro è anche il caso se il file di catena contiene solo il ca cert. Lo so, non è ragionevole ma volevo provare comunque. –