1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
|
/*++
/* NAME
/* local 3h
/* SUMMARY
/* local mail delivery
/* SYNOPSIS
/* #include "local.h"
/* DESCRIPTION
/* .nf
/*
* Utility library.
*/
#include <htable.h>
#include <vstream.h>
#include <vstring.h>
/*
* Global library.
*/
#include <been_here.h>
#include <tok822.h>
#include <deliver_request.h>
#include <mbox_conf.h>
#include <maps.h>
#include <dsn_buf.h>
#include <dsn.h>
#include <delivered_hdr.h>
/*
* User attributes: these control the privileges for delivery to external
* commands, external files, or mailboxes, and the initial environment of
* external commands.
*/
typedef struct USER_ATTR {
uid_t uid; /* file/command access */
gid_t gid; /* file/command access */
char *home; /* null or home directory */
char *logname; /* null or login name */
char *shell; /* null or login shell */
} USER_ATTR;
/*
* Critical macros. Not for obscurity, but to ensure consistency.
*/
#define RESET_USER_ATTR(usr_attr, level) { \
usr_attr.uid = 0; usr_attr.gid = 0; usr_attr.home = 0; \
usr_attr.logname = 0; usr_attr.shell = 0; \
if (msg_verbose) \
msg_info("%s[%d]: reset user_attr", myname, level); \
}
#define SET_USER_ATTR(usr_attr, pwd, level) { \
usr_attr.uid = pwd->pw_uid; usr_attr.gid = pwd->pw_gid; \
usr_attr.home = pwd->pw_dir; usr_attr.logname = pwd->pw_name; \
usr_attr.shell = pwd->pw_shell; \
if (msg_verbose) \
msg_info("%s[%d]: set user_attr: %s", \
myname, level, pwd->pw_name); \
}
/*
* The delivery attributes are inherited from files, from aliases, and from
* whatnot. Some of the information is changed on the fly. DELIVER_ATTR
* structures are therefore passed by value, so there is no need to undo
* changes.
*/
typedef struct DELIVER_ATTR {
int level; /* recursion level */
VSTREAM *fp; /* open queue file */
char *queue_name; /* mail queue id */
char *queue_id; /* mail queue id */
long offset; /* data offset */
char *encoding; /* MIME encoding */
int smtputf8; /* from delivery request */
const char *sender; /* taken from envelope */
char *dsn_envid; /* DSN envelope ID */
int dsn_ret; /* DSN headers/full */
RECIPIENT rcpt; /* from delivery request */
char *domain; /* recipient domain */
char *local; /* recipient full localpart */
char *user; /* recipient localpart, base name */
char *extension; /* recipient localpart, extension */
char *unmatched; /* unmatched extension */
const char *owner; /* null or list owner */
const char *delivered; /* for loop detection */
char *relay; /* relay host */
MSG_STATS msg_stats; /* time profile */
int exp_type; /* expansion type. see below */
char *exp_from; /* expanded_from */
DELIVER_REQUEST *request; /* the kitchen sink */
DSN_BUF *why; /* delivery status */
} DELIVER_ATTR;
extern void deliver_attr_init(DELIVER_ATTR *);
extern void deliver_attr_dump(DELIVER_ATTR *);
extern void deliver_attr_free(DELIVER_ATTR *);
#define EXPAND_TYPE_ALIAS (1<<0)
#define EXPAND_TYPE_FWD (1<<1)
#define EXPAND_TYPE_INCL (1<<2)
/*
* Rather than schlepping around dozens of arguments, here is one that has
* all. Well, almost. The user attributes are just a bit too sensitive, so
* they are passed around separately.
*/
typedef struct LOCAL_STATE {
int level; /* nesting level, for logging */
DELIVER_ATTR msg_attr; /* message attributes */
BH_TABLE *dup_filter; /* internal duplicate filter */
DELIVERED_HDR_INFO *loop_info; /* external loop filter */
DELIVER_REQUEST *request; /* as from queue manager */
} LOCAL_STATE;
#define RESET_OWNER_ATTR(msg_attr, level) { \
msg_attr.owner = 0; \
if (msg_verbose) \
msg_info("%s[%d]: reset owner attr", myname, level); \
}
#define SET_OWNER_ATTR(msg_attr, who, level) { \
msg_attr.sender = msg_attr.owner = who; \
if (msg_verbose) \
msg_info("%s[%d]: set owner attr: %s", \
myname, level, who); \
}
/*
* Bundle up some often-user attributes.
*/
#define BOUNCE_FLAGS(request) DEL_REQ_TRACE_FLAGS((request)->flags)
#define BOUNCE_ATTR(attr) \
attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
DSN_FROM_DSN_BUF(attr.why)
#define BOUNCE_ONE_ATTR(attr) \
attr.queue_name, attr.queue_id, attr.encoding, attr.smtputf8, \
attr.sender, attr.dsn_envid, attr.dsn_ret, \
&attr.msg_stats, &attr.rcpt, attr.relay, \
DSN_FROM_DSN_BUF(attr.why)
#define SENT_ATTR(attr) \
attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
DSN_FROM_DSN_BUF(attr.why)
#define OPENED_ATTR(attr) \
attr.queue_id, attr.sender
#define COPY_ATTR(attr) \
attr.sender, attr.rcpt.orig_addr, attr.delivered, attr.fp
#define MSG_LOG_STATE(m, p) \
msg_info("%s[%d]: local %s recip %s exten %s deliver %s exp_from %s", \
m, \
p.level, \
p.msg_attr.local ? p.msg_attr.local : "" , \
p.msg_attr.rcpt.address ? p.msg_attr.rcpt.address : "", \
p.msg_attr.extension ? p.msg_attr.extension : "", \
p.msg_attr.delivered ? p.msg_attr.delivered : "", \
p.msg_attr.exp_from ? p.msg_attr.exp_from : "")
/*
* "inner" nodes of the delivery graph.
*/
extern int deliver_recipient(LOCAL_STATE, USER_ATTR);
extern int deliver_alias(LOCAL_STATE, USER_ATTR, char *, int *);
extern int deliver_dotforward(LOCAL_STATE, USER_ATTR, int *);
extern int deliver_include(LOCAL_STATE, USER_ATTR, char *);
extern int deliver_token(LOCAL_STATE, USER_ATTR, TOK822 *);
extern int deliver_token_string(LOCAL_STATE, USER_ATTR, char *, int *);
extern int deliver_token_stream(LOCAL_STATE, USER_ATTR, VSTREAM *, int *);
extern int deliver_resolve_tree(LOCAL_STATE, USER_ATTR, TOK822 *);
extern int deliver_resolve_addr(LOCAL_STATE, USER_ATTR, char *);
/*
* "leaf" nodes of the delivery graph.
*/
extern int deliver_mailbox(LOCAL_STATE, USER_ATTR, int *);
extern int deliver_command(LOCAL_STATE, USER_ATTR, const char *);
extern int deliver_file(LOCAL_STATE, USER_ATTR, char *);
extern int deliver_indirect(LOCAL_STATE);
extern int deliver_maildir(LOCAL_STATE, USER_ATTR, char *);
extern int deliver_unknown(LOCAL_STATE, USER_ATTR);
/*
* Restrictions on delivery to sensitive destinations.
*/
extern int local_file_deliver_mask;
extern int local_cmd_deliver_mask;
/*
* Restrictions on extension propagation.
*/
extern int local_ext_prop_mask;
/*
* Mailbox lock protocol.
*/
extern int local_mbox_lock_mask;
/*
* When to prepend a Delivered-To: header upon external delivery.
*/
#define DELIVER_HDR_CMD (1<<0)
#define DELIVER_HDR_FILE (1<<1)
#define DELIVER_HDR_FWD (1<<2)
extern int local_deliver_hdr_mask;
/*
* forward.c
*/
extern int forward_init(void);
extern int forward_append(DELIVER_ATTR);
extern int forward_finish(DELIVER_REQUEST *, DELIVER_ATTR, int);
/*
* feature.c
*/
extern int feature_control(const char *);
/*
* local_expand.c
*/
int local_expand(VSTRING *, const char *, LOCAL_STATE *, USER_ATTR *, const char *);
#define LOCAL_EXP_EXTENSION_MATCHED (1<<MAC_PARSE_USER)
/*
* alias.c
*/
extern MAPS *alias_maps;
/*
* Silly little macros.
*/
#define STR(s) vstring_str(s)
/*
* bounce_workaround.c
*/
int bounce_workaround(LOCAL_STATE);
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
|