A kinder, gentler verification
--#--
The code we have so far is pretty harsh. If the verification fails
for any reason, you can't connect. It might be a good idea
to check the reason why the authentication failed, and perhaps to
allow the connection to go ahead even if it did. (You could always
just ignore the result from ssl_verify_cert_chain, but what's the
point in that?)
We can modify OpenSSL's verification by specifying our own
callback function that will be used internally by the
verification code. Note that this callback will only be called
if the cert chain fails the internal OpenSSL verification function.
If the cert chain is good, the callback never runs.
int my_verify_callback(int ok, X509_STORE_CTX *ctx) {
X509 *cert;
int err;
char c;
/* the variable ok will be 0 here because the callback */
/* doesn't get called unless the chain is !ok */
cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
printf("Error verifying %s\n",
X509_NAME_oneline(X509_get_subject_name(cert), 0, 0));
printf("Error: number %d: %s\n",
err, X509_verify_cert_error_string(err));
printf("Accept it anyway? (y/n) ");
c = getchar();
if (c == 'y') ok = 1;
return ok;
}
To see all the possible errors you can encounter in this callback, look
at the source code for the X509_verify_cert_error_string function. It's
in a file called x509_text.c in the source distribution.
This implementation requires user intervention if the cert chain is
bad. Of course, you might be using similar code in a robot or
other automatonic code, in which case you'd want to put some
decision logic in here.
Integrate this callback into your code this way:
SSL_CTX_load_verify_locations(ssl_ctx, "thawte.der", 0);
-###SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, &my_verify_callback); ###-
ssl = SSL_new(ssl_ctx);
result = SSLsocket(ssl, hostName, port);
if (result < 0) {
sprintf(dieString, "Could not get secure socket on %s:%d", hostName, port);
die(dieString);
}
chain = SSL_get_peer_cert_chain(ssl);
result = ssl_verify_cert_chain(ssl, chain);