summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/smtpd/ssl.c')
-rw-r--r--usr.sbin/smtpd/ssl.c59
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;