1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-09 22:38:01 -08:00

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.
This commit is contained in:
gilles 2011-04-14 20:11:08 +00:00
parent 7eda92f409
commit 3f522ce892
9 changed files with 424 additions and 320 deletions

View File

@ -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> * Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
@ -147,14 +147,14 @@ bounce_event(int fd, short event, void *p)
out: out:
if (*ep == '2') if (*ep == '2')
queue_remove_envelope(&cc->m); queue_envelope_delete(cc->env, Q_QUEUE, &cc->m);
else { else {
if (*ep == '5' || *ep == '6') if (*ep == '5' || *ep == '6')
cc->m.status = S_MESSAGE_PERMFAILURE; cc->m.status = S_MESSAGE_PERMFAILURE;
else else
cc->m.status = S_MESSAGE_TEMPFAILURE; cc->m.status = S_MESSAGE_TEMPFAILURE;
message_set_errormsg(&cc->m, "%s", ep); message_set_errormsg(&cc->m, "%s", ep);
queue_message_update(&cc->m); queue_message_update(cc->env, &cc->m);
} }
cc->env->stats->runner.active--; cc->env->stats->runner.active--;

View File

@ -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> * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@ -35,15 +35,19 @@
#include "smtpd.h" #include "smtpd.h"
#include "log.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 *); 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 *); enum queue_op , struct message *);
struct queue_backend queue_backends[] = { struct queue_backend queue_backends[] = {
{ QT_FS, { QT_FS,
queue_fsqueue_message, fsqueue_init,
queue_fsqueue_envelope } fsqueue_message,
fsqueue_envelope }
}; };
struct queue_backend * struct queue_backend *

View File

@ -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> * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@ -23,6 +23,8 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <event.h> #include <event.h>
#include <imsg.h> #include <imsg.h>
#include <libgen.h> #include <libgen.h>
@ -35,21 +37,391 @@
#include "smtpd.h" #include "smtpd.h"
#include "log.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 *); 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 *); enum queue_op , struct message *);
int static char *
queue_fsqueue_message(struct smtpd *env, enum queue_kind qkind, fsqueue_getpath(enum queue_kind kind)
enum queue_op qop, char *msgid)
{ {
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; return 0;
} }
int int
queue_fsqueue_envelope(struct smtpd *env, enum queue_kind qkind, fsqueue_envelope_delete(struct smtpd *env, enum queue_kind qkind,
enum queue_op qop, struct message *envelope) 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
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
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; return 0;
} }

View File

@ -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> * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@ -404,50 +404,7 @@ queue_open_message_file(char *msgid)
} }
void void
queue_delete_message(char *msgid) queue_message_update(struct smtpd *env, struct message *messagep)
{
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)
{ {
messagep->flags &= ~F_MESSAGE_PROCESSING; messagep->flags &= ~F_MESSAGE_PROCESSING;
messagep->status &= ~(S_MESSAGE_ACCEPTED|S_MESSAGE_REJECTED); messagep->status &= ~(S_MESSAGE_ACCEPTED|S_MESSAGE_REJECTED);
@ -461,124 +418,18 @@ queue_message_update(struct message *messagep)
bounce_record_message(messagep, &bounce); bounce_record_message(messagep, &bounce);
} }
queue_remove_envelope(messagep); queue_envelope_delete(env, Q_QUEUE, messagep);
return; return;
} }
if (messagep->status & S_MESSAGE_TEMPFAILURE) { if (messagep->status & S_MESSAGE_TEMPFAILURE) {
messagep->status &= ~S_MESSAGE_TEMPFAILURE; messagep->status &= ~S_MESSAGE_TEMPFAILURE;
queue_update_envelope(messagep); queue_envelope_update(env, Q_QUEUE, messagep);
return; return;
} }
/* no error, remove envelope */ /* no error, remove envelope */
queue_remove_envelope(messagep); queue_envelope_delete(env, Q_QUEUE, 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;
} }
u_int16_t u_int16_t

View File

@ -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> * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@ -140,7 +140,8 @@ ramqueue_load(struct ramqueue *rqueue, time_t *nsched)
while (qwalk(q, path)) { while (qwalk(q, path)) {
curtm = time(NULL); curtm = time(NULL);
if (! queue_load_envelope(&envelope, basename(path))) if (! queue_envelope_load(rqueue->env, Q_QUEUE,
basename(path), &envelope))
continue; continue;
if (ramqueue_expire(rqueue->env, &envelope, curtm)) if (ramqueue_expire(rqueue->env, &envelope, curtm))
continue; continue;
@ -216,7 +217,7 @@ ramqueue_expire(struct smtpd *env, struct message *envelope, time_t curtm)
envelope->expire / 60 / 60 / 24); envelope->expire / 60 / 60 / 24);
bounce_record_message(envelope, &bounce); bounce_record_message(envelope, &bounce);
ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL)); ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL));
queue_remove_envelope(envelope); queue_envelope_delete(env, Q_QUEUE, envelope);
return 1; return 1;
} }
return 0; return 0;

View File

