--- /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