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]