During the test of my C code using OpenSSL, I noticed that even though
CA certs were not loaded, SSL verification succeeded unexpectedly.
Attached below is a simplified code that demonstrates what I have been
seeing. I intentionally commented out the section where tries to load
CA certs, but SSL_get_verify_results() returns X509_V_OK where I
expects X509_V_ERR_CERT_UNTRUSTED to return. Looking at my log, the
verifyCallback() detected the error, returning 0 to the caller but the
return value from SSL_get_verify_result() did not seem to reflect the
error detected in the verifyCallback().
Here's some tty logs:
(1) When CA certs are not loaded:
TCP connection successful
verifyCallback() - in: preverify_ok=0
Verify error: unable to get local issuer certificate(20)
- depth=1
- sub =/C=US/O=Google Inc/CN=Google Internet Authority
verifyCallback() - out
SSL handshake/verify successful
PASS
(2) When CA certs are loaded:
TCP connection successful
verifyCallback() - in: preverify_ok=1
verifyCallback() - out
verifyCallback() - in: preverify_ok=1
verifyCallback() - out
verifyCallback() - in: preverify_ok=1
verifyCallback() - out
SSL handshake/verify successful
PASS
(3) When CA certs are NOT loaded, and returning 1 always from verifyCallback()
TCP connection successful
verifyCallback() - in: preverify_ok=0
Verify error: unable to get local issuer certificate(20)
- depth=1
- sub =/C=US/O=Google Inc/CN=Google Internet Authority
verifyCallback() - out
verifyCallback() - in: preverify_ok=0
Verify error: certificate not trusted(27)
- depth=1
- sub =/C=US/O=Google Inc/CN=Google Internet Authority
verifyCallback() - out
verifyCallback() - in: preverify_ok=1
verifyCallback() - out
SSL verify failed: CERT_UNTRUSTED(27)
FAIL
As in (3), if 1 is always returned from verifyCallback(),
SSL_get_verify_result() seems to return the expected error.
So, my question is, in order to correctly detect 'CERT_UNTRUSTED'
error in the code, what needs to be done in the implementation? There
may be something I am doing right. Please let me know if you notice
anything.
Here's info of OpenSSL I am using:
OpenSSL 0.9.8r 8 Feb 2011
compiler: -arch x86_64 -fmessage-length=0 -pipe -Wno-trigraphs
-fpascal-strings -fasm-blocks -O3 -D_REENTRANT -DDSO_DLFCN
-DHAVE_DLFCN_H -DL_ENDIAN -DMD32_REG_T=int -DOPENSSL_NO_IDEA
-DOPENSSL_PIC -DOPENSSL_THREADS -DZLIB -mmacosx-version-min=10.6
built on: Apr 22 2011
platform: darwin64-x86_64-llvm
OPENSSLDIR: /System/Library/OpenSSL
Any comments are appreciated!!
- Yutaka
/* ssltest.c */
#include sys/socket.h
#include netinet/in.h
#include unistd.h
#include netdb.h
#include stdio.h
#include openssl/ssl.h
#include openssl/x509.h
#include openssl/err.h
#define HOSTencrypted.google.com
#define PORT(443)
#define MAX_VERIFY_DEPTH(2)
#define CA_CERT_PATH./ca-bundle.crt
static char const* ssl_strerror(SSL* ssl, int ret);
static char const* crt_strerror(int err);
int verifyCallback(int preverify_ok, X509_STORE_CTX *ctx)
{
fprintf(stdout, verifyCallback() - in: preverify_ok=%d\n,
preverify_ok);
if(!preverify_ok)
{
char buf[256];
X509 *err_cert;
int err, depth;
SSL *ssl;
err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx);
ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx,
SSL_get_ex_data_X509_STORE_CTX_idx());
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
fprintf(stderr, Verify error: %s(%d)\n,
X509_verify_cert_error_string(err), err);
fprintf(stderr, - depth=%d\n, depth);
fprintf(stderr, - sub =\%s\\n, buf);
}
fprintf(stdout, verifyCallback() - out\n);
//return 1;
return preverify_ok;
}
int connectTcp()
{
struct hostent *h;
struct sockaddr_in sin;
int fd = -1;
int ret;
memset(sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
/* Resolve remote IP address */
h = gethostbyname(HOST);
if(!h)
{
fprintf(stderr, Could not obtain IP address\n);
return -1;
}
sin.sin_addr = *(struct in_addr*)(h-h_addr_list[0]);
/* Create fd */
fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd 0)
{
return -1;
}
/* Connect to remote */
ret = connect(fd, (struct sockaddr*)sin, sizeof(sin));
if(ret 0)
{
close(fd);
return -1;
}
return fd; /* connected */
}
int test(void)
{
int ret = 0;
SSL_CTX *ctx = 0;
SSL *ssl = 0;
int fd = -1;
/* Create SSL_CTX */
ctx = SSL_CTX_new(SSLv3_client_method());
if(!ctx)
{
fprintf(stderr, SSL_CTX_new filed);
ret = -1;
goto bail;
}
#if 0 /* Intentionally commented out not to load CA certs. */
/* Load CA certs from file */
if(!SSL_CTX_load_verify_locations(ctx, CA_CERT_PATH, NULL))
{