summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Faurot <eric@cvs.openbsd.org>2013-11-28 12:50:41 +0000
committerEric Faurot <eric@cvs.openbsd.org>2013-11-28 12:50:41 +0000
commit45157af4612cf5ad6cd825becacf55fafcabcf25 (patch)
tree0b5f95b5108187a380b924bad65243efe8fed80d
parentde19dab93d5ca0374bd9c48db3a26a5931020099 (diff)
fix loading of passphrase-protected keys.
-rw-r--r--usr.sbin/smtpd/smtpd.c23
-rw-r--r--usr.sbin/smtpd/ssl.c59
-rw-r--r--usr.sbin/smtpd/ssl.h6
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 *);