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