File: | src/usr.sbin/smtpd/smtpd/../lka_session.c |
Warning: | line 530, column 10 3rd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: lka_session.c,v 1.97 2021/09/22 17:19:58 eric Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org> | |||
5 | * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> | |||
6 | * | |||
7 | * Permission to use, copy, modify, and distribute this software for any | |||
8 | * purpose with or without fee is hereby granted, provided that the above | |||
9 | * copyright notice and this permission notice appear in all copies. | |||
10 | * | |||
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
18 | */ | |||
19 | ||||
20 | #include <errno(*__errno()).h> | |||
21 | #include <stdlib.h> | |||
22 | #include <string.h> | |||
23 | ||||
24 | #include "smtpd.h" | |||
25 | #include "log.h" | |||
26 | ||||
27 | #define EXPAND_DEPTH10 10 | |||
28 | ||||
29 | #define F_WAITING0x01 0x01 | |||
30 | ||||
31 | struct lka_session { | |||
32 | uint64_t id; /* given by smtp */ | |||
33 | ||||
34 | TAILQ_HEAD(, envelope)struct { struct envelope *tqh_first; struct envelope **tqh_last ; } deliverylist; | |||
35 | struct expand expand; | |||
36 | ||||
37 | int flags; | |||
38 | int error; | |||
39 | const char *errormsg; | |||
40 | struct envelope envelope; | |||
41 | struct xnodes nodes; | |||
42 | /* waiting for fwdrq */ | |||
43 | struct rule *rule; | |||
44 | struct expandnode *node; | |||
45 | }; | |||
46 | ||||
47 | static void lka_expand(struct lka_session *, struct rule *, | |||
48 | struct expandnode *); | |||
49 | static void lka_submit(struct lka_session *, struct rule *, | |||
50 | struct expandnode *); | |||
51 | static void lka_resume(struct lka_session *); | |||
52 | ||||
53 | static int init; | |||
54 | static struct tree sessions; | |||
55 | ||||
56 | void | |||
57 | lka_session(uint64_t id, struct envelope *envelope) | |||
58 | { | |||
59 | struct lka_session *lks; | |||
60 | struct expandnode xn; | |||
61 | ||||
62 | if (init == 0) { | |||
63 | init = 1; | |||
64 | tree_init(&sessions)do { do { (&((&sessions)->tree))->sph_root = (( void *)0); } while (0); (&sessions)->count = 0; } while (0); | |||
65 | } | |||
66 | ||||
67 | lks = xcalloc(1, sizeof(*lks)); | |||
68 | lks->id = id; | |||
69 | RB_INIT(&lks->expand.tree)do { (&lks->expand.tree)->rbh_root = ((void *)0); } while (0); | |||
70 | TAILQ_INIT(&lks->deliverylist)do { (&lks->deliverylist)->tqh_first = ((void *)0); (&lks->deliverylist)->tqh_last = &(&lks-> deliverylist)->tqh_first; } while (0); | |||
71 | tree_xset(&sessions, lks->id, lks); | |||
72 | ||||
73 | lks->envelope = *envelope; | |||
74 | ||||
75 | TAILQ_INIT(&lks->nodes)do { (&lks->nodes)->tqh_first = ((void *)0); (& lks->nodes)->tqh_last = &(&lks->nodes)->tqh_first ; } while (0); | |||
76 | memset(&xn, 0, sizeof xn); | |||
77 | xn.type = EXPAND_ADDRESS; | |||
78 | xn.u.mailaddr = lks->envelope.rcpt; | |||
79 | lks->expand.parent = NULL((void *)0); | |||
80 | lks->expand.rule = NULL((void *)0); | |||
81 | lks->expand.queue = &lks->nodes; | |||
82 | expand_insert(&lks->expand, &xn); | |||
83 | lka_resume(lks); | |||
84 | } | |||
85 | ||||
86 | void | |||
87 | lka_session_forward_reply(struct forward_req *fwreq, int fd) | |||
88 | { | |||
89 | struct lka_session *lks; | |||
90 | struct dispatcher *dsp; | |||
91 | struct rule *rule; | |||
92 | struct expandnode *xn; | |||
93 | int ret; | |||
94 | ||||
95 | lks = tree_xget(&sessions, fwreq->id); | |||
96 | xn = lks->node; | |||
97 | rule = lks->rule; | |||
98 | ||||
99 | lks->flags &= ~F_WAITING0x01; | |||
100 | ||||
101 | switch (fwreq->status) { | |||
102 | case 0: | |||
103 | /* permanent failure while lookup ~/.forward */ | |||
104 | log_trace(TRACE_EXPAND, "expand: ~/.forward failed for user %s",do { if (tracing & (0x1000)) log_trace0("expand: ~/.forward failed for user %s" , fwreq->user); } while (0) | |||
105 | fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: ~/.forward failed for user %s" , fwreq->user); } while (0); | |||
106 | lks->error = LKA_PERMFAIL; | |||
107 | break; | |||
108 | case 1: | |||
109 | if (fd == -1) { | |||
110 | dsp = dict_get(env->sc_dispatchers, lks->rule->dispatcher); | |||
111 | if (dsp->u.local.forward_only) { | |||
112 | log_trace(TRACE_EXPAND, "expand: no .forward "do { if (tracing & (0x1000)) log_trace0("expand: no .forward " "for user %s on forward-only rule", fwreq->user); } while (0) | |||
113 | "for user %s on forward-only rule", fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: no .forward " "for user %s on forward-only rule", fwreq->user); } while (0); | |||
114 | lks->error = LKA_TEMPFAIL; | |||
115 | } | |||
116 | else if (dsp->u.local.expand_only) { | |||
117 | log_trace(TRACE_EXPAND, "expand: no .forward "do { if (tracing & (0x1000)) log_trace0("expand: no .forward " "for user %s and no default action on rule", fwreq->user) ; } while (0) | |||
118 | "for user %s and no default action on rule", fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: no .forward " "for user %s and no default action on rule", fwreq->user) ; } while (0); | |||
119 | lks->error = LKA_PERMFAIL; | |||
120 | } | |||
121 | else { | |||
122 | log_trace(TRACE_EXPAND, "expand: no .forward for "do { if (tracing & (0x1000)) log_trace0("expand: no .forward for " "user %s, just deliver", fwreq->user); } while (0) | |||
123 | "user %s, just deliver", fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: no .forward for " "user %s, just deliver", fwreq->user); } while (0); | |||
124 | lka_submit(lks, rule, xn); | |||
125 | } | |||
126 | } | |||
127 | else { | |||
128 | dsp = dict_get(env->sc_dispatchers, rule->dispatcher); | |||
129 | ||||
130 | /* expand for the current user and rule */ | |||
131 | lks->expand.rule = rule; | |||
132 | lks->expand.parent = xn; | |||
133 | ||||
134 | /* forwards_get() will close the descriptor no matter what */ | |||
135 | ret = forwards_get(fd, &lks->expand); | |||
136 | if (ret == -1) { | |||
137 | log_trace(TRACE_EXPAND, "expand: temporary "do { if (tracing & (0x1000)) log_trace0("expand: temporary " "forward error for user %s", fwreq->user); } while (0) | |||
138 | "forward error for user %s", fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: temporary " "forward error for user %s", fwreq->user); } while (0); | |||
139 | lks->error = LKA_TEMPFAIL; | |||
140 | } | |||
141 | else if (ret == 0) { | |||
142 | if (dsp->u.local.forward_only) { | |||
143 | log_trace(TRACE_EXPAND, "expand: empty .forward "do { if (tracing & (0x1000)) log_trace0("expand: empty .forward " "for user %s on forward-only rule", fwreq->user); } while (0) | |||
144 | "for user %s on forward-only rule", fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: empty .forward " "for user %s on forward-only rule", fwreq->user); } while (0); | |||
145 | lks->error = LKA_TEMPFAIL; | |||
146 | } | |||
147 | else if (dsp->u.local.expand_only) { | |||
148 | log_trace(TRACE_EXPAND, "expand: empty .forward "do { if (tracing & (0x1000)) log_trace0("expand: empty .forward " "for user %s and no default action on rule", fwreq->user) ; } while (0) | |||
149 | "for user %s and no default action on rule", fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: empty .forward " "for user %s and no default action on rule", fwreq->user) ; } while (0); | |||
150 | lks->error = LKA_PERMFAIL; | |||
151 | } | |||
152 | else { | |||
153 | log_trace(TRACE_EXPAND, "expand: empty .forward "do { if (tracing & (0x1000)) log_trace0("expand: empty .forward " "for user %s, just deliver", fwreq->user); } while (0) | |||
154 | "for user %s, just deliver", fwreq->user)do { if (tracing & (0x1000)) log_trace0("expand: empty .forward " "for user %s, just deliver", fwreq->user); } while (0); | |||
155 | lka_submit(lks, rule, xn); | |||
156 | } | |||
157 | } | |||
158 | } | |||
159 | break; | |||
160 | default: | |||
161 | /* temporary failure while looking up ~/.forward */ | |||
162 | lks->error = LKA_TEMPFAIL; | |||
163 | } | |||
164 | ||||
165 | if (lks->error == LKA_TEMPFAIL && lks->errormsg == NULL((void *)0)) | |||
166 | lks->errormsg = "424 4.2.4 Mailing list expansion problem"; | |||
167 | if (lks->error == LKA_PERMFAIL && lks->errormsg == NULL((void *)0)) | |||
168 | lks->errormsg = "524 5.2.4 Mailing list expansion problem"; | |||
169 | ||||
170 | lka_resume(lks); | |||
171 | } | |||
172 | ||||
173 | static void | |||
174 | lka_resume(struct lka_session *lks) | |||
175 | { | |||
176 | struct envelope *ep; | |||
177 | struct expandnode *xn; | |||
178 | ||||
179 | if (lks->error) | |||
180 | goto error; | |||
181 | ||||
182 | /* pop next node and expand it */ | |||
183 | while ((xn = TAILQ_FIRST(&lks->nodes)((&lks->nodes)->tqh_first))) { | |||
184 | TAILQ_REMOVE(&lks->nodes, xn, tq_entry)do { if (((xn)->tq_entry.tqe_next) != ((void *)0)) (xn)-> tq_entry.tqe_next->tq_entry.tqe_prev = (xn)->tq_entry.tqe_prev ; else (&lks->nodes)->tqh_last = (xn)->tq_entry. tqe_prev; *(xn)->tq_entry.tqe_prev = (xn)->tq_entry.tqe_next ; ; ; } while (0); | |||
185 | lka_expand(lks, xn->rule, xn); | |||
186 | if (lks->flags & F_WAITING0x01) | |||
187 | return; | |||
188 | if (lks->error) | |||
189 | goto error; | |||
190 | } | |||
191 | ||||
192 | /* delivery list is empty, reject */ | |||
193 | if (TAILQ_FIRST(&lks->deliverylist)((&lks->deliverylist)->tqh_first) == NULL((void *)0)) { | |||
194 | log_trace(TRACE_EXPAND, "expand: lka_done: expanded to empty "do { if (tracing & (0x1000)) log_trace0("expand: lka_done: expanded to empty " "delivery list"); } while (0) | |||
195 | "delivery list")do { if (tracing & (0x1000)) log_trace0("expand: lka_done: expanded to empty " "delivery list"); } while (0); | |||
196 | lks->error = LKA_PERMFAIL; | |||
197 | lks->errormsg = "524 5.2.4 Mailing list expansion problem"; | |||
198 | } | |||
199 | error: | |||
200 | if (lks->error) { | |||
201 | m_create(p_dispatcher, IMSG_SMTP_EXPAND_RCPT, 0, 0, -1); | |||
202 | m_add_id(p_dispatcher, lks->id); | |||
203 | m_add_int(p_dispatcher, lks->error); | |||
204 | ||||
205 | if (lks->errormsg) | |||
206 | m_add_string(p_dispatcher, lks->errormsg); | |||
207 | else { | |||
208 | if (lks->error == LKA_PERMFAIL) | |||
209 | m_add_string(p_dispatcher, "550 Invalid recipient"); | |||
210 | else if (lks->error == LKA_TEMPFAIL) | |||
211 | m_add_string(p_dispatcher, "451 Temporary failure"); | |||
212 | } | |||
213 | ||||
214 | m_close(p_dispatcher); | |||
215 | while ((ep = TAILQ_FIRST(&lks->deliverylist)((&lks->deliverylist)->tqh_first)) != NULL((void *)0)) { | |||
216 | TAILQ_REMOVE(&lks->deliverylist, ep, entry)do { if (((ep)->entry.tqe_next) != ((void *)0)) (ep)->entry .tqe_next->entry.tqe_prev = (ep)->entry.tqe_prev; else ( &lks->deliverylist)->tqh_last = (ep)->entry.tqe_prev ; *(ep)->entry.tqe_prev = (ep)->entry.tqe_next; ; ; } while (0); | |||
217 | free(ep); | |||
218 | } | |||
219 | } | |||
220 | else { | |||
221 | /* Process the delivery list and submit envelopes to queue */ | |||
222 | while ((ep = TAILQ_FIRST(&lks->deliverylist)((&lks->deliverylist)->tqh_first)) != NULL((void *)0)) { | |||
223 | TAILQ_REMOVE(&lks->deliverylist, ep, entry)do { if (((ep)->entry.tqe_next) != ((void *)0)) (ep)->entry .tqe_next->entry.tqe_prev = (ep)->entry.tqe_prev; else ( &lks->deliverylist)->tqh_last = (ep)->entry.tqe_prev ; *(ep)->entry.tqe_prev = (ep)->entry.tqe_next; ; ; } while (0); | |||
224 | m_create(p_queue, IMSG_LKA_ENVELOPE_SUBMIT, 0, 0, -1); | |||
225 | m_add_id(p_queue, lks->id); | |||
226 | m_add_envelope(p_queue, ep); | |||
227 | m_close(p_queue); | |||
228 | free(ep); | |||
229 | } | |||
230 | ||||
231 | m_create(p_queue, IMSG_LKA_ENVELOPE_COMMIT, 0, 0, -1); | |||
232 | m_add_id(p_queue, lks->id); | |||
233 | m_close(p_queue); | |||
234 | } | |||
235 | ||||
236 | expand_clear(&lks->expand); | |||
237 | tree_xpop(&sessions, lks->id); | |||
238 | free(lks); | |||
239 | } | |||
240 | ||||
241 | static void | |||
242 | lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) | |||
243 | { | |||
244 | struct forward_req fwreq; | |||
245 | struct envelope ep; | |||
246 | struct expandnode node; | |||
247 | struct mailaddr maddr; | |||
248 | struct dispatcher *dsp; | |||
249 | struct table *userbase; | |||
250 | int r; | |||
251 | union lookup lk; | |||
252 | char *tag; | |||
253 | const char *srs_decoded; | |||
254 | ||||
255 | if (xn->depth >= EXPAND_DEPTH10) { | |||
| ||||
256 | log_trace(TRACE_EXPAND, "expand: lka_expand: node too deep.")do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: node too deep." ); } while (0); | |||
257 | lks->error = LKA_PERMFAIL; | |||
258 | lks->errormsg = "524 5.2.4 Mailing list expansion problem"; | |||
259 | return; | |||
260 | } | |||
261 | ||||
262 | switch (xn->type) { | |||
263 | case EXPAND_INVALID: | |||
264 | case EXPAND_INCLUDE: | |||
265 | fatalx("lka_expand: unexpected type"); | |||
266 | break; | |||
267 | ||||
268 | case EXPAND_ADDRESS: | |||
269 | ||||
270 | log_trace(TRACE_EXPAND, "expand: lka_expand: address: %s@%s "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: address: %s@%s " "[depth=%d]", xn->u.mailaddr.user, xn->u.mailaddr.domain , xn->depth); } while (0) | |||
271 | "[depth=%d]",do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: address: %s@%s " "[depth=%d]", xn->u.mailaddr.user, xn->u.mailaddr.domain , xn->depth); } while (0) | |||
272 | xn->u.mailaddr.user, xn->u.mailaddr.domain, xn->depth)do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: address: %s@%s " "[depth=%d]", xn->u.mailaddr.user, xn->u.mailaddr.domain , xn->depth); } while (0); | |||
273 | ||||
274 | ||||
275 | ep = lks->envelope; | |||
276 | ep.dest = xn->u.mailaddr; | |||
277 | if (xn->parent) /* nodes with parent are forward addresses */ | |||
278 | ep.flags |= EF_INTERNAL; | |||
279 | ||||
280 | /* handle SRS */ | |||
281 | if (env->sc_srs_key != NULL((void *)0) && | |||
282 | ep.sender.user[0] == '\0' && | |||
283 | (strncasecmp(ep.dest.user, "SRS0=", 5) == 0 || | |||
284 | strncasecmp(ep.dest.user, "SRS1=", 5) == 0)) { | |||
285 | srs_decoded = srs_decode(mailaddr_to_text(&ep.dest)); | |||
286 | if (srs_decoded && | |||
287 | text_to_mailaddr(&ep.dest, srs_decoded)) { | |||
288 | /* flag envelope internal and override dest */ | |||
289 | ep.flags |= EF_INTERNAL; | |||
290 | xn->u.mailaddr = ep.dest; | |||
291 | lks->envelope = ep; | |||
292 | } | |||
293 | else { | |||
294 | log_warn("SRS failed to decode: %s", | |||
295 | mailaddr_to_text(&ep.dest)); | |||
296 | } | |||
297 | } | |||
298 | ||||
299 | /* Pass the node through the ruleset */ | |||
300 | rule = ruleset_match(&ep); | |||
301 | if (rule == NULL((void *)0) || rule->reject) { | |||
302 | lks->error = (errno(*__errno()) == EAGAIN35) ? | |||
303 | LKA_TEMPFAIL : LKA_PERMFAIL; | |||
304 | break; | |||
305 | } | |||
306 | ||||
307 | dsp = dict_xget(env->sc_dispatchers, rule->dispatcher); | |||
308 | if (dsp->type == DISPATCHER_REMOTE) { | |||
309 | lka_submit(lks, rule, xn); | |||
310 | } | |||
311 | else if (dsp->u.local.table_virtual) { | |||
312 | /* expand */ | |||
313 | lks->expand.rule = rule; | |||
314 | lks->expand.parent = xn; | |||
315 | ||||
316 | /* temporary replace the mailaddr with a copy where | |||
317 | * we eventually strip the '+'-part before lookup. | |||
318 | */ | |||
319 | maddr = xn->u.mailaddr; | |||
320 | xlowercase(maddr.user, xn->u.mailaddr.user, | |||
321 | sizeof maddr.user); | |||
322 | r = aliases_virtual_get(&lks->expand, &maddr); | |||
323 | if (r == -1) { | |||
324 | lks->error = LKA_TEMPFAIL; | |||
325 | log_trace(TRACE_EXPAND, "expand: lka_expand: "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "error in virtual alias lookup"); } while (0) | |||
326 | "error in virtual alias lookup")do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "error in virtual alias lookup"); } while (0); | |||
327 | } | |||
328 | else if (r == 0) { | |||
329 | lks->error = LKA_PERMFAIL; | |||
330 | log_trace(TRACE_EXPAND, "expand: lka_expand: "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "no aliases for virtual"); } while (0) | |||
331 | "no aliases for virtual")do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "no aliases for virtual"); } while (0); | |||
332 | } | |||
333 | if (lks->error == LKA_TEMPFAIL && lks->errormsg == NULL((void *)0)) | |||
334 | lks->errormsg = "424 4.2.4 Mailing list expansion problem"; | |||
335 | if (lks->error == LKA_PERMFAIL && lks->errormsg == NULL((void *)0)) | |||
336 | lks->errormsg = "524 5.2.4 Mailing list expansion problem"; | |||
337 | } | |||
338 | else { | |||
339 | lks->expand.rule = rule; | |||
340 | lks->expand.parent = xn; | |||
341 | xn->rule = rule; | |||
342 | ||||
343 | memset(&node, 0, sizeof node); | |||
344 | node.type = EXPAND_USERNAME; | |||
345 | xlowercase(node.u.user, xn->u.mailaddr.user, | |||
346 | sizeof node.u.user); | |||
347 | expand_insert(&lks->expand, &node); | |||
348 | } | |||
349 | break; | |||
350 | ||||
351 | case EXPAND_USERNAME: | |||
352 | log_trace(TRACE_EXPAND, "expand: lka_expand: username: %s "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: username: %s " "[depth=%d, sameuser=%d]", xn->u.user, xn->depth, xn-> sameuser); } while (0) | |||
353 | "[depth=%d, sameuser=%d]",do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: username: %s " "[depth=%d, sameuser=%d]", xn->u.user, xn->depth, xn-> sameuser); } while (0) | |||
354 | xn->u.user, xn->depth, xn->sameuser)do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: username: %s " "[depth=%d, sameuser=%d]", xn->u.user, xn->depth, xn-> sameuser); } while (0); | |||
355 | ||||
356 | /* expand aliases with the given rule */ | |||
357 | dsp = dict_xget(env->sc_dispatchers, rule->dispatcher); | |||
358 | ||||
359 | lks->expand.rule = rule; | |||
360 | lks->expand.parent = xn; | |||
361 | ||||
362 | if (!xn->sameuser && | |||
363 | (dsp->u.local.table_alias || dsp->u.local.table_virtual)) { | |||
364 | if (dsp->u.local.table_alias) | |||
365 | r = aliases_get(&lks->expand, xn->u.user); | |||
366 | if (dsp->u.local.table_virtual) | |||
367 | r = aliases_virtual_get(&lks->expand, &xn->u.mailaddr); | |||
368 | if (r == -1) { | |||
369 | log_trace(TRACE_EXPAND, "expand: lka_expand: "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "error in alias lookup"); } while (0) | |||
370 | "error in alias lookup")do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "error in alias lookup"); } while (0); | |||
371 | lks->error = LKA_TEMPFAIL; | |||
372 | if (lks->errormsg == NULL((void *)0)) | |||
373 | lks->errormsg = "424 4.2.4 Mailing list expansion problem"; | |||
374 | } | |||
375 | if (r) | |||
376 | break; | |||
377 | } | |||
378 | ||||
379 | /* gilles+hackers@ -> gilles@ */ | |||
380 | if ((tag = strchr(xn->u.user, *env->sc_subaddressing_delim)) != NULL((void *)0)) { | |||
381 | *tag++ = '\0'; | |||
382 | (void)strlcpy(xn->subaddress, tag, sizeof xn->subaddress); | |||
383 | } | |||
384 | ||||
385 | userbase = table_find(env, dsp->u.local.table_userbase); | |||
386 | r = table_lookup(userbase, K_USERINFO, xn->u.user, &lk); | |||
387 | if (r == -1) { | |||
388 | log_trace(TRACE_EXPAND, "expand: lka_expand: "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "backend error while searching user"); } while (0) | |||
389 | "backend error while searching user")do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "backend error while searching user"); } while (0); | |||
390 | lks->error = LKA_TEMPFAIL; | |||
391 | break; | |||
392 | } | |||
393 | if (r == 0) { | |||
394 | log_trace(TRACE_EXPAND, "expand: lka_expand: "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "user-part does not match system user"); } while (0) | |||
395 | "user-part does not match system user")do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: " "user-part does not match system user"); } while (0); | |||
396 | lks->error = LKA_PERMFAIL; | |||
397 | break; | |||
398 | } | |||
399 | xn->realuser = 1; | |||
400 | ||||
401 | if (xn->sameuser && xn->parent->forwarded) { | |||
402 | log_trace(TRACE_EXPAND, "expand: lka_expand: same "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: same " "user, submitting"); } while (0) | |||
403 | "user, submitting")do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: same " "user, submitting"); } while (0); | |||
404 | lka_submit(lks, rule, xn); | |||
405 | break; | |||
406 | } | |||
407 | ||||
408 | /* no aliases found, query forward file */ | |||
409 | lks->rule = rule; | |||
410 | lks->node = xn; | |||
411 | xn->forwarded = 1; | |||
412 | ||||
413 | memset(&fwreq, 0, sizeof(fwreq)); | |||
414 | fwreq.id = lks->id; | |||
415 | (void)strlcpy(fwreq.user, lk.userinfo.username, sizeof(fwreq.user)); | |||
416 | (void)strlcpy(fwreq.directory, lk.userinfo.directory, sizeof(fwreq.directory)); | |||
417 | fwreq.uid = lk.userinfo.uid; | |||
418 | fwreq.gid = lk.userinfo.gid; | |||
419 | ||||
420 | m_compose(p_parent, IMSG_LKA_OPEN_FORWARD, 0, 0, -1, | |||
421 | &fwreq, sizeof(fwreq)); | |||
422 | lks->flags |= F_WAITING0x01; | |||
423 | break; | |||
424 | ||||
425 | case EXPAND_FILENAME: | |||
426 | dsp = dict_xget(env->sc_dispatchers, rule->dispatcher); | |||
427 | if (dsp->u.local.forward_only) { | |||
428 | log_trace(TRACE_EXPAND, "expand: filename matched on forward-only rule")do { if (tracing & (0x1000)) log_trace0("expand: filename matched on forward-only rule" ); } while (0); | |||
429 | lks->error = LKA_TEMPFAIL; | |||
430 | break; | |||
431 | } | |||
432 | log_trace(TRACE_EXPAND, "expand: lka_expand: filename: %s "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: filename: %s " "[depth=%d]", xn->u.buffer, xn->depth); } while (0) | |||
433 | "[depth=%d]", xn->u.buffer, xn->depth)do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: filename: %s " "[depth=%d]", xn->u.buffer, xn->depth); } while (0); | |||
434 | lka_submit(lks, rule, xn); | |||
435 | break; | |||
436 | ||||
437 | case EXPAND_ERROR: | |||
438 | dsp = dict_xget(env->sc_dispatchers, rule->dispatcher); | |||
439 | if (dsp->u.local.forward_only) { | |||
440 | log_trace(TRACE_EXPAND, "expand: error matched on forward-only rule")do { if (tracing & (0x1000)) log_trace0("expand: error matched on forward-only rule" ); } while (0); | |||
441 | lks->error = LKA_TEMPFAIL; | |||
442 | break; | |||
443 | } | |||
444 | log_trace(TRACE_EXPAND, "expand: lka_expand: error: %s "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: error: %s " "[depth=%d]", xn->u.buffer, xn->depth); } while (0) | |||
445 | "[depth=%d]", xn->u.buffer, xn->depth)do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: error: %s " "[depth=%d]", xn->u.buffer, xn->depth); } while (0); | |||
446 | if (xn->u.buffer[0] == '4') | |||
447 | lks->error = LKA_TEMPFAIL; | |||
448 | else if (xn->u.buffer[0] == '5') | |||
449 | lks->error = LKA_PERMFAIL; | |||
450 | lks->errormsg = xn->u.buffer; | |||
451 | break; | |||
452 | ||||
453 | case EXPAND_FILTER: | |||
454 | dsp = dict_xget(env->sc_dispatchers, rule->dispatcher); | |||
455 | if (dsp->u.local.forward_only) { | |||
456 | log_trace(TRACE_EXPAND, "expand: filter matched on forward-only rule")do { if (tracing & (0x1000)) log_trace0("expand: filter matched on forward-only rule" ); } while (0); | |||
457 | lks->error = LKA_TEMPFAIL; | |||
458 | break; | |||
459 | } | |||
460 | log_trace(TRACE_EXPAND, "expand: lka_expand: filter: %s "do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: filter: %s " "[depth=%d]", xn->u.buffer, xn->depth); } while (0) | |||
461 | "[depth=%d]", xn->u.buffer, xn->depth)do { if (tracing & (0x1000)) log_trace0("expand: lka_expand: filter: %s " "[depth=%d]", xn->u.buffer, xn->depth); } while (0); | |||
462 | lka_submit(lks, rule, xn); | |||
463 | break; | |||
464 | } | |||
465 | } | |||
466 | ||||
467 | static struct expandnode * | |||
468 | lka_find_ancestor(struct expandnode *xn, enum expand_type type) | |||
469 | { | |||
470 | while (xn && (xn->type != type)) | |||
471 | xn = xn->parent; | |||
472 | if (xn == NULL((void *)0)) { | |||
473 | log_warnx("warn: lka_find_ancestor: no ancestors of type %d", | |||
474 | type); | |||
475 | fatalx(NULL((void *)0)); | |||
476 | } | |||
477 | return (xn); | |||
478 | } | |||
479 | ||||
480 | static void | |||
481 | lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn) | |||
482 | { | |||
483 | struct envelope *ep; | |||
484 | struct dispatcher *dsp; | |||
485 | const char *user; | |||
486 | const char *format; | |||
487 | ||||
488 | ep = xmemdup(&lks->envelope, sizeof *ep); | |||
489 | (void)strlcpy(ep->dispatcher, rule->dispatcher, sizeof ep->dispatcher); | |||
490 | ||||
491 | dsp = dict_xget(env->sc_dispatchers, ep->dispatcher); | |||
492 | ||||
493 | switch (dsp->type) { | |||
494 | case DISPATCHER_REMOTE: | |||
495 | if (xn->type != EXPAND_ADDRESS) | |||
496 | fatalx("lka_deliver: expect address"); | |||
497 | ep->type = D_MTA; | |||
498 | ep->dest = xn->u.mailaddr; | |||
499 | break; | |||
500 | ||||
501 | case DISPATCHER_BOUNCE: | |||
502 | case DISPATCHER_LOCAL: | |||
503 | if (xn->type
| |||
504 | xn->type
| |||
505 | xn->type != EXPAND_FILTER) | |||
506 | fatalx("lka_deliver: wrong type: %d", xn->type); | |||
507 | ||||
508 | ep->type = D_MDA; | |||
509 | ep->dest = lka_find_ancestor(xn, EXPAND_ADDRESS)->u.mailaddr; | |||
510 | if (xn->type == EXPAND_USERNAME) { | |||
511 | (void)strlcpy(ep->mda_user, xn->u.user, sizeof(ep->mda_user)); | |||
512 | (void)strlcpy(ep->mda_subaddress, xn->subaddress, sizeof(ep->mda_subaddress)); | |||
513 | } | |||
514 | else { | |||
515 | user = !xn->parent->realuser ? | |||
516 | SMTPD_USER"_smtpd" : | |||
517 | xn->parent->u.user; | |||
518 | (void)strlcpy(ep->mda_user, user, sizeof (ep->mda_user)); | |||
519 | ||||
520 | /* this battle needs to be fought ... */ | |||
521 | if (xn->type == EXPAND_FILTER && | |||
522 | strcmp(ep->mda_user, SMTPD_USER"_smtpd") == 0) | |||
523 | log_warnx("commands executed from aliases " | |||
524 | "run with %s privileges", SMTPD_USER"_smtpd"); | |||
525 | ||||
526 | if (xn->type == EXPAND_FILENAME) | |||
527 | format = "/usr/libexec/mail.mboxfile -f %%{mbox.from} %s"; | |||
528 | else if (xn->type
| |||
529 | format = "%s"; | |||
530 | (void)snprintf(ep->mda_exec, sizeof(ep->mda_exec), | |||
| ||||
531 | format, xn->u.buffer); | |||
532 | } | |||
533 | break; | |||
534 | } | |||
535 | ||||
536 | TAILQ_INSERT_TAIL(&lks->deliverylist, ep, entry)do { (ep)->entry.tqe_next = ((void *)0); (ep)->entry.tqe_prev = (&lks->deliverylist)->tqh_last; *(&lks->deliverylist )->tqh_last = (ep); (&lks->deliverylist)->tqh_last = &(ep)->entry.tqe_next; } while (0); | |||
537 | } |