From: Timo Sirainen Date: Wed, 13 May 2009 23:52:25 +0000 (-0400) Subject: Renamed ssl_cert_file to ssl_cert and ssl_key_file to ssl_key. X-Git-Tag: 2.0.alpha1~777 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=02a0492affdff138f43903c19ca366363923044d;p=thirdparty%2Fdovecot%2Fcore.git Renamed ssl_cert_file to ssl_cert and ssl_key_file to ssl_key. Instead of pointing to files they now contain the certs directly. --HG-- branch : HEAD --- diff --git a/dovecot-example.conf b/dovecot-example.conf index c0d313b095..2b148a16a9 100644 --- a/dovecot-example.conf +++ b/dovecot-example.conf @@ -15,7 +15,7 @@ # or plugin settings are added by default, they're listed only as examples. # Paths are also just examples with the real defaults being based on configure # options. The paths listed here are for configure --prefix=/usr -# --sysconfdir=/etc --localstatedir=/var --with-ssldir=/etc/ssl +# --sysconfdir=/etc --localstatedir=/var # Base directory where to store runtime data. #base_dir = /var/run/dovecot/ @@ -93,8 +93,8 @@ # dropping root privileges, so keep the key file unreadable by anyone but # root. Included doc/mkcert.sh can be used to easily generate self-signed # certificate, just make sure to update the domains in dovecot-openssl.cnf -#ssl_cert_file = /etc/ssl/certs/dovecot.pem -#ssl_key_file = /etc/ssl/private/dovecot.pem +ssl_cert_file = ssl); return FALSE; #else - if (*set->ssl_cert_file == '\0') { - *error_r = "ssl_cert_file not set"; + if (*set->ssl_cert == '\0') { + *error_r = "ssl enabled, but ssl_cert not set"; return FALSE; } - if (*set->ssl_key_file == '\0') { - *error_r = "ssl_key_file not set"; + if (*set->ssl_key == '\0') { + *error_r = "ssl enabled, but ssl_key not set"; return FALSE; } if (set->ssl_verify_client_cert && *set->ssl_ca_file == '\0') { @@ -117,16 +117,6 @@ static int ssl_settings_check(void *_set ATTR_UNUSED, const char **error_r) } #ifndef CONFIG_BINARY - if (access(set->ssl_cert_file, R_OK) < 0) { - *error_r = t_strdup_printf("ssl_cert_file: access(%s) failed: %m", - set->ssl_cert_file); - return FALSE; - } - if (access(set->ssl_key_file, R_OK) < 0) { - *error_r = t_strdup_printf("ssl_key_file: access(%s) failed: %m", - set->ssl_key_file); - return FALSE; - } if (*set->ssl_ca_file != '\0' && access(set->ssl_ca_file, R_OK) < 0) { *error_r = t_strdup_printf("ssl_ca_file: access(%s) failed: %m", set->ssl_ca_file); diff --git a/src/login-common/login-settings.h b/src/login-common/login-settings.h index a505692843..aa721b2f6d 100644 --- a/src/login-common/login-settings.h +++ b/src/login-common/login-settings.h @@ -14,8 +14,8 @@ struct login_settings { const char *ssl; const char *ssl_ca_file; - const char *ssl_cert_file; - const char *ssl_key_file; + const char *ssl_cert; + const char *ssl_key; const char *ssl_key_password; const char *ssl_parameters_file; const char *ssl_cipher_list; diff --git a/src/login-common/ssl-proxy-openssl.c b/src/login-common/ssl-proxy-openssl.c index 5afdda8923..d4f7ea3117 100644 --- a/src/login-common/ssl-proxy-openssl.c +++ b/src/login-common/ssl-proxy-openssl.c @@ -765,22 +765,9 @@ unsigned int ssl_proxy_get_count(void) return ssl_proxy_count; } -static bool is_pem_key_file(const char *path) +static bool is_pem_key(const char *cert) { - char buf[4096]; - int fd, ret; - - /* this code is used only for giving a better error message, - so it needs to catch only the normal key files */ - fd = open(path, O_RDONLY); - if (fd == -1) - return FALSE; - ret = read(fd, buf, sizeof(buf)-1); - close(fd); - if (ret <= 0) - return FALSE; - buf[ret] = '\0'; - return strstr(buf, "PRIVATE KEY---") != NULL; + return strstr(cert, "PRIVATE KEY---") != NULL; } static void @@ -818,8 +805,60 @@ ssl_proxy_ctx_verify_client(SSL_CTX *ssl_ctx, const struct login_settings *set) SSL_load_client_CA_file(set->ssl_ca_file)); } +static int +ssl_proxy_ctx_use_certificate_chain(SSL_CTX *ctx, const char *cert) +{ + /* mostly just copy&pasted from SSL_CTX_use_certificate_chain_file() */ + BIO *in; + int ret = 0; + X509 *x; + + in = BIO_new_mem_buf(t_strdup_noconst(cert), strlen(cert)); + if (in == NULL) + i_fatal("BIO_new_mem_buf() failed"); + + x = PEM_read_bio_X509(in, NULL, NULL, NULL); + if (x == NULL) + goto end; + + ret = SSL_CTX_use_certificate(ctx, x); + if (ERR_peek_error() != 0) + ret = 0; + + if (ret != 0) { + /* If we could set up our certificate, now proceed to + * the CA certificates. + */ + X509 *ca; + int r; + unsigned long err; + + while ((ca = PEM_read_bio_X509(in,NULL,NULL,NULL)) != NULL) { + r = SSL_CTX_add_extra_chain_cert(ctx, ca); + if (!r) { + X509_free(ca); + ret = 0; + goto end; + } + } + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) + ERR_clear_error(); + else + ret = 0; /* some real error */ + } + +end: + if (x != NULL) X509_free(x); + if (in != NULL) BIO_free(in); + return ret; +} + static void ssl_proxy_init_server(const struct login_settings *set) { + BIO *bio; + EVP_PKEY *pkey; char *password; unsigned long err; @@ -832,33 +871,37 @@ static void ssl_proxy_init_server(const struct login_settings *set) set->ssl_cipher_list, ssl_last_error()); } - if (SSL_CTX_use_certificate_chain_file(ssl_server_ctx, - set->ssl_cert_file) != 1) { + if (ssl_proxy_ctx_use_certificate_chain(ssl_server_ctx, + set->ssl_cert) != 1) { err = ERR_peek_error(); if (ERR_GET_LIB(err) != ERR_LIB_PEM || ERR_GET_REASON(err) != PEM_R_NO_START_LINE) { - i_fatal("Can't load certificate file %s: %s", - set->ssl_cert_file, ssl_last_error()); - } else if (is_pem_key_file(set->ssl_cert_file)) { - i_fatal("Can't load certificate file %s: " + i_fatal("Can't load ssl_cert: %s", ssl_last_error()); + } else if (is_pem_key(set->ssl_cert)) { + i_fatal("Can't load ssl_cert: " "The file contains a private key " - "(you've mixed ssl_cert_file and ssl_key_file settings)", - set->ssl_cert_file); + "(you've mixed ssl_cert and ssl_key settings)"); } else { - i_fatal("Can't load certificate file %s: " - "The file doesn't contain a certificate.", - set->ssl_cert_file); + i_fatal("Can't load ssl_cert: There is no certificate."); } } password = t_strdup_noconst(set->ssl_key_password); SSL_CTX_set_default_passwd_cb(ssl_server_ctx, pem_password_callback); SSL_CTX_set_default_passwd_cb_userdata(ssl_server_ctx, password); - if (SSL_CTX_use_PrivateKey_file(ssl_server_ctx, set->ssl_key_file, - SSL_FILETYPE_PEM) != 1) { - i_fatal("Can't load private key file %s: %s", - set->ssl_key_file, ssl_last_error()); - } + + bio = BIO_new_mem_buf(t_strdup_noconst(set->ssl_key), + strlen(set->ssl_key)); + if (bio == NULL) + i_fatal("BIO_new_mem_buf() failed"); + pkey = PEM_read_bio_PrivateKey(bio, NULL, pem_password_callback, + password); + if (pkey == NULL) + i_fatal("Couldn't parse private ssl_key"); + if (SSL_CTX_use_PrivateKey(ssl_server_ctx, pkey) != 1) + i_fatal("Can't load private ssl_key: %s", ssl_last_error()); + EVP_PKEY_free(pkey); + safe_memset(password, 0, strlen(password)); if (set->verbose_ssl)