2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-31 22:25:24 +00:00

snapshot-20001127

This commit is contained in:
Wietse Venema
2000-11-27 00:00:00 -05:00
committed by Viktor Dukhovni
parent 3c2727d996
commit a6f1137bf4
7 changed files with 91 additions and 54 deletions

1
postfix/.indent.pro vendored
View File

@@ -68,6 +68,7 @@
-TMASTER_SERV -TMASTER_SERV
-TMASTER_STATUS -TMASTER_STATUS
-TMBLOCK -TMBLOCK
-TMBOX
-TMKMAP -TMKMAP
-TMKMAP_OPEN_INFO -TMKMAP_OPEN_INFO
-TMULTI_SERVER -TMULTI_SERVER

View File

@@ -15,7 +15,7 @@
* Version of this program. * Version of this program.
*/ */
#define VAR_MAIL_VERSION "mail_version" #define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-20001126" #define DEF_MAIL_VERSION "Snapshot-20001127"
extern char *var_mail_version; extern char *var_mail_version;
/* LICENSE /* LICENSE

View File

@@ -6,7 +6,14 @@
/* SYNOPSIS /* SYNOPSIS
/* #include <mbox_open.h> /* #include <mbox_open.h>
/* /*
/* int mbox_open(path, flags, mode, st, user, group, lock_style, why) /* typedef struct {
/* .in +4
/* /* public members... */
/* VSTREAM *fp;
/* .in -4
/* } MBOX;
/*
/* MBOX *mbox_open(path, flags, mode, st, user, group, lock_style, why)
/* const char *path; /* const char *path;
/* int flags; /* int flags;
/* int mode; /* int mode;
@@ -16,9 +23,8 @@
/* int lock_style; /* int lock_style;
/* VSTRING *why; /* VSTRING *why;
/* /*
/* void mbox_release(path, lock_style) /* void mbox_release(mbox)
/* const char *path; /* MBOX *mbox;
/* int lock_style;
/* DESCRIPTION /* DESCRIPTION
/* This module manages access to UNIX mailbox-style files. /* This module manages access to UNIX mailbox-style files.
/* /*
@@ -29,9 +35,10 @@
/* adequate effective privileges. /* adequate effective privileges.
/* The \fBlock_style\fR argument specifies a lock style from /* The \fBlock_style\fR argument specifies a lock style from
/* mbox_lock_mask(). Kernel locks are applied to regular files only. /* mbox_lock_mask(). Kernel locks are applied to regular files only.
/* The result is a handle that must be destroyed by mbox_release().
/* /*
/* mbox_release() releases the named mailbox. It is up to the /* mbox_release() releases the named mailbox. It is up to the
/* application to close the file. /* application to close the stream.
/* DIAGNOSTICS /* DIAGNOSTICS
/* mbox_open() returns a null pointer in case of problems, and /* mbox_open() returns a null pointer in case of problems, and
/* sets errno to EAGAIN if someone else has exclusive access. /* sets errno to EAGAIN if someone else has exclusive access.
@@ -59,6 +66,8 @@
#include <vstream.h> #include <vstream.h>
#include <vstring.h> #include <vstring.h>
#include <safe_open.h> #include <safe_open.h>
#include <iostuff.h>
#include <mymalloc.h>
/* Global library. */ /* Global library. */
@@ -69,43 +78,58 @@
/* mbox_open - open mailbox-style file for exclusive access */ /* mbox_open - open mailbox-style file for exclusive access */
VSTREAM *mbox_open(const char *path, int flags, int mode, struct stat * st, MBOX *mbox_open(const char *path, int flags, int mode, struct stat * st,
uid_t chown_uid, gid_t chown_gid, uid_t chown_uid, gid_t chown_gid,
int lock_style, VSTRING *why) int lock_style, VSTRING *why)
{ {
struct stat local_statbuf; struct stat local_statbuf;
MBOX *mp;
int locked = 0;
VSTREAM *fp; VSTREAM *fp;
/* /*
* Create dotlock file. This locking method does not work well over NFS: * Create dotlock file. This locking method does not work well over NFS:
* creating files atomically is a problem, and a successful operation can * creating files atomically is a problem, and a successful operation can
* fail with EEXIST. * fail with EEXIST.
*
* If file.lock can't be created, ignore the problem if the application says
* so. We need this so that Postfix can deliver as unprivileged user to
* /dev/null style aliases. Alternatively, we could open the file first,
* and dot-lock the file only if it is a regular file, just like we do
* with kernel locks.
*/ */
if ((lock_style & MBOX_DOT_LOCK) && dot_lockfile(path, why) < 0) { if (lock_style & MBOX_DOT_LOCK) {
if (errno == EEXIST) { if (dot_lockfile(path, why) == 0) {
errno = EAGAIN; locked |= MBOX_DOT_LOCK;
return (0); } else {
if (errno == EEXIST) {
errno = EAGAIN;
return (0);
}
if ((lock_style & MBOX_DOT_LOCK_MAY_FAIL) == 0) {
return (0);
}
} }
/*
* If file.lock can't be created, ignore the problem. We need this so
* that Postfix can deliver as unprivileged user to /dev/null
* aliases.
*/
if ((lock_style & MBOX_DOT_LOCK_MAY_FAIL) == 0)
return (0);
} }
/* /*
* Open or create the target file. * Open or create the target file. In case of a privileged open, the
* privileged user may be attacked through an unsafe parent directory. In
* case of an unprivileged open, the mail system may be attacked by a
* malicious user-specified path, and the unprivileged user may be
* attacked through an unsafe parent directory. Open non-blocking to fend
* off attacks involving FIFOs and other weird targets.
*/ */
if (st == 0) if (st == 0)
st = &local_statbuf; st = &local_statbuf;
if ((fp = safe_open(path, flags, mode, st, chown_uid, chown_gid, why)) == 0) { if ((fp = safe_open(path, flags, mode | O_NONBLOCK, st,
if (lock_style & MBOX_DOT_LOCK) chown_uid, chown_gid, why)) == 0) {
if (locked & MBOX_DOT_LOCK)
dot_unlockfile(path); dot_unlockfile(path);
return (0); return (0);
} }
non_blocking(vstream_fileno(fp), BLOCKING);
close_on_exec(vstream_fileno(fp), CLOSE_ON_EXEC);
/* /*
* Acquire kernel locks, but only if the target is a regular file, in * Acquire kernel locks, but only if the target is a regular file, in
@@ -121,17 +145,23 @@ VSTREAM *mbox_open(const char *path, int flags, int mode, struct stat * st,
|| LOCK_FAIL(MBOX_FCNTL_LOCK, MYFLOCK_STYLE_FCNTL))) { || LOCK_FAIL(MBOX_FCNTL_LOCK, MYFLOCK_STYLE_FCNTL))) {
if (myflock_locked(vstream_fileno(fp))) if (myflock_locked(vstream_fileno(fp)))
errno = EAGAIN; errno = EAGAIN;
if (lock_style & MBOX_DOT_LOCK) if (locked & MBOX_DOT_LOCK)
dot_unlockfile(path); dot_unlockfile(path);
return (0); return (0);
} }
return (fp); mp = (MBOX *) mymalloc(sizeof(*mp));
mp->path = mystrdup(path);
mp->fp = fp;
mp->locked = locked;
return (mp);
} }
/* mbox_release - release mailbox exclusive access */ /* mbox_release - release mailbox exclusive access */
void mbox_release(const char *path, int lock_style) void mbox_release(MBOX *mp)
{ {
if (lock_style & MBOX_DOT_LOCK) if (mp->locked & MBOX_DOT_LOCK)
dot_unlockfile(path); dot_unlockfile(mp->path);
myfree(mp->path);
myfree((char *) mp);
} }

View File

@@ -21,8 +21,13 @@
/* /*
* External interface. * External interface.
*/ */
extern VSTREAM *mbox_open(const char *, int, int, struct stat *, uid_t, gid_t, int, VSTRING *); typedef struct {
extern void mbox_release(const char *, int); char *path; /* saved path, for dot_unlock */
VSTREAM *fp; /* open stream or null */
int locked; /* what locks were set */
} MBOX;
extern MBOX *mbox_open(const char *, int, int, struct stat *, uid_t, gid_t, int, VSTRING *);
extern void mbox_release(MBOX *);
/* LICENSE /* LICENSE
/* .ad /* .ad

View File

@@ -84,7 +84,7 @@ int deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
{ {
char *myname = "deliver_file"; char *myname = "deliver_file";
struct stat st; struct stat st;
VSTREAM *dst; MBOX *mp;
VSTRING *why; VSTRING *why;
int status; int status;
int copy_flags; int copy_flags;
@@ -148,26 +148,27 @@ int deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
copy_flags &= ~MAIL_COPY_DELIVERED; copy_flags &= ~MAIL_COPY_DELIVERED;
set_eugid(usr_attr.uid, usr_attr.gid); set_eugid(usr_attr.uid, usr_attr.gid);
dst = mbox_open(path, O_APPEND | O_CREAT | O_WRONLY, mp = mbox_open(path, O_APPEND | O_CREAT | O_WRONLY,
S_IRUSR | S_IWUSR, &st, -1, -1, S_IRUSR | S_IWUSR, &st, -1, -1,
local_mbox_lock_mask | MBOX_DOT_LOCK_MAY_FAIL, why); local_mbox_lock_mask | MBOX_DOT_LOCK_MAY_FAIL, why);
if (dst == 0) { if (mp == 0) {
status = (errno == EAGAIN ? defer_append : bounce_append) status = (errno == EAGAIN ? defer_append : bounce_append)
(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr), (BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"cannot access destination file %s: %s", path, STR(why)); "cannot access destination file %s: %s", path, STR(why));
} else if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { } else if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
vstream_fclose(dst); vstream_fclose(mp->fp);
status = bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr), status = bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"executable destination file %s", path); "executable destination file %s", path);
} else if (mail_copy(COPY_ATTR(state.msg_attr), dst, S_ISREG(st.st_mode) ? } else if (mail_copy(COPY_ATTR(state.msg_attr), mp->fp,
copy_flags : (copy_flags & ~MAIL_COPY_TOFILE), "\n", why)) { S_ISREG(st.st_mode) ? copy_flags : (copy_flags & ~MAIL_COPY_TOFILE),
"\n", why)) {
status = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr), status = defer_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"cannot append destination file %s: %s", "cannot append destination file %s: %s",
path, STR(why)); path, STR(why));
} else { } else {
status = sent(SENT_ATTR(state.msg_attr), "%s", path); status = sent(SENT_ATTR(state.msg_attr), "%s", path);
} }
mbox_release(path, local_mbox_lock_mask); mbox_release(mp);
set_eugid(var_owner_uid, var_owner_gid); set_eugid(var_owner_uid, var_owner_gid);
/* /*

View File

@@ -96,7 +96,7 @@ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
char *spool_dir; char *spool_dir;
char *mailbox; char *mailbox;
VSTRING *why; VSTRING *why;
VSTREAM *dst; MBOX *mp;
int status; int status;
int copy_flags; int copy_flags;
VSTRING *biff; VSTRING *biff;
@@ -180,23 +180,24 @@ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
copy_flags &= ~MAIL_COPY_DELIVERED; copy_flags &= ~MAIL_COPY_DELIVERED;
set_eugid(spool_uid, spool_gid); set_eugid(spool_uid, spool_gid);
dst = mbox_open(mailbox, O_APPEND | O_WRONLY | O_CREAT, mp = mbox_open(mailbox, O_APPEND | O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR, &st, chown_uid, chown_gid, S_IRUSR | S_IWUSR, &st, chown_uid, chown_gid,
local_mbox_lock_mask, why); local_mbox_lock_mask, why);
if (dst != 0) { if (mp != 0) {
if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid) if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid)
set_eugid(usr_attr.uid, usr_attr.gid); set_eugid(usr_attr.uid, usr_attr.gid);
if (S_ISREG(st.st_mode) == 0) { if (S_ISREG(st.st_mode) == 0) {
vstream_fclose(mp->fp);
vstring_sprintf(why, "file %s should be a regular file", mailbox); vstring_sprintf(why, "file %s should be a regular file", mailbox);
errno = 0; errno = 0;
} else { } else {
end = vstream_fseek(dst, (off_t) 0, SEEK_END); end = vstream_fseek(mp->fp, (off_t) 0, SEEK_END);
status = mail_copy(COPY_ATTR(state.msg_attr), dst, status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp,
copy_flags, "\n", why); copy_flags, "\n", why);
} }
if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid) if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid)
set_eugid(spool_uid, spool_gid); set_eugid(spool_uid, spool_gid);
mbox_release(mailbox, local_mbox_lock_mask); mbox_release(mp);
} }
set_eugid(var_owner_uid, var_owner_gid); set_eugid(var_owner_uid, var_owner_gid);

View File

@@ -142,9 +142,9 @@ int main(int argc, char **argv)
int count; int count;
WAIT_STATUS_T status; WAIT_STATUS_T status;
pid_t pid; pid_t pid;
int mbox_lock; int lock_mask;
char *lock_style = 0; char *lock_style = 0;
VSTREAM *fp; MBOX *mp;
/* /*
* Be consistent with file permissions. * Be consistent with file permissions.
@@ -204,7 +204,7 @@ int main(int argc, char **argv)
* Read the config file. * Read the config file.
*/ */
mail_conf_read(); mail_conf_read();
mbox_lock = mbox_lock_mask(lock_style ? lock_style : lock_mask = mbox_lock_mask(lock_style ? lock_style :
get_mail_conf_str(VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, 1, 0)); get_mail_conf_str(VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, 1, 0));
/* /*
@@ -212,11 +212,10 @@ int main(int argc, char **argv)
* command is not supposed to disappear into the background. * command is not supposed to disappear into the background.
*/ */
why = vstring_alloc(1); why = vstring_alloc(1);
if ((fp = mbox_open(folder, O_APPEND | O_WRONLY | O_CREAT, if ((mp = mbox_open(folder, O_APPEND | O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR, (struct stat *) 0, S_IRUSR | S_IWUSR, (struct stat *) 0,
-1, -1, mbox_lock, why)) == 0) -1, -1, lock_mask, why)) == 0)
msg_fatal("%s", vstring_str(why)); msg_fatal("%s", vstring_str(why));
close_on_exec(vstream_fileno(fp), CLOSE_ON_EXEC);
/* /*
* Run the command. Remove the lock after completion. * Run the command. Remove the lock after completion.
@@ -232,12 +231,12 @@ int main(int argc, char **argv)
default: default:
if (waitpid(pid, &status, 0) < 0) if (waitpid(pid, &status, 0) < 0)
msg_fatal("waitpid: %m"); msg_fatal("waitpid: %m");
mbox_release(folder, mbox_lock); mbox_release(mp);
exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1); exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1);
} }
if (count + 1 < var_fork_tries) if (count + 1 < var_fork_tries)
sleep(var_fork_delay); sleep(var_fork_delay);
} }
mbox_release(folder, mbox_lock); mbox_release(mp);
exit(EX_TEMPFAIL); exit(EX_TEMPFAIL);
} }