diff -r 24ccf040026b src/login-common/ssl-proxy-openssl.c --- a/src/login-common/ssl-proxy-openssl.c Sat Dec 27 09:19:04 2008 +0200 +++ b/src/login-common/ssl-proxy-openssl.c Wed Dec 31 01:27:40 2008 +0200 @@ -21,6 +21,13 @@ #include #include #include + +#ifdef APPLE_OS_X_SERVER +# include +# include +# include +# define APPLE_CERTADMIN_PATH "/usr/sbin/certadmin" +#endif #define DOVECOT_SSL_DEFAULT_CIPHER_LIST "ALL:!LOW:!SSLv2" /* Check every 30 minutes if parameters file has been updated */ @@ -681,6 +688,64 @@ static int ssl_verify_client_cert(int pr return 1; } +#ifdef APPLE_OS_X_SERVER +static int +apple_password_callback(char *buf, int size, int rwflag ATTR_UNUSED, + void *user_data) +{ + const char *keyfile = user_data; + ssize_t ret; + int fd[2]; + const char *args[4]; + pid_t pid; + + /* open a pipe */ + if (pipe(fd) < 0) { + i_error("pipe() failed: %m"); + return 0; + } + + /* fork the child */ + pid = fork(); + if (pid < 0) + i_fatal("fork() failed: %m"); + if (pid == 0) { + /* child: exec certadmin tool */ + (void)close(0); + (void)close(1); + + if (dup2(fd[1], STDOUT_FILENO) < 0) + i_fatal("dup2() failed: %m"); + + /* set up the args list */ + args[0] = APPLE_CERTADMIN_PATH; + args[1] = "--get-private-key-passphrase"; + args[2] = keyfile; + args[3] = NULL; + + /* get the passphrase */ + (void)execv(args[0], (char **)args); + i_fatal("execv(%s) failed: %m", args[0]); + } + + /* parent: read passphrase */ + ret = read(fd[0], buf, size); + if (ret < 0) { + i_error("%s: ssl_key_file %s: read() failed: %m", + APPLE_CERTADMIN_PATH, keyfile); + return 0; + } else if (buf[ret-1] != '\n') { + i_error("%s: ssl_key_file %s: password longer than %d bytes", + APPLE_CERTADMIN_PATH, keyfile, size-1); + return 0; + } else { + /* strip off trailing LF */ + buf[--ret] = '\0'; + return ret; + } + +} +#else static int pem_password_callback(char *buf, int size, int rwflag ATTR_UNUSED, void *userdata) @@ -695,6 +760,7 @@ pem_password_callback(char *buf, int siz return 0; return strlen(buf); } +#endif unsigned int ssl_proxy_get_count(void) { @@ -800,8 +866,14 @@ void ssl_proxy_init(void) } } +#ifdef APPLE_OS_X_SERVER + SSL_CTX_set_default_passwd_cb(ssl_ctx, &apple_password_callback); + SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, i_strdup(keyfile)); +#else SSL_CTX_set_default_passwd_cb(ssl_ctx, pem_password_callback); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, password); +#endif + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, keyfile, SSL_FILETYPE_PEM) != 1) { i_fatal("Can't load private key file %s: %s",