diff options
26 files changed, 83 insertions, 4479 deletions
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index ad279fac12f..e643be436a5 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -1,18 +1,19 @@ -# $OpenBSD: Makefile,v 1.40 2017/12/14 09:27:44 kettenis Exp $ +# $OpenBSD: Makefile,v 1.41 2019/05/11 17:46:02 rob Exp $ # $NetBSD: Makefile,v 1.8 1996/05/16 07:03:28 thorpej Exp $ LIB= util VERSION_SCRIPT= ${.CURDIR}/Symbols.map -HDRS= util.h imsg.h -SRCS= bcrypt_pbkdf.c check_expire.c duid.c getmaxpartitions.c \ +HDRS= ber.h util.h imsg.h +SRCS= bcrypt_pbkdf.c ber.c check_expire.c duid.c getmaxpartitions.c \ getrawpartition.c login.c \ login_tty.c logout.c logwtmp.c opendev.c passwd.c pty.c readlabel.c \ login_fbtab.c uucplock.c fparseln.c opendisk.c pidfile.c \ fmt_scaled.c imsg.c imsg-buffer.c pkcs5_pbkdf2.c -MAN= bcrypt_pbkdf.3 check_expire.3 getmaxpartitions.3 getrawpartition.3 \ +MAN= bcrypt_pbkdf.3 ber.3 check_expire.3 getmaxpartitions.3 \ + getrawpartition.3 \ isduid.3 login.3 \ opendev.3 openpty.3 pw_init.3 pw_lock.3 readlabelfs.3 uucplock.3 \ fparseln.3 opendisk.3 login_fbtab.3 pidfile.3 fmt_scaled.3 imsg_init.3 \ diff --git a/lib/libutil/Symbols.map b/lib/libutil/Symbols.map index 942ea2794fc..7bb605156a4 100644 --- a/lib/libutil/Symbols.map +++ b/lib/libutil/Symbols.map @@ -9,6 +9,51 @@ { global: bcrypt_pbkdf; + ber_add_bitstring; + ber_add_boolean; + ber_add_enumerated; + ber_add_eoc; + ber_add_integer; + ber_add_noid; + ber_add_nstring; + ber_add_null; + ber_add_oid; + ber_add_oidstring; + ber_add_ostring; + ber_add_sequence; + ber_add_set; + ber_add_string; + ber_calc_len; + ber_free; + ber_free_element; + ber_free_elements; + ber_get_bitstring; + ber_get_boolean; + ber_get_element; + ber_get_enumerated; + ber_get_eoc; + ber_get_integer; + ber_get_nstring; + ber_get_null; + ber_get_oid; + ber_get_ostring; + ber_get_string; + ber_get_writebuf; + ber_getpos; + ber_link_elements; + ber_oid2ber; + ber_oid_cmp; + ber_printf_elements; + ber_read_elements; + ber_replace_elements; + ber_scanf_elements; + ber_set_application; + ber_set_header; + ber_set_readbuf; + ber_set_writecallback; + ber_string2oid; + ber_unlink_elements; + ber_write_elements; fdforkpty; fdopenpty; fmt_scaled; diff --git a/usr.sbin/snmpd/ber.3 b/lib/libutil/ber.3 index e41421a1c24..32c1aa4f9a6 100644 --- a/usr.sbin/snmpd/ber.3 +++ b/lib/libutil/ber.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ber.3,v 1.21 2019/03/24 04:54:30 rob Exp $ +.\" $OpenBSD: ber.3,v 1.1 2019/05/11 17:46:02 rob Exp $ .\" .\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: March 24 2019 $ +.Dd $Mdocdate: May 11 2019 $ .Dt BER 3 .Os .Sh NAME diff --git a/usr.bin/ldap/ber.c b/lib/libutil/ber.c index b3b2d1075c4..d6952515481 100644 --- a/usr.bin/ldap/ber.c +++ b/lib/libutil/ber.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ber.c,v 1.22 2019/04/27 14:58:14 rob Exp $ */ +/* $OpenBSD: ber.c,v 1.1 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> diff --git a/usr.bin/ldap/ber.h b/lib/libutil/ber.h index 962249f02cf..a8348150ef9 100644 --- a/usr.bin/ldap/ber.h +++ b/lib/libutil/ber.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ber.h,v 1.8 2018/11/27 12:04:57 martijn Exp $ */ +/* $OpenBSD: ber.h,v 1.1 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> diff --git a/lib/libutil/shlib_version b/lib/libutil/shlib_version index 262f3bc13b6..b91c32ce7c8 100644 --- a/lib/libutil/shlib_version +++ b/lib/libutil/shlib_version @@ -1,2 +1,2 @@ major=13 -minor=0 +minor=1 diff --git a/share/man/man3/intro.3 b/share/man/man3/intro.3 index 4ccbb1e1560..c5f3def516a 100644 --- a/share/man/man3/intro.3 +++ b/share/man/man3/intro.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: intro.3,v 1.88 2019/03/24 05:28:36 deraadt Exp $ +.\" $OpenBSD: intro.3,v 1.89 2019/05/11 17:46:02 rob Exp $ .\" $NetBSD: intro.3,v 1.5 1995/05/10 22:46:24 jtc Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)intro.3 8.1 (Berkeley) 6/5/93 .\" -.Dd $Mdocdate: March 24 2019 $ +.Dd $Mdocdate: May 11 2019 $ .Dt INTRO 3 .Os .Sh NAME @@ -352,6 +352,7 @@ See System utility functions. These are currently .Xr bcrypt_pbkdf 3 , +.Xr ber_get_element 3 , .Xr check_expire 3 , .Xr fmt_scaled 3 , .Xr fparseln 3 , diff --git a/usr.bin/ldap/Makefile b/usr.bin/ldap/Makefile index c526af93938..c7255fbdeea 100644 --- a/usr.bin/ldap/Makefile +++ b/usr.bin/ldap/Makefile @@ -1,5 +1,5 @@ PROG= ldap -SRCS= ldapclient.c aldap.c ber.c log.c +SRCS= ldapclient.c aldap.c log.c LDADD+= -levent -ltls -lssl -lcrypto -lutil DPADD+= ${LIBEVENT} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL} diff --git a/usr.bin/ldap/aldap.h b/usr.bin/ldap/aldap.h index 81fe7703275..bf36c3c2a72 100644 --- a/usr.bin/ldap/aldap.h +++ b/usr.bin/ldap/aldap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: aldap.h,v 1.3 2019/01/17 06:18:27 tedu Exp $ */ +/* $OpenBSD: aldap.h,v 1.4 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> @@ -17,12 +17,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <ber.h> #include <stdio.h> - #include <tls.h> -#include "ber.h" - #define LDAP_URL "ldap://" #define LDAPS_URL "ldaps://" #define LDAPTLS_URL "ldap+tls://" diff --git a/usr.sbin/ldapctl/Makefile b/usr.sbin/ldapctl/Makefile index 32b1f808d99..4b500ef016f 100644 --- a/usr.sbin/ldapctl/Makefile +++ b/usr.sbin/ldapctl/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.9 2017/07/03 22:21:47 espie Exp $ +# $OpenBSD: Makefile,v 1.10 2019/05/11 17:46:02 rob Exp $ .PATH: ${.CURDIR}/../ldapd PROG= ldapctl MAN= ldapctl.8 -SRCS= ldapctl.c parse.y btree.c log.c logmsg.c ber.c util.c \ +SRCS= ldapctl.c parse.y btree.c log.c logmsg.c util.c \ index.c attributes.c schema.c syntax.c matching.c LDADD= -levent -ltls -lssl -lcrypto -lz -lutil diff --git a/usr.sbin/ldapd/Makefile b/usr.sbin/ldapd/Makefile index cc0816908fe..bf445832576 100644 --- a/usr.sbin/ldapd/Makefile +++ b/usr.sbin/ldapd/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.15 2017/01/20 11:55:08 benno Exp $ +# $OpenBSD: Makefile,v 1.16 2019/05/11 17:46:02 rob Exp $ PROG= ldapd MAN= ldapd.8 ldapd.conf.5 -SRCS= ber.c log.c logmsg.c control.c \ +SRCS= log.c logmsg.c control.c \ util.c ldapd.c ldape.c conn.c attributes.c namespace.c \ btree.c filter.c search.c parse.y \ auth.c modify.c index.c evbuffer_tls.c \ diff --git a/usr.sbin/ldapd/aldap.h b/usr.sbin/ldapd/aldap.h index 22a01bd5452..f6f542e4e4a 100644 --- a/usr.sbin/ldapd/aldap.h +++ b/usr.sbin/ldapd/aldap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: aldap.h,v 1.1 2010/05/31 17:36:31 martinh Exp $ */ +/* $OpenBSD: aldap.h,v 1.2 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> @@ -17,8 +17,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <ber.h> #include <stdio.h> -#include "ber.h" enum protocol_op { LDAP_REQ_BIND = 0, diff --git a/usr.sbin/ldapd/ber.c b/usr.sbin/ldapd/ber.c deleted file mode 100644 index bc32578965c..00000000000 --- a/usr.sbin/ldapd/ber.c +++ /dev/null @@ -1,1328 +0,0 @@ -/* $OpenBSD: ber.c,v 1.32 2019/04/27 14:58:14 rob Exp $ */ - -/* - * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> - * 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 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, u_char c); -static void ber_write(struct ber *ber, void *buf, size_t len); -static ssize_t get_id(struct ber *b, unsigned int *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_getc(struct ber *b, u_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 int 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 int 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; - u_int i, len = 0; - u_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; - u_int i, len = 0; - u_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 + 1)) == NULL) - return NULL; - if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) { - free(string); - return NULL; - } - - bcopy(string0, string, len); - elm->be_val = string; - elm->be_len = len; - elm->be_free = 1; /* free string on cleanup */ - - ber_link_elements(prev, elm); - - return elm; -} - -struct ber_element * -ber_add_ostring(struct ber_element *prev, struct ber_octetstring *s) -{ - return ber_add_nstring(prev, s->ostr_val, s->ostr_len); -} - -int -ber_get_string(struct ber_element *elm, char **s) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - /* Some components use getstring on binary data containing \0 */ -#if 0 - if (memchr(elm->be_val, '\0', elm->be_len) != NULL) - return -1; -#endif - - *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; -} - -int -ber_get_ostring(struct ber_element *elm, struct ber_octetstring *s) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - - s->ostr_val = elm->be_val; - s->ostr_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; - } - - bcopy(v0, v, 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, u_int8_t *buf, size_t len) -{ - u_int32_t v; - u_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 >= (u_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); -} - -int -ber_oid_cmp(struct ber_oid *a, struct ber_oid *b) -{ - size_t i; - for (i = 0; i < BER_MAX_OID_LEN; i++) { - if (a->bo_id[i] != 0) { - if (a->bo_id[i] == b->bo_id[i]) - continue; - else if (a->bo_id[i] < b->bo_id[i]) { - /* b is a successor of a */ - return (1); - } else { - /* b is a predecessor of a */ - return (-1); - } - } else if (b->bo_id[i] != 0) { - /* b is larger, but a child of a */ - return (2); - } else - break; - } - - /* b and a are identical */ - return (0); -} - -struct ber_element * -ber_add_oid(struct ber_element *prev, struct ber_oid *o) -{ - struct ber_element *elm; - u_int8_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; - bcopy(&o->bo_id, &no.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) -{ - u_int8_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 int 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 int); - 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 int *t; - long long *i, l; - void **ptr; - size_t *len, ret = 0, n = strlen(fmt); - char **s; - off_t *pos; - 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 'd': - d = va_arg(ap, int *); - if (ber_get_integer(ber, &l) == -1) - goto fail; - *d = l; - 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 int *); - *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 'p': - pos = va_arg(ap, off_t *); - *pos = ber_getpos(ber); - ret++; - continue; - 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++; - break; - 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); - -} - -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); -} - -/* - * write ber elements to the write buffer - * - * params: - * ber holds the destination write buffer byte stream - * root fully populated element tree - * - * returns: - * >=0 number of bytes written - * -1 on failure and sets errno - */ -ssize_t -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; - - return (len); -} - -void -ber_set_readbuf(struct ber *b, void *buf, size_t len) -{ - b->br_rbuf = b->br_rptr = buf; - b->br_rend = (u_int8_t *)buf + len; -} - -/* - * read ber elements from the read buffer - * - * params: - * ber holds a fully populated read buffer byte stream - * 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; -} - -off_t -ber_getpos(struct ber_element *elm) -{ - return elm->be_offs; -} - -void -ber_free_element(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_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); -} - -void -ber_free_elements(struct ber_element *root) -{ - if (root == NULL) - return; - 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 int 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_class == BER_CLASS_UNIVERSAL && - root->be_type == BER_TYPE_EOC && root->be_len == 0) - return (0); - - return (root->be_len + size); -} - -void -ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *)) -{ - b->br_application = cb; -} - -void -ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t), - void *arg) -{ - elm->be_cb = cb; - elm->be_cbarg = arg; -} - -void -ber_free(struct ber *b) -{ - free(b->br_wbuf); -} - -/* - * 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); - if (root->be_cb) - root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf); - - 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) -{ - u_char id = 0, t, buf[5]; - unsigned int 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, u_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) - bcopy(buf, ber->br_wptr, 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 int *tag, int *class, int *cstruct) -{ - u_char u; - size_t i = 0; - unsigned int 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++; - if (i > sizeof(unsigned int)) { - errno = ERANGE; - return -1; - } - } while (u & BER_TAG_MORE); - - *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) -{ - u_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; - } - - if (u == 0x80) { - /* Indefinite length not supported. */ - errno = EINVAL; - 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; - } - - *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 int type; - int i, class, cstruct, elements = 0; - ssize_t len, r, totlen = 0; - u_char c; - - if ((r = get_id(ber, &type, &class, &cstruct)) == -1) - return -1; - DPRINTF("ber read got class %d type %u, %s\n", - class, type, cstruct ? "constructed" : "primitive"); - totlen += r; - if ((r = get_len(ber, &len)) == -1) - return -1; - DPRINTF("ber read element size %zd\n", len); - totlen += r + len; - - /* If the total size of the element is larger than the buffer - * don't bother to continue. */ - if (len > ber->br_rend - ber->br_rptr) { - errno = ECANCELED; - return -1; - } - - elm->be_type = type; - elm->be_len = len; - elm->be_offs = ber->br_offs; /* element position within stream */ - 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 (len < (ssize_t)sizeof(long long) && - (val >> ((len - 1) * 8) & 0x80)) - val |= ULLONG_MAX << (len * 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); - ((u_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) { - /* - * Prevent stack overflow from excessive recursion - * depth in ber_free_elements(). - */ - if (elements >= BER_MAX_SEQ_ELEMENTS) { - errno = ERANGE; - return -1; - } - r = ber_read_element(ber, next); - if (r == -1) - return -1; - elements++; - 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_getc(struct ber *b, u_char *c) -{ - return ber_read(b, c, 1); -} - -static ssize_t -ber_read(struct ber *ber, void *buf, size_t len) -{ - size_t sz; - - if (ber->br_rbuf == NULL) - return -1; - - sz = ber->br_rend - ber->br_rptr; - if (len > sz) { - errno = ECANCELED; - return -1; /* parser wants more data than available */ - } - - bcopy(ber->br_rptr, buf, len); - ber->br_rptr += len; - ber->br_offs += len; - - return len; -} diff --git a/usr.sbin/ldapd/ber.h b/usr.sbin/ldapd/ber.h deleted file mode 100644 index 179466f5222..00000000000 --- a/usr.sbin/ldapd/ber.h +++ /dev/null @@ -1,152 +0,0 @@ -/* $OpenBSD: ber.h,v 1.9 2018/11/27 12:09:38 martijn Exp $ */ - -/* - * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> - * 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. - */ - -#ifndef _BER_H -#define _BER_H - -struct ber_octetstring { - size_t ostr_len; - const void *ostr_val; -}; - -struct ber_element { - struct ber_element *be_next; - unsigned int be_type; - unsigned int be_encoding; - size_t be_len; - off_t be_offs; - int be_free; - u_int8_t be_class; - void (*be_cb)(void *, size_t); - void *be_cbarg; - 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 { - off_t br_offs; - u_char *br_wbuf; - u_char *br_wptr; - u_char *br_wend; - u_char *br_rbuf; - u_char *br_rptr; - u_char *br_rend; - - unsigned int (*br_application)(struct ber_element *); -}; - -/* well-known ber_element types */ -#define BER_TYPE_DEFAULT ((unsigned int)-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 */ -#define BER_MAX_SEQ_ELEMENTS USHRT_MAX /* 65535 */ - -struct ber_oid { - u_int32_t bo_id[BER_MAX_OID_LEN + 1]; - size_t bo_n; -}; - -__BEGIN_DECLS -struct ber_element *ber_get_element(unsigned int); -void ber_set_header(struct ber_element *, int, - unsigned int); -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); -struct ber_element *ber_add_ostring(struct ber_element *, - struct ber_octetstring *); -int ber_get_string(struct ber_element *, char **); -int ber_get_nstring(struct ber_element *, void **, - size_t *); -int ber_get_ostring(struct ber_element *, - struct ber_octetstring *); -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 *, u_int8_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 **); -ssize_t 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 *); -off_t ber_getpos(struct ber_element *); -void ber_free_element(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 int (*)(struct ber_element *)); -void ber_set_writecallback(struct ber_element *, - void (*)(void *, size_t), void *); -void ber_free(struct ber *); -int ber_oid_cmp(struct ber_oid *, struct ber_oid *); - -__END_DECLS - -#endif /* _BER_H */ diff --git a/usr.sbin/snmpctl/Makefile b/usr.sbin/snmpctl/Makefile index b605aaa10c6..e64d73f85cd 100644 --- a/usr.sbin/snmpctl/Makefile +++ b/usr.sbin/snmpctl/Makefile @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile,v 1.8 2019/01/17 06:21:46 tedu Exp $ +# $OpenBSD: Makefile,v 1.9 2019/05/11 17:46:02 rob Exp $ .PATH: ${.CURDIR}/../snmpd PROG= snmpctl -SRCS= log.c ber.c smi.c snmpclient.c snmpctl.c parser.c agentx.c +SRCS= log.c smi.c snmpclient.c snmpctl.c parser.c agentx.c MAN= snmpctl.8 diff --git a/usr.sbin/snmpctl/snmpclient.c b/usr.sbin/snmpctl/snmpclient.c index fb92b3ee932..dd9921a393d 100644 --- a/usr.sbin/snmpctl/snmpclient.c +++ b/usr.sbin/snmpctl/snmpclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpclient.c,v 1.19 2018/12/13 10:54:29 martijn Exp $ */ +/* $OpenBSD: snmpclient.c,v 1.20 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2013 Reyk Floeter <reyk@openbsd.org> @@ -26,6 +26,7 @@ #include <netinet/in.h> #include <arpa/inet.h> +#include <ber.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> @@ -42,7 +43,6 @@ #include "snmpd.h" #include "mib.h" -#include "ber.h" #include "parser.h" struct snmpc { diff --git a/usr.sbin/snmpd/Makefile b/usr.sbin/snmpd/Makefile index d29da8eaf9d..bc72fd96121 100644 --- a/usr.sbin/snmpd/Makefile +++ b/usr.sbin/snmpd/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.15 2017/07/03 22:21:47 espie Exp $ +# $OpenBSD: Makefile,v 1.16 2019/05/11 17:46:02 rob Exp $ PROG= snmpd MAN= snmpd.8 snmpd.conf.5 -SRCS= parse.y ber.c log.c control.c snmpe.c \ +SRCS= parse.y log.c control.c snmpe.c \ mps.c trap.c mib.c smi.c kroute.c snmpd.c timer.c \ pf.c proc.c usm.c agentx.c traphandler.c util.c diff --git a/usr.sbin/snmpd/ber.c b/usr.sbin/snmpd/ber.c deleted file mode 100644 index aac9ded2674..00000000000 --- a/usr.sbin/snmpd/ber.c +++ /dev/null @@ -1,1328 +0,0 @@ -/* $OpenBSD: ber.c,v 1.51 2019/04/27 14:58:15 rob Exp $ */ - -/* - * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> - * 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 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, u_char c); -static void ber_write(struct ber *ber, void *buf, size_t len); -static ssize_t get_id(struct ber *b, unsigned int *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_getc(struct ber *b, u_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 int 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 int 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; - u_int i, len = 0; - u_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; - u_int i, len = 0; - u_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 + 1)) == NULL) - return NULL; - if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) { - free(string); - return NULL; - } - - bcopy(string0, string, len); - elm->be_val = string; - elm->be_len = len; - elm->be_free = 1; /* free string on cleanup */ - - ber_link_elements(prev, elm); - - return elm; -} - -struct ber_element * -ber_add_ostring(struct ber_element *prev, struct ber_octetstring *s) -{ - return ber_add_nstring(prev, s->ostr_val, s->ostr_len); -} - -int -ber_get_string(struct ber_element *elm, char **s) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - /* Some components use getstring on binary data containing \0 */ -#if 0 - if (memchr(elm->be_val, '\0', elm->be_len) != NULL) - return -1; -#endif - - *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; -} - -int -ber_get_ostring(struct ber_element *elm, struct ber_octetstring *s) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - - s->ostr_val = elm->be_val; - s->ostr_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; - } - - bcopy(v0, v, 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, u_int8_t *buf, size_t len) -{ - u_int32_t v; - u_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 >= (u_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); -} - -int -ber_oid_cmp(struct ber_oid *a, struct ber_oid *b) -{ - size_t i; - for (i = 0; i < BER_MAX_OID_LEN; i++) { - if (a->bo_id[i] != 0) { - if (a->bo_id[i] == b->bo_id[i]) - continue; - else if (a->bo_id[i] < b->bo_id[i]) { - /* b is a successor of a */ - return (1); - } else { - /* b is a predecessor of a */ - return (-1); - } - } else if (b->bo_id[i] != 0) { - /* b is larger, but a child of a */ - return (2); - } else - break; - } - - /* b and a are identical */ - return (0); -} - -struct ber_element * -ber_add_oid(struct ber_element *prev, struct ber_oid *o) -{ - struct ber_element *elm; - u_int8_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; - bcopy(&o->bo_id, &no.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) -{ - u_int8_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 int 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 int); - 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 int *t; - long long *i, l; - void **ptr; - size_t *len, ret = 0, n = strlen(fmt); - char **s; - off_t *pos; - 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 'd': - d = va_arg(ap, int *); - if (ber_get_integer(ber, &l) == -1) - goto fail; - *d = l; - 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 int *); - *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 'p': - pos = va_arg(ap, off_t *); - *pos = ber_getpos(ber); - ret++; - continue; - 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++; - break; - 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); - -} - -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); -} - -/* - * write ber elements to the write buffer - * - * params: - * ber holds the destination write buffer byte stream - * root fully populated element tree - * - * returns: - * >=0 number of bytes written - * -1 on failure and sets errno - */ -ssize_t -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; - - return (len); -} - -void -ber_set_readbuf(struct ber *b, void *buf, size_t len) -{ - b->br_rbuf = b->br_rptr = buf; - b->br_rend = (u_int8_t *)buf + len; -} - -/* - * read ber elements from the read buffer - * - * params: - * ber holds a fully populated read buffer byte stream - * 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; -} - -off_t -ber_getpos(struct ber_element *elm) -{ - return elm->be_offs; -} - -void -ber_free_element(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_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); -} - -void -ber_free_elements(struct ber_element *root) -{ - if (root == NULL) - return; - 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 int 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_class == BER_CLASS_UNIVERSAL && - root->be_type == BER_TYPE_EOC && root->be_len == 0) - return (0); - - return (root->be_len + size); -} - -void -ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *)) -{ - b->br_application = cb; -} - -void -ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t), - void *arg) -{ - elm->be_cb = cb; - elm->be_cbarg = arg; -} - -void -ber_free(struct ber *b) -{ - free(b->br_wbuf); -} - -/* - * 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); - if (root->be_cb) - root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf); - - 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) -{ - u_char id = 0, t, buf[5]; - unsigned int 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, u_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) - bcopy(buf, ber->br_wptr, 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 int *tag, int *class, int *cstruct) -{ - u_char u; - size_t i = 0; - unsigned int 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++; - if (i > sizeof(unsigned int)) { - errno = ERANGE; - return -1; - } - } while (u & BER_TAG_MORE); - - *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) -{ - u_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; - } - - if (u == 0x80) { - /* Indefinite length not supported. */ - errno = EINVAL; - 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; - } - - *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 int type; - int i, class, cstruct, elements = 0; - ssize_t len, r, totlen = 0; - u_char c; - - if ((r = get_id(ber, &type, &class, &cstruct)) == -1) - return -1; - DPRINTF("ber read got class %d type %u, %s\n", - class, type, cstruct ? "constructed" : "primitive"); - totlen += r; - if ((r = get_len(ber, &len)) == -1) - return -1; - DPRINTF("ber read element size %zd\n", len); - totlen += r + len; - - /* If the total size of the element is larger than the buffer - * don't bother to continue. */ - if (len > ber->br_rend - ber->br_rptr) { - errno = ECANCELED; - return -1; - } - - elm->be_type = type; - elm->be_len = len; - elm->be_offs = ber->br_offs; /* element position within stream */ - 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 (len < (ssize_t)sizeof(long long) && - (val >> ((len - 1) * 8) & 0x80)) - val |= ULLONG_MAX << (len * 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); - ((u_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) { - /* - * Prevent stack overflow from excessive recursion - * depth in ber_free_elements(). - */ - if (elements >= BER_MAX_SEQ_ELEMENTS) { - errno = ERANGE; - return -1; - } - r = ber_read_element(ber, next); - if (r == -1) - return -1; - elements++; - 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_getc(struct ber *b, u_char *c) -{ - return ber_read(b, c, 1); -} - -static ssize_t -ber_read(struct ber *ber, void *buf, size_t len) -{ - size_t sz; - - if (ber->br_rbuf == NULL) - return -1; - - sz = ber->br_rend - ber->br_rptr; - if (len > sz) { - errno = ECANCELED; - return -1; /* parser wants more data than available */ - } - - bcopy(ber->br_rptr, buf, len); - ber->br_rptr += len; - ber->br_offs += len; - - return len; -} diff --git a/usr.sbin/snmpd/ber.h b/usr.sbin/snmpd/ber.h deleted file mode 100644 index a2cc0fc84d3..00000000000 --- a/usr.sbin/snmpd/ber.h +++ /dev/null @@ -1,152 +0,0 @@ -/* $OpenBSD: ber.h,v 1.15 2018/11/27 12:10:29 martijn Exp $ */ - -/* - * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> - * 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. - */ - -#ifndef _BER_H -#define _BER_H - -struct ber_octetstring { - size_t ostr_len; - const void *ostr_val; -}; - -struct ber_element { - struct ber_element *be_next; - unsigned int be_type; - unsigned int be_encoding; - size_t be_len; - off_t be_offs; - int be_free; - u_int8_t be_class; - void (*be_cb)(void *, size_t); - void *be_cbarg; - 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 { - off_t br_offs; - u_char *br_wbuf; - u_char *br_wptr; - u_char *br_wend; - u_char *br_rbuf; - u_char *br_rptr; - u_char *br_rend; - - unsigned int (*br_application)(struct ber_element *); -}; - -/* well-known ber_element types */ -#define BER_TYPE_DEFAULT ((unsigned int)-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 */ -#define BER_MAX_SEQ_ELEMENTS USHRT_MAX /* 65535 */ - -struct ber_oid { - u_int32_t bo_id[BER_MAX_OID_LEN + 1]; - size_t bo_n; -}; - -__BEGIN_DECLS -struct ber_element *ber_get_element(unsigned int); -void ber_set_header(struct ber_element *, int, - unsigned int); -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); -struct ber_element *ber_add_ostring(struct ber_element *, - struct ber_octetstring *); -int ber_get_string(struct ber_element *, char **); -int ber_get_nstring(struct ber_element *, void **, - size_t *); -int ber_get_ostring(struct ber_element *, - struct ber_octetstring *); -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 *, u_int8_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 **); -ssize_t 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 *); -off_t ber_getpos(struct ber_element *); -void ber_free_element(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 int (*)(struct ber_element *)); -void ber_set_writecallback(struct ber_element *, - void (*)(void *, size_t), void *); -void ber_free(struct ber *); -int ber_oid_cmp(struct ber_oid *, struct ber_oid *); - -__END_DECLS - -#endif /* _BER_H */ diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index 338eeea071b..b97333fd8af 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.81 2019/01/08 15:38:36 bluhm Exp $ */ +/* $OpenBSD: snmpd.h,v 1.82 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -31,10 +31,10 @@ #include <net/pfvar.h> #include <net/route.h> +#include <ber.h> #include <stdio.h> #include <imsg.h> -#include "ber.h" #include "snmp.h" #ifndef nitems diff --git a/usr.sbin/snmpd/traphandler.c b/usr.sbin/snmpd/traphandler.c index 6b7abd50f5d..dfba9e46a7f 100644 --- a/usr.sbin/snmpd/traphandler.c +++ b/usr.sbin/snmpd/traphandler.c @@ -1,4 +1,4 @@ -/* $OpenBSD: traphandler.c,v 1.12 2018/04/15 11:57:29 mpf Exp $ */ +/* $OpenBSD: traphandler.c,v 1.13 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2014 Bret Stephen Lambert <blambert@openbsd.org> @@ -27,6 +27,7 @@ #include <netinet/in.h> #include <arpa/inet.h> +#include <ber.h> #include <event.h> #include <fcntl.h> #include <imsg.h> @@ -38,7 +39,6 @@ #include <unistd.h> #include <pwd.h> -#include "ber.h" #include "snmpd.h" #include "mib.h" diff --git a/usr.sbin/snmpd/util.c b/usr.sbin/snmpd/util.c index d6965b11d39..6bd83231c4a 100644 --- a/usr.sbin/snmpd/util.c +++ b/usr.sbin/snmpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.7 2017/01/09 14:49:22 reyk Exp $ */ +/* $OpenBSD: util.c,v 1.8 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2014 Bret Stephen Lambert <blambert@openbsd.org> * @@ -21,12 +21,12 @@ #include <net/if.h> +#include <ber.h> #include <stdio.h> #include <string.h> #include <netdb.h> #include <event.h> -#include "ber.h" #include "snmp.h" #include "snmpd.h" diff --git a/usr.sbin/ypldap/Makefile b/usr.sbin/ypldap/Makefile index 12a286ffbee..c106d0032fe 100644 --- a/usr.sbin/ypldap/Makefile +++ b/usr.sbin/ypldap/Makefile @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile,v 1.10 2017/07/03 22:21:47 espie Exp $ +# $OpenBSD: Makefile,v 1.11 2019/05/11 17:46:02 rob Exp $ PROG= ypldap SRCS= parse.y ypldap.c log.c \ ldapclient.c entries.c yp.c \ - aldap.c ber.c \ + aldap.c \ ypldap_dns.c MAN= ypldap.8 ypldap.conf.5 diff --git a/usr.sbin/ypldap/aldap.h b/usr.sbin/ypldap/aldap.h index b3c2d58d321..c6a09e8ddad 100644 --- a/usr.sbin/ypldap/aldap.h +++ b/usr.sbin/ypldap/aldap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: aldap.h,v 1.13 2019/01/17 06:22:54 tedu Exp $ */ +/* $OpenBSD: aldap.h,v 1.14 2019/05/11 17:46:02 rob Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> @@ -19,10 +19,9 @@ #include <stdio.h> +#include <ber.h> #include <tls.h> -#include "ber.h" - #define LDAP_URL "ldap://" #define LDAPS_URL "ldaps://" #define LDAPTLS_URL "ldap+tls://" diff --git a/usr.sbin/ypldap/ber.c b/usr.sbin/ypldap/ber.c deleted file mode 100644 index 5d6c6ace796..00000000000 --- a/usr.sbin/ypldap/ber.c +++ /dev/null @@ -1,1328 +0,0 @@ -/* $OpenBSD: ber.c,v 1.34 2019/04/27 14:58:15 rob Exp $ */ - -/* - * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> - * 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 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, u_char c); -static void ber_write(struct ber *ber, void *buf, size_t len); -static ssize_t get_id(struct ber *b, unsigned int *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_getc(struct ber *b, u_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 int 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 int 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; - u_int i, len = 0; - u_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; - u_int i, len = 0; - u_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 + 1)) == NULL) - return NULL; - if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) { - free(string); - return NULL; - } - - bcopy(string0, string, len); - elm->be_val = string; - elm->be_len = len; - elm->be_free = 1; /* free string on cleanup */ - - ber_link_elements(prev, elm); - - return elm; -} - -struct ber_element * -ber_add_ostring(struct ber_element *prev, struct ber_octetstring *s) -{ - return ber_add_nstring(prev, s->ostr_val, s->ostr_len); -} - -int -ber_get_string(struct ber_element *elm, char **s) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - /* Some components use getstring on binary data containing \0 */ -#if 0 - if (memchr(elm->be_val, '\0', elm->be_len) != NULL) - return -1; -#endif - - *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; -} - -int -ber_get_ostring(struct ber_element *elm, struct ber_octetstring *s) -{ - if (elm->be_encoding != BER_TYPE_OCTETSTRING) - return -1; - - s->ostr_val = elm->be_val; - s->ostr_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; - } - - bcopy(v0, v, 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, u_int8_t *buf, size_t len) -{ - u_int32_t v; - u_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 >= (u_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); -} - -int -ber_oid_cmp(struct ber_oid *a, struct ber_oid *b) -{ - size_t i; - for (i = 0; i < BER_MAX_OID_LEN; i++) { - if (a->bo_id[i] != 0) { - if (a->bo_id[i] == b->bo_id[i]) - continue; - else if (a->bo_id[i] < b->bo_id[i]) { - /* b is a successor of a */ - return (1); - } else { - /* b is a predecessor of a */ - return (-1); - } - } else if (b->bo_id[i] != 0) { - /* b is larger, but a child of a */ - return (2); - } else - break; - } - - /* b and a are identical */ - return (0); -} - -struct ber_element * -ber_add_oid(struct ber_element *prev, struct ber_oid *o) -{ - struct ber_element *elm; - u_int8_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; - bcopy(&o->bo_id, &no.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) -{ - u_int8_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 int 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 int); - 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 int *t; - long long *i, l; - void **ptr; - size_t *len, ret = 0, n = strlen(fmt); - char **s; - off_t *pos; - 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 'd': - d = va_arg(ap, int *); - if (ber_get_integer(ber, &l) == -1) - goto fail; - *d = l; - 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 int *); - *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 'p': - pos = va_arg(ap, off_t *); - *pos = ber_getpos(ber); - ret++; - continue; - 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++; - break; - 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); - -} - -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); -} - -/* - * write ber elements to the write buffer - * - * params: - * ber holds the destination write buffer byte stream - * root fully populated element tree - * - * returns: - * >=0 number of bytes written - * -1 on failure and sets errno - */ -ssize_t -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; - - return (len); -} - -void -ber_set_readbuf(struct ber *b, void *buf, size_t len) -{ - b->br_rbuf = b->br_rptr = buf; - b->br_rend = (u_int8_t *)buf + len; -} - -/* - * read ber elements from the read buffer - * - * params: - * ber holds a fully populated read buffer byte stream - * 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; -} - -off_t -ber_getpos(struct ber_element *elm) -{ - return elm->be_offs; -} - -void -ber_free_element(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_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); -} - -void -ber_free_elements(struct ber_element *root) -{ - if (root == NULL) - return; - 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 int 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_class == BER_CLASS_UNIVERSAL && - root->be_type == BER_TYPE_EOC && root->be_len == 0) - return (0); - - return (root->be_len + size); -} - -void -ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *)) -{ - b->br_application = cb; -} - -void -ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t), - void *arg) -{ - elm->be_cb = cb; - elm->be_cbarg = arg; -} - -void -ber_free(struct ber *b) -{ - free(b->br_wbuf); -} - -/* - * 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); - if (root->be_cb) - root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf); - - 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) -{ - u_char id = 0, t, buf[5]; - unsigned int 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, u_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) - bcopy(buf, ber->br_wptr, 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 int *tag, int *class, int *cstruct) -{ - u_char u; - size_t i = 0; - unsigned int 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++; - if (i > sizeof(unsigned int)) { - errno = ERANGE; - return -1; - } - } while (u & BER_TAG_MORE); - - *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) -{ - u_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; - } - - if (u == 0x80) { - /* Indefinite length not supported. */ - errno = EINVAL; - 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; - } - - *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 int type; - int i, class, cstruct, elements = 0; - ssize_t len, r, totlen = 0; - u_char c; - - if ((r = get_id(ber, &type, &class, &cstruct)) == -1) - return -1; - DPRINTF("ber read got class %d type %u, %s\n", - class, type, cstruct ? "constructed" : "primitive"); - totlen += r; - if ((r = get_len(ber, &len)) == -1) - return -1; - DPRINTF("ber read element size %zd\n", len); - totlen += r + len; - - /* If the total size of the element is larger than the buffer - * don't bother to continue. */ - if (len > ber->br_rend - ber->br_rptr) { - errno = ECANCELED; - return -1; - } - - elm->be_type = type; - elm->be_len = len; - elm->be_offs = ber->br_offs; /* element position within stream */ - 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 (len < (ssize_t)sizeof(long long) && - (val >> ((len - 1) * 8) & 0x80)) - val |= ULLONG_MAX << (len * 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); - ((u_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) { - /* - * Prevent stack overflow from excessive recursion - * depth in ber_free_elements(). - */ - if (elements >= BER_MAX_SEQ_ELEMENTS) { - errno = ERANGE; - return -1; - } - r = ber_read_element(ber, next); - if (r == -1) - return -1; - elements++; - 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_getc(struct ber *b, u_char *c) -{ - return ber_read(b, c, 1); -} - -static ssize_t -ber_read(struct ber *ber, void *buf, size_t len) -{ - size_t sz; - - if (ber->br_rbuf == NULL) - return -1; - - sz = ber->br_rend - ber->br_rptr; - if (len > sz) { - errno = ECANCELED; - return -1; /* parser wants more data than available */ - } - - bcopy(ber->br_rptr, buf, len); - ber->br_rptr += len; - ber->br_offs += len; - - return len; -} diff --git a/usr.sbin/ypldap/ber.h b/usr.sbin/ypldap/ber.h deleted file mode 100644 index ad9d0ae14cc..00000000000 --- a/usr.sbin/ypldap/ber.h +++ /dev/null @@ -1,152 +0,0 @@ -/* $OpenBSD: ber.h,v 1.10 2018/11/27 12:06:39 martijn Exp $ */ - -/* - * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> - * 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. - */ - -#ifndef _BER_H -#define _BER_H - -struct ber_octetstring { - size_t ostr_len; - const void *ostr_val; -}; - -struct ber_element { - struct ber_element *be_next; - unsigned int be_type; - unsigned int be_encoding; - size_t be_len; - off_t be_offs; - int be_free; - u_int8_t be_class; - void (*be_cb)(void *, size_t); - void *be_cbarg; - 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 { - off_t br_offs; - u_char *br_wbuf; - u_char *br_wptr; - u_char *br_wend; - u_char *br_rbuf; - u_char *br_rptr; - u_char *br_rend; - - unsigned int (*br_application)(struct ber_element *); -}; - -/* well-known ber_element types */ -#define BER_TYPE_DEFAULT ((unsigned int)-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 */ -#define BER_MAX_SEQ_ELEMENTS USHRT_MAX /* 65535 */ - -struct ber_oid { - u_int32_t bo_id[BER_MAX_OID_LEN + 1]; - size_t bo_n; -}; - -__BEGIN_DECLS -struct ber_element *ber_get_element(unsigned int); -void ber_set_header(struct ber_element *, int, - unsigned int); -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); -struct ber_element *ber_add_ostring(struct ber_element *, - struct ber_octetstring *); -int ber_get_string(struct ber_element *, char **); -int ber_get_nstring(struct ber_element *, void **, - size_t *); -int ber_get_ostring(struct ber_element *, - struct ber_octetstring *); -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 *, u_int8_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 **); -ssize_t 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 *); -off_t ber_getpos(struct ber_element *); -void ber_free_element(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 int (*)(struct ber_element *)); -void ber_set_writecallback(struct ber_element *, - void (*)(void *, size_t), void *); -void ber_free(struct ber *); -int ber_oid_cmp(struct ber_oid *, struct ber_oid *); - -__END_DECLS - -#endif /* _BER_H */ |