@ -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> * 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) { if (m->status & S_MESSAGE_TEMPFAILURE) {
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)); ramqueue_insert(&env->sc_rqueue, m, time(NULL));
runner_setup_events(env); runner_setup_events(env);
return; return;
@ -107,7 +107,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
/* successful delivery or permanent failure, /* successful delivery or permanent failure,
* remove envelope from queue. * remove envelope from queue.
*/ */
queue_remove_envelope(m); queue_envelope_delete(env, Q_QUEUE, m);
return; return;
case IMSG_MDA_SESS_NEW: case IMSG_MDA_SESS_NEW:
@ -126,7 +126,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
m = imsg->data; m = imsg->data;
if (imsg->fd < 0 || !bounce_session(env, imsg->fd, m)) { if (imsg->fd < 0 || !bounce_session(env, imsg->fd, m)) {
m->status = 0; m->status = 0;
queue_update_envelope(m); queue_envelope_update(env, Q_QUEUE, m);
ramqueue_insert(&env->sc_rqueue, m, time(NULL)); ramqueue_insert(&env->sc_rqueue, m, time(NULL));
runner_setup_events(env); runner_setup_events(env);
return; 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; mda_av = env->sc_maxconn - env->stats->mda.sessions_active;
bnc_av = env->sc_maxconn - env->stats->runner.bounces_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; return 0;
if (envelope.type & T_MDA_MESSAGE) { 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); bounce_record_message(&envelope, &bounce);
ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL)); ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL));
runner_setup_events(env); runner_setup_events(env);
queue_remove_envelope(&envelope); queue_envelope_delete(env, Q_QUEUE, &envelope);
return 0; return 0;
} }
@ -395,7 +395,8 @@ runner_process_batch(struct smtpd *env, struct ramqueue_envelope *rq_evp, time_t
switch (batch->type) { switch (batch->type) {
case T_BOUNCE_MESSAGE: case T_BOUNCE_MESSAGE:
while ((rq_evp = ramqueue_batch_first_envelope(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; return;
envelope.lasttry = curtm; envelope.lasttry = curtm;
imsg_compose_event(env->sc_ievs[PROC_QUEUE], 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: case T_MDA_MESSAGE:
rq_evp = ramqueue_batch_first_envelope(batch); 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; return;
envelope.lasttry = curtm; envelope.lasttry = curtm;
fd = queue_open_message_file(envelope.message_id); 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, IMSG_BATCH_CREATE, PROC_MTA, 0, -1, batch,
sizeof *batch); sizeof *batch);
while ((rq_evp = ramqueue_batch_first_envelope(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; return;
envelope.lasttry = curtm; envelope.lasttry = curtm;
envelope.batch_id = batch->b_id; envelope.batch_id = batch->b_id;
@ -502,7 +505,8 @@ runner_force_message_to_ramqueue(struct ramqueue *rqueue, char *mid)
curtm = time(NULL); curtm = time(NULL);
while ((dp = readdir(dirp)) != NULL) { while ((dp = readdir(dirp)) != NULL) {
if (valid_message_uid(dp->d_name)) { 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; continue;
ramqueue_insert(rqueue, &envelope, curtm); ramqueue_insert(rqueue, &envelope, curtm);
} }

View File

@ -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}/.. .PATH: ${.CURDIR}/..
@ -17,7 +17,7 @@ CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare -Wbounded CFLAGS+= -Wsign-compare -Wbounded
CFLAGS+= -DCLIENT_NO_SSL 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 LDADD+= -lutil -levent
DPADD+= ${LIBUTIL} ${LIBEVENT} DPADD+= ${LIBUTIL} ${LIBEVENT}
.include <bsd.prog.mk> .include <bsd.prog.mk>

View File

@ -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> * 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) if ((env.sc_pw = getpwnam(SMTPD_USER)) == NULL)
errx(1, "unknown user %s", SMTPD_USER); 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); env.sc_queue = queue_backend_lookup(QT_FS);
if (env.sc_queue == NULL) if (env.sc_queue == NULL)
errx(1, "could not find queue backend"); errx(1, "could not find queue backend");
if (!env.sc_queue->setup(&env))
errx(1, "invalid directory permissions");
log_init(debug); log_init(debug);
log_verbose(verbose); log_verbose(verbose);
@ -637,135 +637,6 @@ child_lookup(struct smtpd *env, pid_t pid)
return SPLAY_FIND(childtree, &env->children, &key); 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 void
imsg_event_add(struct imsgev *iev) imsg_event_add(struct imsgev *iev)
{ {

View File

@ -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> * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@ -931,6 +931,7 @@ enum queue_op {
struct queue_backend { struct queue_backend {
enum queue_type type; enum queue_type type;
int (*setup)(struct smtpd *);
int (*message)(struct smtpd *, enum queue_kind, enum queue_op, char *); int (*message)(struct smtpd *, enum queue_kind, enum queue_op, char *);
int (*envelope)(struct smtpd *, enum queue_kind, enum queue_op, int (*envelope)(struct smtpd *, enum queue_kind, enum queue_op,
struct message *); struct message *);
@ -1097,7 +1098,7 @@ int queue_remove_incoming_envelope(struct message *);
int queue_commit_incoming_message(struct message *); int queue_commit_incoming_message(struct message *);
int queue_open_incoming_message_file(struct message *); int queue_open_incoming_message_file(struct message *);
int queue_open_message_file(char *msgid); 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 *); void queue_delete_message(char *);
struct qwalk *qwalk_new(char *); struct qwalk *qwalk_new(char *);
int qwalk(struct qwalk *, char *); int qwalk(struct qwalk *, char *);