2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 13:48:06 +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_STATUS
-TMBLOCK
-TMBOX
-TMKMAP
-TMKMAP_OPEN_INFO
-TMULTI_SERVER

View File

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

View File

@@ -6,7 +6,14 @@
/* SYNOPSIS
/* #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;
/* int flags;
/* int mode;
@@ -16,9 +23,8 @@
/* int lock_style;
/* VSTRING *why;
/*
/* void mbox_release(path, lock_style)
/* const char *path;
/* int lock_style;
/* void mbox_release(mbox)
/* MBOX *mbox;
/* DESCRIPTION
/* This module manages access to UNIX mailbox-style files.
/*
@@ -29,9 +35,10 @@
/* adequate effective privileges.
/* The \fBlock_style\fR argument specifies a lock style from
/* 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
/* application to close the file.
/* application to close the stream.
/* DIAGNOSTICS
/* mbox_open() returns a null pointer in case of problems, and
/* sets errno to EAGAIN if someone else has exclusive access.
@@ -59,6 +66,8 @@
#include <vstream.h>
#include <vstring.h>
#include <safe_open.h>
#include <iostuff.h>
#include <mymalloc.h>
/* Global library. */
@@ -69,43 +78,58 @@
/* mbox_open - open mailbox-style file for exclusive access */
VSTREAM *mbox_open(const char *path, int flags, int mode, struct stat * st,
uid_t chown_uid, gid_t chown_gid,
int lock_style, VSTRING *why)
MBOX *mbox_open(const char *path, int flags, int mode, struct stat * st,
uid_t chown_uid, gid_t chown_gid,
int lock_style, VSTRING *why)
{
struct stat local_statbuf;
MBOX *mp;
int locked = 0;
VSTREAM *fp;
/*
* Create dotlock file. This locking method does not work well over NFS:
* creating files atomically is a problem, and a successful operation can
* 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 (errno == EEXIST) {
errno = EAGAIN;
return (0);
if (lock_style & MBOX_DOT_LOCK) {
if (dot_lockfile(path, why) == 0) {
locked |= MBOX_DOT_LOCK;
} 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)
st = &local_statbuf;
if ((fp = safe_open(path, flags, mode, st, chown_uid, chown_gid, why)) == 0) {
if (lock_style & MBOX_DOT_LOCK)
if ((fp = safe_open(path, flags, mode | O_NONBLOCK, st,
chown_uid, chown_gid, why)) == 0) {
if (locked & MBOX_DOT_LOCK)
dot_unlockfile(path);
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
@@ -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))) {
if (myflock_locked(vstream_fileno(fp)))
errno = EAGAIN;
if (lock_style & MBOX_DOT_LOCK)
if (locked & MBOX_DOT_LOCK)
dot_unlockfile(path);
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 */
void mbox_release(const char *path, int lock_style)
void mbox_release(MBOX *mp)
{
if (lock_style & MBOX_DOT_LOCK)
dot_unlockfile(path);
if (mp->locked & MBOX_DOT_LOCK)
dot_unlockfile(mp->path);
myfree(mp->path);
myfree((char *) mp);
}

View File

@@ -21,8 +21,13 @@
/*
* External interface.
*/
extern VSTREAM *mbox_open(const char *, int, int, struct stat *, uid_t, gid_t, int, VSTRING *);
extern void mbox_release(const char *, int);
typedef struct {
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
/* .ad

View File

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

View File

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

View File

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