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]

Reply via email to