ssl.c.patch   [plain text]


--- /tmp/jabberd-2.2.13/sx/ssl.c	2011-02-23 08:24:34.000000000 -0800
+++ ./jabberd2/sx/ssl.c	2011-02-24 17:30:46.000000000 -0800
@@ -176,6 +176,8 @@ static int _sx_ssl_process(sx_t s, sx_pl
             if(s->plugin_data[p->index] != NULL) {
                 if( ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile != NULL )
                     free(((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile);
+                if( ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password != NULL )
+                    free(((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password);
                 free(s->plugin_data[p->index]);
                 s->plugin_data[p->index] = NULL;
             }
@@ -622,6 +624,8 @@ static void _sx_ssl_client(sx_t s, sx_pl
     SSL_CTX *ctx;
     char *pemfile = NULL;
     int ret, i;
+    char *pemfile_password = NULL;
+    ssl_userdata_t ssl_userdata;
 
     /* only bothering if they asked for wrappermode */
     if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
@@ -663,6 +667,7 @@ static void _sx_ssl_client(sx_t s, sx_pl
      *     help the admin at all to figure out what happened */
     if(s->plugin_data[p->index] != NULL) {
         pemfile = ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile;
+        pemfile_password = ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password;
         free(s->plugin_data[p->index]);
         s->plugin_data[p->index] = NULL;
     }
@@ -677,6 +682,31 @@ static void _sx_ssl_client(sx_t s, sx_pl
             return;
         }
 
+        // Add apple password callback
+#ifdef __APPLE__
+        _sx_debug(ZONE, "Adding Apple-custom SSL password callback");
+        {
+            if(strlen(pemfile))
+            {
+                ssl_userdata = (ssl_userdata_t)malloc(sizeof(struct ssl_userdata_st));
+                ssl_userdata->pemfile = pemfile;
+                ssl_userdata->password = NULL;
+
+                // See if a password has been saved
+                if(pemfile_password != NULL) {
+                    ssl_userdata->password = pemfile_password;
+                }
+
+                SSL_CTX_set_default_passwd_cb_userdata(sc->ssl->ctx, (void *)ssl_userdata);
+                SSL_CTX_set_default_passwd_cb(sc->ssl->ctx, &sx_apple_password_callback);
+
+                _sx_debug(ZONE, "Apple-custom SSL password callback enabled for %s", pemfile);
+            }
+            else
+		        _sx_debug(ZONE, "Could not set custom callback for %s", pemfile);
+        }
+#endif /* __APPLE__ */
+
         /* load the private key */
         ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
         if(ret != 1) {
@@ -780,6 +810,8 @@ static void _sx_ssl_free(sx_t s, sx_plug
 
     if(sc->pemfile != NULL) free(sc->pemfile);
 
+    if(sc->private_key_password != NULL) free(sc->private_key_password);
+
     if(sc->ssl != NULL) SSL_free(sc->ssl);      /* frees wbio and rbio too */
 
     if(sc->wq != NULL) {
@@ -809,9 +841,9 @@ static void _sx_ssl_unload(sx_plugin_t p
 
 int sx_openssl_initialized = 0;
 
-/** args: name, pemfile, cachain, mode */
+/** args: name, pemfile, cachain, mode, password */
 int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args) {
-    char *name, *pemfile, *cachain;
+    char *name, *pemfile, *cachain, *password;
     int ret;
     int mode;
 
@@ -827,6 +859,7 @@ int sx_ssl_init(sx_env_t env, sx_plugin_
 
     cachain = va_arg(args, char *);
     mode = va_arg(args, int);
+    password = va_arg(args, char *);
 
     /* !!! output openssl error messages to the debug log */
 
@@ -837,7 +870,7 @@ int sx_ssl_init(sx_env_t env, sx_plugin_
     }
     sx_openssl_initialized = 1;
 
-    ret = sx_ssl_server_addcert(p, name, pemfile, cachain, mode);
+    ret = sx_ssl_server_addcert(p, name, pemfile, cachain, mode, password);
     if(ret)
         return 1;
 
@@ -856,14 +889,15 @@ int sx_ssl_init(sx_env_t env, sx_plugin_
     return 0;
 }
 
-/** args: name, pemfile, cachain, mode */
-int sx_ssl_server_addcert(sx_plugin_t p, char *name, char *pemfile, char *cachain, int mode) {
+/** args: name, pemfile, cachain, mode, password */
+int sx_ssl_server_addcert(sx_plugin_t p, char *name, char *pemfile, char *cachain, int mode, char *password) {
     xht contexts = (xht) p->private;
     SSL_CTX *ctx;
     SSL_CTX *tmp;
     STACK_OF(X509_NAME) *cert_names;
     X509_STORE * store;
     int ret;
+    ssl_userdata_t ssl_userdata;
 
     if(!sx_openssl_initialized) {
         _sx_debug(ZONE, "ssl plugin not initialised");
@@ -886,6 +920,13 @@ int sx_ssl_server_addcert(sx_plugin_t p,
         return 1;
     }
 
+    // Set allowed ciphers
+	if (SSL_CTX_set_cipher_list(ctx, "ALL:!LOW:!SSLv2:!EXP:!aNULL") != 1) {
+        _sx_debug(ZONE, "Can't set cipher list for SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
+        SSL_CTX_free(ctx);
+        return 1;
+    }
+
     /* Load the CA chain, if configured */
     if (cachain != NULL) {
         ret = SSL_CTX_load_verify_locations (ctx, cachain, NULL);
@@ -924,6 +965,30 @@ int sx_ssl_server_addcert(sx_plugin_t p,
         return 1;
     }
 
+    // Add apple password callback
+#ifdef __APPLE__
+
+    _sx_debug(ZONE, "Adding Apple-custom SSL password callback");
+    {
+        if(strlen(pemfile))
+        {
+            ssl_userdata = (ssl_userdata_t)malloc(sizeof(struct ssl_userdata_st));
+            ssl_userdata->pemfile = pemfile;
+            ssl_userdata->password = NULL;
+            
+            if (password != NULL) {
+                ssl_userdata->password = password;
+            }
+            SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)ssl_userdata);
+            SSL_CTX_set_default_passwd_cb(ctx, &sx_apple_password_callback);
+
+            _sx_debug(ZONE, "Apple-custom SSL password callback enabled for %s", pemfile);
+        }
+        else
+            _sx_debug(ZONE, "Could not set custom callback for %s", pemfile);
+    }
+#endif /* __APPLE__ */
+
     /* load the private key */
     ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);
     if(ret != 1) {
@@ -950,7 +1015,7 @@ int sx_ssl_server_addcert(sx_plugin_t p,
 
         /* this is the first context, if it's not the default then make a copy of it as the default */
         if(!(name[0] == '*' && name[1] == 0)) {
-            int ret = sx_ssl_server_addcert(p, "*", pemfile, cachain, mode);
+            int ret = sx_ssl_server_addcert(p, "*", pemfile, cachain, mode, password);
 
             if(ret) {
                 /* uh-oh */
@@ -973,7 +1038,7 @@ int sx_ssl_server_addcert(sx_plugin_t p,
     return 0;
 }
 
-int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, char *pemfile) {
+int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, char *pemfile, char *private_key_password) {
     assert((int) (p != NULL));
     assert((int) (s != NULL));
 
@@ -995,6 +1060,10 @@ int sx_ssl_client_starttls(sx_plugin_t p
     if(pemfile != NULL) {
         s->plugin_data[p->index] = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
         ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile = strdup(pemfile);
+
+         /* save the given password for later */
+         if(private_key_password != NULL)
+             ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password = strdup(private_key_password);
     }
 
     /* go */
@@ -1004,3 +1073,33 @@ int sx_ssl_client_starttls(sx_plugin_t p
 
     return 0;
 }
+
+#ifdef __APPLE__
+int sx_apple_password_callback(char *return_buf, int return_buf_size, int in_rwflag, void *in_userdata)
+{
+    ssl_userdata_t ssl_userdata;
+    size_t passwd_len = 0;
+
+    if(in_userdata == NULL)
+    {
+        _sx_debug(ZONE, "Invalid arguments in callback");
+        return 0;
+    }
+
+    ssl_userdata = (ssl_userdata_t)in_userdata;
+
+    // If we already know the password, just return it
+    if (ssl_userdata->password != NULL) {
+        passwd_len = strlen(ssl_userdata->password);
+        if (passwd_len >= return_buf_size) {
+            _sx_debug(ZONE, "Error: password too long for return buffer");
+            return 0;
+        }
+        strncpy(return_buf, ssl_userdata->password, return_buf_size);
+        return (int)passwd_len;
+    } else {
+        _sx_debug(ZONE, "No private key password specified for pemfile");
+        return 0;
+    }
+}
+#endif