diff options
Diffstat (limited to 'smtpd/lka.c')
-rw-r--r-- | smtpd/lka.c | 489 |
1 files changed, 234 insertions, 255 deletions
diff --git a/smtpd/lka.c b/smtpd/lka.c index 22d186d6..210d41a7 100644 --- a/smtpd/lka.c +++ b/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.199 2017/05/17 14:00:06 deraadt Exp $ */ +/* $OpenBSD: lka.c,v 1.202 2018/01/03 11:12:21 sunil Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -86,294 +86,277 @@ lka_imsg(struct mproc *p, struct imsg *imsg) if (imsg == NULL) lka_shutdown(); - if (imsg->hdr.type == IMSG_MTA_DNS_HOST || - imsg->hdr.type == IMSG_MTA_DNS_PTR || - imsg->hdr.type == IMSG_SMTP_DNS_PTR || - imsg->hdr.type == IMSG_MTA_DNS_MX || - imsg->hdr.type == IMSG_MTA_DNS_MX_PREFERENCE) { + switch (imsg->hdr.type) { + + case IMSG_MTA_DNS_HOST: + case IMSG_MTA_DNS_PTR: + case IMSG_SMTP_DNS_PTR: + case IMSG_MTA_DNS_MX: + case IMSG_MTA_DNS_MX_PREFERENCE: dns_imsg(p, imsg); return; - } - if (p->proc == PROC_PONY) { - switch (imsg->hdr.type) { - case IMSG_SMTP_CHECK_SENDER: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_string(&m, &tablename); - m_get_string(&m, &username); - m_get_mailaddr(&m, &maddr); - m_end(&m); - - ret = lka_mailaddrmap(tablename, username, &maddr); - - m_create(p, IMSG_SMTP_CHECK_SENDER, 0, 0, -1); - m_add_id(p, reqid); - m_add_int(p, ret); - m_close(p); - return; + case IMSG_SMTP_CHECK_SENDER: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_string(&m, &tablename); + m_get_string(&m, &username); + m_get_mailaddr(&m, &maddr); + m_end(&m); - case IMSG_SMTP_EXPAND_RCPT: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_envelope(&m, &evp); - m_end(&m); - lka_session(reqid, &evp); - return; + ret = lka_mailaddrmap(tablename, username, &maddr); - case IMSG_SMTP_LOOKUP_HELO: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_string(&m, &tablename); - m_get_sockaddr(&m, (struct sockaddr *)&ss); - m_end(&m); - - ret = lka_addrname(tablename, (struct sockaddr*)&ss, - &addrname); - - m_create(p, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1); - m_add_id(p, reqid); - m_add_int(p, ret); - if (ret == LKA_OK) - m_add_string(p, addrname.name); - m_close(p); - return; + m_create(p, IMSG_SMTP_CHECK_SENDER, 0, 0, -1); + m_add_id(p, reqid); + m_add_int(p, ret); + m_close(p); + return; - case IMSG_SMTP_TLS_INIT: - case IMSG_MTA_TLS_INIT: - req_ca_cert = imsg->data; - resp_ca_cert.reqid = req_ca_cert->reqid; - - xlowercase(buf, req_ca_cert->name, sizeof(buf)); - log_debug("debug: lka: looking up pki \"%s\"", buf); - pki = dict_get(env->sc_pki_dict, buf); - if (pki == NULL) - if (req_ca_cert->fallback) - pki = dict_get(env->sc_pki_dict, "*"); - if (pki == NULL) { - resp_ca_cert.status = CA_FAIL; - m_compose(p, imsg->hdr.type, 0, 0, -1, &resp_ca_cert, - sizeof(resp_ca_cert)); - return; - } - resp_ca_cert.status = CA_OK; - resp_ca_cert.cert_len = pki->pki_cert_len; - (void)strlcpy(resp_ca_cert.name, pki->pki_name, sizeof resp_ca_cert.name); - iov[0].iov_base = &resp_ca_cert; - iov[0].iov_len = sizeof(resp_ca_cert); - iov[1].iov_base = pki->pki_cert; - iov[1].iov_len = pki->pki_cert_len; - m_composev(p, imsg->hdr.type, 0, 0, -1, iov, nitems(iov)); - return; + case IMSG_SMTP_EXPAND_RCPT: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_envelope(&m, &evp); + m_end(&m); + lka_session(reqid, &evp); + return; - case IMSG_SMTP_TLS_VERIFY_CERT: - case IMSG_MTA_TLS_VERIFY_CERT: - req_ca_vrfy = xmemdup(imsg->data, sizeof *req_ca_vrfy, "lka:ca_vrfy"); - req_ca_vrfy->cert = xmemdup((char *)imsg->data + - sizeof *req_ca_vrfy, req_ca_vrfy->cert_len, "lka:ca_vrfy"); - req_ca_vrfy->chain_cert = xcalloc(req_ca_vrfy->n_chain, - sizeof (unsigned char *), "lka:ca_vrfy"); - req_ca_vrfy->chain_cert_len = xcalloc(req_ca_vrfy->n_chain, - sizeof (off_t), "lka:ca_vrfy"); - return; + case IMSG_SMTP_LOOKUP_HELO: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_string(&m, &tablename); + m_get_sockaddr(&m, (struct sockaddr *)&ss); + m_end(&m); + + ret = lka_addrname(tablename, (struct sockaddr*)&ss, + &addrname); + + m_create(p, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1); + m_add_id(p, reqid); + m_add_int(p, ret); + if (ret == LKA_OK) + m_add_string(p, addrname.name); + m_close(p); + return; - case IMSG_SMTP_TLS_VERIFY_CHAIN: - case IMSG_MTA_TLS_VERIFY_CHAIN: - if (req_ca_vrfy == NULL) - fatalx("lka:ca_vrfy: chain without a certificate"); - req_ca_vrfy_chain = imsg->data; - req_ca_vrfy->chain_cert[req_ca_vrfy->chain_offset] = xmemdup((char *)imsg->data + - sizeof *req_ca_vrfy_chain, req_ca_vrfy_chain->cert_len, "lka:ca_vrfy"); - req_ca_vrfy->chain_cert_len[req_ca_vrfy->chain_offset] = req_ca_vrfy_chain->cert_len; - req_ca_vrfy->chain_offset++; + case IMSG_SMTP_TLS_INIT: + case IMSG_MTA_TLS_INIT: + req_ca_cert = imsg->data; + resp_ca_cert.reqid = req_ca_cert->reqid; + + xlowercase(buf, req_ca_cert->name, sizeof(buf)); + log_debug("debug: lka: looking up pki \"%s\"", buf); + pki = dict_get(env->sc_pki_dict, buf); + if (pki == NULL) + if (req_ca_cert->fallback) + pki = dict_get(env->sc_pki_dict, "*"); + if (pki == NULL) { + resp_ca_cert.status = CA_FAIL; + m_compose(p, imsg->hdr.type, 0, 0, -1, &resp_ca_cert, + sizeof(resp_ca_cert)); return; + } + resp_ca_cert.status = CA_OK; + resp_ca_cert.cert_len = pki->pki_cert_len; + (void)strlcpy(resp_ca_cert.name, pki->pki_name, sizeof resp_ca_cert.name); + iov[0].iov_base = &resp_ca_cert; + iov[0].iov_len = sizeof(resp_ca_cert); + iov[1].iov_base = pki->pki_cert; + iov[1].iov_len = pki->pki_cert_len; + m_composev(p, imsg->hdr.type, 0, 0, -1, iov, nitems(iov)); + return; - case IMSG_SMTP_TLS_VERIFY: - case IMSG_MTA_TLS_VERIFY: - if (req_ca_vrfy == NULL) - fatalx("lka:ca_vrfy: verify without a certificate"); - lka_certificate_verify(imsg->hdr.type, req_ca_vrfy); - req_ca_vrfy = NULL; - return; + case IMSG_SMTP_TLS_VERIFY_CERT: + case IMSG_MTA_TLS_VERIFY_CERT: + req_ca_vrfy = xmemdup(imsg->data, sizeof *req_ca_vrfy, "lka:ca_vrfy"); + req_ca_vrfy->cert = xmemdup((char *)imsg->data + + sizeof *req_ca_vrfy, req_ca_vrfy->cert_len, "lka:ca_vrfy"); + req_ca_vrfy->chain_cert = xcalloc(req_ca_vrfy->n_chain, + sizeof (unsigned char *), "lka:ca_vrfy"); + req_ca_vrfy->chain_cert_len = xcalloc(req_ca_vrfy->n_chain, + sizeof (off_t), "lka:ca_vrfy"); + return; - case IMSG_SMTP_AUTHENTICATE: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_string(&m, &tablename); - m_get_string(&m, &username); - m_get_string(&m, &password); - m_end(&m); - - if (!tablename[0]) { - m_create(p_parent, IMSG_LKA_AUTHENTICATE, - 0, 0, -1); - m_add_id(p_parent, reqid); - m_add_string(p_parent, username); - m_add_string(p_parent, password); - m_close(p_parent); - return; - } + case IMSG_SMTP_TLS_VERIFY_CHAIN: + case IMSG_MTA_TLS_VERIFY_CHAIN: + if (req_ca_vrfy == NULL) + fatalx("lka:ca_vrfy: chain without a certificate"); + req_ca_vrfy_chain = imsg->data; + req_ca_vrfy->chain_cert[req_ca_vrfy->chain_offset] = xmemdup((char *)imsg->data + + sizeof *req_ca_vrfy_chain, req_ca_vrfy_chain->cert_len, "lka:ca_vrfy"); + req_ca_vrfy->chain_cert_len[req_ca_vrfy->chain_offset] = req_ca_vrfy_chain->cert_len; + req_ca_vrfy->chain_offset++; + return; - ret = lka_authenticate(tablename, username, password); + case IMSG_SMTP_TLS_VERIFY: + case IMSG_MTA_TLS_VERIFY: + if (req_ca_vrfy == NULL) + fatalx("lka:ca_vrfy: verify without a certificate"); + lka_certificate_verify(imsg->hdr.type, req_ca_vrfy); + req_ca_vrfy = NULL; + return; - m_create(p, IMSG_SMTP_AUTHENTICATE, 0, 0, -1); - m_add_id(p, reqid); - m_add_int(p, ret); - m_close(p); + case IMSG_SMTP_AUTHENTICATE: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_string(&m, &tablename); + m_get_string(&m, &username); + m_get_string(&m, &password); + m_end(&m); + + if (!tablename[0]) { + m_create(p_parent, IMSG_LKA_AUTHENTICATE, + 0, 0, -1); + m_add_id(p_parent, reqid); + m_add_string(p_parent, username); + m_add_string(p_parent, password); + m_close(p_parent); return; } - } - if (p->proc == PROC_PONY) { - switch (imsg->hdr.type) { - case IMSG_MDA_LOOKUP_USERINFO: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_string(&m, &tablename); - m_get_string(&m, &username); - m_end(&m); - - ret = lka_userinfo(tablename, username, &userinfo); - - m_create(p, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1); - m_add_id(p, reqid); - m_add_int(p, ret); - if (ret == LKA_OK) - m_add_data(p, &userinfo, sizeof(userinfo)); - m_close(p); - return; - } - } + ret = lka_authenticate(tablename, username, password); + + m_create(p, IMSG_SMTP_AUTHENTICATE, 0, 0, -1); + m_add_id(p, reqid); + m_add_int(p, ret); + m_close(p); + return; - if (p->proc == PROC_PONY) { - switch (imsg->hdr.type) { + case IMSG_MDA_LOOKUP_USERINFO: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_string(&m, &tablename); + m_get_string(&m, &username); + m_end(&m); + + ret = lka_userinfo(tablename, username, &userinfo); + + m_create(p, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1); + m_add_id(p, reqid); + m_add_int(p, ret); + if (ret == LKA_OK) + m_add_data(p, &userinfo, sizeof(userinfo)); + m_close(p); + return; - case IMSG_MTA_LOOKUP_CREDENTIALS: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_string(&m, &tablename); - m_get_string(&m, &label); - m_end(&m); + case IMSG_MTA_LOOKUP_CREDENTIALS: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_string(&m, &tablename); + m_get_string(&m, &label); + m_end(&m); - lka_credentials(tablename, label, buf, sizeof(buf)); + lka_credentials(tablename, label, buf, sizeof(buf)); - m_create(p, IMSG_MTA_LOOKUP_CREDENTIALS, 0, 0, -1); - m_add_id(p, reqid); - m_add_string(p, buf); - m_close(p); - return; + m_create(p, IMSG_MTA_LOOKUP_CREDENTIALS, 0, 0, -1); + m_add_id(p, reqid); + m_add_string(p, buf); + m_close(p); + return; - case IMSG_MTA_LOOKUP_SOURCE: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_string(&m, &tablename); - m_end(&m); + case IMSG_MTA_LOOKUP_SOURCE: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_string(&m, &tablename); + m_end(&m); - table = table_find(tablename, NULL); + table = table_find(tablename, NULL); - m_create(p, IMSG_MTA_LOOKUP_SOURCE, 0, 0, -1); - m_add_id(p, reqid); + m_create(p, IMSG_MTA_LOOKUP_SOURCE, 0, 0, -1); + m_add_id(p, reqid); - if (table == NULL) { - log_warn("warn: source address table %s missing", - tablename); + if (table == NULL) { + log_warn("warn: source address table %s missing", + tablename); + m_add_int(p, LKA_TEMPFAIL); + } + else { + ret = table_fetch(table, NULL, K_SOURCE, &lk); + if (ret == -1) m_add_int(p, LKA_TEMPFAIL); - } + else if (ret == 0) + m_add_int(p, LKA_PERMFAIL); else { - ret = table_fetch(table, NULL, K_SOURCE, &lk); - if (ret == -1) - m_add_int(p, LKA_TEMPFAIL); - else if (ret == 0) - m_add_int(p, LKA_PERMFAIL); - else { - m_add_int(p, LKA_OK); - m_add_sockaddr(p, - (struct sockaddr *)&lk.source.addr); - } + m_add_int(p, LKA_OK); + m_add_sockaddr(p, + (struct sockaddr *)&lk.source.addr); } - m_close(p); - return; - - case IMSG_MTA_LOOKUP_HELO: - m_msg(&m, imsg); - m_get_id(&m, &reqid); - m_get_string(&m, &tablename); - m_get_sockaddr(&m, (struct sockaddr *)&ss); - m_end(&m); - - ret = lka_addrname(tablename, (struct sockaddr*)&ss, - &addrname); - - m_create(p, IMSG_MTA_LOOKUP_HELO, 0, 0, -1); - m_add_id(p, reqid); - m_add_int(p, ret); - if (ret == LKA_OK) - m_add_string(p, addrname.name); - m_close(p); - return; - } - } + m_close(p); + return; - if (p->proc == PROC_PARENT) { - switch (imsg->hdr.type) { - case IMSG_CONF_START: - return; + case IMSG_MTA_LOOKUP_HELO: + m_msg(&m, imsg); + m_get_id(&m, &reqid); + m_get_string(&m, &tablename); + m_get_sockaddr(&m, (struct sockaddr *)&ss); + m_end(&m); + + ret = lka_addrname(tablename, (struct sockaddr*)&ss, + &addrname); + + m_create(p, IMSG_MTA_LOOKUP_HELO, 0, 0, -1); + m_add_id(p, reqid); + m_add_int(p, ret); + if (ret == LKA_OK) + m_add_string(p, addrname.name); + m_close(p); + return; - case IMSG_CONF_END: - if (tracing & TRACE_TABLES) - table_dump_all(); + case IMSG_CONF_START: + return; - /* fork & exec tables that need it */ - table_open_all(); + case IMSG_CONF_END: + if (tracing & TRACE_TABLES) + table_dump_all(); - /* revoke proc & exec */ - if (pledge("stdio rpath inet dns getpw recvfd", - NULL) == -1) - err(1, "pledge"); + /* fork & exec tables that need it */ + table_open_all(); - /* Start fulfilling requests */ - mproc_enable(p_pony); - return; + /* revoke proc & exec */ + if (pledge("stdio rpath inet dns getpw recvfd", + NULL) == -1) + err(1, "pledge"); - case IMSG_LKA_OPEN_FORWARD: - lka_session_forward_reply(imsg->data, imsg->fd); - return; + /* Start fulfilling requests */ + mproc_enable(p_pony); + return; - case IMSG_LKA_AUTHENTICATE: - imsg->hdr.type = IMSG_SMTP_AUTHENTICATE; - m_forward(p_pony, imsg); - return; - } - } + case IMSG_LKA_OPEN_FORWARD: + lka_session_forward_reply(imsg->data, imsg->fd); + return; - if (p->proc == PROC_CONTROL) { - switch (imsg->hdr.type) { + case IMSG_LKA_AUTHENTICATE: + imsg->hdr.type = IMSG_SMTP_AUTHENTICATE; + m_forward(p_pony, imsg); + return; - case IMSG_CTL_VERBOSE: - m_msg(&m, imsg); - m_get_int(&m, &v); - m_end(&m); - log_trace_verbose(v); - return; + case IMSG_CTL_VERBOSE: + m_msg(&m, imsg); + m_get_int(&m, &v); + m_end(&m); + log_trace_verbose(v); + return; - case IMSG_CTL_PROFILE: - m_msg(&m, imsg); - m_get_int(&m, &v); - m_end(&m); - profiling = v; - return; + case IMSG_CTL_PROFILE: + m_msg(&m, imsg); + m_get_int(&m, &v); + m_end(&m); + profiling = v; + return; - case IMSG_CTL_UPDATE_TABLE: - table = table_find(imsg->data, NULL); - if (table == NULL) { - log_warnx("warn: Lookup table not found: " - "\"%s\"", (char *)imsg->data); - return; - } - table_update(table); - return; - } + case IMSG_CTL_UPDATE_TABLE: + ret = 0; + table = table_find(imsg->data, NULL); + if (table == NULL) { + log_warnx("warn: Lookup table not found: " + "\"%s\"", (char *)imsg->data); + } else + ret = table_update(table); + + m_compose(p_control, + (ret == 1) ? IMSG_CTL_OK : IMSG_CTL_FAIL, + imsg->hdr.peerid, 0, -1, NULL, 0); + return; } errx(1, "lka_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); @@ -453,7 +436,6 @@ static int lka_authenticate(const char *tablename, const char *user, const char *password) { struct table *table; - char *cpass; union lookup lk; log_debug("debug: lka: authenticating for %s:%s", tablename, user); @@ -472,10 +454,7 @@ lka_authenticate(const char *tablename, const char *user, const char *password) case 0: return (LKA_PERMFAIL); default: - cpass = crypt(password, lk.creds.password); - if (cpass == NULL) - return (LKA_PERMFAIL); - if (!strcmp(lk.creds.password, cpass)) + if (crypt_checkpass(password, lk.creds.password) == 0) return (LKA_OK); return (LKA_PERMFAIL); } |