| 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 | } |