ssl.c.patch   [plain text]


--- /tmp/jabberd-2.1.24.1/sx/ssl.c	2008-04-27 02:57:25.000000000 -0700
+++ ./jabberd2/sx/ssl.c	2009-06-09 12:16:14.000000000 -0700
@@ -155,6 +155,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;
             }
@@ -484,7 +486,9 @@ static int _sx_ssl_rio(sx_t s, sx_plugin
 static void _sx_ssl_client(sx_t s, sx_plugin_t p) {
     _sx_ssl_conn_t sc;
     char *pemfile = NULL;
+    char *pemfile_password = NULL;
     int ret;
+    ssl_userdata_t ssl_userdata;
 
     /* only bothering if they asked for wrappermode */
     if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
@@ -514,6 +518,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;
     }
@@ -528,6 +533,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) {
@@ -611,6 +641,7 @@ static void _sx_ssl_free(sx_t s, sx_plug
 
     if(sc->external_id != NULL) free(sc->external_id);
     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 */
 
@@ -632,12 +663,13 @@ static void _sx_ssl_unload(sx_plugin_t p
 
 int sx_openssl_initialized = 0;
 
-/** args: pemfile, cachain, mode */
+/** args: pemfile, cachain, mode, password (opt) */
 int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args) {
-    char *pemfile, *cachain;
+    char *pemfile, *cachain, *password;
     SSL_CTX *ctx;
     int ret;
     int mode;
+    ssl_userdata_t ssl_userdata;
 
     _sx_debug(ZONE, "initialising ssl plugin");
 
@@ -650,6 +682,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 */
 
@@ -682,6 +715,30 @@ int sx_ssl_init(sx_env_t env, sx_plugin_
         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) {
@@ -721,7 +778,7 @@ int sx_ssl_init(sx_env_t env, sx_plugin_
     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));
 
@@ -743,6 +800,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 */
@@ -752,3 +813,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