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:
parent
7eda92f409
commit
3f522ce892
@ -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--;
|
||||||
|
@ -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 *
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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 *);
|
||||||
|
Loading…
Reference in New Issue
Block a user