diff options
author | 2015-11-30 19:54:25 +0000 | |
---|---|---|
committer | 2015-11-30 19:54:25 +0000 | |
commit | f3100b90685ee81355453a29e3cfd732f4ad706b (patch) | |
tree | ad87c4a56c59482b7b441ebb1e6a00a1ef8f1220 | |
parent | Revert the sync -> fsync conversion (at least for the time being) - there (diff) | |
download | wireguard-openbsd-f3100b90685ee81355453a29e3cfd732f4ad706b.tar.xz wireguard-openbsd-f3100b90685ee81355453a29e3cfd732f4ad706b.zip |
remove table-passwd, table-sqlite, and table-ldap
about 4k lines seldom used code
people who rely on this install mail/opensmtpd-extras
direction discussed (and agreed) with many
ok gilles
-rw-r--r-- | usr.sbin/smtpd/Makefile | 6 | ||||
-rw-r--r-- | usr.sbin/smtpd/aldap.c | 1276 | ||||
-rw-r--r-- | usr.sbin/smtpd/aldap.h | 218 | ||||
-rw-r--r-- | usr.sbin/smtpd/ber.c | 1269 | ||||
-rw-r--r-- | usr.sbin/smtpd/ber.h | 128 | ||||
-rw-r--r-- | usr.sbin/smtpd/table-ldap/Makefile | 30 | ||||
-rw-r--r-- | usr.sbin/smtpd/table-passwd/Makefile | 28 | ||||
-rw-r--r-- | usr.sbin/smtpd/table-sqlite/Makefile | 28 | ||||
-rw-r--r-- | usr.sbin/smtpd/table_ldap.c | 569 | ||||
-rw-r--r-- | usr.sbin/smtpd/table_passwd.5 | 64 | ||||
-rw-r--r-- | usr.sbin/smtpd/table_passwd.c | 267 | ||||
-rw-r--r-- | usr.sbin/smtpd/table_sqlite.c | 523 |
12 files changed, 1 insertions, 4405 deletions
diff --git a/usr.sbin/smtpd/Makefile b/usr.sbin/smtpd/Makefile index 660ecddd536..eb429a6bb1f 100644 --- a/usr.sbin/smtpd/Makefile +++ b/usr.sbin/smtpd/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.13 2015/11/23 13:16:48 gilles Exp $ +# $OpenBSD: Makefile,v 1.14 2015/11/30 19:54:25 jung Exp $ .include <bsd.own.mk> @@ -6,8 +6,4 @@ SUBDIR = smtpd SUBDIR+= smtpctl SUBDIR+= makemap -SUBDIR+= table-ldap -SUBDIR+= table-passwd -SUBDIR+= table-sqlite - .include <bsd.subdir.mk> diff --git a/usr.sbin/smtpd/aldap.c b/usr.sbin/smtpd/aldap.c deleted file mode 100644 index 796b36107e2..00000000000 --- a/usr.sbin/smtpd/aldap.c +++ /dev/null @@ -1,1276 +0,0 @@ -/* $OpenBSD: aldap.c,v 1.8 2015/11/05 12:35:58 jung Exp $ */ - -/* - * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> - * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <errno.h> -#include <inttypes.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> - -#include "aldap.h" - -#if 0 -#define DEBUG -#endif -#define ALDAP_VERSION 3 - -static struct ber_element *ldap_parse_search_filter(struct ber_element *, - char *); -static struct ber_element *ldap_do_parse_search_filter( - struct ber_element *, char **); -char **aldap_get_stringset(struct ber_element *); -char *utoa(char *); -char *parseval(char *, size_t); -int aldap_create_page_control(struct ber_element *, - int, struct aldap_page_control *); - -#ifdef DEBUG -void ldap_debug_elements(struct ber_element *); -#endif - -#ifdef DEBUG -#define DPRINTF(x...) printf(x) -#define LDAP_DEBUG(x, y) do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0) -#else -#define DPRINTF(x...) do { } while (0) -#define LDAP_DEBUG(x, y) do { } while (0) -#endif - -int -aldap_close(struct aldap *al) -{ - if (close(al->ber.fd) == -1) - return (-1); - - ber_free(&al->ber); - free(al); - - return (0); -} - -struct aldap * -aldap_init(int fd) -{ - struct aldap *a; - - if ((a = calloc(1, sizeof(*a))) == NULL) - return NULL; - a->ber.fd = fd; - - return a; -} - -int -aldap_bind(struct aldap *ldap, char *binddn, char *bindcred) -{ - struct ber_element *root = NULL, *elm; - int error; - - if (binddn == NULL) - binddn = ""; - if (bindcred == NULL) - bindcred = ""; - - if ((root = ber_add_sequence(NULL)) == NULL) - goto fail; - - elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP, - (unsigned long)LDAP_REQ_BIND, ALDAP_VERSION, binddn, bindcred, - BER_CLASS_CONTEXT, (unsigned long)LDAP_AUTH_SIMPLE); - if (elm == NULL) - goto fail; - - LDAP_DEBUG("aldap_bind", root); - - error = ber_write_elements(&ldap->ber, root); - ber_free_elements(root); - root = NULL; - if (error == -1) - goto fail; - - return (ldap->msgid); -fail: - if (root != NULL) - ber_free_elements(root); - - ldap->err = ALDAP_ERR_OPERATION_FAILED; - return (-1); -} - -int -aldap_unbind(struct aldap *ldap) -{ - struct ber_element *root = NULL, *elm; - int error; - - if ((root = ber_add_sequence(NULL)) == NULL) - goto fail; - elm = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP, - LDAP_REQ_UNBIND_30); - if (elm == NULL) - goto fail; - - LDAP_DEBUG("aldap_unbind", root); - - error = ber_write_elements(&ldap->ber, root); - ber_free_elements(root); - root = NULL; - if (error == -1) - goto fail; - - return (ldap->msgid); -fail: - if (root != NULL) - ber_free_elements(root); - - ldap->err = ALDAP_ERR_OPERATION_FAILED; - - return (-1); -} - -int -aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, - char **attrs, int typesonly, int sizelimit, int timelimit, - struct aldap_page_control *page) -{ - struct ber_element *root = NULL, *ber, *c; - int i, error; - - if ((root = ber_add_sequence(NULL)) == NULL) - goto fail; - - ber = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP, - (unsigned long) LDAP_REQ_SEARCH); - if (ber == NULL) { - ldap->err = ALDAP_ERR_OPERATION_FAILED; - goto fail; - } - - c = ber; - ber = ber_printf_elements(ber, "sEEddb", basedn, (long long)scope, - (long long)LDAP_DEREF_NEVER, sizelimit, - timelimit, typesonly); - if (ber == NULL) { - ldap->err = ALDAP_ERR_OPERATION_FAILED; - goto fail; - } - - if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) { - ldap->err = ALDAP_ERR_PARSER_ERROR; - goto fail; - } - - if ((ber = ber_add_sequence(ber)) == NULL) - goto fail; - if (attrs != NULL) - for (i = 0; attrs[i] != NULL; i++) { - if ((ber = ber_add_string(ber, attrs[i])) == NULL) - goto fail; - } - - aldap_create_page_control(c, 100, page); - - LDAP_DEBUG("aldap_search", root); - - error = ber_write_elements(&ldap->ber, root); - ber_free_elements(root); - root = NULL; - if (error == -1) { - ldap->err = ALDAP_ERR_OPERATION_FAILED; - goto fail; - } - - return (ldap->msgid); - -fail: - if (root != NULL) - ber_free_elements(root); - - return (-1); -} - -int -aldap_create_page_control(struct ber_element *elm, int size, - struct aldap_page_control *page) -{ - int len; - struct ber c; - struct ber_element *ber = NULL; - - c.br_wbuf = NULL; - c.fd = -1; - - ber = ber_add_sequence(NULL); - - if (page == NULL) { - if (ber_printf_elements(ber, "ds", 50, "") == NULL) - goto fail; - } else { - if (ber_printf_elements(ber, "dx", 50, page->cookie, - page->cookie_len) == NULL) - goto fail; - } - - if ((len = ber_write_elements(&c, ber)) < 1) - goto fail; - if (ber_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID, - c.br_wbuf, (size_t)len) == NULL) - goto fail; - - ber_free_elements(ber); - ber_free(&c); - return len; -fail: - if (ber != NULL) - ber_free_elements(ber); - ber_free(&c); - - return (-1); -} - -struct aldap_message * -aldap_parse(struct aldap *ldap) -{ - int class; - unsigned long type; - long long msgid = 0; - struct aldap_message *m; - struct ber_element *a = NULL, *ep; - - if ((m = calloc(1, sizeof(struct aldap_message))) == NULL) - return NULL; - - if ((m->msg = ber_read_elements(&ldap->ber, NULL)) == NULL) - goto parsefail; - - LDAP_DEBUG("message", m->msg); - - if (ber_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0) - goto parsefail; - m->msgid = msgid; - m->message_type = type; - m->protocol_op = a; - - switch (m->message_type) { - case LDAP_RES_BIND: - case LDAP_RES_MODIFY: - case LDAP_RES_ADD: - case LDAP_RES_DELETE: - case LDAP_RES_MODRDN: - case LDAP_RES_COMPARE: - case LDAP_RES_SEARCH_RESULT: - if (ber_scanf_elements(m->protocol_op, "{EeSeSe", - &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0) - goto parsefail; - if (m->body.res.rescode == LDAP_REFERRAL) - if (ber_scanf_elements(a, "{e", &m->references) != 0) - goto parsefail; - if (m->msg->be_sub) { - for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) { - ber_scanf_elements(ep, "t", &class, &type); - if (class == 2 && type == 0) - m->page = aldap_parse_page_control(ep->be_sub->be_sub, - ep->be_sub->be_sub->be_len); - } - } else - m->page = NULL; - break; - case LDAP_RES_SEARCH_ENTRY: - if (ber_scanf_elements(m->protocol_op, "{eS{e", &m->dn, - &m->body.search.attrs) != 0) - goto parsefail; - break; - case LDAP_RES_SEARCH_REFERENCE: - if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0) - goto parsefail; - break; - } - - return m; -parsefail: - ldap->err = ALDAP_ERR_PARSER_ERROR; - aldap_freemsg(m); - return NULL; -} - -struct aldap_page_control * -aldap_parse_page_control(struct ber_element *control, size_t len) -{ - char *oid, *s; - char *encoded; - struct ber b; - struct ber_element *elm; - struct aldap_page_control *page; - - b.br_wbuf = NULL; - b.fd = -1; - ber_scanf_elements(control, "ss", &oid, &encoded); - ber_set_readbuf(&b, encoded, control->be_next->be_len); - elm = ber_read_elements(&b, NULL); - if (elm == NULL) { - ber_free(&b); - return NULL; - } - - if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) { - ber_free_elements(elm); - ber_free(&b); - return NULL; - } - - ber_scanf_elements(elm->be_sub, "is", &page->size, &s); - page->cookie_len = elm->be_sub->be_next->be_len; - - if ((page->cookie = malloc(page->cookie_len)) == NULL) { - ber_free_elements(elm); - ber_free(&b); - free(page); - return NULL; - } - memcpy(page->cookie, s, page->cookie_len); - - ber_free_elements(elm); - ber_free(&b); - return page; -} - -void -aldap_freepage(struct aldap_page_control *page) -{ - if (page->cookie) - free(page->cookie); - free(page); -} - -void -aldap_freemsg(struct aldap_message *msg) -{ - if (msg->msg) - ber_free_elements(msg->msg); - free(msg); -} - -int -aldap_get_resultcode(struct aldap_message *msg) -{ - return msg->body.res.rescode; -} - -char * -aldap_get_dn(struct aldap_message *msg) -{ - char *dn; - - if (msg->dn == NULL) - return NULL; - - if (ber_get_string(msg->dn, &dn) == -1) - return NULL; - - return utoa(dn); -} - -char ** -aldap_get_references(struct aldap_message *msg) -{ - if (msg->references == NULL) - return NULL; - return aldap_get_stringset(msg->references); -} - -void -aldap_free_references(char **values) -{ - int i; - - if (values == NULL) - return; - - for (i = 0; values[i] != NULL; i++) - free(values[i]); - - free(values); -} - -char * -aldap_get_diagmsg(struct aldap_message *msg) -{ - char *s; - - if (msg->body.res.diagmsg == NULL) - return NULL; - - if (ber_get_string(msg->body.res.diagmsg, &s) == -1) - return NULL; - - return utoa(s); -} - -int -aldap_count_attrs(struct aldap_message *msg) -{ - int i; - struct ber_element *a; - - if (msg->body.search.attrs == NULL) - return (-1); - - for (i = 0, a = msg->body.search.attrs; - a != NULL && ber_get_eoc(a) != 0; - i++, a = a->be_next) - ; - - return i; -} - -int -aldap_first_attr(struct aldap_message *msg, char **outkey, char ***outvalues) -{ - struct ber_element *b, *c; - char *key; - char **ret; - - if (msg->body.search.attrs == NULL) - goto fail; - - if (ber_scanf_elements(msg->body.search.attrs, "{s(e)}e", - &key, &b, &c) != 0) - goto fail; - - msg->body.search.iter = msg->body.search.attrs->be_next; - - if ((ret = aldap_get_stringset(b)) == NULL) - goto fail; - - (*outvalues) = ret; - (*outkey) = utoa(key); - - return (1); -fail: - (*outkey) = NULL; - (*outvalues) = NULL; - return (-1); -} - -int -aldap_next_attr(struct aldap_message *msg, char **outkey, char ***outvalues) -{ - struct ber_element *a, *b; - char *key; - char **ret; - - if (msg->body.search.iter == NULL) - goto notfound; - - LDAP_DEBUG("attr", msg->body.search.iter); - - if (ber_get_eoc(msg->body.search.iter) == 0) - goto notfound; - - if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b) - != 0) - goto fail; - - msg->body.search.iter = msg->body.search.iter->be_next; - - if ((ret = aldap_get_stringset(a)) == NULL) - goto fail; - - (*outvalues) = ret; - (*outkey) = utoa(key); - - return (1); -fail: -notfound: - (*outkey) = NULL; - (*outvalues) = NULL; - return (-1); -} - -int -aldap_match_attr(struct aldap_message *msg, char *inkey, char ***outvalues) -{ - struct ber_element *a, *b; - char *descr = NULL; - char **ret; - - if (msg->body.search.attrs == NULL) - goto fail; - - LDAP_DEBUG("attr", msg->body.search.attrs); - - for (a = msg->body.search.attrs;;) { - if (a == NULL) - goto notfound; - if (ber_get_eoc(a) == 0) - goto notfound; - if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0) - goto fail; - if (strcasecmp(descr, inkey) == 0) - goto attrfound; - a = a->be_next; - } - -attrfound: - if ((ret = aldap_get_stringset(b)) == NULL) - goto fail; - - (*outvalues) = ret; - - return (1); -fail: -notfound: - (*outvalues) = NULL; - return (-1); -} - -int -aldap_free_attr(char **values) -{ - int i; - - if (values == NULL) - return -1; - - for (i = 0; values[i] != NULL; i++) - free(values[i]); - - free(values); - - return (1); -} - -void -aldap_free_url(struct aldap_url *lu) -{ - free(lu->buffer); - free(lu->filter); -} - -int -aldap_parse_url(char *url, struct aldap_url *lu) -{ - char *p, *forward, *forward2; - const char *errstr = NULL; - int i; - - if ((lu->buffer = strdup(url)) == NULL) - return (-1); - p = lu->buffer; - - /* protocol */ - if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) != 0) - goto fail; - lu->protocol = LDAP; - p += strlen(LDAP_URL); - - /* host and optional port */ - if ((forward = strchr(p, '/')) != NULL) - *forward = '\0'; - /* find the optional port */ - if ((forward2 = strchr(p, ':')) != NULL) { - *forward2 = '\0'; - /* if a port is given */ - if (*(forward2+1) != '\0') { -#define PORT_MAX UINT16_MAX - lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr); - if (errstr) - goto fail; - } - } else { - lu->port = LDAP_PORT; - } - /* fail if no host is given */ - if (strlen(p) == 0) - goto fail; - lu->host = p; - if (forward == NULL) - goto done; - /* p is assigned either a pointer to a character or to '\0' */ - p = ++forward; - if (strlen(p) == 0) - goto done; - - /* dn */ - if ((forward = strchr(p, '?')) != NULL) - *forward = '\0'; - lu->dn = p; - if (forward == NULL) - goto done; - /* p is assigned either a pointer to a character or to '\0' */ - p = ++forward; - if (strlen(p) == 0) - goto done; - - /* attributes */ - if ((forward = strchr(p, '?')) != NULL) - *forward = '\0'; - for (i = 0; i < MAXATTR; i++) { - if ((forward2 = strchr(p, ',')) == NULL) { - if (strlen(p) == 0) - break; - lu->attributes[i] = p; - break; - } - *forward2 = '\0'; - lu->attributes[i] = p; - p = ++forward2; - } - if (forward == NULL) - goto done; - /* p is assigned either a pointer to a character or to '\0' */ - p = ++forward; - if (strlen(p) == 0) - goto done; - - /* scope */ - if ((forward = strchr(p, '?')) != NULL) - *forward = '\0'; - if (strcmp(p, "base") == 0) - lu->scope = LDAP_SCOPE_BASE; - else if (strcmp(p, "one") == 0) - lu->scope = LDAP_SCOPE_ONELEVEL; - else if (strcmp(p, "sub") == 0) - lu->scope = LDAP_SCOPE_SUBTREE; - else - goto fail; - if (forward == NULL) - goto done; - p = ++forward; - if (strlen(p) == 0) - goto done; - - /* filter */ - if (p) - lu->filter = p; -done: - free(url); - return (1); -fail: - free(lu->buffer); - lu->buffer = NULL; - return (-1); -} - -#if 0 -int -aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit, - int timelimit) -{ - struct aldap_url *lu; - - if ((lu = calloc(1, sizeof(*lu))) == NULL) - return (-1); - - if (aldap_parse_url(url, lu)) - goto fail; - - if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes, - typesonly, sizelimit, timelimit) == -1) - goto fail; - - aldap_free_url(lu); - return (ldap->msgid); -fail: - aldap_free_url(lu); - return (-1); -} -#endif - -/* - * internal functions - */ - -char ** -aldap_get_stringset(struct ber_element *elm) -{ - struct ber_element *a; - int i; - char **ret; - char *s; - - if (elm->be_type != BER_TYPE_OCTETSTRING) - return NULL; - - for (a = elm, i = 1; i > 0 && a != NULL && a->be_type == - BER_TYPE_OCTETSTRING; a = a->be_next, i++) - ; - if (i == 1) - return NULL; - - if ((ret = calloc(i + 1, sizeof(char *))) == NULL) - return NULL; - - for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING; - a = a->be_next, i++) { - - ber_get_string(a, &s); - ret[i] = utoa(s); - } - ret[i + 1] = NULL; - - return ret; -} - -/* - * Base case for ldap_do_parse_search_filter - * - * returns: - * struct ber_element *, ber_element tree - * NULL, parse failed - */ -static struct ber_element * -ldap_parse_search_filter(struct ber_element *ber, char *filter) -{ - struct ber_element *elm; - char *cp; - - cp = filter; - - if (cp == NULL || *cp == '\0') { - errno = EINVAL; - return (NULL); - } - - if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL) - return (NULL); - - if (*cp != '\0') { - ber_free_elements(elm); - ber_link_elements(ber, NULL); - errno = EINVAL; - return (NULL); - } - - return (elm); -} - -/* - * Translate RFC4515 search filter string into ber_element tree - * - * returns: - * struct ber_element *, ber_element tree - * NULL, parse failed - * - * notes: - * when cp is passed to a recursive invocation, it is updated - * to point one character beyond the filter that was passed - * i.e., cp jumps to "(filter)" upon return - * ^ - * goto's used to discriminate error-handling based on error type - * doesn't handle extended filters (yet) - * - */ -static struct ber_element * -ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) -{ - struct ber_element *elm, *root = NULL; - char *attr_desc, *attr_val, *parsed_val, *cp; - size_t len; - unsigned long type; - - root = NULL; - - /* cpp should pass in pointer to opening parenthesis of "(filter)" */ - cp = *cpp; - if (*cp != '(') - goto syntaxfail; - - switch (*++cp) { - case '&': /* AND */ - case '|': /* OR */ - if (*cp == '&') - type = LDAP_FILT_AND; - else - type = LDAP_FILT_OR; - - if ((elm = ber_add_set(prev)) == NULL) - goto callfail; - root = elm; - ber_set_header(elm, BER_CLASS_CONTEXT, type); - - if (*++cp != '(') /* opening `(` of filter */ - goto syntaxfail; - - while (*cp == '(') { - if ((elm = - ldap_do_parse_search_filter(elm, &cp)) == NULL) - goto bad; - } - - if (*cp != ')') /* trailing `)` of filter */ - goto syntaxfail; - break; - - case '!': /* NOT */ - if ((root = ber_add_sequence(prev)) == NULL) - goto callfail; - ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT); - - cp++; /* now points to sub-filter */ - if (ldap_do_parse_search_filter(root, &cp) == NULL) - goto bad; - - if (*cp != ')') /* trailing `)` of filter */ - goto syntaxfail; - break; - - default: /* SIMPLE || PRESENCE */ - attr_desc = cp; - - len = strcspn(cp, "()<>~="); - cp += len; - switch (*cp) { - case '~': - type = LDAP_FILT_APPR; - cp++; - break; - case '<': - type = LDAP_FILT_LE; - cp++; - break; - case '>': - type = LDAP_FILT_GE; - cp++; - break; - case '=': - type = LDAP_FILT_EQ; /* assume EQ until disproven */ - break; - case '(': - case ')': - default: - goto syntaxfail; - } - attr_val = ++cp; - - /* presence filter */ - if (strncmp(attr_val, "*)", 2) == 0) { - cp++; /* point to trailing `)` */ - if ((root = - ber_add_nstring(prev, attr_desc, len)) == NULL) - goto bad; - - ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES); - break; - } - - if ((root = ber_add_sequence(prev)) == NULL) - goto callfail; - ber_set_header(root, BER_CLASS_CONTEXT, type); - - if ((elm = ber_add_nstring(root, attr_desc, len)) == NULL) - goto callfail; - - len = strcspn(attr_val, "*)"); - if (len == 0 && *cp != '*') - goto syntaxfail; - cp += len; - if (*cp == '\0') - goto syntaxfail; - - if (*cp == '*') { /* substring filter */ - int initial; - - cp = attr_val; - - ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS); - - if ((elm = ber_add_sequence(elm)) == NULL) - goto callfail; - - for (initial = 1;; cp++, initial = 0) { - attr_val = cp; - - len = strcspn(attr_val, "*)"); - if (len == 0) { - if (*cp == ')') - break; - else - continue; - } - cp += len; - if (*cp == '\0') - goto syntaxfail; - - if (initial) - type = LDAP_FILT_SUBS_INIT; - else if (*cp == ')') - type = LDAP_FILT_SUBS_FIN; - else - type = LDAP_FILT_SUBS_ANY; - - if ((parsed_val = parseval(attr_val, len)) == - NULL) - goto callfail; - elm = ber_add_nstring(elm, parsed_val, - strlen(parsed_val)); - free(parsed_val); - if (elm == NULL) - goto callfail; - ber_set_header(elm, BER_CLASS_CONTEXT, type); - if (type == LDAP_FILT_SUBS_FIN) - break; - } - break; - } - - if ((parsed_val = parseval(attr_val, len)) == NULL) - goto callfail; - elm = ber_add_nstring(elm, parsed_val, strlen(parsed_val)); - free(parsed_val); - if (elm == NULL) - goto callfail; - break; - } - - cp++; /* now points one char beyond the trailing `)` */ - - *cpp = cp; - return (root); - -syntaxfail: /* XXX -- error reporting */ -callfail: -bad: - if (root != NULL) - ber_free_elements(root); - ber_link_elements(prev, NULL); - return (NULL); -} - -#ifdef DEBUG -/* - * Display a list of ber elements. - * - */ -void -ldap_debug_elements(struct ber_element *root) -{ - static int indent = 0; - long long v; - int d; - char *buf; - size_t len; - unsigned int i; - int constructed; - struct ber_oid o; - - /* calculate lengths */ - ber_calc_len(root); - - switch (root->be_encoding) { - case BER_TYPE_SEQUENCE: - case BER_TYPE_SET: - constructed = root->be_encoding; - break; - default: - constructed = 0; - break; - } - - fprintf(stderr, "%*slen %lu ", indent, "", root->be_len); - switch (root->be_class) { - case BER_CLASS_UNIVERSAL: - fprintf(stderr, "class: universal(%u) type: ", root->be_class); - switch (root->be_type) { - case BER_TYPE_EOC: - fprintf(stderr, "end-of-content"); - break; - case BER_TYPE_BOOLEAN: - fprintf(stderr, "boolean"); - break; - case BER_TYPE_INTEGER: - fprintf(stderr, "integer"); - break; - case BER_TYPE_BITSTRING: - fprintf(stderr, "bit-string"); - break; - case BER_TYPE_OCTETSTRING: - fprintf(stderr, "octet-string"); - break; - case BER_TYPE_NULL: - fprintf(stderr, "null"); - break; - case BER_TYPE_OBJECT: - fprintf(stderr, "object"); - break; - case BER_TYPE_ENUMERATED: - fprintf(stderr, "enumerated"); - break; - case BER_TYPE_SEQUENCE: - fprintf(stderr, "sequence"); - break; - case BER_TYPE_SET: - fprintf(stderr, "set"); - break; - } - break; - case BER_CLASS_APPLICATION: - fprintf(stderr, "class: application(%u) type: ", - root->be_class); - switch (root->be_type) { - case LDAP_REQ_BIND: - fprintf(stderr, "bind"); - break; - case LDAP_RES_BIND: - fprintf(stderr, "bind"); - break; - case LDAP_REQ_UNBIND_30: - break; - case LDAP_REQ_SEARCH: - fprintf(stderr, "search"); - break; - case LDAP_RES_SEARCH_ENTRY: - fprintf(stderr, "search_entry"); - break; - case LDAP_RES_SEARCH_RESULT: - fprintf(stderr, "search_result"); - break; - case LDAP_REQ_MODIFY: - fprintf(stderr, "modify"); - break; - case LDAP_RES_MODIFY: - fprintf(stderr, "modify"); - break; - case LDAP_REQ_ADD: - fprintf(stderr, "add"); - break; - case LDAP_RES_ADD: - fprintf(stderr, "add"); - break; - case LDAP_REQ_DELETE_30: - fprintf(stderr, "delete"); - break; - case LDAP_RES_DELETE: - fprintf(stderr, "delete"); - break; - case LDAP_REQ_MODRDN: - fprintf(stderr, "modrdn"); - break; - case LDAP_RES_MODRDN: - fprintf(stderr, "modrdn"); - break; - case LDAP_REQ_COMPARE: - fprintf(stderr, "compare"); - break; - case LDAP_RES_COMPARE: - fprintf(stderr, "compare"); - break; - case LDAP_REQ_ABANDON_30: - fprintf(stderr, "abandon"); - break; - } - break; - case BER_CLASS_PRIVATE: - fprintf(stderr, "class: private(%u) type: ", root->be_class); - fprintf(stderr, "encoding (%lu) type: ", root->be_encoding); - break; - case BER_CLASS_CONTEXT: - /* XXX: this is not correct */ - fprintf(stderr, "class: context(%u) type: ", root->be_class); - switch(root->be_type) { - case LDAP_AUTH_SIMPLE: - fprintf(stderr, "auth simple"); - break; - } - break; - default: - fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class); - break; - } - fprintf(stderr, "(%lu) encoding %lu ", - root->be_type, root->be_encoding); - - if (constructed) - root->be_encoding = constructed; - - switch (root->be_encoding) { - case BER_TYPE_BOOLEAN: - if (ber_get_boolean(root, &d) == -1) { - fprintf(stderr, "<INVALID>\n"); - break; - } - fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d); - break; - case BER_TYPE_INTEGER: - if (ber_get_integer(root, &v) == -1) { - fprintf(stderr, "<INVALID>\n"); - break; - } - fprintf(stderr, "value %lld\n", v); - break; - case BER_TYPE_ENUMERATED: - if (ber_get_enumerated(root, &v) == -1) { - fprintf(stderr, "<INVALID>\n"); - break; - } - fprintf(stderr, "value %lld\n", v); - break; - case BER_TYPE_BITSTRING: - if (ber_get_bitstring(root, (void *)&buf, &len) == -1) { - fprintf(stderr, "<INVALID>\n"); - break; - } - fprintf(stderr, "hexdump "); - for (i = 0; i < len; i++) - fprintf(stderr, "%02x", buf[i]); - fprintf(stderr, "\n"); - break; - case BER_TYPE_OBJECT: - if (ber_get_oid(root, &o) == -1) { - fprintf(stderr, "<INVALID>\n"); - break; - } - fprintf(stderr, "\n"); - break; - case BER_TYPE_OCTETSTRING: - if (ber_get_nstring(root, (void *)&buf, &len) == -1) { - fprintf(stderr, "<INVALID>\n"); - break; - } - fprintf(stderr, "string \"%.*s\"\n", len, buf); - break; - case BER_TYPE_NULL: /* no payload */ - case BER_TYPE_EOC: - case BER_TYPE_SEQUENCE: - case BER_TYPE_SET: - default: - fprintf(stderr, "\n"); - break; - } - - if (constructed && root->be_sub) { - indent += 2; - ldap_debug_elements(root->be_sub); - indent -= 2; - } - if (root->be_next) - ldap_debug_elements(root->be_next); -} -#endif - -/* - * Convert UTF-8 to ASCII. - * notes: - * non-ASCII characters are displayed as '?' - * the argument u should be a NULL terminated sequence of UTF-8 bytes. - */ -char * -utoa(char *u) -{ - int len, i, j; - char *str; - - /* calculate the length to allocate */ - for (len = 0, i = 0; u[i] != '\0'; ) { - if ((u[i] & 0xF0) == 0xF0) - i += 4; - else if ((u[i] & 0xE0) == 0xE0) - i += 3; - else if ((u[i] & 0xC0) == 0xC0) - i += 2; - else - i += 1; - len++; - } - - if ((str = calloc(len + 1, sizeof(char))) == NULL) - return NULL; - - /* copy the ASCII characters to the newly allocated string */ - for (i = 0, j = 0; u[i] != '\0'; j++) { - if ((u[i] & 0xF0) == 0xF0) { - str[j] = '?'; - i += 4; - } else if ((u[i] & 0xE0) == 0xE0) { - str[j] = '?'; - i += 3; - } else if ((u[i] & 0xC0) == 0xC0) { - str[j] = '?'; - i += 2; - } else { - str[j] = u[i]; - i += 1; - } - } - - return str; -} - -/* - * Parse a LDAP value - * notes: - * the argument u should be a NULL terminated sequence of ASCII bytes. - */ -char * -parseval(char *p, size_t len) -{ - char hex[3]; - char *cp = p, *buffer, *newbuffer; - size_t size, newsize, i, j; - - size = 50; - if ((buffer = calloc(1, size)) == NULL) - return NULL; - - for (i = j = 0; j < len; i++) { - if (i >= size) { - newsize = size + 1024; - if ((newbuffer = realloc(buffer, newsize)) == NULL) { - free(buffer); - return (NULL); - } - buffer = newbuffer; - size = newsize; - } - - if (cp[j] == '\\') { - (void)strlcpy(hex, cp + j + 1, sizeof(hex)); - buffer[i] = (char)strtoumax(hex, NULL, 16); - j += 3; - } else { - buffer[i] = cp[j]; - j++; - } - } - - return buffer; -} - -int -aldap_get_errno(struct aldap *a, const char **estr) -{ - switch (a->err) { - case ALDAP_ERR_SUCCESS: - *estr = "success"; - break; - case ALDAP_ERR_PARSER_ERROR: - *estr = "parser failed"; - break; - case ALDAP_ERR_INVALID_FILTER: - *estr = "invalid filter"; - break; - case ALDAP_ERR_OPERATION_FAILED: - *estr = "operation failed"; - break; - default: - *estr = "unknown"; - break; - } - return (a->err); -} diff --git a/usr.sbin/smtpd/aldap.h b/usr.sbin/smtpd/aldap.h deleted file mode 100644 index 0793613346e..00000000000 --- a/usr.sbin/smtpd/aldap.h +++ /dev/null @@ -1,218 +0,0 @@ -/* $OpenBSD: aldap.h,v 1.6 2015/11/05 12:35:58 jung Exp $ */ - -/* - * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> - * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ber.h" - -#define LDAP_URL "ldap://" -#define LDAP_PORT 389 -#define LDAP_PAGED_OID "1.2.840.113556.1.4.319" - -struct aldap { -#define ALDAP_ERR_SUCCESS 0 -#define ALDAP_ERR_PARSER_ERROR 1 -#define ALDAP_ERR_INVALID_FILTER 2 -#define ALDAP_ERR_OPERATION_FAILED 3 - uint8_t err; - int msgid; - struct ber ber; -}; - -struct aldap_page_control { - int size; - char *cookie; - unsigned int cookie_len; -}; - -struct aldap_message { - int msgid; - int message_type; - - struct ber_element *msg; - - struct ber_element *header; - struct ber_element *protocol_op; - - struct ber_element *dn; - - union { - struct { - long long rescode; - struct ber_element *diagmsg; - } res; - struct { - struct ber_element *iter; - struct ber_element *attrs; - } search; - } body; - struct ber_element *references; - struct aldap_page_control *page; -}; - -enum aldap_protocol { - LDAP, - LDAPS -}; - -struct aldap_url { - int protocol; - char *host; - in_port_t port; - char *dn; -#define MAXATTR 1024 - char *attributes[MAXATTR]; - int scope; - char *filter; - char *buffer; -}; - -enum protocol_op { - LDAP_REQ_BIND = 0, - LDAP_RES_BIND = 1, - LDAP_REQ_UNBIND_30 = 2, - LDAP_REQ_SEARCH = 3, - LDAP_RES_SEARCH_ENTRY = 4, - LDAP_RES_SEARCH_RESULT = 5, - LDAP_REQ_MODIFY = 6, - LDAP_RES_MODIFY = 7, - LDAP_REQ_ADD = 8, - LDAP_RES_ADD = 9, - LDAP_REQ_DELETE_30 = 10, - LDAP_RES_DELETE = 11, - LDAP_REQ_MODRDN = 12, - LDAP_RES_MODRDN = 13, - LDAP_REQ_COMPARE = 14, - LDAP_RES_COMPARE = 15, - LDAP_REQ_ABANDON_30 = 16, - - LDAP_RES_SEARCH_REFERENCE = 19, -}; - -enum deref_aliases { - LDAP_DEREF_NEVER = 0, - LDAP_DEREF_SEARCHING = 1, - LDAP_DEREF_FINDING = 2, - LDAP_DEREF_ALWAYS = 3, -}; - -enum authentication_choice { - LDAP_AUTH_SIMPLE = 0, -}; - -enum scope { - LDAP_SCOPE_BASE = 0, - LDAP_SCOPE_ONELEVEL = 1, - LDAP_SCOPE_SUBTREE = 2, -}; - -enum result_code { - LDAP_SUCCESS = 0, - LDAP_OPERATIONS_ERROR = 1, - LDAP_PROTOCOL_ERROR = 2, - LDAP_TIMELIMIT_EXCEEDED = 3, - LDAP_SIZELIMIT_EXCEEDED = 4, - LDAP_COMPARE_FALSE = 5, - LDAP_COMPARE_TRUE = 6, - LDAP_STRONG_AUTH_NOT_SUPPORTED = 7, - LDAP_STRONG_AUTH_REQUIRED = 8, - - LDAP_REFERRAL = 10, - LDAP_ADMINLIMIT_EXCEEDED = 11, - LDAP_UNAVAILABLE_CRITICAL_EXTENSION = 12, - LDAP_CONFIDENTIALITY_REQUIRED = 13, - LDAP_SASL_BIND_IN_PROGRESS = 14, - LDAP_NO_SUCH_ATTRIBUTE = 16, - LDAP_UNDEFINED_TYPE = 17, - LDAP_INAPPROPRIATE_MATCHING = 18, - LDAP_CONSTRAINT_VIOLATION = 19, - LDAP_TYPE_OR_VALUE_EXISTS = 20, - LDAP_INVALID_SYNTAX = 21, - - LDAP_NO_SUCH_OBJECT = 32, - LDAP_ALIAS_PROBLEM = 33, - LDAP_INVALID_DN_SYNTAX = 34, - - LDAP_ALIAS_DEREF_PROBLEM = 36, - - LDAP_INAPPROPRIATE_AUTH = 48, - LDAP_INVALID_CREDENTIALS = 49, - LDAP_INSUFFICIENT_ACCESS = 50, - LDAP_BUSY = 51, - LDAP_UNAVAILABLE = 52, - LDAP_UNWILLING_TO_PERFORM = 53, - LDAP_LOOP_DETECT = 54, - - LDAP_NAMING_VIOLATION = 64, - LDAP_OBJECT_CLASS_VIOLATION = 65, - LDAP_NOT_ALLOWED_ON_NONLEAF = 66, - LDAP_NOT_ALLOWED_ON_RDN = 67, - LDAP_ALREADY_EXISTS = 68, - LDAP_NO_OBJECT_CLASS_MODS = 69, - - LDAP_AFFECTS_MULTIPLE_DSAS = 71, - - LDAP_OTHER = 80, -}; - -enum ldap_filter { - LDAP_FILT_AND = 0, - LDAP_FILT_OR = 1, - LDAP_FILT_NOT = 2, - LDAP_FILT_EQ = 3, - LDAP_FILT_SUBS = 4, - LDAP_FILT_GE = 5, - LDAP_FILT_LE = 6, - LDAP_FILT_PRES = 7, - LDAP_FILT_APPR = 8, -}; - -enum ldap_subfilter { - LDAP_FILT_SUBS_INIT = 0, - LDAP_FILT_SUBS_ANY = 1, - LDAP_FILT_SUBS_FIN = 2, -}; - -struct aldap *aldap_init(int fd); -int aldap_close(struct aldap *); -struct aldap_message *aldap_parse(struct aldap *); -void aldap_freemsg(struct aldap_message *); - -int aldap_bind(struct aldap *, char *, char *); -int aldap_unbind(struct aldap *); -int aldap_search(struct aldap *, char *, enum scope, char *, char **, int, int, int, struct aldap_page_control *); -int aldap_get_errno(struct aldap *, const char **); - -int aldap_get_resultcode(struct aldap_message *); -char *aldap_get_dn(struct aldap_message *); -char *aldap_get_diagmsg(struct aldap_message *); -char **aldap_get_references(struct aldap_message *); -void aldap_free_references(char **values); -int aldap_parse_url(char *, struct aldap_url *); -void aldap_free_url(struct aldap_url *); -#if 0 -int aldap_search_url(struct aldap *, char *, int, int, int); -#endif - -int aldap_count_attrs(struct aldap_message *); -int aldap_match_attr(struct aldap_message *, char *, char ***); -int aldap_first_attr(struct aldap_message *, char **, char ***); -int aldap_next_attr(struct aldap_message *, char **, char ***); -int aldap_free_attr(char **); - -struct aldap_page_control *aldap_parse_page_control(struct ber_element *, size_t len); -void aldap_freepage(struct aldap_page_control *); diff --git a/usr.sbin/smtpd/ber.c b/usr.sbin/smtpd/ber.c deleted file mode 100644 index e44fbe04791..00000000000 --- a/usr.sbin/smtpd/ber.c +++ /dev/null @@ -1,1269 +0,0 @@ -/* $OpenBSD: ber.c,v 1.8 2015/11/23 13:22:37 gilles Exp $ */ - -/* - * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net> - * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org> - * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <stdlib.h> -#include <err.h> /* XXX for debug output */ -#include <stdio.h> /* XXX for debug output */ -#include <string.h> -#include <unistd.h> -#include <stdarg.h> - -#include "ber.h" - -#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) - -#define BER_TYPE_CONSTRUCTED 0x20 /* otherwise primitive */ -#define BER_TYPE_SINGLE_MAX 30 -#define BER_TAG_MASK 0x1f -#define BER_TAG_MORE 0x80 /* more subsequent octets */ -#define BER_TAG_TYPE_MASK 0x7f -#define BER_CLASS_SHIFT 6 - -static int ber_dump_element(struct ber *ber, struct ber_element *root); -static void ber_dump_header(struct ber *ber, struct ber_element *root); -static void ber_putc(struct ber *ber, unsigned char c); -static void ber_write(struct ber *ber, void *buf, size_t len); -static ssize_t get_id(struct ber *b, unsigned long *tag, int *class, - int *cstruct); -static ssize_t get_len(struct ber *b, ssize_t *len); -static ssize_t ber_read_element(struct ber *ber, struct ber_element *elm); -static ssize_t ber_readbuf(struct ber *b, void *buf, size_t nbytes); -static ssize_t ber_getc(struct ber *b, unsigned char *c); -static ssize_t ber_read(struct ber *ber, void *buf, size_t len); - -#ifdef DEBUG -#define DPRINTF(...) printf(__VA_ARGS__) -#else -#define DPRINTF(...) do { } while (0) -#endif - -struct ber_element * -ber_get_element(unsigned long encoding) -{ - struct ber_element *elm; - - if ((elm = calloc(1, sizeof(*elm))) == NULL) - return NULL; - - elm->be_encoding = encoding; - ber_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT); - - return elm; -} - -void -ber_set_header(struct ber_element *elm, int class, unsigned long type) -{ - elm->be_class = class & BER_CLASS_MASK; - if (type == BER_TYPE_DEFAULT) - type = elm->be_encoding; - elm->be_type = type; -} - -void -ber_link_elements(struct ber_element *prev, struct ber_element *elm) -{ - if (prev != NULL) { - if ((prev->be_encoding == BER_TYPE_SEQUENCE || - prev->be_encoding == BER_TYPE_SET) && - prev->be_sub == NULL) - prev->be_sub = elm; - else - prev->be_next = elm; - } -} - -struct ber_element * -ber_unlink_elements(struct ber_element *prev) -{ - struct ber_element *elm; - - if ((prev->be_encoding == BER_TYPE_SEQUENCE || - prev->be_encoding == BER_TYPE_SET) && - prev->be_sub != NULL) { - elm = prev->be_sub; - prev->be_sub = NULL; - } else { - elm = prev->be_next; - prev->be_next = NULL; - } - - return (elm); -} - -void -ber_replace_elements(struct ber_element *prev, struct ber_element *new) -{ - struct ber_element *ber, *next; - - ber = ber_unlink_elements(prev); - next = ber_unlink_elements(ber); - ber_link_elements(new, next); - ber_link_elements(prev, new); - - /* cleanup old element */ - ber_free_elements(ber); -} - -struct ber_element * -ber_add_sequence(struct ber_element *prev) -{ - struct ber_element *elm; - - if ((elm = ber_get_element(BER_TYPE_SEQUENCE)) == NULL) - return NULL; - - ber_link_elements(prev, elm); - - return elm; -} - -struct ber_element * -ber_add_set(struct ber_element *prev) -{ - struct ber_element *elm; - - if ((elm = ber_get_element(BER_TYPE_SET)) == NULL) - return NULL; - - ber_link_elements(prev, elm); - - return elm; -} - -struct ber_element * -ber_add_enumerated(struct ber_element *prev, long long val) -{ - struct ber_element *elm; - unsigned int i, len = 0; - unsigned char cur, last = 0; - - if ((elm = ber_get_element(BER_TYPE_ENUMERATED)) == NULL) - return NULL; - - elm->be_numeric = val; - - for (i = 0; i < sizeof(long long); i++) { - cur = val & 0xff; - if (cur != 0 && cur != 0xff) - len = i; - if ((cur == 0 && last & 0x80) || - (cur == 0xff && (last & 0x80) == 0)) - len = i; - val >>= 8; - last = cur; - } - elm->be_len = len + 1; - - ber_link_elements(prev, elm); - - return elm; -} - -struct ber_element * -ber_add_integer(struct ber_element *prev, long long val) -{ - struct ber_element *elm; - unsigned int i, len = 0; - unsigned char cur, last = 0; - - if ((elm = ber_get_element(BER_TYPE_INTEGER)) == NULL) - return NULL; - - elm->be_numeric = val; - - for (i = 0; i < sizeof(long long); i++) { - cur = val & 0xff; - if (cur != 0 && cur != 0xff) - len = i; - if ((cur == 0 && last & 0x80) || - (cur == 0xff && (last & 0x80) == 0)) - len = i; - val >>= 8; - last = cur; - } - elm->be_len = len + 1; - - ber_link_elements(prev, elm); - - return elm; -} - -int -ber_get_integer(struct ber_element *elm, long long *n) -{ - if (elm->be_encoding != BER_TYPE_INTEGER) - return -1; - - *n = elm->be_numeric; - return 0; -} - -int -ber_get_enumerated(struct ber_element *elm, long long *n) -{ - if (elm->be_encoding != BER_TYPE_ENUMERATED) - return -1; - - *n = elm->be_numeric; - return 0; -} - - -struct ber_element * -ber_add_boolean(struct ber_element *prev, int bool) -{ - struct ber_element *elm; - - if ((elm = ber_get_element(BER_TYPE_BOOLEAN)) == NULL) - return NULL; - - elm->be_numeric = bool ? 0xff : 0; - elm->be_len = 1; - - ber_link_elements(prev, elm); - - return elm; -} - -int -ber_get_boolean(struct ber_element *elm, int *b) -{ - if (elm->be_encoding != BER_TYPE_BOOLEAN) - return -1; - - *b = !(elm->be_numeric == 0); - return 0; -} - -struct ber_element * -ber_add_string(struct ber_element *prev, const char *string) -{ - return ber_add_nstring(prev, string, strlen(string)); -} - -struct ber_element * -ber_add_nstring(struct ber_element *prev, const char *string0, size_t len) -{ - struct ber_element *elm; - char *string; - - if ((string = calloc(1, len)) == NULL) - return NULL; - if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) { - free(string); - return NULL; - } - - memmove(string, string0, len); - elm->be_val = string; - elm->be_len = len; - elm->be_free = 1; /* free string on cleanup */ - - ber_link_elements(prev, elm); - - return elm; -} - -int -ber_get_string(struct ber_element *elm, char **s) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - - *s = elm->be_val; - return 0; -} - -int -ber_get_nstring(struct ber_element *elm, void **p, size_t *len) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - - *p = elm->be_val; - *len = elm->be_len; - return 0; -} - -struct ber_element * -ber_add_bitstring(struct ber_element *prev, const void *v0, size_t len) -{ - struct ber_element *elm; - void *v; - - if ((v = calloc(1, len)) == NULL) - return NULL; - if ((elm = ber_get_element(BER_TYPE_BITSTRING)) == NULL) { - free(v); - return NULL; - } - - memmove(v, v0, len); - elm->be_val = v; - elm->be_len = len; - elm->be_free = 1; /* free string on cleanup */ - - ber_link_elements(prev, elm); - - return elm; -} - -int -ber_get_bitstring(struct ber_element *elm, void **v, size_t *len) -{ - if (elm->be_encoding != BER_TYPE_BITSTRING) - return -1; - - *v = elm->be_val; - *len = elm->be_len; - return 0; -} - -struct ber_element * -ber_add_null(struct ber_element *prev) -{ - struct ber_element *elm; - - if ((elm = ber_get_element(BER_TYPE_NULL)) == NULL) - return NULL; - - ber_link_elements(prev, elm); - - return elm; -} - -int -ber_get_null(struct ber_element *elm) -{ - if (elm->be_encoding != BER_TYPE_NULL) - return -1; - - return 0; -} - -struct ber_element * -ber_add_eoc(struct ber_element *prev) -{ - struct ber_element *elm; - - if ((elm = ber_get_element(BER_TYPE_EOC)) == NULL) - return NULL; - - ber_link_elements(prev, elm); - - return elm; -} - -int -ber_get_eoc(struct ber_element *elm) -{ - if (elm->be_encoding != BER_TYPE_EOC) - return -1; - - return 0; -} - -size_t -ber_oid2ber(struct ber_oid *o, uint8_t *buf, size_t len) -{ - uint32_t v; - unsigned int i, j = 0, k; - - if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN || - o->bo_id[0] > 2 || o->bo_id[1] > 40) - return (0); - - v = (o->bo_id[0] * 40) + o->bo_id[1]; - for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) { - for (k = 28; k >= 7; k -= 7) { - if (v >= (unsigned int)(1 << k)) { - if (len) - buf[j] = v >> k | BER_TAG_MORE; - j++; - } - } - if (len) - buf[j] = v & BER_TAG_TYPE_MASK; - j++; - } - - return (j); -} - -int -ber_string2oid(const char *oidstr, struct ber_oid *o) -{ - char *sp, *p, str[BUFSIZ]; - const char *errstr; - - if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str)) - return (-1); - memset(o, 0, sizeof(*o)); - - /* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */ - for (p = sp = str; p != NULL; sp = p) { - if ((p = strpbrk(p, "._-")) != NULL) - *p++ = '\0'; - o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr); - if (errstr || o->bo_n > BER_MAX_OID_LEN) - return (-1); - } - - return (0); -} - -struct ber_element * -ber_add_oid(struct ber_element *prev, struct ber_oid *o) -{ - struct ber_element *elm; - uint8_t *buf; - size_t len; - - if ((elm = ber_get_element(BER_TYPE_OBJECT)) == NULL) - return (NULL); - - if ((len = ber_oid2ber(o, NULL, 0)) == 0) - goto fail; - - if ((buf = calloc(1, len)) == NULL) - goto fail; - - elm->be_val = buf; - elm->be_len = len; - elm->be_free = 1; - - if (ber_oid2ber(o, buf, len) != len) - goto fail; - - ber_link_elements(prev, elm); - - return (elm); - - fail: - ber_free_elements(elm); - return (NULL); -} - -struct ber_element * -ber_add_noid(struct ber_element *prev, struct ber_oid *o, int n) -{ - struct ber_oid no; - - if (n > BER_MAX_OID_LEN) - return (NULL); - no.bo_n = n; - memmove(&no.bo_id, &o->bo_id, sizeof(no.bo_id)); - - return (ber_add_oid(prev, &no)); -} - -struct ber_element * -ber_add_oidstring(struct ber_element *prev, const char *oidstr) -{ - struct ber_oid o; - - if (ber_string2oid(oidstr, &o) == -1) - return (NULL); - - return (ber_add_oid(prev, &o)); -} - -int -ber_get_oid(struct ber_element *elm, struct ber_oid *o) -{ - uint8_t *buf; - size_t len, i = 0, j = 0; - - if (elm->be_encoding != BER_TYPE_OBJECT) - return (-1); - - buf = elm->be_val; - len = elm->be_len; - - if (!buf[i]) - return (-1); - - memset(o, 0, sizeof(*o)); - o->bo_id[j++] = buf[i] / 40; - o->bo_id[j++] = buf[i++] % 40; - for (; i < len && j < BER_MAX_OID_LEN; i++) { - o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80); - if (buf[i] & 0x80) - continue; - j++; - } - o->bo_n = j; - - return (0); -} - -struct ber_element * -ber_printf_elements(struct ber_element *ber, char *fmt, ...) -{ - va_list ap; - int d, class; - size_t len; - unsigned long type; - long long i; - char *s; - void *p; - struct ber_oid *o; - struct ber_element *sub = ber, *e; - - va_start(ap, fmt); - while (*fmt) { - switch (*fmt++) { - case 'B': - p = va_arg(ap, void *); - len = va_arg(ap, size_t); - if ((ber = ber_add_bitstring(ber, p, len)) == NULL) - goto fail; - break; - case 'b': - d = va_arg(ap, int); - if ((ber = ber_add_boolean(ber, d)) == NULL) - goto fail; - break; - case 'd': - d = va_arg(ap, int); - if ((ber = ber_add_integer(ber, d)) == NULL) - goto fail; - break; - case 'e': - e = va_arg(ap, struct ber_element *); - ber_link_elements(ber, e); - break; - case 'E': - i = va_arg(ap, long long); - if ((ber = ber_add_enumerated(ber, i)) == NULL) - goto fail; - break; - case 'i': - i = va_arg(ap, long long); - if ((ber = ber_add_integer(ber, i)) == NULL) - goto fail; - break; - case 'O': - o = va_arg(ap, struct ber_oid *); - if ((ber = ber_add_oid(ber, o)) == NULL) - goto fail; - break; - case 'o': - s = va_arg(ap, char *); - if ((ber = ber_add_oidstring(ber, s)) == NULL) - goto fail; - break; - case 's': - s = va_arg(ap, char *); - if ((ber = ber_add_string(ber, s)) == NULL) - goto fail; - break; - case 't': - class = va_arg(ap, int); - type = va_arg(ap, unsigned long); - ber_set_header(ber, class, type); - break; - case 'x': - s = va_arg(ap, char *); - len = va_arg(ap, size_t); - if ((ber = ber_add_nstring(ber, s, len)) == NULL) - goto fail; - break; - case '0': - if ((ber = ber_add_null(ber)) == NULL) - goto fail; - break; - case '{': - if ((ber = sub = ber_add_sequence(ber)) == NULL) - goto fail; - break; - case '(': - if ((ber = sub = ber_add_set(ber)) == NULL) - goto fail; - break; - case '}': - case ')': - ber = sub; - break; - case '.': - if ((e = ber_add_eoc(ber)) == NULL) - goto fail; - ber = e; - break; - default: - break; - } - } - va_end(ap); - - return (ber); - fail: - ber_free_elements(ber); - return (NULL); -} - -int -ber_scanf_elements(struct ber_element *ber, char *fmt, ...) -{ -#define _MAX_SEQ 128 - va_list ap; - int *d, level = -1; - unsigned long *t; - long long *i; - void **ptr; - size_t *len, ret = 0, n = strlen(fmt); - char **s; - struct ber_oid *o; - struct ber_element *parent[_MAX_SEQ], **e; - - memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ); - - va_start(ap, fmt); - while (*fmt) { - switch (*fmt++) { - case 'B': - ptr = va_arg(ap, void **); - len = va_arg(ap, size_t *); - if (ber_get_bitstring(ber, ptr, len) == -1) - goto fail; - ret++; - break; - case 'b': - d = va_arg(ap, int *); - if (ber_get_boolean(ber, d) == -1) - goto fail; - ret++; - break; - case 'e': - e = va_arg(ap, struct ber_element **); - *e = ber; - ret++; - continue; - case 'E': - i = va_arg(ap, long long *); - if (ber_get_enumerated(ber, i) == -1) - goto fail; - ret++; - break; - case 'i': - i = va_arg(ap, long long *); - if (ber_get_integer(ber, i) == -1) - goto fail; - ret++; - break; - case 'o': - o = va_arg(ap, struct ber_oid *); - if (ber_get_oid(ber, o) == -1) - goto fail; - ret++; - break; - case 'S': - ret++; - break; - case 's': - s = va_arg(ap, char **); - if (ber_get_string(ber, s) == -1) - goto fail; - ret++; - break; - case 't': - d = va_arg(ap, int *); - t = va_arg(ap, unsigned long *); - *d = ber->be_class; - *t = ber->be_type; - ret++; - continue; - case 'x': - ptr = va_arg(ap, void **); - len = va_arg(ap, size_t *); - if (ber_get_nstring(ber, ptr, len) == -1) - goto fail; - ret++; - break; - case '0': - if (ber->be_encoding != BER_TYPE_NULL) - goto fail; - ret++; - break; - case '.': - if (ber->be_encoding != BER_TYPE_EOC) - goto fail; - ret++; - break; - case '{': - case '(': - if (ber->be_encoding != BER_TYPE_SEQUENCE && - ber->be_encoding != BER_TYPE_SET) - goto fail; - if (ber->be_sub == NULL || level >= _MAX_SEQ-1) - goto fail; - parent[++level] = ber; - ber = ber->be_sub; - ret++; - continue; - case '}': - case ')': - if (parent[level] == NULL) - goto fail; - ber = parent[level--]; - ret++; - continue; - default: - goto fail; - } - - if (ber->be_next == NULL) - continue; - ber = ber->be_next; - } - va_end(ap); - return (ret == n ? 0 : -1); - - fail: - va_end(ap); - return (-1); - -} - -/* - * write ber elements to the socket - * - * params: - * ber holds the socket - * root fully populated element tree - * - * returns: - * >=0 number of bytes written - * -1 on failure and sets errno - */ -int -ber_write_elements(struct ber *ber, struct ber_element *root) -{ - size_t len; - - /* calculate length because only the definite form is required */ - len = ber_calc_len(root); - DPRINTF("write ber element of %zd bytes length\n", len); - - if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) { - free(ber->br_wbuf); - ber->br_wbuf = NULL; - } - if (ber->br_wbuf == NULL) { - if ((ber->br_wbuf = malloc(len)) == NULL) - return -1; - ber->br_wend = ber->br_wbuf + len; - } - - /* reset write pointer */ - ber->br_wptr = ber->br_wbuf; - - if (ber_dump_element(ber, root) == -1) - return -1; - - /* XXX this should be moved to a different function */ - if (ber->fd != -1) - return write(ber->fd, ber->br_wbuf, len); - - return (len); -} - -/* - * read ber elements from the socket - * - * params: - * ber holds the socket and lot more - * root if NULL, build up an element tree from what we receive on - * the wire. If not null, use the specified encoding for the - * elements received. - * - * returns: - * !=NULL, elements read and store in the ber_element tree - * NULL, type mismatch or read error - */ -struct ber_element * -ber_read_elements(struct ber *ber, struct ber_element *elm) -{ - struct ber_element *root = elm; - - if (root == NULL) { - if ((root = ber_get_element(0)) == NULL) - return NULL; - } - - DPRINTF("read ber elements, root %p\n", root); - - if (ber_read_element(ber, root) == -1) { - /* Cleanup if root was allocated by us */ - if (elm == NULL) - ber_free_elements(root); - return NULL; - } - - return root; -} - -void -ber_free_elements(struct ber_element *root) -{ - if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE || - root->be_encoding == BER_TYPE_SET)) - ber_free_elements(root->be_sub); - if (root->be_next) - ber_free_elements(root->be_next); - if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING || - root->be_encoding == BER_TYPE_BITSTRING || - root->be_encoding == BER_TYPE_OBJECT)) - free(root->be_val); - free(root); -} - -size_t -ber_calc_len(struct ber_element *root) -{ - unsigned long t; - size_t s; - size_t size = 2; /* minimum 1 byte head and 1 byte size */ - - /* calculate the real length of a sequence or set */ - if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE || - root->be_encoding == BER_TYPE_SET)) - root->be_len = ber_calc_len(root->be_sub); - - /* fix header length for extended types */ - if (root->be_type > BER_TYPE_SINGLE_MAX) - for (t = root->be_type; t > 0; t >>= 7) - size++; - if (root->be_len >= BER_TAG_MORE) - for (s = root->be_len; s > 0; s >>= 8) - size++; - - /* calculate the length of the following elements */ - if (root->be_next) - size += ber_calc_len(root->be_next); - - /* This is an empty element, do not use a minimal size */ - if (root->be_type == BER_TYPE_EOC && root->be_len == 0) - return (0); - - return (root->be_len + size); -} - -/* - * internal functions - */ - -static int -ber_dump_element(struct ber *ber, struct ber_element *root) -{ - unsigned long long l; - int i; - uint8_t u; - - ber_dump_header(ber, root); - - switch (root->be_encoding) { - case BER_TYPE_BOOLEAN: - case BER_TYPE_INTEGER: - case BER_TYPE_ENUMERATED: - l = (unsigned long long)root->be_numeric; - for (i = root->be_len; i > 0; i--) { - u = (l >> ((i - 1) * 8)) & 0xff; - ber_putc(ber, u); - } - break; - case BER_TYPE_BITSTRING: - return -1; - case BER_TYPE_OCTETSTRING: - case BER_TYPE_OBJECT: - ber_write(ber, root->be_val, root->be_len); - break; - case BER_TYPE_NULL: /* no payload */ - case BER_TYPE_EOC: - break; - case BER_TYPE_SEQUENCE: - case BER_TYPE_SET: - if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1) - return -1; - break; - } - - if (root->be_next == NULL) - return 0; - return ber_dump_element(ber, root->be_next); -} - -static void -ber_dump_header(struct ber *ber, struct ber_element *root) -{ - unsigned char id = 0, t, buf[8]; - unsigned long type; - size_t size; - - /* class universal, type encoding depending on type value */ - /* length encoding */ - if (root->be_type <= BER_TYPE_SINGLE_MAX) { - id = root->be_type | (root->be_class << BER_CLASS_SHIFT); - if (root->be_encoding == BER_TYPE_SEQUENCE || - root->be_encoding == BER_TYPE_SET) - id |= BER_TYPE_CONSTRUCTED; - - ber_putc(ber, id); - } else { - id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT); - if (root->be_encoding == BER_TYPE_SEQUENCE || - root->be_encoding == BER_TYPE_SET) - id |= BER_TYPE_CONSTRUCTED; - - ber_putc(ber, id); - - for (t = 0, type = root->be_type; type > 0; type >>= 7) - buf[t++] = type & ~BER_TAG_MORE; - - while (t-- > 0) { - if (t > 0) - buf[t] |= BER_TAG_MORE; - ber_putc(ber, buf[t]); - } - } - - if (root->be_len < BER_TAG_MORE) { - /* short form */ - ber_putc(ber, root->be_len); - } else { - for (t = 0, size = root->be_len; size > 0; size >>= 8) - buf[t++] = size & 0xff; - - ber_putc(ber, t | BER_TAG_MORE); - - while (t > 0) - ber_putc(ber, buf[--t]); - } -} - -static void -ber_putc(struct ber *ber, unsigned char c) -{ - if (ber->br_wptr + 1 <= ber->br_wend) - *ber->br_wptr = c; - ber->br_wptr++; -} - -static void -ber_write(struct ber *ber, void *buf, size_t len) -{ - if (ber->br_wptr + len <= ber->br_wend) - memmove(ber->br_wptr, buf, len); - - ber->br_wptr += len; -} - -/* - * extract a BER encoded tag. There are two types, a short and long form. - */ -static ssize_t -get_id(struct ber *b, unsigned long *tag, int *class, int *cstruct) -{ - unsigned char u; - size_t i = 0; - unsigned long t = 0; - - if (ber_getc(b, &u) == -1) - return -1; - - *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK; - *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED; - - if ((u & BER_TAG_MASK) != BER_TAG_MASK) { - *tag = u & BER_TAG_MASK; - return 1; - } - - do { - if (ber_getc(b, &u) == -1) - return -1; - t = (t << 7) | (u & ~BER_TAG_MORE); - i++; - } while (u & BER_TAG_MORE); - - if (i > sizeof(unsigned long)) { - errno = ERANGE; - return -1; - } - - *tag = t; - return i + 1; -} - -/* - * extract length of a ber object -- if length is unknown an error is returned. - */ -static ssize_t -get_len(struct ber *b, ssize_t *len) -{ - unsigned char u, n; - ssize_t s, r; - - if (ber_getc(b, &u) == -1) - return -1; - if ((u & BER_TAG_MORE) == 0) { - /* short form */ - *len = u; - return 1; - } - - n = u & ~BER_TAG_MORE; - if (sizeof(ssize_t) < n) { - errno = ERANGE; - return -1; - } - r = n + 1; - - for (s = 0; n > 0; n--) { - if (ber_getc(b, &u) == -1) - return -1; - s = (s << 8) | u; - } - - if (s < 0) { - /* overflow */ - errno = ERANGE; - return -1; - } - - if (s == 0) { - /* invalid encoding */ - errno = EINVAL; - return -1; - } - - *len = s; - return r; -} - -static ssize_t -ber_read_element(struct ber *ber, struct ber_element *elm) -{ - long long val = 0; - struct ber_element *next; - unsigned long type; - int i, class, cstruct; - ssize_t len, r, totlen = 0; - unsigned char c; - - if ((r = get_id(ber, &type, &class, &cstruct)) == -1) - return -1; - DPRINTF("ber read got class %d type %lu, %s\n", - class, type, cstruct ? "constructive" : "primitive"); - totlen += r; - if ((r = get_len(ber, &len)) == -1) - return -1; - DPRINTF("ber read element size %zd\n", len); - totlen += r + len; - - elm->be_type = type; - elm->be_len = len; - elm->be_class = class; - - if (elm->be_encoding == 0) { - /* try to figure out the encoding via class, type and cstruct */ - if (cstruct) - elm->be_encoding = BER_TYPE_SEQUENCE; - else if (class == BER_CLASS_UNIVERSAL) - elm->be_encoding = type; - else if (ber->br_application != NULL) { - /* - * Ask the application to map the encoding to a - * universal type. For example, a SMI IpAddress - * type is defined as 4 byte OCTET STRING. - */ - elm->be_encoding = (*ber->br_application)(elm); - } else - /* last resort option */ - elm->be_encoding = BER_TYPE_NULL; - } - - switch (elm->be_encoding) { - case BER_TYPE_EOC: /* End-Of-Content */ - break; - case BER_TYPE_BOOLEAN: - case BER_TYPE_INTEGER: - case BER_TYPE_ENUMERATED: - if (len > (ssize_t)sizeof(long long)) - return -1; - for (i = 0; i < len; i++) { - if (ber_getc(ber, &c) != 1) - return -1; - val <<= 8; - val |= c; - } - - /* sign extend if MSB is set */ - if (val >> ((i - 1) * 8) & 0x80) - val |= ULLONG_MAX << (i * 8); - elm->be_numeric = val; - break; - case BER_TYPE_BITSTRING: - elm->be_val = malloc(len); - if (elm->be_val == NULL) - return -1; - elm->be_free = 1; - elm->be_len = len; - ber_read(ber, elm->be_val, len); - break; - case BER_TYPE_OCTETSTRING: - case BER_TYPE_OBJECT: - elm->be_val = malloc(len + 1); - if (elm->be_val == NULL) - return -1; - elm->be_free = 1; - elm->be_len = len; - ber_read(ber, elm->be_val, len); - ((unsigned char *)elm->be_val)[len] = '\0'; - break; - case BER_TYPE_NULL: /* no payload */ - if (len != 0) - return -1; - break; - case BER_TYPE_SEQUENCE: - case BER_TYPE_SET: - if (elm->be_sub == NULL) { - if ((elm->be_sub = ber_get_element(0)) == NULL) - return -1; - } - next = elm->be_sub; - while (len > 0) { - r = ber_read_element(ber, next); - if (r == -1) - return -1; - len -= r; - if (len > 0 && next->be_next == NULL) { - if ((next->be_next = ber_get_element(0)) == - NULL) - return -1; - } - next = next->be_next; - } - break; - } - return totlen; -} - -static ssize_t -ber_readbuf(struct ber *b, void *buf, size_t nbytes) -{ - size_t sz; - size_t len; - - if (b->br_rbuf == NULL) - return -1; - - sz = b->br_rend - b->br_rptr; - len = MINIMUM(nbytes, sz); - if (len == 0) { - errno = ECANCELED; - return (-1); /* end of buffer and parser wants more data */ - } - - memmove(buf, b->br_rptr, len); - b->br_rptr += len; - - return (len); -} - -void -ber_set_readbuf(struct ber *b, void *buf, size_t len) -{ - b->br_rbuf = b->br_rptr = buf; - b->br_rend = (uint8_t *)buf + len; -} - -ssize_t -ber_get_writebuf(struct ber *b, void **buf) -{ - if (b->br_wbuf == NULL) - return -1; - *buf = b->br_wbuf; - return (b->br_wend - b->br_wbuf); -} - -void -ber_set_application(struct ber *b, unsigned long (*cb)(struct ber_element *)) -{ - b->br_application = cb; -} - -void -ber_free(struct ber *b) -{ - if (b->br_wbuf != NULL) - free (b->br_wbuf); -} - -static ssize_t -ber_getc(struct ber *b, unsigned char *c) -{ - ssize_t r; - /* - * XXX calling read here is wrong in many ways. The most obvious one - * being that we will block till data arrives. - * But for now it is _good enough_ *gulp* - */ - if (b->fd == -1) - r = ber_readbuf(b, c, 1); - else - r = read(b->fd, c, 1); - return r; -} - -static ssize_t -ber_read(struct ber *ber, void *buf, size_t len) -{ - unsigned char *b = buf; - ssize_t r, remain = len; - - /* - * XXX calling read here is wrong in many ways. The most obvious one - * being that we will block till data arrives. - * But for now it is _good enough_ *gulp* - */ - - while (remain > 0) { - if (ber->fd == -1) - r = ber_readbuf(ber, b, remain); - else - r = read(ber->fd, b, remain); - if (r == -1) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - if (r == 0) - return (b - (unsigned char *)buf); - b += r; - remain -= r; - } - return (b - (unsigned char *)buf); -} diff --git a/usr.sbin/smtpd/ber.h b/usr.sbin/smtpd/ber.h deleted file mode 100644 index 525e5451dd2..00000000000 --- a/usr.sbin/smtpd/ber.h +++ /dev/null @@ -1,128 +0,0 @@ -/* $OpenBSD: ber.h,v 1.4 2015/11/05 12:35:58 jung Exp $ */ - -/* - * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net> - * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -struct ber_element { - struct ber_element *be_next; - unsigned long be_type; - unsigned long be_encoding; - size_t be_len; - int be_free; - uint8_t be_class; - union { - struct ber_element *bv_sub; - void *bv_val; - long long bv_numeric; - } be_union; -#define be_sub be_union.bv_sub -#define be_val be_union.bv_val -#define be_numeric be_union.bv_numeric -}; - -struct ber { - int fd; - unsigned char *br_wbuf; - unsigned char *br_wptr; - unsigned char *br_wend; - unsigned char *br_rbuf; - unsigned char *br_rptr; - unsigned char *br_rend; - - unsigned long (*br_application)(struct ber_element *); -}; - -/* well-known ber_element types */ -#define BER_TYPE_DEFAULT ((unsigned long)-1) -#define BER_TYPE_EOC 0 -#define BER_TYPE_BOOLEAN 1 -#define BER_TYPE_INTEGER 2 -#define BER_TYPE_BITSTRING 3 -#define BER_TYPE_OCTETSTRING 4 -#define BER_TYPE_NULL 5 -#define BER_TYPE_OBJECT 6 -#define BER_TYPE_ENUMERATED 10 -#define BER_TYPE_SEQUENCE 16 -#define BER_TYPE_SET 17 - -/* ber classes */ -#define BER_CLASS_UNIVERSAL 0x0 -#define BER_CLASS_UNIV BER_CLASS_UNIVERSAL -#define BER_CLASS_APPLICATION 0x1 -#define BER_CLASS_APP BER_CLASS_APPLICATION -#define BER_CLASS_CONTEXT 0x2 -#define BER_CLASS_PRIVATE 0x3 -#define BER_CLASS_MASK 0x3 - -/* common definitions */ -#define BER_MIN_OID_LEN 2 /* OBJECT */ -#define BER_MAX_OID_LEN 32 /* OBJECT */ - -struct ber_oid { - uint32_t bo_id[BER_MAX_OID_LEN + 1]; - size_t bo_n; -}; - -__BEGIN_DECLS -struct ber_element *ber_get_element(unsigned long); -void ber_set_header(struct ber_element *, int, - unsigned long); -void ber_link_elements(struct ber_element *, - struct ber_element *); -struct ber_element *ber_unlink_elements(struct ber_element *); -void ber_replace_elements(struct ber_element *, - struct ber_element *); -struct ber_element *ber_add_sequence(struct ber_element *); -struct ber_element *ber_add_set(struct ber_element *); -struct ber_element *ber_add_integer(struct ber_element *, long long); -int ber_get_integer(struct ber_element *, long long *); -struct ber_element *ber_add_enumerated(struct ber_element *, long long); -int ber_get_enumerated(struct ber_element *, long long *); -struct ber_element *ber_add_boolean(struct ber_element *, int); -int ber_get_boolean(struct ber_element *, int *); -struct ber_element *ber_add_string(struct ber_element *, const char *); -struct ber_element *ber_add_nstring(struct ber_element *, const char *, - size_t); -int ber_get_string(struct ber_element *, char **); -int ber_get_nstring(struct ber_element *, void **, - size_t *); -struct ber_element *ber_add_bitstring(struct ber_element *, const void *, - size_t); -int ber_get_bitstring(struct ber_element *, void **, - size_t *); -struct ber_element *ber_add_null(struct ber_element *); -int ber_get_null(struct ber_element *); -struct ber_element *ber_add_eoc(struct ber_element *); -int ber_get_eoc(struct ber_element *); -struct ber_element *ber_add_oid(struct ber_element *, struct ber_oid *); -struct ber_element *ber_add_noid(struct ber_element *, struct ber_oid *, int); -struct ber_element *ber_add_oidstring(struct ber_element *, const char *); -int ber_get_oid(struct ber_element *, struct ber_oid *); -size_t ber_oid2ber(struct ber_oid *, uint8_t *, size_t); -int ber_string2oid(const char *, struct ber_oid *); -struct ber_element *ber_printf_elements(struct ber_element *, char *, ...); -int ber_scanf_elements(struct ber_element *, char *, ...); -ssize_t ber_get_writebuf(struct ber *, void **); -int ber_write_elements(struct ber *, struct ber_element *); -void ber_set_readbuf(struct ber *, void *, size_t); -struct ber_element *ber_read_elements(struct ber *, struct ber_element *); -void ber_free_elements(struct ber_element *); -size_t ber_calc_len(struct ber_element *); -void ber_set_application(struct ber *, - unsigned long (*)(struct ber_element *)); -void ber_free(struct ber *); -__END_DECLS diff --git a/usr.sbin/smtpd/table-ldap/Makefile b/usr.sbin/smtpd/table-ldap/Makefile deleted file mode 100644 index 2b9d700dff6..00000000000 --- a/usr.sbin/smtpd/table-ldap/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# $OpenBSD: Makefile,v 1.5 2015/10/06 00:30:32 deraadt Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= table-ldap - -SRCS= table_ldap.c -SRCS+= table_api.c -SRCS+= aldap.c -SRCS+= ber.c -SRCS+= dict.c -SRCS+= log.c - -NOMAN= noman - -BINDIR= /usr/libexec/smtpd - -DPADD= ${LIBUTIL} -LDADD= -lutil - -CFLAGS+= -fstack-protector-all -CFLAGS+= -I${.CURDIR}/.. -CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes -CFLAGS+= -Wmissing-declarations -CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual -CFLAGS+= -Wsign-compare -CFLAGS+= -DNO_IO -#CFLAGS+= -Werror # during development phase (breaks some archs) - -.include <bsd.prog.mk> diff --git a/usr.sbin/smtpd/table-passwd/Makefile b/usr.sbin/smtpd/table-passwd/Makefile deleted file mode 100644 index b542368b71d..00000000000 --- a/usr.sbin/smtpd/table-passwd/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# $OpenBSD: Makefile,v 1.5 2015/10/06 00:30:32 deraadt Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= table-passwd - -SRCS= table_passwd.c -SRCS+= table_api.c -SRCS+= dict.c -SRCS+= log.c - -MAN= table_passwd.5 - -BINDIR= /usr/libexec/smtpd - -DPADD= ${LIBUTIL} -LDADD= -lutil - -CFLAGS+= -fstack-protector-all -CFLAGS+= -I${.CURDIR}/.. -CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes -CFLAGS+= -Wmissing-declarations -CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual -CFLAGS+= -Wsign-compare -CFLAGS+= -DNO_IO -#CFLAGS+= -Werror # during development phase (breaks some archs) - -.include <bsd.prog.mk> diff --git a/usr.sbin/smtpd/table-sqlite/Makefile b/usr.sbin/smtpd/table-sqlite/Makefile deleted file mode 100644 index eb69c00f1b3..00000000000 --- a/usr.sbin/smtpd/table-sqlite/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# $OpenBSD: Makefile,v 1.4 2015/10/06 00:30:32 deraadt Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= table-sqlite - -SRCS= table_sqlite.c -SRCS+= table_api.c -SRCS+= dict.c -SRCS+= log.c - -NOMAN= noman - -BINDIR= /usr/libexec/smtpd - -DPADD= ${LIBUTIL} ${LIBSQLITE3} -LDADD= -lutil -lsqlite3 - -CFLAGS+= -fstack-protector-all -CFLAGS+= -I${.CURDIR}/.. -CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes -CFLAGS+= -Wmissing-declarations -CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual -CFLAGS+= -Wsign-compare -CFLAGS+= -DNO_IO -#CFLAGS+= -Werror # during development phase (breaks some archs) - -.include <bsd.prog.mk> diff --git a/usr.sbin/smtpd/table_ldap.c b/usr.sbin/smtpd/table_ldap.c deleted file mode 100644 index cc650f33b23..00000000000 --- a/usr.sbin/smtpd/table_ldap.c +++ /dev/null @@ -1,569 +0,0 @@ -/* $OpenBSD: table_ldap.c,v 1.15 2015/10/11 12:50:00 sunil Exp $ */ - -/* - * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/tree.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <netdb.h> - -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <limits.h> - -#include "smtpd-defines.h" -#include "smtpd-api.h" -#include "log.h" -#include "aldap.h" - -#define MAX_LDAP_IDENTIFIER 32 -#define MAX_LDAP_URL 256 -#define MAX_LDAP_USERNAME 256 -#define MAX_LDAP_PASSWORD 256 -#define MAX_LDAP_BASELEN 128 -#define MAX_LDAP_FILTERLEN 1024 -#define MAX_LDAP_FIELDLEN 128 - - -enum { - LDAP_ALIAS = 0, - LDAP_DOMAIN, - LDAP_CREDENTIALS, - LDAP_NETADDR, - LDAP_USERINFO, - LDAP_SOURCE, - LDAP_MAILADDR, - LDAP_ADDRNAME, - - LDAP_MAX -}; - -#define MAX_ATTRS 6 - -struct query { - char *filter; - char *attrs[MAX_ATTRS]; - int attrn; -}; - -static int table_ldap_update(void); -static int table_ldap_check(int, struct dict *, const char *); -static int table_ldap_lookup(int, struct dict *, const char *, char *, size_t); -static int table_ldap_fetch(int, struct dict *, char *, size_t); - -static int ldap_config(void); -static int ldap_open(void); -static int ldap_query(const char *, char **, char ***, size_t); -static int ldap_parse_attributes(struct query *, const char *, const char *, size_t); -static int ldap_run_query(int type, const char *, char *, size_t); - -static char *config; - -static char *url; -static char *username; -static char *password; -static char *basedn; - -static struct aldap *aldap; -static struct query queries[LDAP_MAX]; - -int -main(int argc, char **argv) -{ - int ch; - - log_init(1); - log_verbose(~0); - - while ((ch = getopt(argc, argv, "")) != -1) { - switch (ch) { - default: - log_warnx("warn: table-ldap: bad option"); - return (1); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - if (argc != 1) { - log_warnx("warn: table-ldap: bogus argument(s)"); - return (1); - } - - config = argv[0]; - - if (!ldap_config()) { - log_warnx("warn: table-ldap: could not parse config"); - return (1); - } - - log_debug("debug: table-ldap: done reading config"); - - if (!ldap_open()) { - log_warnx("warn: table-ldap: failed to connect"); - return (1); - } - - log_debug("debug: table-ldap: connected"); - - table_api_on_update(table_ldap_update); - table_api_on_check(table_ldap_check); - table_api_on_lookup(table_ldap_lookup); - table_api_on_fetch(table_ldap_fetch); - table_api_dispatch(); - - return (0); -} - -static int -table_ldap_update(void) -{ - return (1); -} - -static int -table_ldap_check(int service, struct dict *params, const char *key) -{ - switch(service) { - case K_ALIAS: - case K_DOMAIN: - case K_CREDENTIALS: - case K_USERINFO: - case K_MAILADDR: - return ldap_run_query(service, key, NULL, 0); - default: - return (-1); - } -} - -static int -table_ldap_lookup(int service, struct dict *params, const char *key, char *dst, size_t sz) -{ - switch(service) { - case K_ALIAS: - case K_DOMAIN: - case K_CREDENTIALS: - case K_USERINFO: - case K_MAILADDR: - return ldap_run_query(service, key, dst, sz); - default: - return (-1); - } -} - -static int -table_ldap_fetch(int service, struct dict *params, char *dst, size_t sz) -{ - return (-1); -} - -static struct aldap * -ldap_connect(const char *addr) -{ - struct aldap_url lu; - struct addrinfo hints, *res0, *res; - char *buf; - int error, fd = -1; - - if ((buf = strdup(addr)) == NULL) - return (NULL); - - /* aldap_parse_url frees buf on success */ - if (aldap_parse_url(buf, &lu) != 1) { - log_warnx("warn: table-ldap: ldap_parse_url fail"); - free(buf); - return (NULL); - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; /* DUMMY */ - error = getaddrinfo(lu.host, NULL, &hints, &res0); - if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) - return (NULL); - if (error) { - log_warnx("warn: table-ldap: could not parse \"%s\": %s", - lu.host, gai_strerror(error)); - return (NULL); - } - - for (res = res0; res; res = res->ai_next) { - if (res->ai_family != AF_INET && res->ai_family != AF_INET6) - continue; - - fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (fd == -1) - continue; - - if (res->ai_family == AF_INET) { - struct sockaddr_in sin4 = *(struct sockaddr_in *)res->ai_addr; - sin4.sin_port = htons(lu.port); - if (connect(fd, (struct sockaddr *)&sin4, res->ai_addrlen) == 0) - return aldap_init(fd); - } - else if (res->ai_family == AF_INET6) { - struct sockaddr_in6 sin6 = *(struct sockaddr_in6 *)res->ai_addr; - sin6.sin6_port = htons(lu.port); - if (connect(fd, (struct sockaddr *)&sin6, res->ai_addrlen) == 0) - return aldap_init(fd); - } - - close(fd); - fd = -1; - } - - return (NULL); -} - -static int -read_value(char **store, const char *key, const char *value) -{ - log_debug("debug: table-ldap: reading key \"%s\" -> \"%s\"", - key, value); - - if (*store) { - log_warnx("warn: table-ldap: duplicate key %s", key); - return (0); - } - - if ((*store = strdup(value)) == NULL) { - log_warn("warn: table-ldap: strdup"); - return (0); - } - - return (1); -} - -static int -ldap_parse_attributes(struct query *query, const char *key, const char *line, - size_t expect) -{ - char buffer[1024]; - char *p; - size_t m, n; - - log_debug("debug: table-ldap: parsing attribute \"%s\" (%zu) -> \"%s\"", - key, expect, line); - - if (strlcpy(buffer, line, sizeof buffer) >= sizeof buffer) - return (0); - - m = 1; - for (p = buffer; *p; ++p) { - if (*p == ',') { - *p = 0; - m++; - } - } - if (expect != m) - return (0); - - p = buffer; - for (n = 0; n < expect; ++n) - query->attrs[n] = NULL; - for (n = 0; n < m; ++n) { - query->attrs[n] = strdup(p); - if (query->attrs[n] == NULL) { - log_warnx("warn: table-ldap: strdup"); - return (0); /* XXX cleanup */ - } - p += strlen(p) + 1; - query->attrn++; - } - return (1); -} - -static int -ldap_config(void) -{ - size_t sz = 0; - ssize_t flen; - FILE *fp; - char *key, *value, *buf = NULL; - - fp = fopen(config, "r"); - if (fp == NULL) - return (0); - - while ((flen = getline(&buf, &sz, fp)) != -1) { - if (buf[flen - 1] == '\n') - buf[flen - 1] = '\0'; - - key = buf; - while (isspace((unsigned char)*key)) - ++key; - if (*key == '\0' || *key == '#') - continue; - value = key; - strsep(&value, " \t:"); - if (value) { - while (*value) { - if (!isspace((unsigned char)*value) && - !(*value == ':' && isspace((unsigned char)*(value + 1)))) - break; - ++value; - } - if (*value == '\0') - value = NULL; - } - - if (value == NULL) { - log_warnx("warn: table-ldap: missing value for key %s", key); - continue; - } - - if (!strcmp(key, "url")) - read_value(&url, key, value); - else if (!strcmp(key, "username")) - read_value(&username, key, value); - else if (!strcmp(key, "password")) - read_value(&password, key, value); - else if (!strcmp(key, "basedn")) - read_value(&basedn, key, value); - - else if (!strcmp(key, "alias_filter")) - read_value(&queries[LDAP_ALIAS].filter, key, value); - else if (!strcmp(key, "alias_attributes")) { - ldap_parse_attributes(&queries[LDAP_ALIAS], - key, value, 1); - } - - else if (!strcmp(key, "credentials_filter")) - read_value(&queries[LDAP_CREDENTIALS].filter, key, value); - else if (!strcmp(key, "credentials_attributes")) { - ldap_parse_attributes(&queries[LDAP_CREDENTIALS], - key, value, 2); - } - - else if (!strcmp(key, "domain_filter")) - read_value(&queries[LDAP_DOMAIN].filter, key, value); - else if (!strcmp(key, "domain_attributes")) { - ldap_parse_attributes(&queries[LDAP_DOMAIN], - key, value, 1); - } - - else if (!strcmp(key, "userinfo_filter")) - read_value(&queries[LDAP_USERINFO].filter, key, value); - else if (!strcmp(key, "userinfo_attributes")) { - ldap_parse_attributes(&queries[LDAP_USERINFO], - key, value, 3); - } - - else if (!strcmp(key, "mailaddr_filter")) - read_value(&queries[LDAP_MAILADDR].filter, key, value); - else if (!strcmp(key, "mailaddr_attributes")) { - ldap_parse_attributes(&queries[LDAP_MAILADDR], - key, value, 1); - } - else - log_warnx("warn: table-ldap: bogus entry \"%s\"", key); - } - - free(buf); - fclose(fp); - return (1); -} - -static int -ldap_open(void) -{ - struct aldap_message *amsg = NULL; - - aldap = ldap_connect(url); - if (aldap == NULL) { - log_warnx("warn: table-ldap: ldap_connect error"); - goto err; - } - - if (aldap_bind(aldap, username, password) == -1) { - log_warnx("warn: table-ldap: aldap_bind error"); - goto err; - } - - if ((amsg = aldap_parse(aldap)) == NULL) { - log_warnx("warn: table-ldap: aldap_parse"); - goto err; - } - - switch (aldap_get_resultcode(amsg)) { - case LDAP_SUCCESS: - log_debug("debug: table-ldap: ldap server accepted credentials"); - break; - case LDAP_INVALID_CREDENTIALS: - log_warnx("warn: table-ldap: ldap server refused credentials"); - goto err; - default: - log_warnx("warn: table-ldap: failed to bind, result #%d", - aldap_get_resultcode(amsg)); - goto err; - } - - if (amsg) - aldap_freemsg(amsg); - return (1); - -err: - if (aldap) - aldap_close(aldap); - if (amsg) - aldap_freemsg(amsg); - return (0); -} - -static int -ldap_query(const char *filter, char **attributes, char ***outp, size_t n) -{ - struct aldap_message *m = NULL; - struct aldap_page_control *pg = NULL; - int ret, found; - size_t i; - char basedn__[MAX_LDAP_BASELEN]; - char filter__[MAX_LDAP_FILTERLEN]; - - if (strlcpy(basedn__, basedn, sizeof basedn__) >= sizeof basedn__) - return -1; - if (strlcpy(filter__, filter, sizeof filter__) >= sizeof filter__) - return -1; - found = 0; - do { - if ((ret = aldap_search(aldap, basedn__, LDAP_SCOPE_SUBTREE, - filter__, NULL, 0, 0, 0, pg)) == -1) { - log_debug("ret=%d", ret); - return -1; - } - if (pg != NULL) { - aldap_freepage(pg); - pg = NULL; - } - - while ((m = aldap_parse(aldap)) != NULL) { - if (aldap->msgid != m->msgid) - goto error; - if (m->message_type == LDAP_RES_SEARCH_RESULT) { - if (m->page != NULL && m->page->cookie_len) - pg = m->page; - aldap_freemsg(m); - m = NULL; - break; - } - if (m->message_type != LDAP_RES_SEARCH_ENTRY) - goto error; - - found = 1; - for (i = 0; i < n; ++i) - if (aldap_match_attr(m, attributes[i], &outp[i]) != 1) - goto error; - aldap_freemsg(m); - m = NULL; - } - } while (pg != NULL); - - ret = found ? 1 : 0; - goto end; - -error: - ret = -1; - -end: - if (m) - aldap_freemsg(m); - log_debug("debug: table_ldap: ldap_query: filter=%s, ret=%d", filter, ret); - return ret; -} - -static int -ldap_run_query(int type, const char *key, char *dst, size_t sz) -{ - struct query *q; - char **res[4], filter[MAX_LDAP_FILTERLEN]; - int ret, i; - - switch (type) { - case K_ALIAS: q = &queries[LDAP_ALIAS]; break; - case K_DOMAIN: q = &queries[LDAP_DOMAIN]; break; - case K_CREDENTIALS: q = &queries[LDAP_CREDENTIALS]; break; - case K_NETADDR: q = &queries[LDAP_NETADDR]; break; - case K_USERINFO: q = &queries[LDAP_USERINFO]; break; - case K_SOURCE: q = &queries[LDAP_SOURCE]; break; - case K_MAILADDR: q = &queries[LDAP_MAILADDR]; break; - case K_ADDRNAME: q = &queries[LDAP_ADDRNAME]; break; - default: - return (-1); - } - - if (snprintf(filter, sizeof(filter), q->filter, key) - >= (int)sizeof(filter)) { - log_warnx("warn: table-ldap: filter too large"); - return (-1); - } - - memset(res, 0, sizeof(res)); - ret = ldap_query(filter, q->attrs, res, q->attrn); - if (ret <= 0 || dst == NULL) - goto end; - - switch (type) { - - case K_ALIAS: - memset(dst, 0, sz); - for (i = 0; res[0][i]; i++) { - if (i && strlcat(dst, ", ", sz) >= sz) { - ret = -1; - break; - } - if (strlcat(dst, res[0][i], sz) >= sz) { - ret = -1; - break; - } - } - break; - case K_DOMAIN: - case K_MAILADDR: - if (strlcpy(dst, res[0][0], sz) >= sz) - ret = -1; - break; - case K_CREDENTIALS: - if (snprintf(dst, sz, "%s:%s", res[0][0], res[1][0]) >= (int)sz) - ret = -1; - break; - case K_USERINFO: - if (snprintf(dst, sz, "%s:%s:%s", res[0][0], res[1][0], - res[2][0]) >= (int)sz) - ret = -1; - break; - default: - log_warnx("warn: table-ldap: unsupported lookup kind"); - ret = -1; - } - - if (ret == -1) - log_warnx("warn: table-ldap: could not format result"); - -end: - for (i = 0; i < q->attrn; ++i) - if (res[i]) - aldap_free_attr(res[i]); - - return (ret); -} diff --git a/usr.sbin/smtpd/table_passwd.5 b/usr.sbin/smtpd/table_passwd.5 deleted file mode 100644 index 847324e98cd..00000000000 --- a/usr.sbin/smtpd/table_passwd.5 +++ /dev/null @@ -1,64 +0,0 @@ -.\" $OpenBSD: table_passwd.5,v 1.2 2014/02/04 17:47:02 jmc Exp $ -.\" -.\" Copyright (c) 2014 Gilles Chehade <gilles@poolp.org> -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" -.Dd $Mdocdate: February 4 2014 $ -.Dt TABLE_PASSWD 5 -.Os -.Sh NAME -.Nm table_passwd -.Nd format description for smtpd passwd tables -.Sh DESCRIPTION -This manual page documents the file format of "passwd" tables used by the -.Xr smtpd 8 -mail daemon. -.Pp -The format described here applies to tables as defined in -.Xr smtpd.conf 5 . -.Sh PASSWD TABLE -A "passwd" table stores information regarding local users. -The information is encoded using the traditional -.Xr passwd 5 -format and allows the sharing of a user database across different software -supporting this format. -.Pp -The table is used by -.Xr smtpd 8 -when authenticating a user or when user information such as user-id or -home directory is required for a delivery. -.Pp -A "passwd" table consists of a flat file containing the user entries, each -one on a line by itself, with fields separated by a colon: -.Bd -literal -offset indent -gilles:*:1000:1000:Gilles:/home/gilles:/sbin/nologin -eric:*:1001:1001:Eric:/home/eric:/sbin/nologin -chl:*:1002:1002:Charles:/home/chl:/sbin/nologin -.Ed -.Pp -If the table is used for authentication, the second field may contain a -password encrypted using the -.Xr crypt 3 -function. -Such passwords can be generated using the -.Xr encrypt 1 -utility or -.Xr smtpctl 8 -encrypt command. -.Sh SEE ALSO -.Xr passwd 5 , -.Xr smtpd.conf 5 , -.Xr smtpctl 8 , -.Xr smtpd 8 diff --git a/usr.sbin/smtpd/table_passwd.c b/usr.sbin/smtpd/table_passwd.c deleted file mode 100644 index 7cef61a83e4..00000000000 --- a/usr.sbin/smtpd/table_passwd.c +++ /dev/null @@ -1,267 +0,0 @@ -/* $OpenBSD: table_passwd.c,v 1.11 2015/10/11 12:50:00 sunil Exp $ */ - -/* - * Copyright (c) 2013 Gilles Chehade <gilles@poolp.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/tree.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <netdb.h> - -#include <err.h> -#include <pwd.h> -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <string.h> -#include <unistd.h> - -#include "smtpd-defines.h" -#include "smtpd-api.h" -#include "log.h" - -static int table_passwd_update(void); -static int table_passwd_check(int, struct dict *, const char *); -static int table_passwd_lookup(int, struct dict *, const char *, char *, size_t); -static int table_passwd_fetch(int, struct dict *, char *, size_t); -static int parse_passwd_entry(struct passwd *, char *); - -static char *config; -static struct dict *passwd; - -int -main(int argc, char **argv) -{ - int ch; - - log_init(1); - - while ((ch = getopt(argc, argv, "")) != -1) { - switch (ch) { - default: - log_warnx("warn: table-passwd: bad option"); - return (1); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - if (argc != 1) { - log_warnx("warn: table-passwd: bogus argument(s)"); - return (1); - } - - config = argv[0]; - - if (table_passwd_update() == 0) { - log_warnx("warn: table-passwd: error parsing config file"); - return (1); - } - - table_api_on_update(table_passwd_update); - table_api_on_check(table_passwd_check); - table_api_on_lookup(table_passwd_lookup); - table_api_on_fetch(table_passwd_fetch); - table_api_dispatch(); - - return (0); -} - -static int -table_passwd_update(void) -{ - FILE *fp; - char *buf = NULL, *p; - char tmp[LINE_MAX]; - size_t sz = 0; - ssize_t len; - char *line; - struct passwd pw; - struct dict *npasswd; - - /* Parse configuration */ - fp = fopen(config, "r"); - if (fp == NULL) - return (0); - - npasswd = calloc(1, sizeof *passwd); - if (npasswd == NULL) - goto err; - - dict_init(npasswd); - - while ((len = getline(&buf, &sz, fp)) != -1) { - if (buf[len - 1] == '\n') - buf[len - 1] = '\0'; - - if (strlcpy(tmp, buf, sizeof tmp) >= sizeof tmp) { - log_warnx("warn: table-passwd: line too long"); - goto err; - } - if (! parse_passwd_entry(&pw, tmp)) { - log_warnx("warn: table-passwd: invalid entry"); - goto err; - } - if ((line = strdup(buf)) == NULL) - err(1, NULL); - dict_set(npasswd, pw.pw_name, line); - } - fclose(fp); - - /* swap passwd table and release old one*/ - if (passwd) - while (dict_poproot(passwd, (void**)&p)) - free(p); - passwd = npasswd; - - return (1); - -err: - if (fp) - fclose(fp); - free(buf); - - /* release passwd table */ - if (npasswd) { - while (dict_poproot(npasswd, (void**)&p)) - free(p); - free(npasswd); - } - return (0); -} - -static int -table_passwd_check(int service, struct dict *params, const char *key) -{ - return (-1); -} - -static int -table_passwd_lookup(int service, struct dict *params, const char *key, char *dst, size_t sz) -{ - int r; - struct passwd pw; - char *line; - char tmp[LINE_MAX]; - - line = dict_get(passwd, key); - if (line == NULL) - return 0; - - (void)strlcpy(tmp, line, sizeof tmp); - if (! parse_passwd_entry(&pw, tmp)) { - log_warnx("warn: table-passwd: invalid entry"); - return -1; - } - - r = 1; - switch (service) { - case K_CREDENTIALS: - if (snprintf(dst, sz, "%s:%s", - pw.pw_name, pw.pw_passwd) >= (ssize_t)sz) { - log_warnx("warn: table-passwd: result too large"); - r = -1; - } - break; - case K_USERINFO: - if (snprintf(dst, sz, "%d:%d:%s", - pw.pw_uid, pw.pw_gid, pw.pw_dir) - >= (ssize_t)sz) { - log_warnx("warn: table-passwd: result too large"); - r = -1; - } - break; - default: - log_warnx("warn: table-passwd: unknown service %d", - service); - r = -1; - } - - return (r); -} - -static int -table_passwd_fetch(int service, struct dict *params, char *dst, size_t sz) -{ - return (-1); -} - -static int -parse_passwd_entry(struct passwd *pw, char *buf) -{ - const char *errstr; - char *p, *q; - - p = buf; - - /* username */ - q = p; - if ((p = strchr(q, ':')) == NULL) - return 0; - *p++ = 0; - pw->pw_name = q; - - /* password */ - q = p; - if ((p = strchr(q, ':')) == NULL) - return 0; - *p++ = 0; - pw->pw_passwd = q; - - /* uid */ - q = p; - if ((p = strchr(q, ':')) == NULL) - return 0; - *p++ = 0; - pw->pw_uid = strtonum(q, 1, UID_MAX, &errstr); - if (errstr) - return 0; - - /* gid */ - q = p; - if ((p = strchr(q, ':')) == NULL) - return 0; - *p++ = 0; - pw->pw_gid = strtonum(q, 1, GID_MAX, &errstr); - if (errstr) - return 0; - - /* gecos */ - q = p; - if ((p = strchr(q, ':')) == NULL) - return 0; - *p++ = 0; - pw->pw_gecos = q; - - /* home */ - q = p; - if ((p = strchr(q, ':')) == NULL) - return 0; - *p++ = 0; - pw->pw_dir = q; - - /* shell */ - q = p; - if (strchr(q, ':') != NULL) - return 0; - pw->pw_shell = q; - - return 1; -} diff --git a/usr.sbin/smtpd/table_sqlite.c b/usr.sbin/smtpd/table_sqlite.c deleted file mode 100644 index f65be0e59bc..00000000000 --- a/usr.sbin/smtpd/table_sqlite.c +++ /dev/null @@ -1,523 +0,0 @@ -/* $OpenBSD: table_sqlite.c,v 1.17 2015/10/11 12:50:00 sunil Exp $ */ - -/* - * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/tree.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <netdb.h> - -#include <ctype.h> -#include <fcntl.h> -#include <sqlite3.h> -#include <stdio.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <limits.h> - -#include "smtpd-defines.h" -#include "smtpd-api.h" -#include "log.h" - -enum { - SQL_ALIAS = 0, - SQL_DOMAIN, - SQL_CREDENTIALS, - SQL_NETADDR, - SQL_USERINFO, - SQL_SOURCE, - SQL_MAILADDR, - SQL_ADDRNAME, - - SQL_MAX -}; - -static int table_sqlite_update(void); -static int table_sqlite_lookup(int, struct dict *, const char *, char *, size_t); -static int table_sqlite_check(int, struct dict *, const char *); -static int table_sqlite_fetch(int, struct dict *, char *, size_t); - -static sqlite3_stmt *table_sqlite_query(const char *, int); - -#define DEFAULT_EXPIRE 60 -#define DEFAULT_REFRESH 1000 - -static char *config; -static sqlite3 *db; -static sqlite3_stmt *statements[SQL_MAX]; -static sqlite3_stmt *stmt_fetch_source; -static struct dict sources; -static void *source_iter; -static size_t source_refresh = 1000; -static size_t source_ncall; -static int source_expire = 60; -static time_t source_update; - -int -main(int argc, char **argv) -{ - int ch; - - log_init(1); - log_verbose(~0); - - while ((ch = getopt(argc, argv, "")) != -1) { - switch (ch) { - default: - log_warnx("warn: table-sqlite: bad option"); - return (1); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - if (argc != 1) { - log_warnx("warn: table-sqlite: bogus argument(s)"); - return (1); - } - - config = argv[0]; - - dict_init(&sources); - - if (table_sqlite_update() == 0) { - log_warnx("warn: table-sqlite: error parsing config file"); - return (1); - } - - table_api_on_update(table_sqlite_update); - table_api_on_check(table_sqlite_check); - table_api_on_lookup(table_sqlite_lookup); - table_api_on_fetch(table_sqlite_fetch); - table_api_dispatch(); - - return (0); -} - -static int -table_sqlite_getconfstr(const char *key, const char *value, char **var) -{ - if (*var) { - log_warnx("warn: table-sqlite: duplicate %s %s", key, value); - free(*var); - } - *var = strdup(value); - if (*var == NULL) { - log_warn("warn: table-sqlite: strdup"); - return (-1); - } - return (0); -} - -static sqlite3_stmt * -table_sqlite_prepare_stmt(sqlite3 *_db, const char *query, int ncols) -{ - sqlite3_stmt *stmt; - - if (sqlite3_prepare_v2(_db, query, -1, &stmt, 0) != SQLITE_OK) { - log_warnx("warn: table-sqlite: sqlite3_prepare_v2: %s", - sqlite3_errmsg(_db)); - goto end; - } - if (sqlite3_column_count(stmt) != ncols) { - log_warnx("warn: table-sqlite: columns: invalid columns count for query: %s", query); - goto end; - } - - return (stmt); - end: - sqlite3_finalize(stmt); - return (NULL); -} - -static int -table_sqlite_update(void) -{ - static const struct { - const char *name; - int cols; - } qspec[SQL_MAX] = { - { "query_alias", 1 }, - { "query_domain", 1 }, - { "query_credentials", 2 }, - { "query_netaddr", 1 }, - { "query_userinfo", 3 }, - { "query_source", 1 }, - { "query_mailaddr", 1 }, - { "query_addrname", 1 }, - }; - sqlite3 *_db; - sqlite3_stmt *_statements[SQL_MAX]; - sqlite3_stmt *_stmt_fetch_source; - char *_query_fetch_source; - char *queries[SQL_MAX]; - ssize_t flen; - size_t sz = 0, _source_refresh; - int _source_expire; - FILE *fp; - char *key, *value, *buf = NULL, *dbpath; - const char *e; - int i, ret; - long long ll; - - dbpath = NULL; - _db = NULL; - memset(queries, 0, sizeof(queries)); - memset(_statements, 0, sizeof(_statements)); - _query_fetch_source = NULL; - _stmt_fetch_source = NULL; - - _source_refresh = DEFAULT_REFRESH; - _source_expire = DEFAULT_EXPIRE; - - ret = 0; - - /* Parse configuration */ - - fp = fopen(config, "r"); - if (fp == NULL) - return (0); - - while ((flen = getline(&buf, &sz, fp)) != -1) { - if (buf[flen - 1] == '\n') - buf[flen - 1] = '\0'; - - key = buf; - while (isspace((unsigned char)*key)) - ++key; - if (*key == '\0' || *key == '#') - continue; - value = key; - strsep(&value, " \t:"); - if (value) { - while (*value) { - if (!isspace((unsigned char)*value) && - !(*value == ':' && isspace((unsigned char)*(value + 1)))) - break; - ++value; - } - if (*value == '\0') - value = NULL; - } - - if (value == NULL) { - log_warnx("warn: table-sqlite: missing value for key %s", key); - continue; - } - - if (!strcmp("dbpath", key)) { - if (table_sqlite_getconfstr(key, value, &dbpath) == -1) - goto end; - continue; - } - if (!strcmp("fetch_source", key)) { - if (table_sqlite_getconfstr(key, value, &_query_fetch_source) == -1) - goto end; - continue; - } - if (!strcmp("fetch_source_expire", key)) { - e = NULL; - ll = strtonum(value, 0, INT_MAX, &e); - if (e) { - log_warnx("warn: table-sqlite: bad value for %s: %s", key, e); - goto end; - } - _source_expire = ll; - continue; - } - if (!strcmp("fetch_source_refresh", key)) { - e = NULL; - ll = strtonum(value, 0, INT_MAX, &e); - if (e) { - log_warnx("warn: table-sqlite: bad value for %s: %s", key, e); - goto end; - } - _source_refresh = ll; - continue; - } - - for(i = 0; i < SQL_MAX; i++) - if (!strcmp(qspec[i].name, key)) - break; - if (i == SQL_MAX) { - log_warnx("warn: table-sqlite: bogus key %s", key); - continue; - } - - if (queries[i]) { - log_warnx("warn: table-sqlite: duplicate key %s", key); - continue; - } - - queries[i] = strdup(value); - if (queries[i] == NULL) { - log_warnx("warn: table-sqlite: strdup"); - goto end; - } - } - - /* Setup db */ - - log_debug("debug: table-sqlite: opening %s", dbpath); - - if (sqlite3_open(dbpath, &_db) != SQLITE_OK) { - log_warnx("warn: table-sqlite: open: %s", - sqlite3_errmsg(_db)); - goto end; - } - - for (i = 0; i < SQL_MAX; i++) { - if (queries[i] == NULL) - continue; - if ((_statements[i] = table_sqlite_prepare_stmt(_db, queries[i], qspec[i].cols)) == NULL) - goto end; - } - - if (_query_fetch_source && - (_stmt_fetch_source = table_sqlite_prepare_stmt(_db, _query_fetch_source, 1)) == NULL) - goto end; - - /* Replace previous setup */ - - for (i = 0; i < SQL_MAX; i++) { - if (statements[i]) - sqlite3_finalize(statements[i]); - statements[i] = _statements[i]; - _statements[i] = NULL; - } - if (stmt_fetch_source) - sqlite3_finalize(stmt_fetch_source); - stmt_fetch_source = _stmt_fetch_source; - _stmt_fetch_source = NULL; - - if (db) - sqlite3_close(_db); - db = _db; - _db = NULL; - - source_update = 0; /* force update */ - source_expire = _source_expire; - source_refresh = _source_refresh; - - log_debug("debug: table-sqlite: config successfully updated"); - ret = 1; - - end: - - /* Cleanup */ - for (i = 0; i < SQL_MAX; i++) { - if (_statements[i]) - sqlite3_finalize(_statements[i]); - free(queries[i]); - } - if (_db) - sqlite3_close(_db); - - free(dbpath); - free(_query_fetch_source); - - free(buf); - fclose(fp); - return (ret); -} - -static sqlite3_stmt * -table_sqlite_query(const char *key, int service) -{ - int i; - sqlite3_stmt *stmt; - - stmt = NULL; - for(i = 0; i < SQL_MAX; i++) - if (service == (1 << i)) { - stmt = statements[i]; - break; - } - - if (stmt == NULL) - return (NULL); - - if (sqlite3_bind_text(stmt, 1, key, strlen(key), NULL) != SQLITE_OK) { - log_warnx("warn: table-sqlite: sqlite3_bind_text: %s", - sqlite3_errmsg(db)); - return (NULL); - } - - return (stmt); -} - -static int -table_sqlite_check(int service, struct dict *params, const char *key) -{ - sqlite3_stmt *stmt; - int r; - - stmt = table_sqlite_query(key, service); - if (stmt == NULL) - return (-1); - - r = sqlite3_step(stmt); - sqlite3_reset(stmt); - - if (r == SQLITE_ROW) - return (1); - - if (r == SQLITE_DONE) - return (0); - - return (-1); -} - -static int -table_sqlite_lookup(int service, struct dict *params, const char *key, char *dst, size_t sz) -{ - sqlite3_stmt *stmt; - const char *value; - int r, s; - - stmt = table_sqlite_query(key, service); - if (stmt == NULL) - return (-1); - - s = sqlite3_step(stmt); - if (s == SQLITE_DONE) { - sqlite3_reset(stmt); - return (0); - } - - if (s != SQLITE_ROW) { - log_warnx("warn: table-sqlite: sqlite3_step: %s", - sqlite3_errmsg(db)); - sqlite3_reset(stmt); - return (-1); - } - - r = 1; - - switch(service) { - case K_ALIAS: - memset(dst, 0, sz); - do { - value = sqlite3_column_text(stmt, 0); - if (dst[0] && strlcat(dst, ", ", sz) >= sz) { - log_warnx("warn: table-sqlite: result too large"); - r = -1; - break; - } - if (strlcat(dst, value, sz) >= sz) { - log_warnx("warn: table-sqlite: result too large"); - r = -1; - break; - } - s = sqlite3_step(stmt); - } while (s == SQLITE_ROW); - if (s != SQLITE_ROW && s != SQLITE_DONE) { - log_warnx("warn: table-sqlite: sqlite3_step: %s", - sqlite3_errmsg(db)); - r = -1; - } - break; - case K_CREDENTIALS: - if (snprintf(dst, sz, "%s:%s", - sqlite3_column_text(stmt, 0), - sqlite3_column_text(stmt, 1)) >= (ssize_t)sz) { - log_warnx("warn: table-sqlite: result too large"); - r = -1; - } - break; - case K_USERINFO: - if (snprintf(dst, sz, "%d:%d:%s", - sqlite3_column_int(stmt, 0), - sqlite3_column_int(stmt, 1), - sqlite3_column_text(stmt, 2)) >= (ssize_t)sz) { - log_warnx("warn: table-sqlite: result too large"); - r = -1; - } - break; - case K_DOMAIN: - case K_NETADDR: - case K_SOURCE: - case K_MAILADDR: - case K_ADDRNAME: - if (strlcpy(dst, sqlite3_column_text(stmt, 0), sz) >= sz) { - log_warnx("warn: table-sqlite: result too large"); - r = -1; - } - break; - default: - log_warnx("warn: table-sqlite: unknown service %d", service); - r = -1; - } - - sqlite3_reset(stmt); - return (r); -} - -static int -table_sqlite_fetch(int service, struct dict *params, char *dst, size_t sz) -{ - const char *k; - int s; - - if (service != K_SOURCE) - return (-1); - - if (stmt_fetch_source == NULL) - return (-1); - - if (source_ncall < source_refresh && - time(NULL) - source_update < source_expire) - goto fetch; - - source_iter = NULL; - while (dict_poproot(&sources, NULL)) - ; - - while ((s = sqlite3_step(stmt_fetch_source)) == SQLITE_ROW) - dict_set(&sources, sqlite3_column_text(stmt_fetch_source, 0), NULL); - - if (s != SQLITE_DONE) - log_warnx("warn: table-sqlite: sqlite3_step: %s", - sqlite3_errmsg(db)); - - sqlite3_reset(stmt_fetch_source); - - source_update = time(NULL); - source_ncall = 0; - - fetch: - - source_ncall += 1; - - if (! dict_iter(&sources, &source_iter, &k, (void **)NULL)) { - source_iter = NULL; - if (! dict_iter(&sources, &source_iter, &k, (void **)NULL)) - return (0); - } - - if (strlcpy(dst, k, sz) >= sz) - return (-1); - - return (1); -} |