diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2011-04-14 20:11:09 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2011-04-14 20:11:09 +0000 |
commit | 88bf84069c919f11e6072a750f6b1ac7a9f492ed (patch) | |
tree | aa65e237bb6da0e7a3a54688a157d9dad87cec47 /usr.sbin/smtpd | |
parent | 37d103bd8ed97c8b053353cc4a7f56b18f87a1af (diff) |
fsqueue queue backend will implement a filesystem queue:
- fsqueue->setup() performs the queue initialization;
- fsqueue->message() controls messages;
- fsqueue->envelope() controls envelopes;
This commit brings the following to fsbackend:
fsqueue_setup(), fsqueue_message_delete(), fsqueue_envelope_load(),
fsqueue_envelope_update(), fsqueue_envelope_delete().
It also makes smtpd use the queue_backend API for these operations.
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r-- | usr.sbin/smtpd/bounce.c | 6 | ||||
-rw-r--r-- | usr.sbin/smtpd/queue_backend.c | 14 | ||||
-rw-r--r-- | usr.sbin/smtpd/queue_fsqueue.c | 382 | ||||
-rw-r--r-- | usr.sbin/smtpd/queue_shared.c | 159 | ||||
-rw-r--r-- | usr.sbin/smtpd/ramqueue.c | 7 | ||||
-rw-r--r-- | usr.sbin/smtpd/runner.c | 24 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpctl/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 137 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 5 |
9 files changed, 421 insertions, 317 deletions
diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c index 780e1f894b5..9bea66eb241 100644 --- a/usr.sbin/smtpd/bounce.c +++ b/usr.sbin/smtpd/bounce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bounce.c,v 1.26 2011/03/26 10:59:59 gilles Exp $ */ +/* $OpenBSD: bounce.c,v 1.27 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org> @@ -147,14 +147,14 @@ bounce_event(int fd, short event, void *p) out: if (*ep == '2') - queue_remove_envelope(&cc->m); + queue_envelope_delete(cc->env, Q_QUEUE, &cc->m); else { if (*ep == '5' || *ep == '6') cc->m.status = S_MESSAGE_PERMFAILURE; else cc->m.status = S_MESSAGE_TEMPFAILURE; message_set_errormsg(&cc->m, "%s", ep); - queue_message_update(&cc->m); + queue_message_update(cc->env, &cc->m); } cc->env->stats->runner.active--; diff --git a/usr.sbin/smtpd/queue_backend.c b/usr.sbin/smtpd/queue_backend.c index aa9847b929c..ac677521882 100644 --- a/usr.sbin/smtpd/queue_backend.c +++ b/usr.sbin/smtpd/queue_backend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue_backend.c,v 1.5 2011/04/14 17:06:43 gilles Exp $ */ +/* $OpenBSD: queue_backend.c,v 1.6 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org> @@ -35,15 +35,19 @@ #include "smtpd.h" #include "log.h" -int queue_fsqueue_message(struct smtpd *, enum queue_kind, +/* fsqueue backend */ +int fsqueue_init(struct smtpd *); +int fsqueue_message(struct smtpd *, enum queue_kind, enum queue_op, char *); -int queue_fsqueue_envelope(struct smtpd *, enum queue_kind, +int fsqueue_envelope(struct smtpd *, enum queue_kind, enum queue_op , struct message *); + struct queue_backend queue_backends[] = { { QT_FS, - queue_fsqueue_message, - queue_fsqueue_envelope } + fsqueue_init, + fsqueue_message, + fsqueue_envelope } }; struct queue_backend * diff --git a/usr.sbin/smtpd/queue_fsqueue.c b/usr.sbin/smtpd/queue_fsqueue.c index ee2766c69cd..ef5668d049a 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.1 2011/04/14 17:06:43 gilles Exp $ */ +/* $OpenBSD: queue_fsqueue.c,v 1.2 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org> @@ -23,6 +23,8 @@ #include <sys/socket.h> #include <sys/stat.h> +#include <err.h> +#include <errno.h> #include <event.h> #include <imsg.h> #include <libgen.h> @@ -35,21 +37,391 @@ #include "smtpd.h" #include "log.h" -int queue_fsqueue_message(struct smtpd *, enum queue_kind, +static char *fsqueue_getpath(enum queue_kind); +static u_int16_t fsqueue_hash(char *); + +static int fsqueue_envelope_load(struct smtpd *, enum queue_kind, struct message *); +static int fsqueue_envelope_update(struct smtpd *, enum queue_kind, struct message *); +static int fsqueue_envelope_delete(struct smtpd *, enum queue_kind, struct message *); + +static int fsqueue_message_delete(struct smtpd *, enum queue_kind, char *); + +int fsqueue_init(struct smtpd *); +int fsqueue_message(struct smtpd *, enum queue_kind, enum queue_op, char *); -int queue_fsqueue_envelope(struct smtpd *, enum queue_kind, +int fsqueue_envelope(struct smtpd *, enum queue_kind, enum queue_op , struct message *); +static char * +fsqueue_getpath(enum queue_kind kind) +{ + switch (kind) { + case Q_INCOMING: + return (PATH_INCOMING); + + case Q_ENQUEUE: + return (PATH_INCOMING); + + case Q_QUEUE: + return (PATH_QUEUE); + + case Q_PURGE: + return (PATH_PURGE); + + case Q_OFFLINE: + return (PATH_OFFLINE); + + case Q_BOUNCE: + return (PATH_BOUNCE); + + default: + fatalx("queue_fsqueue_getpath: unsupported queue kind."); + } + return NULL; +} + +static u_int16_t +fsqueue_hash(char *msgid) +{ + u_int16_t h; + + for (h = 5381; *msgid; msgid++) + h = ((h << 5) + h) + *msgid; + + return (h % DIRHASH_BUCKETS); +} + +static int +fsqueue_envelope_load(struct smtpd *env, enum queue_kind qkind, + struct message *envelope) +{ + char pathname[MAXPATHLEN]; + char msgid[MAX_ID_SIZE]; + FILE *fp; + + if (strlcpy(msgid, envelope->message_uid, sizeof(msgid)) >= sizeof(msgid)) + return 0; + + *strrchr(msgid, '.') = '\0'; + if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s", + fsqueue_getpath(qkind), + fsqueue_hash(msgid), msgid, PATH_ENVELOPES, envelope->message_uid)) + fatalx("fsqueue_envelope_load: snprintf"); + + fp = fopen(pathname, "r"); + if (fp == NULL) { + if (errno == ENOENT || errno == ENFILE) + return 0; + fatal("fsqueue_envelope_load: fopen"); + } + if (fread(envelope, sizeof(struct message), 1, fp) != 1) + fatal("fsqueue_envelope_load: fread"); + fclose(fp); + return 1; +} + +int +fsqueue_envelope_update(struct smtpd *env, enum queue_kind qkind, + struct message *envelope) +{ + char temp[MAXPATHLEN]; + char dest[MAXPATHLEN]; + FILE *fp; + u_int64_t batch_id; + + batch_id = envelope->batch_id; + envelope->batch_id = 0; + + if (! bsnprintf(temp, sizeof(temp), "%s/envelope.tmp", PATH_QUEUE)) + fatalx("fsqueue_envelope_update"); + + if (! bsnprintf(dest, sizeof(dest), "%s/%d/%s%s/%s", + fsqueue_getpath(qkind), + fsqueue_hash(envelope->message_id), + envelope->message_id, + PATH_ENVELOPES, envelope->message_uid)) + fatal("fsqueue_envelope_update: snprintf"); + + fp = fopen(temp, "w"); + if (fp == NULL) { + if (errno == ENOSPC || errno == ENFILE) + goto tempfail; + fatal("fsqueue_envelope_update: open"); + } + if (fwrite(envelope, sizeof(struct message), 1, fp) != 1) { + if (errno == ENOSPC) + goto tempfail; + fatal("fsqueue_envelope_update: fwrite"); + } + if (! safe_fclose(fp)) + goto tempfail; + + if (rename(temp, dest) == -1) { + if (errno == ENOSPC) + goto tempfail; + fatal("fsqueue_envelope_update: rename"); + } + + envelope->batch_id = batch_id; + return 1; + +tempfail: + if (unlink(temp) == -1) + fatal("fsqueue_envelope_update: unlink"); + if (fp) + fclose(fp); + + envelope->batch_id = batch_id; + return 0; +} + +int +fsqueue_envelope_delete(struct smtpd *env, enum queue_kind qkind, + struct message *envelope) +{ + char pathname[MAXPATHLEN]; + u_int16_t hval; + + hval = fsqueue_hash(envelope->message_id); + + if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s", + fsqueue_getpath(qkind), + hval, envelope->message_id, PATH_ENVELOPES, + envelope->message_uid)) + fatal("fsqueue_envelope_delete: snprintf"); + + if (unlink(pathname) == -1) + fatal("fsqueue_envelope_delete: unlink"); + + if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s", PATH_QUEUE, + hval, envelope->message_id, PATH_ENVELOPES)) + fatal("fsqueue_envelope_delete: snprintf"); + + if (rmdir(pathname) != -1) + fsqueue_message_delete(env, qkind, envelope->message_id); + + return 1; +} + +int +fsqueue_message_delete(struct smtpd *env, enum queue_kind qkind, char *msgid) +{ + char rootdir[MAXPATHLEN]; + char evpdir[MAXPATHLEN]; + char msgpath[MAXPATHLEN]; + u_int16_t hval; + + hval = queue_hash(msgid); + if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d/%s", PATH_QUEUE, + hval, msgid)) + fatal("queue_delete_message: snprintf"); + + if (! bsnprintf(evpdir, sizeof(evpdir), "%s%s", rootdir, + PATH_ENVELOPES)) + fatal("queue_delete_message: snprintf"); + + if (! bsnprintf(msgpath, sizeof(msgpath), "%s/message", rootdir)) + fatal("queue_delete_message: snprintf"); + + if (unlink(msgpath) == -1) + fatal("queue_delete_message: unlink"); + + if (rmdir(evpdir) == -1) { + /* It is ok to fail rmdir with ENOENT here + * because upon successful delivery of the + * last envelope, we remove the directory. + */ + if (errno != ENOENT) + fatal("queue_delete_message: rmdir"); + } + + if (rmdir(rootdir) == -1) + fatal("#2 queue_delete_message: rmdir"); + + if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d", PATH_QUEUE, hval)) + fatal("queue_delete_message: snprintf"); + + rmdir(rootdir); + + return 1; +} + +int +fsqueue_init(struct smtpd *env) +{ + unsigned int n; + char *paths[] = { PATH_INCOMING, PATH_ENQUEUE, PATH_QUEUE, + PATH_PURGE, PATH_OFFLINE, PATH_BOUNCE }; + char pathname[MAXPATHLEN]; + struct stat sb; + 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 = env->sc_pw->pw_gid; + } + + 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); + } + + /* check that it is owned by owner/group */ + if (sb.st_uid != owner) { + 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; +} + int -queue_fsqueue_message(struct smtpd *env, enum queue_kind qkind, +fsqueue_message(struct smtpd *env, enum queue_kind qkind, enum queue_op qop, char *msgid) { + switch (qop) { + case QOP_CREATE: + return 0; + + case QOP_DELETE: + return fsqueue_message_delete(env, qkind, msgid); + + case QOP_COMMIT: + return 0; + + case QOP_FD_R: + return 0; + + case QOP_FD_RW: + return 0; + + default: + fatalx("queue_fsqueue_message: unsupported operation."); + } + return 0; } int -queue_fsqueue_envelope(struct smtpd *env, enum queue_kind qkind, +fsqueue_envelope(struct smtpd *env, enum queue_kind qkind, enum queue_op qop, struct message *envelope) { + switch (qop) { + case QOP_CREATE: + return 0; + + case QOP_DELETE: + return fsqueue_envelope_delete(env, qkind, envelope); + + case QOP_LOAD: + return fsqueue_envelope_load(env, qkind, envelope); + + case QOP_UPDATE: + return fsqueue_envelope_update(env, qkind, envelope); + + default: + fatalx("queue_fsqueue_envelope: unsupported operation."); + } + return 0; } diff --git a/usr.sbin/smtpd/queue_shared.c b/usr.sbin/smtpd/queue_shared.c index 18549901553..1d8f1c415ef 100644 --- a/usr.sbin/smtpd/queue_shared.c +++ b/usr.sbin/smtpd/queue_shared.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue_shared.c,v 1.37 2011/04/13 20:53:18 gilles Exp $ */ +/* $OpenBSD: queue_shared.c,v 1.38 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -404,50 +404,7 @@ queue_open_message_file(char *msgid) } void -queue_delete_message(char *msgid) -{ - char rootdir[MAXPATHLEN]; - char evpdir[MAXPATHLEN]; - char msgpath[MAXPATHLEN]; - u_int16_t hval; - - hval = queue_hash(msgid); - if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d/%s", PATH_QUEUE, - hval, msgid)) - fatal("queue_delete_message: snprintf"); - - if (! bsnprintf(evpdir, sizeof(evpdir), "%s%s", rootdir, - PATH_ENVELOPES)) - fatal("queue_delete_message: snprintf"); - - if (! bsnprintf(msgpath, sizeof(msgpath), "%s/message", rootdir)) - fatal("queue_delete_message: snprintf"); - - if (unlink(msgpath) == -1) - fatal("queue_delete_message: unlink"); - - if (rmdir(evpdir) == -1) { - /* It is ok to fail rmdir with ENOENT here - * because upon successful delivery of the - * last envelope, we remove the directory. - */ - if (errno != ENOENT) - fatal("queue_delete_message: rmdir"); - } - - if (rmdir(rootdir) == -1) - fatal("#2 queue_delete_message: rmdir"); - - if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d", PATH_QUEUE, hval)) - fatal("queue_delete_message: snprintf"); - - rmdir(rootdir); - - return; -} - -void -queue_message_update(struct message *messagep) +queue_message_update(struct smtpd *env, struct message *messagep) { messagep->flags &= ~F_MESSAGE_PROCESSING; messagep->status &= ~(S_MESSAGE_ACCEPTED|S_MESSAGE_REJECTED); @@ -461,124 +418,18 @@ queue_message_update(struct message *messagep) bounce_record_message(messagep, &bounce); } - queue_remove_envelope(messagep); + queue_envelope_delete(env, Q_QUEUE, messagep); return; } if (messagep->status & S_MESSAGE_TEMPFAILURE) { messagep->status &= ~S_MESSAGE_TEMPFAILURE; - queue_update_envelope(messagep); + queue_envelope_update(env, Q_QUEUE, messagep); return; } /* no error, remove envelope */ - queue_remove_envelope(messagep); -} - -int -queue_remove_envelope(struct message *messagep) -{ - char pathname[MAXPATHLEN]; - u_int16_t hval; - - hval = queue_hash(messagep->message_id); - - if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s", - PATH_QUEUE, hval, messagep->message_id, PATH_ENVELOPES, - messagep->message_uid)) - fatal("queue_remove_envelope: snprintf"); - - if (unlink(pathname) == -1) - fatal("queue_remove_envelope: unlink"); - - if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s", PATH_QUEUE, - hval, messagep->message_id, PATH_ENVELOPES)) - fatal("queue_remove_envelope: snprintf"); - - if (rmdir(pathname) != -1) - queue_delete_message(messagep->message_id); - - return 1; -} - -int -queue_update_envelope(struct message *messagep) -{ - char temp[MAXPATHLEN]; - char dest[MAXPATHLEN]; - FILE *fp; - u_int64_t batch_id; - - batch_id = messagep->batch_id; - messagep->batch_id = 0; - - if (! bsnprintf(temp, sizeof(temp), "%s/envelope.tmp", PATH_QUEUE)) - fatalx("queue_update_envelope"); - - if (! bsnprintf(dest, sizeof(dest), "%s/%d/%s%s/%s", PATH_QUEUE, - queue_hash(messagep->message_id), messagep->message_id, - PATH_ENVELOPES, messagep->message_uid)) - fatal("queue_update_envelope: snprintf"); - - fp = fopen(temp, "w"); - if (fp == NULL) { - if (errno == ENOSPC || errno == ENFILE) - goto tempfail; - fatal("queue_update_envelope: open"); - } - if (fwrite(messagep, sizeof(struct message), 1, fp) != 1) { - if (errno == ENOSPC) - goto tempfail; - fatal("queue_update_envelope: fwrite"); - } - if (! safe_fclose(fp)) - goto tempfail; - - if (rename(temp, dest) == -1) { - if (errno == ENOSPC) - goto tempfail; - fatal("queue_update_envelope: rename"); - } - - messagep->batch_id = batch_id; - return 1; - -tempfail: - if (unlink(temp) == -1) - fatal("queue_update_envelope: unlink"); - if (fp) - fclose(fp); - - messagep->batch_id = batch_id; - return 0; -} - -int -queue_load_envelope(struct message *messagep, char *evpid) -{ - char pathname[MAXPATHLEN]; - char msgid[MAX_ID_SIZE]; - FILE *fp; - - if (strlcpy(msgid, evpid, sizeof(msgid)) >= sizeof(msgid)) - fatalx("queue_load_envelope: truncation"); - *strrchr(msgid, '.') = '\0'; - - if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s", PATH_QUEUE, - queue_hash(msgid), msgid, PATH_ENVELOPES, evpid)) - fatalx("queue_load_envelope: snprintf"); - - fp = fopen(pathname, "r"); - if (fp == NULL) { - if (errno == ENOENT || errno == ENFILE) - return 0; - fatal("queue_load_envelope: fopen"); - } - if (fread(messagep, sizeof(struct message), 1, fp) != 1) - fatal("queue_load_envelope: fread"); - fclose(fp); - - return 1; + queue_envelope_delete(env, Q_QUEUE, messagep); } u_int16_t diff --git a/usr.sbin/smtpd/ramqueue.c b/usr.sbin/smtpd/ramqueue.c index 17d10f7002b..8e98de29dc0 100644 --- a/usr.sbin/smtpd/ramqueue.c +++ b/usr.sbin/smtpd/ramqueue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ramqueue.c,v 1.1 2011/04/13 20:53:18 gilles Exp $ */ +/* $OpenBSD: ramqueue.c,v 1.2 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org> @@ -140,7 +140,8 @@ ramqueue_load(struct ramqueue *rqueue, time_t *nsched) while (qwalk(q, path)) { curtm = time(NULL); - if (! queue_load_envelope(&envelope, basename(path))) + if (! queue_envelope_load(rqueue->env, Q_QUEUE, + basename(path), &envelope)) continue; if (ramqueue_expire(rqueue->env, &envelope, curtm)) continue; @@ -216,7 +217,7 @@ ramqueue_expire(struct smtpd *env, struct message *envelope, time_t curtm) envelope->expire / 60 / 60 / 24); bounce_record_message(envelope, &bounce); ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL)); - queue_remove_envelope(envelope); + queue_envelope_delete(env, Q_QUEUE, envelope); return 1; } return 0; diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c index da71b28eb53..fb8e185f0ab 100644 --- a/usr.sbin/smtpd/runner.c +++ b/usr.sbin/smtpd/runner.c @@ -1,4 +1,4 @@ -/* $OpenBSD: runner.c,v 1.96 2011/04/13 20:53:18 gilles Exp $ */ +/* $OpenBSD: runner.c,v 1.97 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -84,7 +84,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) */ if (m->status & S_MESSAGE_TEMPFAILURE) { m->status &= ~S_MESSAGE_TEMPFAILURE; - queue_update_envelope(m); + queue_envelope_update(env, Q_QUEUE, m); ramqueue_insert(&env->sc_rqueue, m, time(NULL)); runner_setup_events(env); return; @@ -107,7 +107,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) /* successful delivery or permanent failure, * remove envelope from queue. */ - queue_remove_envelope(m); + queue_envelope_delete(env, Q_QUEUE, m); return; case IMSG_MDA_SESS_NEW: @@ -126,7 +126,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) m = imsg->data; if (imsg->fd < 0 || !bounce_session(env, imsg->fd, m)) { m->status = 0; - queue_update_envelope(m); + queue_envelope_update(env, Q_QUEUE, m); ramqueue_insert(&env->sc_rqueue, m, time(NULL)); runner_setup_events(env); return; @@ -339,7 +339,7 @@ runner_process_envelope(struct smtpd *env, struct ramqueue_envelope *rq_evp, tim mda_av = env->sc_maxconn - env->stats->mda.sessions_active; bnc_av = env->sc_maxconn - env->stats->runner.bounces_active; - if (! queue_load_envelope(&envelope, rq_evp->id)) + if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id, &envelope)) return 0; if (envelope.type & T_MDA_MESSAGE) { @@ -370,7 +370,7 @@ runner_process_envelope(struct smtpd *env, struct ramqueue_envelope *rq_evp, tim bounce_record_message(&envelope, &bounce); ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL)); runner_setup_events(env); - queue_remove_envelope(&envelope); + queue_envelope_delete(env, Q_QUEUE, &envelope); return 0; } @@ -395,7 +395,8 @@ runner_process_batch(struct smtpd *env, struct ramqueue_envelope *rq_evp, time_t switch (batch->type) { case T_BOUNCE_MESSAGE: while ((rq_evp = ramqueue_batch_first_envelope(batch))) { - if (! queue_load_envelope(&envelope, rq_evp->id)) + if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id, + &envelope)) return; envelope.lasttry = curtm; imsg_compose_event(env->sc_ievs[PROC_QUEUE], @@ -416,7 +417,8 @@ runner_process_batch(struct smtpd *env, struct ramqueue_envelope *rq_evp, time_t case T_MDA_MESSAGE: rq_evp = ramqueue_batch_first_envelope(batch); - if (! queue_load_envelope(&envelope, rq_evp->id)) + if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id, + &envelope)) return; envelope.lasttry = curtm; fd = queue_open_message_file(envelope.message_id); @@ -440,7 +442,8 @@ runner_process_batch(struct smtpd *env, struct ramqueue_envelope *rq_evp, time_t IMSG_BATCH_CREATE, PROC_MTA, 0, -1, batch, sizeof *batch); while ((rq_evp = ramqueue_batch_first_envelope(batch))) { - if (! queue_load_envelope(&envelope, rq_evp->id)) + if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id, + &envelope)) return; envelope.lasttry = curtm; envelope.batch_id = batch->b_id; @@ -502,7 +505,8 @@ runner_force_message_to_ramqueue(struct ramqueue *rqueue, char *mid) curtm = time(NULL); while ((dp = readdir(dirp)) != NULL) { if (valid_message_uid(dp->d_name)) { - if (! queue_load_envelope(&envelope, dp->d_name)) + if (! queue_envelope_load(rqueue->env, Q_QUEUE, dp->d_name, + &envelope)) continue; ramqueue_insert(rqueue, &envelope, curtm); } diff --git a/usr.sbin/smtpd/smtpctl/Makefile b/usr.sbin/smtpd/smtpctl/Makefile index 9d794d0ff24..7cf59de82eb 100644 --- a/usr.sbin/smtpd/smtpctl/Makefile +++ b/usr.sbin/smtpd/smtpctl/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.16 2010/10/09 22:05:35 gilles Exp $ +# $OpenBSD: Makefile,v 1.17 2011/04/14 20:11:08 gilles Exp $ .PATH: ${.CURDIR}/.. @@ -17,7 +17,7 @@ CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+= -Wsign-compare -Wbounded CFLAGS+= -DCLIENT_NO_SSL -SRCS= smtpctl.c parser.c log.c enqueue.c queue_shared.c util.c client.c +SRCS= smtpctl.c parser.c log.c enqueue.c queue_shared.c util.c client.c queue_backend.c queue_fsqueue.c LDADD+= -lutil -levent DPADD+= ${LIBUTIL} ${LIBEVENT} .include <bsd.prog.mk> diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index f1719b6ef00..4aed7f9664e 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.118 2011/04/14 17:06:43 gilles Exp $ */ +/* $OpenBSD: smtpd.c,v 1.119 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -488,13 +488,13 @@ main(int argc, char *argv[]) if ((env.sc_pw = getpwnam(SMTPD_USER)) == NULL) errx(1, "unknown user %s", SMTPD_USER); - if (!setup_spool(env.sc_pw->pw_uid, 0)) - errx(1, "invalid directory permissions"); - env.sc_queue = queue_backend_lookup(QT_FS); if (env.sc_queue == NULL) errx(1, "could not find queue backend"); + if (!env.sc_queue->setup(&env)) + errx(1, "invalid directory permissions"); + log_init(debug); log_verbose(verbose); @@ -637,135 +637,6 @@ child_lookup(struct smtpd *env, pid_t pid) return SPLAY_FIND(childtree, &env->children, &key); } -int -setup_spool(uid_t uid, gid_t gid) -{ - unsigned int n; - char *paths[] = { PATH_INCOMING, PATH_ENQUEUE, PATH_QUEUE, - PATH_PURGE, PATH_OFFLINE, PATH_BOUNCE }; - char pathname[MAXPATHLEN]; - struct stat sb; - 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 = uid; - group = gid; - } - - 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); - } - - /* check that it is owned by owner/group */ - if (sb.st_uid != owner) { - 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; -} - void imsg_event_add(struct imsgev *iev) { diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index d1d84cccc58..67ca4e3c1fb 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.209 2011/04/14 17:06:43 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.210 2011/04/14 20:11:08 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -931,6 +931,7 @@ enum queue_op { struct queue_backend { enum queue_type type; + int (*setup)(struct smtpd *); int (*message)(struct smtpd *, enum queue_kind, enum queue_op, char *); int (*envelope)(struct smtpd *, enum queue_kind, enum queue_op, struct message *); @@ -1097,7 +1098,7 @@ int queue_remove_incoming_envelope(struct message *); int queue_commit_incoming_message(struct message *); int queue_open_incoming_message_file(struct message *); int queue_open_message_file(char *msgid); -void queue_message_update(struct message *); +void queue_message_update(struct smtpd *, struct message *); void queue_delete_message(char *); struct qwalk *qwalk_new(char *); int qwalk(struct qwalk *, char *); |