diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2011-05-17 18:54:33 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2011-05-17 18:54:33 +0000 |
commit | 9ff5eb03c0801271c66e35a31b930bccfa701e39 (patch) | |
tree | 977d90c3d77da6b09e1756c09e06fb8448f4c06d /usr.sbin/smtpd/smtpd.c | |
parent | d0de42170315935a0a78d8218e8d58287064ffb8 (diff) |
introduce new user_backend API for smtpd to lookup the users it wants to
deliver mail to. the only backend supported for now is USER_GETPWNAM and
it is not yet possible to switch to an alternate backend.
yes this means that we're very close from smtpd being able to handle fully
virtual accounts for both incoming and outgoing messages.
Diffstat (limited to 'usr.sbin/smtpd/smtpd.c')
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index 2e4d1002cf8..a8333ed159f 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.125 2011/05/17 16:42:06 gilles Exp $ */ +/* $OpenBSD: smtpd.c,v 1.126 2011/05/17 18:54:32 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -687,16 +687,18 @@ forkmda(struct imsgev *iev, u_int32_t id, struct deliver *deliver) { char ebuf[128], sfn[32]; - struct passwd *pw; + struct user_backend *ub; + struct user u; struct child *child; pid_t pid; int n, allout, pipefd[2]; log_debug("forkmda: to %s as %s", deliver->to, deliver->user); + bzero(&u, sizeof (u)); + ub = user_backend_lookup(USER_GETPWNAM); errno = 0; - pw = getpwnam(deliver->user); - if (pw == NULL) { + if (! ub->getbyname(&u, deliver->user)) { n = snprintf(ebuf, sizeof ebuf, "getpwnam: %s", errno ? strerror(errno) : "no such user"); imsg_compose_event(iev, IMSG_MDA_DONE, id, 0, -1, ebuf, n + 1); @@ -704,7 +706,7 @@ forkmda(struct imsgev *iev, u_int32_t id, } /* lower privs early to allow fork fail due to ulimit */ - if (seteuid(pw->pw_uid) < 0) + if (seteuid(u.uid) < 0) fatal("cannot lower privileges"); if (pipe(pipefd) < 0) { @@ -757,7 +759,7 @@ forkmda(struct imsgev *iev, u_int32_t id, #define error(m) { perror(m); _exit(1); } if (seteuid(0) < 0) error("forkmda: cannot restore privileges"); - if (chdir(pw->pw_dir) < 0 && chdir("/") < 0) + if (chdir(u.directory) < 0 && chdir("/") < 0) error("chdir"); if (dup2(pipefd[0], STDIN_FILENO) < 0 || dup2(allout, STDOUT_FILENO) < 0 || @@ -765,9 +767,9 @@ forkmda(struct imsgev *iev, u_int32_t id, error("forkmda: dup2"); if (closefrom(STDERR_FILENO + 1) < 0) error("closefrom"); - if (setgroups(1, &pw->pw_gid) || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + if (setgroups(1, &u.gid) || + setresgid(u.gid, u.gid, u.gid) || + setresuid(u.uid, u.uid, u.uid)) error("forkmda: cannot drop privileges"); if (setsid() < 0) error("setsid"); @@ -888,7 +890,8 @@ static int parent_enqueue_offline(char *runner_path) { char path[MAXPATHLEN]; - struct passwd *pw; + struct user_backend *ub; + struct user u; struct stat sb; pid_t pid; @@ -916,8 +919,10 @@ parent_enqueue_offline(char *runner_path) fatal("parent_enqueue_offline: chflags"); } + ub = user_backend_lookup(USER_GETPWNAM); + bzero(&u, sizeof (u)); errno = 0; - if ((pw = getpwuid(sb.st_uid)) == NULL) { + if (! ub->getbyuid(&u, sb.st_uid)) { log_warn("parent_enqueue_offline: getpwuid for uid %d failed", sb.st_uid); unlink(path); @@ -944,9 +949,9 @@ parent_enqueue_offline(char *runner_path) bzero(&args, sizeof(args)); - if (setgroups(1, &pw->pw_gid) || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) || + if (setgroups(1, &u.gid) || + setresgid(u.gid, u.gid, u.gid) || + setresuid(u.uid, u.uid, u.uid) || closefrom(STDERR_FILENO + 1) == -1) { unlink(path); _exit(1); @@ -958,7 +963,7 @@ parent_enqueue_offline(char *runner_path) } unlink(path); - if (chdir(pw->pw_dir) == -1 && chdir("/") == -1) + if (chdir(u.directory) == -1 && chdir("/") == -1) _exit(1); if (setsid() == -1 || @@ -1033,15 +1038,17 @@ queueing_done(void) static int parent_forward_open(char *username) { - struct passwd *pw; + struct user_backend *ub; + struct user u; char pathname[MAXPATHLEN]; int fd; - pw = getpwnam(username); - if (pw == NULL) + bzero(&u, sizeof (u)); + ub = user_backend_lookup(USER_GETPWNAM); + if (! ub->getbyname(&u, username)) return -1; - if (! bsnprintf(pathname, sizeof (pathname), "%s/.forward", pw->pw_dir)) + if (! bsnprintf(pathname, sizeof (pathname), "%s/.forward", u.directory)) fatal("snprintf"); fd = open(pathname, O_RDONLY); @@ -1052,7 +1059,7 @@ parent_forward_open(char *username) return -1; } - if (! secure_file(fd, pathname, pw, 1)) { + if (! secure_file(fd, pathname, u.directory, u.uid, 1)) { log_warnx("%s: unsecure file", pathname); close(fd); return -1; |