1 /* $OpenBSD: lka.c,v 1.250 2024/06/11 16:30:06 tb Exp $ */
2
3 /*
4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
6 * Copyright (c) 2012 Eric Faurot <eric@faurot.net>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 #include <sys/wait.h>
22
23 #include <errno.h>
24 #include <pwd.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28
29 #include "smtpd.h"
30 #include "log.h"
31
32 static void lka_imsg(struct mproc *, struct imsg *);
33 static void lka_shutdown(void);
34 static void lka_sig_handler(int, short, void *);
35 static int lka_authenticate(const char *, const char *, const char *);
36 static int lka_credentials(const char *, const char *, char *, size_t);
37 static int lka_userinfo(const char *, const char *, struct userinfo *);
38 static int lka_addrname(const char *, const struct sockaddr *,
39 struct addrname *);
40 static int lka_mailaddrmap(const char *, const char *, const struct mailaddr *);
41
42 static void proc_timeout(int fd, short event, void *p);
43
44 struct event ev_proc_ready;
45
46 static void
lka_imsg(struct mproc * p,struct imsg * imsg)47 lka_imsg(struct mproc *p, struct imsg *imsg)
48 {
49 struct table *table;
50 int ret, fd;
51 struct sockaddr_storage ss;
52 struct userinfo userinfo;
53 struct addrname addrname;
54 struct envelope evp;
55 struct mailaddr maddr;
56 struct msg m;
57 union lookup lk;
58 char buf[LINE_MAX];
59 const char *tablename, *username, *password, *label, *procname;
60 uint64_t reqid;
61 int v;
62 struct timeval tv;
63 const char *direction;
64 const char *rdns;
65 const char *command;
66 const char *response;
67 const char *ciphers;
68 const char *address;
69 const char *domain;
70 const char *helomethod;
71 const char *heloname;
72 const char *filter_name;
73 const char *result;
74 struct sockaddr_storage ss_src, ss_dest;
75 int filter_response;
76 int filter_phase;
77 const char *filter_param;
78 uint32_t msgid;
79 uint32_t subsystems;
80 uint64_t evpid;
81 size_t msgsz;
82 int ok;
83 int fcrdns;
84
85 if (imsg == NULL)
86 lka_shutdown();
87
88 switch (imsg->hdr.type) {
89
90 case IMSG_GETADDRINFO:
91 case IMSG_GETNAMEINFO:
92 case IMSG_RES_QUERY:
93 resolver_dispatch_request(p, imsg);
94 return;
95
96 case IMSG_MTA_DNS_HOST:
97 case IMSG_MTA_DNS_MX:
98 case IMSG_MTA_DNS_MX_PREFERENCE:
99 dns_imsg(p, imsg);
100 return;
101
102 case IMSG_SMTP_CHECK_SENDER:
103 m_msg(&m, imsg);
104 m_get_id(&m, &reqid);
105 m_get_string(&m, &tablename);
106 m_get_string(&m, &username);
107 m_get_mailaddr(&m, &maddr);
108 m_end(&m);
109
110 ret = lka_mailaddrmap(tablename, username, &maddr);
111
112 m_create(p, IMSG_SMTP_CHECK_SENDER, 0, 0, -1);
113 m_add_id(p, reqid);
114 m_add_int(p, ret);
115 m_close(p);
116 return;
117
118 case IMSG_SMTP_EXPAND_RCPT:
119 m_msg(&m, imsg);
120 m_get_id(&m, &reqid);
121 m_get_envelope(&m, &evp);
122 m_end(&m);
123 lka_session(reqid, &evp);
124 return;
125
126 case IMSG_SMTP_LOOKUP_HELO:
127 m_msg(&m, imsg);
128 m_get_id(&m, &reqid);
129 m_get_string(&m, &tablename);
130 m_get_sockaddr(&m, (struct sockaddr *)&ss);
131 m_end(&m);
132
133 ret = lka_addrname(tablename, (struct sockaddr*)&ss,
134 &addrname);
135
136 m_create(p, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1);
137 m_add_id(p, reqid);
138 m_add_int(p, ret);
139 if (ret == LKA_OK)
140 m_add_string(p, addrname.name);
141 m_close(p);
142 return;
143
144 case IMSG_SMTP_AUTHENTICATE:
145 m_msg(&m, imsg);
146 m_get_id(&m, &reqid);
147 m_get_string(&m, &tablename);
148 m_get_string(&m, &username);
149 m_get_string(&m, &password);
150 m_end(&m);
151
152 if (!tablename[0]) {
153 m_create(p_parent, IMSG_LKA_AUTHENTICATE,
154 0, 0, -1);
155 m_add_id(p_parent, reqid);
156 m_add_string(p_parent, username);
157 m_add_string(p_parent, password);
158 m_close(p_parent);
159 return;
160 }
161
162 ret = lka_authenticate(tablename, username, password);
163
164 m_create(p, IMSG_SMTP_AUTHENTICATE, 0, 0, -1);
165 m_add_id(p, reqid);
166 m_add_int(p, ret);
167 m_close(p);
168 return;
169
170 case IMSG_MDA_LOOKUP_USERINFO:
171 m_msg(&m, imsg);
172 m_get_id(&m, &reqid);
173 m_get_string(&m, &tablename);
174 m_get_string(&m, &username);
175 m_end(&m);
176
177 ret = lka_userinfo(tablename, username, &userinfo);
178
179 m_create(p, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1);
180 m_add_id(p, reqid);
181 m_add_int(p, ret);
182 if (ret == LKA_OK)
183 m_add_data(p, &userinfo, sizeof(userinfo));
184 m_close(p);
185 return;
186
187 case IMSG_MTA_LOOKUP_CREDENTIALS:
188 m_msg(&m, imsg);
189 m_get_id(&m, &reqid);
190 m_get_string(&m, &tablename);
191 m_get_string(&m, &label);
192 m_end(&m);
193
194 lka_credentials(tablename, label, buf, sizeof(buf));
195
196 m_create(p, IMSG_MTA_LOOKUP_CREDENTIALS, 0, 0, -1);
197 m_add_id(p, reqid);
198 m_add_string(p, buf);
199 m_close(p);
200 return;
201
202 case IMSG_MTA_LOOKUP_SOURCE:
203 m_msg(&m, imsg);
204 m_get_id(&m, &reqid);
205 m_get_string(&m, &tablename);
206 m_end(&m);
207
208 table = table_find(env, tablename);
209
210 m_create(p, IMSG_MTA_LOOKUP_SOURCE, 0, 0, -1);
211 m_add_id(p, reqid);
212
213 if (table == NULL) {
214 log_warn("warn: source address table %s missing",
215 tablename);
216 m_add_int(p, LKA_TEMPFAIL);
217 }
218 else {
219 ret = table_fetch(table, K_SOURCE, &lk);
220 if (ret == -1)
221 m_add_int(p, LKA_TEMPFAIL);
222 else if (ret == 0)
223 m_add_int(p, LKA_PERMFAIL);
224 else {
225 m_add_int(p, LKA_OK);
226 m_add_sockaddr(p,
227 (struct sockaddr *)&lk.source.addr);
228 }
229 }
230 m_close(p);
231 return;
232
233 case IMSG_MTA_LOOKUP_HELO:
234 m_msg(&m, imsg);
235 m_get_id(&m, &reqid);
236 m_get_string(&m, &tablename);
237 m_get_sockaddr(&m, (struct sockaddr *)&ss);
238 m_end(&m);
239
240 ret = lka_addrname(tablename, (struct sockaddr*)&ss,
241 &addrname);
242
243 m_create(p, IMSG_MTA_LOOKUP_HELO, 0, 0, -1);
244 m_add_id(p, reqid);
245 m_add_int(p, ret);
246 if (ret == LKA_OK)
247 m_add_string(p, addrname.name);
248 m_close(p);
249 return;
250
251 case IMSG_MTA_LOOKUP_SMARTHOST:
252 m_msg(&m, imsg);
253 m_get_id(&m, &reqid);
254 m_get_string(&m, &domain);
255 m_get_string(&m, &tablename);
256 m_end(&m);
257
258 table = table_find(env, tablename);
259
260 m_create(p, IMSG_MTA_LOOKUP_SMARTHOST, 0, 0, -1);
261 m_add_id(p, reqid);
262
263 if (table == NULL) {
264 log_warn("warn: smarthost table %s missing", tablename);
265 m_add_int(p, LKA_TEMPFAIL);
266 }
267 else {
268 if (domain == NULL)
269 ret = table_fetch(table, K_RELAYHOST, &lk);
270 else
271 ret = table_lookup(table, K_RELAYHOST, domain, &lk);
272
273 if (ret == -1)
274 m_add_int(p, LKA_TEMPFAIL);
275 else if (ret == 0)
276 m_add_int(p, LKA_PERMFAIL);
277 else {
278 m_add_int(p, LKA_OK);
279 m_add_string(p, lk.relayhost);
280 }
281 }
282 m_close(p);
283 return;
284
285 case IMSG_CONF_START:
286 return;
287
288 case IMSG_CONF_END:
289 if (tracing & TRACE_TABLES)
290 table_dump_all(env);
291
292 /* fork & exec tables that need it */
293 table_open_all(env);
294
295 /* revoke proc & exec */
296 if (pledge("stdio rpath inet dns getpw recvfd sendfd",
297 NULL) == -1)
298 fatal("pledge");
299
300 /* setup proc registering task */
301 evtimer_set(&ev_proc_ready, proc_timeout, &ev_proc_ready);
302 tv.tv_sec = 0;
303 tv.tv_usec = 10;
304 evtimer_add(&ev_proc_ready, &tv);
305 return;
306
307 case IMSG_LKA_OPEN_FORWARD:
308 lka_session_forward_reply(imsg->data, imsg_get_fd(imsg));
309 return;
310
311 case IMSG_LKA_AUTHENTICATE:
312 imsg->hdr.type = IMSG_SMTP_AUTHENTICATE;
313 m_forward(p_dispatcher, imsg);
314 return;
315
316 case IMSG_CTL_VERBOSE:
317 m_msg(&m, imsg);
318 m_get_int(&m, &v);
319 m_end(&m);
320 log_trace_verbose(v);
321 return;
322
323 case IMSG_CTL_PROFILE:
324 m_msg(&m, imsg);
325 m_get_int(&m, &v);
326 m_end(&m);
327 profiling = v;
328 return;
329
330 case IMSG_CTL_UPDATE_TABLE:
331 ret = 0;
332 table = table_find(env, imsg->data);
333 if (table == NULL) {
334 log_warnx("warn: Lookup table not found: "
335 "\"%s\"", (char *)imsg->data);
336 } else
337 ret = table_update(table);
338
339 m_compose(p_control,
340 (ret == 1) ? IMSG_CTL_OK : IMSG_CTL_FAIL,
341 imsg->hdr.peerid, 0, -1, NULL, 0);
342 return;
343
344 case IMSG_LKA_PROCESSOR_FORK:
345 m_msg(&m, imsg);
346 m_get_string(&m, &procname);
347 m_get_u32(&m, &subsystems);
348 m_end(&m);
349
350 m_create(p, IMSG_LKA_PROCESSOR_ERRFD, 0, 0, -1);
351 m_add_string(p, procname);
352 m_close(p);
353
354 lka_proc_forked(procname, subsystems, imsg_get_fd(imsg));
355 return;
356
357 case IMSG_LKA_PROCESSOR_ERRFD:
358 m_msg(&m, imsg);
359 m_get_string(&m, &procname);
360 m_end(&m);
361
362 fd = imsg_get_fd(imsg);
363 lka_proc_errfd(procname, fd);
364 shutdown(fd, SHUT_WR);
365 return;
366
367 case IMSG_REPORT_SMTP_LINK_CONNECT:
368 m_msg(&m, imsg);
369 m_get_string(&m, &direction);
370 m_get_timeval(&m, &tv);
371 m_get_id(&m, &reqid);
372 m_get_string(&m, &rdns);
373 m_get_int(&m, &fcrdns);
374 m_get_sockaddr(&m, (struct sockaddr *)&ss_src);
375 m_get_sockaddr(&m, (struct sockaddr *)&ss_dest);
376 m_end(&m);
377
378 lka_report_smtp_link_connect(direction, &tv, reqid, rdns, fcrdns, &ss_src, &ss_dest);
379 return;
380
381 case IMSG_REPORT_SMTP_LINK_GREETING:
382 m_msg(&m, imsg);
383 m_get_string(&m, &direction);
384 m_get_timeval(&m, &tv);
385 m_get_id(&m, &reqid);
386 m_get_string(&m, &domain);
387 m_end(&m);
388
389 lka_report_smtp_link_greeting(direction, reqid, &tv, domain);
390 return;
391
392 case IMSG_REPORT_SMTP_LINK_DISCONNECT:
393 m_msg(&m, imsg);
394 m_get_string(&m, &direction);
395 m_get_timeval(&m, &tv);
396 m_get_id(&m, &reqid);
397 m_end(&m);
398
399 lka_report_smtp_link_disconnect(direction, &tv, reqid);
400 return;
401
402 case IMSG_REPORT_SMTP_LINK_IDENTIFY:
403 m_msg(&m, imsg);
404 m_get_string(&m, &direction);
405 m_get_timeval(&m, &tv);
406 m_get_id(&m, &reqid);
407 m_get_string(&m, &helomethod);
408 m_get_string(&m, &heloname);
409 m_end(&m);
410
411 lka_report_smtp_link_identify(direction, &tv, reqid, helomethod, heloname);
412 return;
413
414 case IMSG_REPORT_SMTP_LINK_TLS:
415 m_msg(&m, imsg);
416 m_get_string(&m, &direction);
417 m_get_timeval(&m, &tv);
418 m_get_id(&m, &reqid);
419 m_get_string(&m, &ciphers);
420 m_end(&m);
421
422 lka_report_smtp_link_tls(direction, &tv, reqid, ciphers);
423 return;
424
425 case IMSG_REPORT_SMTP_LINK_AUTH:
426 m_msg(&m, imsg);
427 m_get_string(&m, &direction);
428 m_get_timeval(&m, &tv);
429 m_get_id(&m, &reqid);
430 m_get_string(&m, &username);
431 m_get_string(&m, &result);
432 m_end(&m);
433
434 lka_report_smtp_link_auth(direction, &tv, reqid, username, result);
435 return;
436
437 case IMSG_REPORT_SMTP_TX_RESET:
438 m_msg(&m, imsg);
439 m_get_string(&m, &direction);
440 m_get_timeval(&m, &tv);
441 m_get_id(&m, &reqid);
442 m_get_u32(&m, &msgid);
443 m_end(&m);
444
445 lka_report_smtp_tx_reset(direction, &tv, reqid, msgid);
446 return;
447
448 case IMSG_REPORT_SMTP_TX_BEGIN:
449 m_msg(&m, imsg);
450 m_get_string(&m, &direction);
451 m_get_timeval(&m, &tv);
452 m_get_id(&m, &reqid);
453 m_get_u32(&m, &msgid);
454 m_end(&m);
455
456 lka_report_smtp_tx_begin(direction, &tv, reqid, msgid);
457 return;
458
459 case IMSG_REPORT_SMTP_TX_MAIL:
460 m_msg(&m, imsg);
461 m_get_string(&m, &direction);
462 m_get_timeval(&m, &tv);
463 m_get_id(&m, &reqid);
464 m_get_u32(&m, &msgid);
465 m_get_string(&m, &address);
466 m_get_int(&m, &ok);
467 m_end(&m);
468
469 lka_report_smtp_tx_mail(direction, &tv, reqid, msgid, address, ok);
470 return;
471
472 case IMSG_REPORT_SMTP_TX_RCPT:
473 m_msg(&m, imsg);
474 m_get_string(&m, &direction);
475 m_get_timeval(&m, &tv);
476 m_get_id(&m, &reqid);
477 m_get_u32(&m, &msgid);
478 m_get_string(&m, &address);
479 m_get_int(&m, &ok);
480 m_end(&m);
481
482 lka_report_smtp_tx_rcpt(direction, &tv, reqid, msgid, address, ok);
483 return;
484
485 case IMSG_REPORT_SMTP_TX_ENVELOPE:
486 m_msg(&m, imsg);
487 m_get_string(&m, &direction);
488 m_get_timeval(&m, &tv);
489 m_get_id(&m, &reqid);
490 m_get_u32(&m, &msgid);
491 m_get_id(&m, &evpid);
492 m_end(&m);
493
494 lka_report_smtp_tx_envelope(direction, &tv, reqid, msgid, evpid);
495 return;
496
497 case IMSG_REPORT_SMTP_TX_DATA:
498 m_msg(&m, imsg);
499 m_get_string(&m, &direction);
500 m_get_timeval(&m, &tv);
501 m_get_id(&m, &reqid);
502 m_get_u32(&m, &msgid);
503 m_get_int(&m, &ok);
504 m_end(&m);
505
506 lka_report_smtp_tx_data(direction, &tv, reqid, msgid, ok);
507 return;
508
509 case IMSG_REPORT_SMTP_TX_COMMIT:
510 m_msg(&m, imsg);
511 m_get_string(&m, &direction);
512 m_get_timeval(&m, &tv);
513 m_get_id(&m, &reqid);
514 m_get_u32(&m, &msgid);
515 m_get_size(&m, &msgsz);
516 m_end(&m);
517
518 lka_report_smtp_tx_commit(direction, &tv, reqid, msgid, msgsz);
519 return;
520
521 case IMSG_REPORT_SMTP_TX_ROLLBACK:
522 m_msg(&m, imsg);
523 m_get_string(&m, &direction);
524 m_get_timeval(&m, &tv);
525 m_get_id(&m, &reqid);
526 m_get_u32(&m, &msgid);
527 m_end(&m);
528
529 lka_report_smtp_tx_rollback(direction, &tv, reqid, msgid);
530 return;
531
532 case IMSG_REPORT_SMTP_PROTOCOL_CLIENT:
533 m_msg(&m, imsg);
534 m_get_string(&m, &direction);
535 m_get_timeval(&m, &tv);
536 m_get_id(&m, &reqid);
537 m_get_string(&m, &command);
538 m_end(&m);
539
540 lka_report_smtp_protocol_client(direction, &tv, reqid, command);
541 return;
542
543 case IMSG_REPORT_SMTP_PROTOCOL_SERVER:
544 m_msg(&m, imsg);
545 m_get_string(&m, &direction);
546 m_get_timeval(&m, &tv);
547 m_get_id(&m, &reqid);
548 m_get_string(&m, &response);
549 m_end(&m);
550
551 lka_report_smtp_protocol_server(direction, &tv, reqid, response);
552 return;
553
554 case IMSG_REPORT_SMTP_FILTER_RESPONSE:
555 m_msg(&m, imsg);
556 m_get_string(&m, &direction);
557 m_get_timeval(&m, &tv);
558 m_get_id(&m, &reqid);
559 m_get_int(&m, &filter_phase);
560 m_get_int(&m, &filter_response);
561 m_get_string(&m, &filter_param);
562 m_end(&m);
563
564 lka_report_smtp_filter_response(direction, &tv, reqid,
565 filter_phase, filter_response, filter_param);
566 return;
567
568 case IMSG_REPORT_SMTP_TIMEOUT:
569 m_msg(&m, imsg);
570 m_get_string(&m, &direction);
571 m_get_timeval(&m, &tv);
572 m_get_id(&m, &reqid);
573 m_end(&m);
574
575 lka_report_smtp_timeout(direction, &tv, reqid);
576 return;
577
578 case IMSG_FILTER_SMTP_PROTOCOL:
579 m_msg(&m, imsg);
580 m_get_id(&m, &reqid);
581 m_get_int(&m, &filter_phase);
582 m_get_string(&m, &filter_param);
583 m_end(&m);
584
585 lka_filter_protocol(reqid, filter_phase, filter_param);
586 return;
587
588 case IMSG_FILTER_SMTP_BEGIN:
589 m_msg(&m, imsg);
590 m_get_id(&m, &reqid);
591 m_get_string(&m, &filter_name);
592 m_end(&m);
593
594 lka_filter_begin(reqid, filter_name);
595 return;
596
597 case IMSG_FILTER_SMTP_END:
598 m_msg(&m, imsg);
599 m_get_id(&m, &reqid);
600 m_end(&m);
601
602 lka_filter_end(reqid);
603 return;
604
605 case IMSG_FILTER_SMTP_DATA_BEGIN:
606 m_msg(&m, imsg);
607 m_get_id(&m, &reqid);
608 m_end(&m);
609
610 lka_filter_data_begin(reqid);
611 return;
612
613 case IMSG_FILTER_SMTP_DATA_END:
614 m_msg(&m, imsg);
615 m_get_id(&m, &reqid);
616 m_end(&m);
617
618 lka_filter_data_end(reqid);
619 return;
620
621 }
622
623 fatalx("lka_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
624 }
625
626 static void
lka_sig_handler(int sig,short event,void * p)627 lka_sig_handler(int sig, short event, void *p)
628 {
629 int status;
630 pid_t pid;
631
632 switch (sig) {
633 case SIGCHLD:
634 do {
635 pid = waitpid(-1, &status, WNOHANG);
636 } while (pid > 0 || (pid == -1 && errno == EINTR));
637 break;
638 default:
639 fatalx("lka_sig_handler: unexpected signal");
640 }
641 }
642
643 void
lka_shutdown(void)644 lka_shutdown(void)
645 {
646 log_debug("debug: lookup agent exiting");
647 _exit(0);
648 }
649
650 int
lka(void)651 lka(void)
652 {
653 struct passwd *pw;
654 struct event ev_sigchld;
655
656 purge_config(PURGE_LISTENERS);
657
658 if ((pw = getpwnam(SMTPD_USER)) == NULL)
659 fatalx("unknown user " SMTPD_USER);
660
661 config_process(PROC_LKA);
662
663 if (initgroups(pw->pw_name, pw->pw_gid) ||
664 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
665 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
666 fatal("lka: cannot drop privileges");
667
668 imsg_callback = lka_imsg;
669 event_init();
670
671 signal_set(&ev_sigchld, SIGCHLD, lka_sig_handler, NULL);
672 signal_add(&ev_sigchld, NULL);
673 signal(SIGINT, SIG_IGN);
674 signal(SIGTERM, SIG_IGN);
675 signal(SIGPIPE, SIG_IGN);
676 signal(SIGHUP, SIG_IGN);
677
678 config_peer(PROC_PARENT);
679 config_peer(PROC_QUEUE);
680 config_peer(PROC_CONTROL);
681 config_peer(PROC_DISPATCHER);
682
683 /* Ignore them until we get our config */
684 mproc_disable(p_dispatcher);
685
686 lka_report_init();
687 lka_filter_init();
688
689 /* proc & exec will be revoked before serving requests */
690 if (pledge("stdio rpath inet dns getpw recvfd sendfd proc exec", NULL) == -1)
691 fatal("pledge");
692
693 event_dispatch();
694 fatalx("exited event loop");
695
696 return (0);
697 }
698
699 static void
proc_timeout(int fd,short event,void * p)700 proc_timeout(int fd, short event, void *p)
701 {
702 struct event *ev = p;
703 struct timeval tv;
704
705 if (!lka_proc_ready())
706 goto reset;
707
708 lka_filter_ready();
709 mproc_enable(p_dispatcher);
710 return;
711
712 reset:
713 tv.tv_sec = 0;
714 tv.tv_usec = 10;
715 evtimer_add(ev, &tv);
716 }
717
718
719 static int
lka_authenticate(const char * tablename,const char * user,const char * password)720 lka_authenticate(const char *tablename, const char *user, const char *password)
721 {
722 struct table *table;
723 char offloadkey[LINE_MAX];
724 union lookup lk;
725
726 log_debug("debug: lka: authenticating for %s:%s", tablename, user);
727 table = table_find(env, tablename);
728 if (table == NULL) {
729 log_warnx("warn: could not find table %s needed for authentication",
730 tablename);
731 return (LKA_TEMPFAIL);
732 }
733
734 /* table backend supports authentication offloading */
735 if (table_check_service(table, K_AUTH)) {
736 if (!bsnprintf(offloadkey, sizeof(offloadkey), "%s:%s",
737 user, password)) {
738 log_warnx("warn: key serialization failed for %s:%s",
739 tablename, user);
740 return (LKA_TEMPFAIL);
741 }
742 switch (table_match(table, K_AUTH, offloadkey)) {
743 case -1:
744 log_warnx("warn: user credentials lookup fail for %s:%s",
745 tablename, user);
746 return (LKA_TEMPFAIL);
747 case 0:
748 return (LKA_PERMFAIL);
749 default:
750 return (LKA_OK);
751 }
752 }
753
754 switch (table_lookup(table, K_CREDENTIALS, user, &lk)) {
755 case -1:
756 log_warnx("warn: user credentials lookup fail for %s:%s",
757 tablename, user);
758 return (LKA_TEMPFAIL);
759 case 0:
760 return (LKA_PERMFAIL);
761 default:
762 if (crypt_checkpass(password, lk.creds.password) == 0)
763 return (LKA_OK);
764 return (LKA_PERMFAIL);
765 }
766 }
767
768 static int
lka_credentials(const char * tablename,const char * label,char * dst,size_t sz)769 lka_credentials(const char *tablename, const char *label, char *dst, size_t sz)
770 {
771 struct table *table;
772 union lookup lk;
773 char *buf;
774 int buflen, r;
775
776 table = table_find(env, tablename);
777 if (table == NULL) {
778 log_warnx("warn: credentials table %s missing", tablename);
779 return (LKA_TEMPFAIL);
780 }
781
782 dst[0] = '\0';
783
784 switch (table_lookup(table, K_CREDENTIALS, label, &lk)) {
785 case -1:
786 log_warnx("warn: credentials lookup fail for %s:%s",
787 tablename, label);
788 return (LKA_TEMPFAIL);
789 case 0:
790 log_warnx("warn: credentials not found for %s:%s",
791 tablename, label);
792 return (LKA_PERMFAIL);
793 default:
794 if ((buflen = asprintf(&buf, "%c%s%c%s", '\0',
795 lk.creds.username, '\0', lk.creds.password)) == -1) {
796 log_warn("warn");
797 return (LKA_TEMPFAIL);
798 }
799
800 r = base64_encode((unsigned char *)buf, buflen, dst, sz);
801 free(buf);
802
803 if (r == -1) {
804 log_warnx("warn: credentials parse error for %s:%s",
805 tablename, label);
806 return (LKA_TEMPFAIL);
807 }
808 return (LKA_OK);
809 }
810 }
811
812 static int
lka_userinfo(const char * tablename,const char * username,struct userinfo * res)813 lka_userinfo(const char *tablename, const char *username, struct userinfo *res)
814 {
815 struct table *table;
816 union lookup lk;
817
818 log_debug("debug: lka: userinfo %s:%s", tablename, username);
819 table = table_find(env, tablename);
820 if (table == NULL) {
821 log_warnx("warn: cannot find user table %s", tablename);
822 return (LKA_TEMPFAIL);
823 }
824
825 switch (table_lookup(table, K_USERINFO, username, &lk)) {
826 case -1:
827 log_warnx("warn: failure during userinfo lookup %s:%s",
828 tablename, username);
829 return (LKA_TEMPFAIL);
830 case 0:
831 return (LKA_PERMFAIL);
832 default:
833 *res = lk.userinfo;
834 return (LKA_OK);
835 }
836 }
837
838 static int
lka_addrname(const char * tablename,const struct sockaddr * sa,struct addrname * res)839 lka_addrname(const char *tablename, const struct sockaddr *sa,
840 struct addrname *res)
841 {
842 struct table *table;
843 union lookup lk;
844 const char *source;
845
846 source = sa_to_text(sa);
847
848 log_debug("debug: lka: helo %s:%s", tablename, source);
849 table = table_find(env, tablename);
850 if (table == NULL) {
851 log_warnx("warn: cannot find helo table %s", tablename);
852 return (LKA_TEMPFAIL);
853 }
854
855 switch (table_lookup(table, K_ADDRNAME, source, &lk)) {
856 case -1:
857 log_warnx("warn: failure during helo lookup %s:%s",
858 tablename, source);
859 return (LKA_TEMPFAIL);
860 case 0:
861 return (LKA_PERMFAIL);
862 default:
863 *res = lk.addrname;
864 return (LKA_OK);
865 }
866 }
867
868 static int
lka_mailaddrmap(const char * tablename,const char * username,const struct mailaddr * maddr)869 lka_mailaddrmap(const char *tablename, const char *username, const struct mailaddr *maddr)
870 {
871 struct table *table;
872 struct maddrnode *mn;
873 union lookup lk;
874 int found;
875
876 log_debug("debug: lka: mailaddrmap %s:%s", tablename, username);
877 table = table_find(env, tablename);
878 if (table == NULL) {
879 log_warnx("warn: cannot find mailaddrmap table %s", tablename);
880 return (LKA_TEMPFAIL);
881 }
882
883 switch (table_lookup(table, K_MAILADDRMAP, username, &lk)) {
884 case -1:
885 log_warnx("warn: failure during mailaddrmap lookup %s:%s",
886 tablename, username);
887 return (LKA_TEMPFAIL);
888 case 0:
889 return (LKA_PERMFAIL);
890 default:
891 found = 0;
892 TAILQ_FOREACH(mn, &lk.maddrmap->queue, entries) {
893 if (!mailaddr_match(maddr, &mn->mailaddr))
894 continue;
895 found = 1;
896 break;
897 }
898 maddrmap_free(lk.maddrmap);
899 if (found)
900 return (LKA_OK);
901 return (LKA_PERMFAIL);
902 }
903 return (LKA_OK);
904 }
905