1 /* $OpenBSD: lka.c,v 1.175 2015/01/20 17:37:54 deraadt 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/types.h> 22 #include <sys/queue.h> 23 #include <sys/tree.h> 24 #include <sys/socket.h> 25 #include <sys/wait.h> 26 #include <sys/uio.h> 27 28 #include <netinet/in.h> 29 30 #include <ctype.h> 31 #include <err.h> 32 #include <errno.h> 33 #include <event.h> 34 #include <imsg.h> 35 #include <openssl/err.h> 36 #include <openssl/ssl.h> 37 #include <pwd.h> 38 #include <resolv.h> 39 #include <limits.h> 40 #include <signal.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include "smtpd.h" 47 #include "log.h" 48 #include "ssl.h" 49 50 static void lka_imsg(struct mproc *, struct imsg *); 51 static void lka_shutdown(void); 52 static void lka_sig_handler(int, short, void *); 53 static int lka_authenticate(const char *, const char *, const char *); 54 static int lka_credentials(const char *, const char *, char *, size_t); 55 static int lka_userinfo(const char *, const char *, struct userinfo *); 56 static int lka_addrname(const char *, const struct sockaddr *, 57 struct addrname *); 58 static int lka_X509_verify(struct ca_vrfy_req_msg *, const char *, const char *); 59 60 static void 61 lka_imsg(struct mproc *p, struct imsg *imsg) 62 { 63 struct table *table; 64 int ret; 65 struct pki *pki; 66 struct iovec iov[2]; 67 static struct ca_vrfy_req_msg *req_ca_vrfy_smtp = NULL; 68 static struct ca_vrfy_req_msg *req_ca_vrfy_mta = NULL; 69 struct ca_vrfy_req_msg *req_ca_vrfy_chain; 70 struct ca_vrfy_resp_msg resp_ca_vrfy; 71 struct ca_cert_req_msg *req_ca_cert; 72 struct ca_cert_resp_msg resp_ca_cert; 73 struct sockaddr_storage ss; 74 struct userinfo userinfo; 75 struct addrname addrname; 76 struct envelope evp; 77 struct msg m; 78 union lookup lk; 79 char buf[LINE_MAX]; 80 const char *tablename, *username, *password, *label; 81 uint64_t reqid; 82 size_t i; 83 int v; 84 const char *cafile = NULL; 85 86 if (imsg->hdr.type == IMSG_MTA_DNS_HOST || 87 imsg->hdr.type == IMSG_MTA_DNS_PTR || 88 imsg->hdr.type == IMSG_SMTP_DNS_PTR || 89 imsg->hdr.type == IMSG_MTA_DNS_MX || 90 imsg->hdr.type == IMSG_MTA_DNS_MX_PREFERENCE) { 91 dns_imsg(p, imsg); 92 return; 93 } 94 95 if (p->proc == PROC_PONY) { 96 switch (imsg->hdr.type) { 97 case IMSG_SMTP_EXPAND_RCPT: 98 m_msg(&m, imsg); 99 m_get_id(&m, &reqid); 100 m_get_envelope(&m, &evp); 101 m_end(&m); 102 lka_session(reqid, &evp); 103 return; 104 105 case IMSG_SMTP_LOOKUP_HELO: 106 m_msg(&m, imsg); 107 m_get_id(&m, &reqid); 108 m_get_string(&m, &tablename); 109 m_get_sockaddr(&m, (struct sockaddr *)&ss); 110 m_end(&m); 111 112 ret = lka_addrname(tablename, (struct sockaddr*)&ss, 113 &addrname); 114 115 m_create(p, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1); 116 m_add_id(p, reqid); 117 m_add_int(p, ret); 118 if (ret == LKA_OK) 119 m_add_string(p, addrname.name); 120 m_close(p); 121 return; 122 123 case IMSG_SMTP_SSL_INIT: 124 req_ca_cert = imsg->data; 125 resp_ca_cert.reqid = req_ca_cert->reqid; 126 127 xlowercase(buf, req_ca_cert->name, sizeof(buf)); 128 log_debug("debug: lka: looking up pki \"%s\"", buf); 129 pki = dict_get(env->sc_pki_dict, buf); 130 if (pki == NULL) { 131 resp_ca_cert.status = CA_FAIL; 132 m_compose(p, IMSG_SMTP_SSL_INIT, 0, 0, -1, &resp_ca_cert, 133 sizeof(resp_ca_cert)); 134 return; 135 } 136 resp_ca_cert.status = CA_OK; 137 resp_ca_cert.cert_len = pki->pki_cert_len; 138 iov[0].iov_base = &resp_ca_cert; 139 iov[0].iov_len = sizeof(resp_ca_cert); 140 iov[1].iov_base = pki->pki_cert; 141 iov[1].iov_len = pki->pki_cert_len; 142 m_composev(p, IMSG_SMTP_SSL_INIT, 0, 0, -1, iov, nitems(iov)); 143 return; 144 145 case IMSG_SMTP_SSL_VERIFY_CERT: 146 req_ca_vrfy_smtp = xmemdup(imsg->data, sizeof *req_ca_vrfy_smtp, "lka:ca_vrfy"); 147 req_ca_vrfy_smtp->cert = xmemdup((char *)imsg->data + 148 sizeof *req_ca_vrfy_smtp, req_ca_vrfy_smtp->cert_len, "lka:ca_vrfy"); 149 req_ca_vrfy_smtp->chain_cert = xcalloc(req_ca_vrfy_smtp->n_chain, 150 sizeof (unsigned char *), "lka:ca_vrfy"); 151 req_ca_vrfy_smtp->chain_cert_len = xcalloc(req_ca_vrfy_smtp->n_chain, 152 sizeof (off_t), "lka:ca_vrfy"); 153 return; 154 155 case IMSG_SMTP_SSL_VERIFY_CHAIN: 156 if (req_ca_vrfy_smtp == NULL) 157 fatalx("lka:ca_vrfy: chain without a certificate"); 158 req_ca_vrfy_chain = imsg->data; 159 req_ca_vrfy_smtp->chain_cert[req_ca_vrfy_smtp->chain_offset] = xmemdup((char *)imsg->data + 160 sizeof *req_ca_vrfy_chain, req_ca_vrfy_chain->cert_len, "lka:ca_vrfy"); 161 req_ca_vrfy_smtp->chain_cert_len[req_ca_vrfy_smtp->chain_offset] = req_ca_vrfy_chain->cert_len; 162 req_ca_vrfy_smtp->chain_offset++; 163 return; 164 165 case IMSG_SMTP_SSL_VERIFY: 166 if (req_ca_vrfy_smtp == NULL) 167 fatalx("lka:ca_vrfy: verify without a certificate"); 168 169 resp_ca_vrfy.reqid = req_ca_vrfy_smtp->reqid; 170 pki = dict_xget(env->sc_pki_dict, req_ca_vrfy_smtp->pkiname); 171 cafile = CA_FILE; 172 if (pki->pki_ca_file) 173 cafile = pki->pki_ca_file; 174 if (! lka_X509_verify(req_ca_vrfy_smtp, cafile, NULL)) 175 resp_ca_vrfy.status = CA_FAIL; 176 else 177 resp_ca_vrfy.status = CA_OK; 178 179 m_compose(p, IMSG_SMTP_SSL_VERIFY, 0, 0, -1, &resp_ca_vrfy, 180 sizeof resp_ca_vrfy); 181 182 for (i = 0; i < req_ca_vrfy_smtp->n_chain; ++i) 183 free(req_ca_vrfy_smtp->chain_cert[i]); 184 free(req_ca_vrfy_smtp->chain_cert); 185 free(req_ca_vrfy_smtp->chain_cert_len); 186 free(req_ca_vrfy_smtp->cert); 187 free(req_ca_vrfy_smtp); 188 return; 189 190 case IMSG_SMTP_AUTHENTICATE: 191 m_msg(&m, imsg); 192 m_get_id(&m, &reqid); 193 m_get_string(&m, &tablename); 194 m_get_string(&m, &username); 195 m_get_string(&m, &password); 196 m_end(&m); 197 198 if (!tablename[0]) { 199 m_create(p_parent, IMSG_LKA_AUTHENTICATE, 200 0, 0, -1); 201 m_add_id(p_parent, reqid); 202 m_add_string(p_parent, username); 203 m_add_string(p_parent, password); 204 m_close(p_parent); 205 return; 206 } 207 208 ret = lka_authenticate(tablename, username, password); 209 210 m_create(p, IMSG_SMTP_AUTHENTICATE, 0, 0, -1); 211 m_add_id(p, reqid); 212 m_add_int(p, ret); 213 m_close(p); 214 return; 215 } 216 } 217 218 if (p->proc == PROC_PONY) { 219 switch (imsg->hdr.type) { 220 case IMSG_MDA_LOOKUP_USERINFO: 221 m_msg(&m, imsg); 222 m_get_id(&m, &reqid); 223 m_get_string(&m, &tablename); 224 m_get_string(&m, &username); 225 m_end(&m); 226 227 ret = lka_userinfo(tablename, username, &userinfo); 228 229 m_create(p, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1); 230 m_add_id(p, reqid); 231 m_add_int(p, ret); 232 if (ret == LKA_OK) 233 m_add_data(p, &userinfo, sizeof(userinfo)); 234 m_close(p); 235 return; 236 } 237 } 238 239 if (p->proc == PROC_PONY) { 240 switch (imsg->hdr.type) { 241 242 case IMSG_MTA_SSL_INIT: 243 req_ca_cert = imsg->data; 244 resp_ca_cert.reqid = req_ca_cert->reqid; 245 246 xlowercase(buf, req_ca_cert->name, sizeof(buf)); 247 log_debug("debug: lka: looking up pki \"%s\"", buf); 248 pki = dict_get(env->sc_pki_dict, buf); 249 if (pki == NULL) { 250 resp_ca_cert.status = CA_FAIL; 251 m_compose(p, IMSG_MTA_SSL_INIT, 0, 0, -1, &resp_ca_cert, 252 sizeof(resp_ca_cert)); 253 return; 254 } 255 resp_ca_cert.status = CA_OK; 256 resp_ca_cert.cert_len = pki->pki_cert_len; 257 iov[0].iov_base = &resp_ca_cert; 258 iov[0].iov_len = sizeof(resp_ca_cert); 259 iov[1].iov_base = pki->pki_cert; 260 iov[1].iov_len = pki->pki_cert_len; 261 m_composev(p, IMSG_MTA_SSL_INIT, 0, 0, -1, iov, nitems(iov)); 262 return; 263 264 case IMSG_MTA_SSL_VERIFY_CERT: 265 req_ca_vrfy_mta = xmemdup(imsg->data, sizeof *req_ca_vrfy_mta, "lka:ca_vrfy"); 266 req_ca_vrfy_mta->cert = xmemdup((char *)imsg->data + 267 sizeof *req_ca_vrfy_mta, req_ca_vrfy_mta->cert_len, "lka:ca_vrfy"); 268 req_ca_vrfy_mta->chain_cert = xcalloc(req_ca_vrfy_mta->n_chain, 269 sizeof (unsigned char *), "lka:ca_vrfy"); 270 req_ca_vrfy_mta->chain_cert_len = xcalloc(req_ca_vrfy_mta->n_chain, 271 sizeof (off_t), "lka:ca_vrfy"); 272 return; 273 274 case IMSG_MTA_SSL_VERIFY_CHAIN: 275 if (req_ca_vrfy_mta == NULL) 276 fatalx("lka:ca_vrfy: verify without a certificate"); 277 278 req_ca_vrfy_chain = imsg->data; 279 req_ca_vrfy_mta->chain_cert[req_ca_vrfy_mta->chain_offset] = xmemdup((char *)imsg->data + 280 sizeof *req_ca_vrfy_chain, req_ca_vrfy_chain->cert_len, "lka:ca_vrfy"); 281 req_ca_vrfy_mta->chain_cert_len[req_ca_vrfy_mta->chain_offset] = req_ca_vrfy_chain->cert_len; 282 req_ca_vrfy_mta->chain_offset++; 283 return; 284 285 case IMSG_MTA_SSL_VERIFY: 286 if (req_ca_vrfy_mta == NULL) 287 fatalx("lka:ca_vrfy: verify without a certificate"); 288 289 resp_ca_vrfy.reqid = req_ca_vrfy_mta->reqid; 290 pki = dict_get(env->sc_pki_dict, req_ca_vrfy_mta->pkiname); 291 292 cafile = CA_FILE; 293 if (pki && pki->pki_ca_file) 294 cafile = pki->pki_ca_file; 295 if (! lka_X509_verify(req_ca_vrfy_mta, cafile, NULL)) 296 resp_ca_vrfy.status = CA_FAIL; 297 else 298 resp_ca_vrfy.status = CA_OK; 299 300 m_compose(p, IMSG_MTA_SSL_VERIFY, 0, 0, -1, &resp_ca_vrfy, 301 sizeof resp_ca_vrfy); 302 303 for (i = 0; i < req_ca_vrfy_mta->n_chain; ++i) 304 free(req_ca_vrfy_mta->chain_cert[i]); 305 free(req_ca_vrfy_mta->chain_cert); 306 free(req_ca_vrfy_mta->chain_cert_len); 307 free(req_ca_vrfy_mta->cert); 308 free(req_ca_vrfy_mta); 309 return; 310 311 case IMSG_MTA_LOOKUP_CREDENTIALS: 312 m_msg(&m, imsg); 313 m_get_id(&m, &reqid); 314 m_get_string(&m, &tablename); 315 m_get_string(&m, &label); 316 m_end(&m); 317 318 lka_credentials(tablename, label, buf, sizeof(buf)); 319 320 m_create(p, IMSG_MTA_LOOKUP_CREDENTIALS, 0, 0, -1); 321 m_add_id(p, reqid); 322 m_add_string(p, buf); 323 m_close(p); 324 return; 325 326 case IMSG_MTA_LOOKUP_SOURCE: 327 m_msg(&m, imsg); 328 m_get_id(&m, &reqid); 329 m_get_string(&m, &tablename); 330 m_end(&m); 331 332 table = table_find(tablename, NULL); 333 334 m_create(p, IMSG_MTA_LOOKUP_SOURCE, 0, 0, -1); 335 m_add_id(p, reqid); 336 337 if (table == NULL) { 338 log_warn("warn: source address table %s missing", 339 tablename); 340 m_add_int(p, LKA_TEMPFAIL); 341 } 342 else { 343 ret = table_fetch(table, NULL, K_SOURCE, &lk); 344 if (ret == -1) 345 m_add_int(p, LKA_TEMPFAIL); 346 else if (ret == 0) 347 m_add_int(p, LKA_PERMFAIL); 348 else { 349 m_add_int(p, LKA_OK); 350 m_add_sockaddr(p, 351 (struct sockaddr *)&lk.source.addr); 352 } 353 } 354 m_close(p); 355 return; 356 357 case IMSG_MTA_LOOKUP_HELO: 358 m_msg(&m, imsg); 359 m_get_id(&m, &reqid); 360 m_get_string(&m, &tablename); 361 m_get_sockaddr(&m, (struct sockaddr *)&ss); 362 m_end(&m); 363 364 ret = lka_addrname(tablename, (struct sockaddr*)&ss, 365 &addrname); 366 367 m_create(p, IMSG_MTA_LOOKUP_HELO, 0, 0, -1); 368 m_add_id(p, reqid); 369 m_add_int(p, ret); 370 if (ret == LKA_OK) 371 m_add_string(p, addrname.name); 372 m_close(p); 373 return; 374 375 } 376 } 377 378 if (p->proc == PROC_PARENT) { 379 switch (imsg->hdr.type) { 380 case IMSG_CONF_START: 381 return; 382 383 case IMSG_CONF_END: 384 if (verbose & TRACE_TABLES) 385 table_dump_all(); 386 table_open_all(); 387 388 /* Start fulfilling requests */ 389 mproc_enable(p_pony); 390 return; 391 392 case IMSG_LKA_OPEN_FORWARD: 393 lka_session_forward_reply(imsg->data, imsg->fd); 394 return; 395 396 case IMSG_LKA_AUTHENTICATE: 397 imsg->hdr.type = IMSG_SMTP_AUTHENTICATE; 398 m_forward(p_pony, imsg); 399 return; 400 } 401 } 402 403 if (p->proc == PROC_CONTROL) { 404 switch (imsg->hdr.type) { 405 406 case IMSG_CTL_VERBOSE: 407 m_msg(&m, imsg); 408 m_get_int(&m, &v); 409 m_end(&m); 410 log_verbose(v); 411 return; 412 413 case IMSG_CTL_PROFILE: 414 m_msg(&m, imsg); 415 m_get_int(&m, &v); 416 m_end(&m); 417 profiling = v; 418 return; 419 420 case IMSG_CTL_UPDATE_TABLE: 421 table = table_find(imsg->data, NULL); 422 if (table == NULL) { 423 log_warnx("warn: Lookup table not found: " 424 "\"%s\"", (char *)imsg->data); 425 return; 426 } 427 table_update(table); 428 return; 429 } 430 } 431 432 errx(1, "lka_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); 433 } 434 435 static void 436 lka_sig_handler(int sig, short event, void *p) 437 { 438 int status; 439 pid_t pid; 440 441 switch (sig) { 442 case SIGINT: 443 case SIGTERM: 444 lka_shutdown(); 445 break; 446 case SIGCHLD: 447 do { 448 pid = waitpid(-1, &status, WNOHANG); 449 } while (pid > 0 || (pid == -1 && errno == EINTR)); 450 break; 451 default: 452 fatalx("lka_sig_handler: unexpected signal"); 453 } 454 } 455 456 void 457 lka_shutdown(void) 458 { 459 log_info("info: lookup agent exiting"); 460 _exit(0); 461 } 462 463 pid_t 464 lka(void) 465 { 466 pid_t pid; 467 struct passwd *pw; 468 struct event ev_sigint; 469 struct event ev_sigterm; 470 struct event ev_sigchld; 471 472 switch (pid = fork()) { 473 case -1: 474 fatal("lka: cannot fork"); 475 case 0: 476 post_fork(PROC_LKA); 477 break; 478 default: 479 return (pid); 480 } 481 482 purge_config(PURGE_LISTENERS); 483 484 if ((pw = getpwnam(SMTPD_USER)) == NULL) 485 fatalx("unknown user " SMTPD_USER); 486 487 config_process(PROC_LKA); 488 489 if (setgroups(1, &pw->pw_gid) || 490 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 491 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 492 fatal("lka: cannot drop privileges"); 493 494 imsg_callback = lka_imsg; 495 event_init(); 496 497 signal_set(&ev_sigint, SIGINT, lka_sig_handler, NULL); 498 signal_set(&ev_sigterm, SIGTERM, lka_sig_handler, NULL); 499 signal_set(&ev_sigchld, SIGCHLD, lka_sig_handler, NULL); 500 signal_add(&ev_sigint, NULL); 501 signal_add(&ev_sigterm, NULL); 502 signal_add(&ev_sigchld, NULL); 503 signal(SIGPIPE, SIG_IGN); 504 signal(SIGHUP, SIG_IGN); 505 506 config_peer(PROC_PARENT); 507 config_peer(PROC_QUEUE); 508 config_peer(PROC_CONTROL); 509 config_peer(PROC_PONY); 510 config_done(); 511 512 /* Ignore them until we get our config */ 513 mproc_disable(p_pony); 514 515 if (event_dispatch() < 0) 516 fatal("event_dispatch"); 517 lka_shutdown(); 518 519 return (0); 520 } 521 522 static int 523 lka_authenticate(const char *tablename, const char *user, const char *password) 524 { 525 struct table *table; 526 char *cpass; 527 union lookup lk; 528 529 log_debug("debug: lka: authenticating for %s:%s", tablename, user); 530 table = table_find(tablename, NULL); 531 if (table == NULL) { 532 log_warnx("warn: could not find table %s needed for authentication", 533 tablename); 534 return (LKA_TEMPFAIL); 535 } 536 537 switch (table_lookup(table, NULL, user, K_CREDENTIALS, &lk)) { 538 case -1: 539 log_warnx("warn: user credentials lookup fail for %s:%s", 540 tablename, user); 541 return (LKA_TEMPFAIL); 542 case 0: 543 return (LKA_PERMFAIL); 544 default: 545 cpass = crypt(password, lk.creds.password); 546 if (cpass == NULL) 547 return (LKA_PERMFAIL); 548 if (!strcmp(lk.creds.password, cpass)) 549 return (LKA_OK); 550 return (LKA_PERMFAIL); 551 } 552 } 553 554 static int 555 lka_credentials(const char *tablename, const char *label, char *dst, size_t sz) 556 { 557 struct table *table; 558 union lookup lk; 559 char *buf; 560 int buflen, r; 561 562 table = table_find(tablename, NULL); 563 if (table == NULL) { 564 log_warnx("warn: credentials table %s missing", tablename); 565 return (LKA_TEMPFAIL); 566 } 567 568 dst[0] = '\0'; 569 570 switch(table_lookup(table, NULL, label, K_CREDENTIALS, &lk)) { 571 case -1: 572 log_warnx("warn: credentials lookup fail for %s:%s", 573 tablename, label); 574 return (LKA_TEMPFAIL); 575 case 0: 576 log_warnx("warn: credentials not found for %s:%s", 577 tablename, label); 578 return (LKA_PERMFAIL); 579 default: 580 if ((buflen = asprintf(&buf, "%c%s%c%s", '\0', 581 lk.creds.username, '\0', lk.creds.password)) == -1) { 582 log_warn("warn"); 583 return (LKA_TEMPFAIL); 584 } 585 586 r = base64_encode((unsigned char *)buf, buflen, dst, sz); 587 free(buf); 588 589 if (r == -1) { 590 log_warnx("warn: credentials parse error for %s:%s", 591 tablename, label); 592 return (LKA_TEMPFAIL); 593 } 594 return (LKA_OK); 595 } 596 } 597 598 static int 599 lka_userinfo(const char *tablename, const char *username, struct userinfo *res) 600 { 601 struct table *table; 602 union lookup lk; 603 604 log_debug("debug: lka: userinfo %s:%s", tablename, username); 605 table = table_find(tablename, NULL); 606 if (table == NULL) { 607 log_warnx("warn: cannot find user table %s", tablename); 608 return (LKA_TEMPFAIL); 609 } 610 611 switch (table_lookup(table, NULL, username, K_USERINFO, &lk)) { 612 case -1: 613 log_warnx("warn: failure during userinfo lookup %s:%s", 614 tablename, username); 615 return (LKA_TEMPFAIL); 616 case 0: 617 return (LKA_PERMFAIL); 618 default: 619 *res = lk.userinfo; 620 return (LKA_OK); 621 } 622 } 623 624 static int 625 lka_addrname(const char *tablename, const struct sockaddr *sa, 626 struct addrname *res) 627 { 628 struct table *table; 629 union lookup lk; 630 const char *source; 631 632 source = sa_to_text(sa); 633 634 log_debug("debug: lka: helo %s:%s", tablename, source); 635 table = table_find(tablename, NULL); 636 if (table == NULL) { 637 log_warnx("warn: cannot find helo table %s", tablename); 638 return (LKA_TEMPFAIL); 639 } 640 641 switch (table_lookup(table, NULL, source, K_ADDRNAME, &lk)) { 642 case -1: 643 log_warnx("warn: failure during helo lookup %s:%s", 644 tablename, source); 645 return (LKA_TEMPFAIL); 646 case 0: 647 return (LKA_PERMFAIL); 648 default: 649 *res = lk.addrname; 650 return (LKA_OK); 651 } 652 } 653 654 static int 655 lka_X509_verify(struct ca_vrfy_req_msg *vrfy, 656 const char *CAfile, const char *CRLfile) 657 { 658 X509 *x509; 659 X509 *x509_tmp; 660 STACK_OF(X509) *x509_chain; 661 const unsigned char *d2i; 662 size_t i; 663 int ret = 0; 664 const char *errstr; 665 666 x509 = NULL; 667 x509_tmp = NULL; 668 x509_chain = NULL; 669 670 d2i = vrfy->cert; 671 if (d2i_X509(&x509, &d2i, vrfy->cert_len) == NULL) { 672 x509 = NULL; 673 goto end; 674 } 675 676 if (vrfy->n_chain) { 677 x509_chain = sk_X509_new_null(); 678 for (i = 0; i < vrfy->n_chain; ++i) { 679 d2i = vrfy->chain_cert[i]; 680 if (d2i_X509(&x509_tmp, &d2i, vrfy->chain_cert_len[i]) == NULL) 681 goto end; 682 sk_X509_insert(x509_chain, x509_tmp, i); 683 x509_tmp = NULL; 684 } 685 } 686 if (! ca_X509_verify(x509, x509_chain, CAfile, NULL, &errstr)) 687 log_debug("debug: lka: X509 verify: %s", errstr); 688 else 689 ret = 1; 690 691 end: 692 if (x509) 693 X509_free(x509); 694 if (x509_tmp) 695 X509_free(x509_tmp); 696 if (x509_chain) 697 sk_X509_pop_free(x509_chain, X509_free); 698 699 return ret; 700 } 701