mturk 2005/06/02 04:07:07 Modified: jni/native/include ssl_private.h jni/native/src sslcontext.c sslutils.c Log: Implement Client Authentication verify callback and CA initialization. Revision Changes Path 1.11 +12 -1 jakarta-tomcat-connectors/jni/native/include/ssl_private.h Index: ssl_private.h =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/jni/native/include/ssl_private.h,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- ssl_private.h 2 Jun 2005 07:44:38 -0000 1.10 +++ ssl_private.h 2 Jun 2005 11:07:06 -0000 1.11 @@ -88,6 +88,14 @@ #define SSL_DEFAULT_CACHE_SIZE (256) #define SSL_DEFAULT_VHOST_NAME ("_default_:443") #define SSL_MAX_STR_LEN 2048 + +#define SSL_CVERIFY_UNSET (-1) +#define SSL_CVERIFY_NONE (0) +#define SSL_CVERIFY_OPTIONAL (1) +#define SSL_CVERIFY_REQUIRE (2) +#define SSL_CVERIFY_OPTIONAL_NO_CA (3) +#define SSL_VERIFY_PEER_STRICT (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + /* public cert/private key */ typedef struct { /* @@ -167,5 +175,8 @@ RSA *SSL_callback_tmp_RSA(SSL *, int, int); DH *SSL_callback_tmp_DH(SSL *, int, int); void SSL_vhost_algo_id(const unsigned char *, unsigned char *, int); +int SSL_callback_SSL_verify(int, X509_STORE_CTX *); +STACK_OF(X509_NAME) + *SSL_init_findCAList(tcn_ssl_ctxt_t *, const char *, const char *); #endif /* SSL_PRIVATE_H */ 1.18 +66 -4 jakarta-tomcat-connectors/jni/native/src/sslcontext.c Index: sslcontext.c =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/jni/native/src/sslcontext.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- sslcontext.c 2 Jun 2005 10:19:32 -0000 1.17 +++ sslcontext.c 2 Jun 2005 11:07:06 -0000 1.18 @@ -183,8 +183,8 @@ SSL_CTX_set_tmp_rsa_callback(c->ctx, SSL_callback_tmp_RSA); SSL_CTX_set_tmp_dh_callback(c->ctx, SSL_callback_tmp_DH); - - /* Set default Certificate verification level + + /* Set default Certificate verification level * and depth for the Client Authentication */ c->verify_depth = 1; @@ -565,11 +565,73 @@ jint level) { tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *); + int verify = SSL_VERIFY_NONE; + STACK_OF(X509_NAME) *ca_list; UNREFERENCED_STDARGS; TCN_ASSERT(ctx != 0); c->verify_mode = level; - /* TODO: Add verification code callback */ + + if (c->verify_mode == SSL_CVERIFY_UNSET) + c->verify_mode = SSL_CVERIFY_NONE; + + /* + * Configure callbacks for SSL context + */ + if (c->verify_mode == SSL_CVERIFY_REQUIRE) + verify |= SSL_VERIFY_PEER_STRICT; + if ((c->verify_mode == SSL_CVERIFY_OPTIONAL) || + (c->verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA)) + verify |= SSL_VERIFY_PEER; + + SSL_CTX_set_verify(c->ctx, verify, SSL_callback_SSL_verify); + /* + * Configure Client Authentication details + */ + if (c->ca_cert_file || c->ca_cert_path) { + if (!SSL_CTX_load_verify_locations(c->ctx, + c->ca_cert_file, + c->ca_cert_path)) { + BIO_printf(c->bio_os, "[ERROR] " + "Unable to configure verify locations " + "for client authentication"); + return JNI_FALSE; + } + + if (c->mode && (c->pk.s.ca_name_file || c->pk.s.ca_name_path)) { + ca_list = SSL_init_findCAList(c, + c->pk.s.ca_name_file, + c->pk.s.ca_name_path); + } + else { + ca_list = SSL_init_findCAList(c, + c->ca_cert_file, + c->ca_cert_path); + } + if (!ca_list) { + BIO_printf(c->bio_os, "[ERROR] " + "Unable to determine list of acceptable " + "CA certificates for client authentication"); + return JNI_FALSE; + } + SSL_CTX_set_client_CA_list(c->ctx, (STACK *)ca_list); + } + + /* + * Give a warning when no CAs were configured but client authentication + * should take place. This cannot work. + */ + if (c->verify_mode == SSL_CVERIFY_REQUIRE) { + ca_list = (STACK_OF(X509_NAME) *)SSL_CTX_get_client_CA_list(c->ctx); + + if (sk_X509_NAME_num(ca_list) == 0) { + BIO_printf(c->bio_os, + "[WARN] Oops, you want to request client " + "authentication, but no CAs are known for " + "verification!? [Hint: setCACertificate*]"); + } + } + return JNI_TRUE; } 1.10 +109 -1 jakarta-tomcat-connectors/jni/native/src/sslutils.c Index: sslutils.c =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/jni/native/src/sslutils.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- sslutils.c 2 Jun 2005 07:44:39 -0000 1.9 +++ sslutils.c 2 Jun 2005 11:07:07 -0000 1.10 @@ -25,6 +25,7 @@ #include "apr_portable.h" #include "apr_thread_mutex.h" #include "apr_hash.h" +#include "apr_strings.h" #include "tcn.h" @@ -431,6 +432,113 @@ return n; } +static int ssl_init_X509NameCmp(X509_NAME **a, X509_NAME **b) +{ + return (X509_NAME_cmp(*a, *b)); +} + +static void ssl_init_pushCAList(STACK_OF(X509_NAME) *ca_list, + const char *file) +{ + int n; + STACK_OF(X509_NAME) *sk; + + sk = (STACK_OF(X509_NAME) *) + SSL_load_client_CA_file((char *)file); + + if (!sk) { + return; + } + + for (n = 0; n < sk_X509_NAME_num(sk); n++) { + X509_NAME *name = sk_X509_NAME_value(sk, n); + /* + * note that SSL_load_client_CA_file() checks for duplicates, + * but since we call it multiple times when reading a directory + * we must also check for duplicates ourselves. + */ + + if (sk_X509_NAME_find(ca_list, name) < 0) { + /* this will be freed when ca_list is */ + sk_X509_NAME_push(ca_list, name); + } + else { + /* need to free this ourselves, else it will leak */ + X509_NAME_free(name); + } + } + sk_X509_NAME_free(sk); +} + +STACK_OF(X509_NAME) *SSL_init_findCAList(tcn_ssl_ctxt_t *c, + const char *ca_file, + const char *ca_path) +{ + STACK_OF(X509_NAME) *ca_list; + + /* + * Start with a empty stack/list where new + * entries get added in sorted order. + */ + ca_list = sk_X509_NAME_new(ssl_init_X509NameCmp); + + /* + * Process CA certificate bundle file + */ + if (ca_file) + ssl_init_pushCAList(ca_list, ca_file); + + /* + * Process CA certificate path files + */ + if (ca_path) { + apr_dir_t *dir; + apr_finfo_t direntry; + apr_int32_t finfo_flags = APR_FINFO_TYPE|APR_FINFO_NAME; + apr_status_t rv; + apr_pool_t *ptemp; + + if ((apr_pool_create(&ptemp, c->pool)) != APR_SUCCESS) + return NULL; + if ((rv = apr_dir_open(&dir, ca_path, c->pool)) != APR_SUCCESS) { + BIO_printf(c->bio_os, "[ERROR] " + "Failed to open Certificate Path `%s'", + ca_path); + apr_pool_destroy(ptemp); + return NULL; + } + + while ((apr_dir_read(&direntry, finfo_flags, dir)) == APR_SUCCESS) { + const char *file; + if (direntry.filetype == APR_DIR) + continue; /* don't try to load directories */ + file = apr_pstrcat(ptemp, ca_path, "/", direntry.name, NULL); + ssl_init_pushCAList(ca_list, file); + } + + apr_dir_close(dir); + apr_pool_destroy(ptemp); + } + + /* + * Cleanup + */ + sk_X509_NAME_set_cmp_func(ca_list, NULL); + return ca_list; +} + + +/* + * This OpenSSL callback function is called when OpenSSL + * does client authentication and verifies the certificate chain. + */ +int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx) +{ + + /* TODO: Dummy function for now */ + return 1; +} + #else /* OpenSSL is not supported * If someday we make OpenSSL optional
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]