diff options
Diffstat (limited to 'usr.sbin/smtpd/ssl.c')
-rw-r--r-- | usr.sbin/smtpd/ssl.c | 59 |
1 files changed, 50 insertions, 9 deletions
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; |