mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 22:25:24 +00:00
snapshot-20001127
This commit is contained in:
committed by
Viktor Dukhovni
parent
3c2727d996
commit
a6f1137bf4
1
postfix/.indent.pro
vendored
1
postfix/.indent.pro
vendored
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user