diff options
author | Eric Faurot <eric@cvs.openbsd.org> | 2013-11-28 12:50:41 +0000 |
---|---|---|
committer | Eric Faurot <eric@cvs.openbsd.org> | 2013-11-28 12:50:41 +0000 |
commit | 45157af4612cf5ad6cd825becacf55fafcabcf25 (patch) | |
tree | 0b5f95b5108187a380b924bad65243efe8fed80d | |
parent | de19dab93d5ca0374bd9c48db3a26a5931020099 (diff) |
fix loading of passphrase-protected keys.
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 23 | ||||
-rw-r--r-- | usr.sbin/smtpd/ssl.c | 59 | ||||
-rw-r--r-- | usr.sbin/smtpd/ssl.h | 6 |
3 files changed, 64 insertions, 24 deletions
diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index 479a0391d02..6520e519a6e 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.206 2013/11/13 13:02:44 eric Exp $ */ +/* $OpenBSD: smtpd.c,v 1.207 2013/11/28 12:50:40 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -742,6 +742,8 @@ main(int argc, char *argv[]) log_init(foreground); log_verbose(verbose); + load_ssl_tree(); + log_info("info: %s %s starting", SMTPD_NAME, SMTPD_VERSION); if (! foreground) @@ -764,8 +766,6 @@ main(int argc, char *argv[]) errx(1, "machine does not have a hostname set"); env->sc_uptime = time(NULL); - load_ssl_tree(); - fork_peers(); config_process(PROC_PARENT); @@ -827,24 +827,23 @@ load_ssl_tree(void) log_debug("debug: init ssl-tree"); iter_dict = NULL; while (dict_iter(env->sc_ssl_dict, &iter_dict, &k, (void **)&ssl)) { - log_debug("debug: loading pki information for %s", k); - + log_debug("info: loading pki information for %s", k); if (ssl->ssl_cert_file == NULL) - errx(1, "load_ssl_tree: missing certificate file for %s", k); + fatalx("load_ssl_tree: missing certificate file"); if (ssl->ssl_key_file == NULL) - errx(1, "load_ssl_tree: missing key file for %s", k); + fatalx("load_ssl_tree: missing key file"); if (! ssl_load_certificate(ssl, ssl->ssl_cert_file)) - errx(1, "load_ssl_tree: failed to load certificate file for %s", k); - if (! ssl_load_keyfile(ssl, ssl->ssl_key_file)) - errx(1, "load_ssl_tree: failed to load certificate file for %s", k); + fatalx("load_ssl_tree: failed to load certificate file"); + if (! ssl_load_keyfile(ssl, ssl->ssl_key_file, k)) + fatalx("load_ssl_tree: failed to load key file"); if (ssl->ssl_ca_file) if (! ssl_load_cafile(ssl, ssl->ssl_ca_file)) - errx(1, "load_ssl_tree: failed to load CA file for %s", k); + fatalx("load_ssl_tree: failed to load CA file"); if (ssl->ssl_dhparams_file) if (! ssl_load_dhparams(ssl, ssl->ssl_dhparams_file)) - errx(1, "load_ssl_tree: failed to load dhparams file for %s", k); + fatalx("load_ssl_tree: failed to load dhparams file"); } } diff --git a/usr.sbin/smtpd/ssl.c b/usr.sbin/smtpd/ssl.c index 7b7adb8fd54..b6c064711f2 100644 --- a/usr.sbin/smtpd/ssl.c +++ b/usr.sbin/smtpd/ssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.c,v 1.56 2013/11/06 10:01:29 eric Exp $ */ +/* $OpenBSD: ssl.c,v 1.57 2013/11/28 12:50:40 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -146,6 +146,7 @@ fail: return (NULL); } +#if 0 static int ssl_password_cb(char *buf, int size, int rwflag, void *u) { @@ -158,15 +159,39 @@ ssl_password_cb(char *buf, int size, int rwflag, void *u) return (0); return (len); } +#endif + +static int +ssl_getpass_cb(char *buf, int size, int rwflag, void *u) +{ + int ret = 0; + size_t len; + char *pass; + + pass = getpass((const char *)u); + if (pass == NULL) + return 0; + len = strlen(pass); + if (strlcpy(buf, pass, size) >= (size_t)size) + goto end; + ret = len; +end: + if (len) + bzero(pass, len); + return ret; +} char * -ssl_load_key(const char *name, off_t *len, char *pass) +ssl_load_key(const char *name, off_t *len, char *pass, mode_t perm, const char *pkiname) { FILE *fp; EVP_PKEY *key = NULL; BIO *bio = NULL; long size; char *data, *buf = NULL; + struct stat st; + char mode[12]; + char prompt[2048]; /* Initialize SSL library once */ ssl_init(); @@ -177,11 +202,26 @@ ssl_load_key(const char *name, off_t *len, char *pass) if ((fp = fopen(name, "r")) == NULL) return (NULL); - key = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, pass); + if (fstat(fileno(fp), &st) != 0) + goto fail; + if (st.st_uid != 0) { + log_warnx("warn: %s: not owned by uid 0", name); + errno = EACCES; + goto fail; + } + if (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO) & ~perm) { + strmode(perm, mode); + log_warnx("warn: %s: insecure permissions: must be at most %s", + name, &mode[1]); + errno = EACCES; + goto fail; + } + + (void)snprintf(prompt, sizeof prompt, "passphrase for %s: ", pkiname); + key = PEM_read_PrivateKey(fp, NULL, ssl_getpass_cb, prompt); fclose(fp); if (key == NULL) goto fail; - /* * Write unencrypted key to memory buffer */ @@ -191,17 +231,16 @@ ssl_load_key(const char *name, off_t *len, char *pass) goto fail; if ((size = BIO_get_mem_data(bio, &data)) <= 0) goto fail; - if ((buf = calloc(1, size)) == NULL) + if ((buf = calloc(1, size + 1)) == NULL) goto fail; memcpy(buf, data, size); BIO_free_all(bio); - *len = (off_t)size; + *len = (off_t)size + 1; return (buf); fail: ssl_error("ssl_load_key"); - free(buf); if (bio != NULL) BIO_free_all(bio); @@ -244,9 +283,11 @@ ssl_load_certificate(struct ssl *s, const char *pathname) } int -ssl_load_keyfile(struct ssl *s, const char *pathname) +ssl_load_keyfile(struct ssl *s, const char *pathname, const char *pkiname) { - s->ssl_key = ssl_load_file(pathname, &s->ssl_key_len, 0700); + char pass[1024]; + + s->ssl_key = ssl_load_key(pathname, &s->ssl_key_len, pass, 0700, pkiname); if (s->ssl_key == NULL) return 0; return 1; diff --git a/usr.sbin/smtpd/ssl.h b/usr.sbin/smtpd/ssl.h index 9d127beffac..cbf5574da4b 100644 --- a/usr.sbin/smtpd/ssl.h +++ b/usr.sbin/smtpd/ssl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.h,v 1.3 2013/11/06 10:01:29 eric Exp $ */ +/* $OpenBSD: ssl.h,v 1.4 2013/11/28 12:50:40 eric Exp $ */ /* * Copyright (c) 2013 Gilles Chehade <gilles@poolp.org> * @@ -52,13 +52,13 @@ void ssl_set_ephemeral_key_exchange(SSL_CTX *, DH *); void ssl_set_ecdh_curve(SSL_CTX *); extern int ssl_ctx_load_verify_memory(SSL_CTX *, char *, off_t); char *ssl_load_file(const char *, off_t *, mode_t); -char *ssl_load_key(const char *, off_t *, char *); +char *ssl_load_key(const char *, off_t *, char *, mode_t, const char *); const char *ssl_to_text(const SSL *); void ssl_error(const char *); int ssl_load_certificate(struct ssl *, const char *); -int ssl_load_keyfile(struct ssl *, const char *); +int ssl_load_keyfile(struct ssl *, const char *, const char *); int ssl_load_cafile(struct ssl *, const char *); int ssl_load_dhparams(struct ssl *, const char *); |