Postfix3.3.1
file.c
[詳解]
1 /*++
2 /* NAME
3 /* file 3
4 /* SUMMARY
5 /* mail delivery to arbitrary file
6 /* SYNOPSIS
7 /* #include "local.h"
8 /*
9 /* int deliver_file(state, usr_attr, path)
10 /* LOCAL_STATE state;
11 /* USER_ATTR usr_attr;
12 /* char *path;
13 /* DESCRIPTION
14 /* deliver_file() appends a message to a file, UNIX mailbox format,
15 /* or qmail maildir format,
16 /* with duplicate suppression. It will deliver only to non-executable
17 /* regular files.
18 /*
19 /* Arguments:
20 /* .IP state
21 /* The attributes that specify the message, recipient and more.
22 /* Attributes describing alias, include or forward expansion.
23 /* A table with the results from expanding aliases or lists.
24 /* .IP usr_attr
25 /* Attributes describing user rights and environment information.
26 /* .IP path
27 /* The file to deliver to. If the name ends in '/', delivery is done
28 /* in qmail maildir format, otherwise delivery is done in UNIX mailbox
29 /* format.
30 /* DIAGNOSTICS
31 /* deliver_file() returns non-zero when delivery should be tried again.
32 /* SEE ALSO
33 /* defer(3)
34 /* bounce(3)
35 /* LICENSE
36 /* .ad
37 /* .fi
38 /* The Secure Mailer license must be distributed with this software.
39 /* AUTHOR(S)
40 /* Wietse Venema
41 /* IBM T.J. Watson Research
42 /* P.O. Box 704
43 /* Yorktown Heights, NY 10598, USA
44 /*--*/
45 
46 /* System library. */
47 
48 #include <sys_defs.h>
49 #include <sys/stat.h>
50 #include <unistd.h>
51 #include <fcntl.h>
52 #include <errno.h>
53 #include <string.h>
54 
55 /* Utility library. */
56 
57 #include <msg.h>
58 #include <htable.h>
59 #include <vstring.h>
60 #include <vstream.h>
61 #include <deliver_flock.h>
62 #include <set_eugid.h>
63 
64 /* Global library. */
65 
66 #include <mail_copy.h>
67 #include <bounce.h>
68 #include <defer.h>
69 #include <sent.h>
70 #include <been_here.h>
71 #include <mail_params.h>
72 #include <mbox_conf.h>
73 #include <mbox_open.h>
74 #include <dsn_util.h>
75 
76 /* Application-specific. */
77 
78 #include "local.h"
79 
80 /* deliver_file - deliver to file */
81 
82 int deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
83 {
84  const char *myname = "deliver_file";
85  struct stat st;
86  MBOX *mp;
87  DSN_BUF *why = state.msg_attr.why;
88  int mail_copy_status = MAIL_COPY_STAT_WRITE;
89  int deliver_status;
90  int copy_flags;
91 
92  /*
93  * Make verbose logging easier to understand.
94  */
95  state.level++;
96  if (msg_verbose)
97  MSG_LOG_STATE(myname, state);
98 
99  /*
100  * DUPLICATE ELIMINATION
101  *
102  * Skip this file if it was already delivered to as this user.
103  */
104  if (been_here(state.dup_filter, "file %ld %s", (long) usr_attr.uid, path))
105  return (0);
106 
107  /*
108  * DELIVERY POLICY
109  *
110  * Do we allow delivery to files?
111  */
112  if ((local_file_deliver_mask & state.msg_attr.exp_type) == 0) {
113  dsb_simple(why, "5.7.1", "mail to file is restricted");
114  /* Account for possible owner- sender address override. */
115  return (bounce_workaround(state));
116  }
117 
118  /*
119  * Don't deliver trace-only requests.
120  */
121  if (DEL_REQ_TRACE_ONLY(state.request->flags)) {
122  dsb_simple(why, "2.0.0", "delivers to file: %s", path);
123  return (sent(BOUNCE_FLAGS(state.request),
124  SENT_ATTR(state.msg_attr)));
125  }
126 
127  /*
128  * DELIVERY RIGHTS
129  *
130  * Use a default uid/gid when none are given.
131  */
132  if (usr_attr.uid == 0 && (usr_attr.uid = var_default_uid) == 0)
133  msg_panic("privileged default user id");
134  if (usr_attr.gid == 0 && (usr_attr.gid = var_default_gid) == 0)
135  msg_panic("privileged default group id");
136 
137  /*
138  * If the name ends in /, use maildir-style delivery instead.
139  */
140  if (path[strlen(path) - 1] == '/')
141  return (deliver_maildir(state, usr_attr, path));
142 
143  /*
144  * Deliver. From here on, no early returns or we have a memory leak.
145  */
146  if (msg_verbose)
147  msg_info("deliver_file (%ld,%ld): %s",
148  (long) usr_attr.uid, (long) usr_attr.gid, path);
149  if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
150  msg_fatal("seek queue file %s: %m", state.msg_attr.queue_id);
151 
152  /*
153  * As the specified user, open or create the file, lock it, and append
154  * the message.
155  */
156  copy_flags = MAIL_COPY_MBOX;
158  copy_flags &= ~MAIL_COPY_DELIVERED;
159 
160  set_eugid(usr_attr.uid, usr_attr.gid);
161  mp = mbox_open(path, O_APPEND | O_CREAT | O_WRONLY,
162  S_IRUSR | S_IWUSR, &st, -1, -1,
164  "5.2.0", why);
165  if (mp != 0) {
166  if (S_ISREG(st.st_mode) && st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
167  vstream_fclose(mp->fp);
168  dsb_simple(why, "5.7.1", "file is executable");
169  } else {
170  mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp,
171  S_ISREG(st.st_mode) ? copy_flags :
172  (copy_flags & ~MAIL_COPY_TOFILE),
173  "\n", why);
174  }
175  mbox_release(mp);
176  }
178 
179  /*
180  * As the mail system, bounce, defer delivery, or report success.
181  */
182  if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
183  deliver_status = DEL_STAT_DEFER;
184  } else if (mail_copy_status != 0) {
186  "cannot append message to file %s: ", path);
187  /* Account for possible owner- sender address override. */
188  deliver_status = bounce_workaround(state);
189  } else {
190  dsb_simple(why, "2.0.0", "delivered to file: %s", path);
191  deliver_status = sent(BOUNCE_FLAGS(state.request),
192  SENT_ATTR(state.msg_attr));
193  }
194  return (deliver_status);
195 }
int msg_verbose
Definition: msg.c:177
#define SENT_ATTR(attr)
Definition: local.h:142
#define DELIVER_HDR_FILE
Definition: local.h:203
#define MAIL_COPY_STAT_WRITE
Definition: mail_copy.h:50
VSTRING * vstring_sprintf_prepend(VSTRING *vp, const char *format,...)
Definition: vstring.c:645
gid_t var_default_gid
Definition: mail_params.c:240
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
int local_mbox_lock_mask
Definition: local.c:686
#define stat(p, s)
Definition: warn_stat.h:18
int deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
Definition: file.c:82
#define MBOX_DOT_LOCK_MAY_FAIL
Definition: mbox_conf.h:25
#define DEL_REQ_TRACE_ONLY(f)
DELIVER_REQUEST * request
Definition: local.h:113
uid_t var_default_uid
Definition: mail_params.c:239
#define COPY_ATTR(attr)
Definition: local.h:147
#define BOUNCE_FLAGS(request)
int exp_type
Definition: local.h:89
BH_TABLE * dup_filter
Definition: local.h:111
gid_t var_owner_gid
Definition: mail_params.c:235
uid_t var_owner_uid
Definition: mail_params.c:234
int been_here(BH_TABLE *dup_filter, const char *fmt,...)
Definition: been_here.c:124
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
int mail_copy(const char *sender, const char *orig_rcpt, const char *delivered, VSTREAM *src, VSTREAM *dst, int flags, const char *eol, DSN_BUF *why)
Definition: mail_copy.c:134
Definition: mbox_open.h:29
#define MAIL_COPY_MBOX
Definition: mail_copy.h:40
DELIVER_ATTR msg_attr
Definition: local.h:110
void mbox_release(MBOX *mp)
Definition: mbox_open.c:224
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
Definition: dsn_buf.c:275
#define MAIL_COPY_DELIVERED
Definition: mail_copy.h:35
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
Definition: vstream.c:1093
VSTREAM * fp
Definition: local.h:70
#define DEL_STAT_DEFER
gid_t gid
Definition: local.h:37
void set_eugid(uid_t euid, gid_t egid)
Definition: set_eugid.c:54
int bounce_workaround(LOCAL_STATE state)
DSN_BUF * why
Definition: local.h:92
#define MAIL_COPY_TOFILE
Definition: mail_copy.h:33
int level
Definition: local.h:109
char * queue_id
Definition: local.h:72
VSTRING * reason
Definition: dsn_buf.h:37
uid_t uid
Definition: local.h:36
int deliver_maildir(LOCAL_STATE, USER_ATTR, char *)
Definition: maildir.c:78
#define MAIL_COPY_STAT_CORRUPT
Definition: mail_copy.h:48
int local_file_deliver_mask
Definition: local.c:683
int sent(int flags, const char *id, MSG_STATS *stats, RECIPIENT *recipient, const char *relay, DSN *dsn)
Definition: sent.c:95
long offset
Definition: local.h:73
#define MSG_LOG_STATE(m, p)
Definition: local.h:150
MBOX * mbox_open(const char *path, int flags, mode_t mode, struct stat *st, uid_t chown_uid, gid_t chown_gid, int lock_style, const char *def_dsn, DSN_BUF *why)
Definition: mbox_open.c:105
int local_deliver_hdr_mask
Definition: local.c:685
void msg_info(const char *fmt,...)
Definition: msg.c:199