From 680fe47acf2a83581fa86e4d6b952600b13e3a37 Mon Sep 17 00:00:00 2001 From: Eric Faurot Date: Mon, 14 Nov 2011 11:53:11 +0000 Subject: The spool and offline directories are backend-independent, so they must be created early by smtpd, rather than in fsqueue. ok gilles@ chl@ --- usr.sbin/smtpd/queue_fsqueue.c | 123 +++-------------------------------------- usr.sbin/smtpd/smtpd.c | 9 ++- usr.sbin/smtpd/smtpd.h | 3 +- usr.sbin/smtpd/util.c | 67 +++++++++++++++++++++- 4 files changed, 82 insertions(+), 120 deletions(-) (limited to 'usr.sbin/smtpd') diff --git a/usr.sbin/smtpd/queue_fsqueue.c b/usr.sbin/smtpd/queue_fsqueue.c index 2b76f252308..b1de423f397 100644 --- a/usr.sbin/smtpd/queue_fsqueue.c +++ b/usr.sbin/smtpd/queue_fsqueue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue_fsqueue.c,v 1.17 2011/11/06 16:57:27 eric Exp $ */ +/* $OpenBSD: queue_fsqueue.c,v 1.18 2011/11/14 11:53:10 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade @@ -484,127 +484,18 @@ fsqueue_init(void) { unsigned int n; char *paths[] = { PATH_INCOMING, PATH_ENQUEUE, PATH_QUEUE, - PATH_PURGE, PATH_OFFLINE, PATH_BOUNCE, - PATH_CORRUPT }; - char pathname[MAXPATHLEN]; - struct stat sb; + PATH_PURGE, PATH_BOUNCE, PATH_CORRUPT }; + char path[MAXPATHLEN]; int ret; - if (! bsnprintf(pathname, sizeof(pathname), "%s", PATH_SPOOL)) - fatal("snprintf"); - - if (stat(pathname, &sb) == -1) { - if (errno != ENOENT) { - warn("stat: %s", pathname); - return 0; - } - - if (mkdir(pathname, 0711) == -1) { - warn("mkdir: %s", pathname); - return 0; - } - - if (chown(pathname, 0, 0) == -1) { - warn("chown: %s", pathname); - return 0; - } - - if (stat(pathname, &sb) == -1) - err(1, "stat: %s", pathname); - } - - /* check if it's a directory */ - if (!S_ISDIR(sb.st_mode)) { - warnx("%s is not a directory", pathname); - return 0; - } - - /* check that it is owned by uid/gid */ - if (sb.st_uid != 0 || sb.st_gid != 0) { - warnx("%s must be owned by root:wheel", pathname); - return 0; - } - - /* check permission */ - if ((sb.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR) || - (sb.st_mode & (S_IRGRP|S_IWGRP|S_IXGRP)) != S_IXGRP || - (sb.st_mode & (S_IROTH|S_IWOTH|S_IXOTH)) != S_IXOTH) { - warnx("%s must be rwx--x--x (0711)", pathname); - return 0; - } - ret = 1; for (n = 0; n < nitems(paths); n++) { - mode_t mode; - uid_t owner; - gid_t group; - - if (!strcmp(paths[n], PATH_OFFLINE)) { - mode = 01777; - owner = 0; - group = 0; - } else { - mode = 0700; - owner = env->sc_pw->pw_uid; - group = 0; - } - - if (! bsnprintf(pathname, sizeof(pathname), "%s%s", PATH_SPOOL, - paths[n])) - fatal("snprintf"); - - if (stat(pathname, &sb) == -1) { - if (errno != ENOENT) { - warn("stat: %s", pathname); - ret = 0; - continue; - } - - /* chmod is deffered to avoid umask effect */ - if (mkdir(pathname, 0) == -1) { - ret = 0; - warn("mkdir: %s", pathname); - } - - if (chown(pathname, owner, group) == -1) { - ret = 0; - warn("chown: %s", pathname); - } - - if (chmod(pathname, mode) == -1) { - ret = 0; - warn("chmod: %s", pathname); - } - - if (stat(pathname, &sb) == -1) - err(1, "stat: %s", pathname); - } - - /* check if it's a directory */ - if (!S_ISDIR(sb.st_mode)) { - ret = 0; - warnx("%s is not a directory", pathname); - } + strlcpy(path, PATH_SPOOL, sizeof(path)); + if (strlcat(path, paths[n], sizeof(path)) >= sizeof(path)) + errx(1, "path too long %s%s", PATH_SPOOL, paths[n]); - /* check that it is owned by owner/group */ - if (sb.st_uid != owner) { + if (ckdir(path, 0700, env->sc_pw->pw_uid, 0, 1) == 0) ret = 0; - warnx("%s is not owned by uid %d", pathname, owner); - } - if (sb.st_gid != group) { - ret = 0; - warnx("%s is not owned by gid %d", pathname, group); - } - - /* check permission */ - if ((sb.st_mode & 07777) != mode) { - char mode_str[12]; - - ret = 0; - strmode(mode, mode_str); - mode_str[10] = '\0'; - warnx("%s must be %s (%o)", pathname, mode_str + 1, mode); - } } return ret; } diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index 90d95a2b6e9..17c01be3a36 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.135 2011/11/07 11:14:10 eric Exp $ */ +/* $OpenBSD: smtpd.c,v 1.136 2011/11/14 11:53:10 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -488,12 +488,17 @@ main(int argc, char *argv[]) if ((env->sc_pw = getpwnam(SMTPD_USER)) == NULL) errx(1, "unknown user %s", SMTPD_USER); + if (ckdir(PATH_SPOOL, 0711, 0, 0, 1) == 0) + errx(1, "error in spool directory setup"); + if (ckdir(PATH_SPOOL PATH_OFFLINE, 01777, 0, 0, 1) == 0) + errx(1, "error in offline directory setup"); + env->sc_queue = queue_backend_lookup(QT_FS); if (env->sc_queue == NULL) errx(1, "could not find queue backend"); if (!env->sc_queue->init()) - errx(1, "invalid directory permissions"); + errx(1, "could not initialize queue backend"); log_init(debug); log_verbose(verbose); diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index bf16fbbbe8d..cc2b2f0596f 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.248 2011/11/07 11:14:10 eric Exp $ */ +/* $OpenBSD: smtpd.h,v 1.249 2011/11/14 11:53:10 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -1226,3 +1226,4 @@ u_int64_t msgid_to_evpid(u_int32_t); u_int32_t filename_to_msgid(char *); u_int64_t filename_to_evpid(char *); void log_imsg(int, int, struct imsg*); +int ckdir(const char *, mode_t, uid_t, gid_t, int); diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c index a627e5ae89d..e11307142dd 100644 --- a/usr.sbin/smtpd/util.c +++ b/usr.sbin/smtpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.49 2011/10/27 14:32:57 chl Exp $ */ +/* $OpenBSD: util.c,v 1.50 2011/11/14 11:53:10 eric Exp $ */ /* * Copyright (c) 2000,2001 Markus Friedl. All rights reserved. @@ -66,6 +66,71 @@ bsnprintf(char *str, size_t size, const char *format, ...) return 1; } +int +ckdir(const char *path, mode_t mode, uid_t owner, gid_t group, int create) +{ + char mode_str[12]; + int ret; + struct stat sb; + + if (stat(path, &sb) == -1) { + if (errno != ENOENT || create == 0) { + warn("stat: %s", path); + return (0); + } + + /* chmod is deferred to avoid umask effect */ + if (mkdir(path, 0) == -1) { + warn("mkdir: %s", path); + return (0); + } + + if (chown(path, owner, group) == -1) { + warn("chown: %s", path); + return (0); + } + + if (chmod(path, mode) == -1) { + warn("chmod: %s", path); + return (0); + } + + if (stat(path, &sb) == -1) { + warn("stat: %s", path); + return (0); + } + } + + ret = 1; + + /* check if it's a directory */ + if (!S_ISDIR(sb.st_mode)) { + ret = 0; + warnx("%s is not a directory", path); + } + + /* check that it is owned by owner/group */ + if (sb.st_uid != owner) { + ret = 0; + warnx("%s is not owned by uid %d", path, owner); + } + if (sb.st_gid != group) { + ret = 0; + warnx("%s is not owned by gid %d", path, group); + } + + /* check permission */ + if ((sb.st_mode & 07777) != mode) { + ret = 0; + strmode(mode, mode_str); + mode_str[10] = '\0'; + warnx("%s must be %s (%o)", path, mode_str + 1, mode); + } + + return ret; +} + + /* Close file, signifying temporary error condition (if any) to the caller. */ int safe_fclose(FILE *fp) -- cgit v1.2.3