Alas, I meant to send this in weeks ago, before it was too late for 0.9.7; also apologies if this comes as a duplicate (we're changing email addresses here, this can cause obvious chicken-related problems with subscribers-post-only lists...).
This is a patch to actually hand the user-supplied argument into calls to app_verify_callback. It affects the following 5 files: ssl/ssl.h ssl/ssl_cert.c ssl/ssl_lib.c ssl/ssltest.c test/testssl In the first three cases, the change is 1-3 lines of code, and a few more lines of comments (e.g. removing comments saying that the argument is ignored); there's a slightly larger chunk of code to test it in ssltest.c. The implementation was done against the 12/09 snapshot, and the patch re-generated and re-tested against the 2/12 snapshot. (The patch applies cleanly to 2/13 as well, but that snap fails to build for me for unrelated reasons already mentioned on the list.) thanks, Diana Smetters PARC ============================================================== <BEGIN LONG BACKGROUND/RATIONALE, SKIP IF UNINTERESTED> Why this is useful: I'm looking at generating an updated Java SSL package that wraps OpenSSL and matches the JDK1.4 SSL APIs (there is at least one Java wrapper for OpenSSL, but it doesn't match any of the recent APIs distributed by Sun). One of the things offered by this API is the ability to have the code verifying the certificates passed in the handshake do so by calling back into a piece of arbitrary Java code. That Java code can be object instance specific (e.g. it can depend on state contained in a particular object instance), and the object providing it is tied to a particular SSL context. That means to find the code to call back into from the OpenSSL side, you have to know which particular Java object instance contains that code. Without passing either the SSL context or an argument into the app_verify_callback, it's hard to do that (there might be some table-based hack you could do, but...). Since the API was already defined to take an app-specified argument, it seems the most effective solution would be to fix the bug whereby the argument is ignored. Taking the alternate route of relying on the built-in verification algorithms and then using the verify_callback at the end to override the built-in behavior had two problems: first, that callback takes no app-defined args, and there's no reasonable way to change that. Second, it is very likely to end up with duplicated work, as the app isn't going to know that all that checking is being done ahead for it; it isn't in other Java SSL implementations that are using these callback mechanisms, and so relying on it would prevent this being a drop-in replacement. Keep in mind that 99.9% of Java applications using SSL do *not* use this option to manage verification themselves, they rely on built-in behavior provided by their SSL package. (In this case, that would result in them using OpenSSL's standard chain verification code.) I'm hoping to distribute this work freely; it'll be a lot easier for people to use if it doesn't require patching OpenSSL. If there's a better way of doing this that I've missed, I'd love to hear about it offline. Personally, I like and use this feature of the Java API because I do research in things like new ways of handling trust management, certificates, etc. <END BACKGROUND>
diff -ur ./ssl/ssl.h ../openssl-SNAP-20020212/ssl/ssl.h --- ./ssl/ssl.h Mon Jan 14 16:03:04 2002 +++ ../openssl-SNAP-20020212/ssl/ssl.h Thu Feb 14 12:03:14 2002 @@ -608,7 +608,7 @@ /* if defined, these override the X509_verify_cert() calls */ int (*app_verify_callback)(); - char *app_verify_arg; /* never used; should be void * */ + void *app_verify_arg; /* app-supplied argument passed to callback function */ /* Default password callback. */ pem_password_cb *default_passwd_callback; @@ -1232,7 +1232,7 @@ void SSL_CTX_set_verify(SSL_CTX *ctx,int mode, int (*callback)(int, X509_STORE_CTX *)); void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth); -void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(),char *arg); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(),void *arg); #ifndef OPENSSL_NO_RSA int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); #endif diff -ur ./ssl/ssl_cert.c ../openssl-SNAP-20020212/ssl/ssl_cert.c --- ./ssl/ssl_cert.c Wed Oct 24 09:01:31 2001 +++ ../openssl-SNAP-20020212/ssl/ssl_cert.c Thu Feb 14 12:03:14 2002 @@ -483,7 +483,7 @@ X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); if (s->ctx->app_verify_callback != NULL) - i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */ + i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); else { #ifndef OPENSSL_NO_X509_VERIFY diff -ur ./ssl/ssl_lib.c ../openssl-SNAP-20020212/ssl/ssl_lib.c --- ./ssl/ssl_lib.c Fri Feb 8 08:00:55 2002 +++ ../openssl-SNAP-20020212/ssl/ssl_lib.c Thu Feb 14 12:03:14 2002 @@ -1445,15 +1445,15 @@ ctx->default_passwd_callback_userdata=u; } -void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,int (*cb)(),char *arg) +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,int (*cb)(),void *arg) { /* now - * int (*cb)(X509_STORE_CTX *), - * but should be - * int (*cb)(X509_STORE_CTX *, void *arg) + * int (*cb)(X509_STORE_CTX *ctx, void *arg) + * + * on verification failure, cb should set ctx->error */ ctx->app_verify_callback=cb; - ctx->app_verify_arg=arg; /* never used */ + ctx->app_verify_arg=arg; /* passed to callback */ } void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *)) diff -ur ./ssl/ssltest.c ../openssl-SNAP-20020212/ssl/ssltest.c --- ./ssl/ssltest.c Mon Sep 10 03:02:02 2001 +++ ../openssl-SNAP-20020212/ssl/ssltest.c Thu Feb 14 12:03:14 2002 @@ -158,6 +158,10 @@ static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength); static void free_tmp_rsa(void); #endif +static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg); +#define APP_CALLBACK "Test Callback Argument" +static char *app_verify_arg = APP_CALLBACK; + #ifndef OPENSSL_NO_DH static DH *get_dh512(void); static DH *get_dh1024(void); @@ -336,6 +340,7 @@ int tls1=0,ssl2=0,ssl3=0,ret=1; int client_auth=0; int server_auth=0,i; + int app_verify=0; char *server_cert=TEST_SERVER_CERT; char *server_key=NULL; char *client_cert=TEST_CLIENT_CERT; @@ -489,6 +494,10 @@ { comp = COMP_RLE; } + else if (strcmp(*argv,"-app_verify") == 0) + { + app_verify = 1; + } else { fprintf(stderr,"unknown option %s\n",*argv); @@ -640,12 +649,20 @@ SSL_CTX_set_verify(s_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); + if (app_verify) + { + SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, +app_verify_arg); + } } if (server_auth) { BIO_printf(bio_err,"server authentication\n"); SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, verify_callback); + if (app_verify) + { + SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, +app_verify_arg); + } } { @@ -1428,6 +1445,25 @@ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: ok=1; } + } + + return(ok); + } + +static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg) + { + char *s = NULL,buf[256]; + int ok=1; + + fprintf(stderr, "In app_verify_callback, allowing cert. "); + fprintf(stderr, "Arg is: %s\n", (char *)arg); + fprintf(stderr, "Finished printing do we have a context? 0x%x a cert? 0x%x\n", + ctx, ctx->cert); + if (ctx->cert) + s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256); + if (s != NULL) + { + fprintf(stderr,"cert depth=%d %s\n",ctx->error_depth,buf); } return(ok); diff -ur ./test/testssl ../openssl-SNAP-20020212/test/testssl --- ./test/testssl Thu Nov 30 04:00:50 2000 +++ ../openssl-SNAP-20020212/test/testssl Thu Feb 14 12:03:14 2002 @@ -116,6 +116,9 @@ echo test sslv2/sslv3 with both client and server authentication via BIO pair $ssltest -bio_pair -server_auth -client_auth $CA $extra || exit 1 +echo test sslv2/sslv3 with both client and server authentication via BIO pair and app +verify +$ssltest -bio_pair -server_auth -client_auth -app_verify $CA $extra || exit 1 + ############################################################################# echo test tls1 with 1024bit anonymous DH, multiple handshakes