summaryrefslogtreecommitdiffstats
path: root/usr.sbin/snmpd
diff options
context:
space:
mode:
authorrob <rob@openbsd.org>2019-05-11 17:46:02 +0000
committerrob <rob@openbsd.org>2019-05-11 17:46:02 +0000
commitd4b95dc4510ec3aba30ea226454b203d5350dc55 (patch)
treed9f5922063183a5130b73047df55bbf3df8e561b /usr.sbin/snmpd
parentmake rw-lock adaptive (diff)
downloadwireguard-openbsd-d4b95dc4510ec3aba30ea226454b203d5350dc55.tar.xz
wireguard-openbsd-d4b95dc4510ec3aba30ea226454b203d5350dc55.zip
The BER API is currently used by ldap, ldapd, ldapctl, ypldap, snmpd, and
snmpctl. Separate copies of ber.[ch] have existed and been maintained in sync in ldap, ldapd, ypldap and snmpd. This commit moves the BER API into /usr/lib/libutil. All current consumers already link libutil. ldapd and snmpd regress passes, and release builds. With help from tb@ and guenther@. ok deraadt@, tb@
Diffstat (limited to 'usr.sbin/snmpd')
-rw-r--r--usr.sbin/snmpd/Makefile4
-rw-r--r--usr.sbin/snmpd/ber.3453
-rw-r--r--usr.sbin/snmpd/ber.c1328
-rw-r--r--usr.sbin/snmpd/ber.h152
-rw-r--r--usr.sbin/snmpd/snmpd.h4
-rw-r--r--usr.sbin/snmpd/traphandler.c4
-rw-r--r--usr.sbin/snmpd/util.c4
7 files changed, 8 insertions, 1941 deletions
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.3 b/usr.sbin/snmpd/ber.3
deleted file mode 100644
index e41421a1c24..00000000000
--- a/usr.sbin/snmpd/ber.3
+++ /dev/null
@@ -1,453 +0,0 @@
-.\" $OpenBSD: ber.3,v 1.21 2019/03/24 04:54:30 rob Exp $
-.\"
-.\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@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.
-.\"
-.Dd $Mdocdate: March 24 2019 $
-.Dt BER 3
-.Os
-.Sh NAME
-.Nm ber_get_element ,
-.Nm ber_set_header ,
-.Nm ber_link_elements ,
-.Nm ber_unlink_elements ,
-.Nm ber_replace_elements ,
-.Nm ber_add_sequence ,
-.Nm ber_add_set ,
-.Nm ber_add_enumerated ,
-.Nm ber_add_integer ,
-.Nm ber_get_integer ,
-.Nm ber_get_enumerated ,
-.Nm ber_add_boolean ,
-.Nm ber_get_boolean ,
-.Nm ber_add_string ,
-.Nm ber_add_nstring ,
-.Nm ber_add_ostring ,
-.Nm ber_add_bitstring ,
-.Nm ber_get_string ,
-.Nm ber_get_nstring ,
-.Nm ber_get_ostring ,
-.Nm ber_get_bitstring ,
-.Nm ber_add_null ,
-.Nm ber_get_null ,
-.Nm ber_add_eoc ,
-.Nm ber_get_eoc ,
-.Nm ber_add_oid ,
-.Nm ber_add_noid ,
-.Nm ber_add_oidstring ,
-.Nm ber_get_oid ,
-.Nm ber_oid2ber ,
-.Nm ber_string2oid ,
-.Nm ber_oid_cmp ,
-.Nm ber_printf_elements ,
-.Nm ber_scanf_elements ,
-.Nm ber_get_writebuf ,
-.Nm ber_write_elements ,
-.Nm ber_set_readbuf ,
-.Nm ber_read_elements ,
-.Nm ber_getpos ,
-.Nm ber_free_element ,
-.Nm ber_free_elements ,
-.Nm ber_calc_len ,
-.Nm ber_set_application ,
-.Nm ber_set_writecallback ,
-.Nm ber_free
-.Nd encode and decode ASN.1 with Basic Encoding Rules
-.Sh SYNOPSIS
-.In ber.h
-.Ft "struct ber_element *"
-.Fn "ber_get_element" "unsigned int encoding"
-.Ft "void"
-.Fn "ber_set_header" "struct ber_element *elm" "int class" "unsigned int type"
-.Ft "void"
-.Fn "ber_link_elements" "struct ber_element *prev" "struct ber_element *elm"
-.Ft "struct ber_element *"
-.Fn "ber_unlink_elements" "struct ber_element *prev"
-.Ft "void"
-.Fn "ber_replace_elements" "struct ber_element *prev" "struct ber_element *elm"
-.Ft "struct ber_element *"
-.Fn "ber_add_sequence" "struct ber_element *prev"
-.Ft "struct ber_element *"
-.Fn "ber_add_set" "struct ber_element *prev"
-.Ft "struct ber_element *"
-.Fn "ber_add_integer" "struct ber_element *prev" "long long val"
-.Ft "int"
-.Fn "ber_get_integer" "struct ber_element *root" "long long *val"
-.Ft "struct ber_element *"
-.Fn "ber_add_enumerated" "struct ber_element *prev" "long long val"
-.Ft "int"
-.Fn "ber_get_enumerated" "struct ber_element *root" "long long *val"
-.Ft "struct ber_element *"
-.Fn "ber_add_boolean" "struct ber_element *prev" "int bool"
-.Ft "int"
-.Fn "ber_get_boolean" "struct ber_element *root" "int *bool"
-.Ft "struct ber_element *"
-.Fn "ber_add_string" "struct ber_element *prev" "const char *string"
-.Ft "struct ber_element *"
-.Fn "ber_add_nstring" "struct ber_element *prev" "const char *string" "size_t size"
-.Ft "struct ber_element *"
-.Fo "ber_add_ostring"
-.Fa "struct ber_element *prev"
-.Fa "struct ber_octetstring *ostring"
-.Fc
-.Ft "int"
-.Fn "ber_get_string" "struct ber_element *root" "char **charbuf"
-.Ft "int"
-.Fn "ber_get_nstring" "struct ber_element *root" "void **buf" "size_t *size"
-.Ft "int"
-.Fn "ber_get_ostring" "struct ber_element *root" "struct ber_octetstring *ostring"
-.Ft "struct ber_element *"
-.Fo "ber_add_bitstring"
-.Fa "struct ber_element *prev"
-.Fa "const void *buf"
-.Fa "size_t size"
-.Fc
-.Ft "int"
-.Fn "ber_get_bitstring" "struct ber_element *root" "void **buf" "size_t *size"
-.Ft "struct ber_element *"
-.Fn "ber_add_null" "struct ber_element *prev"
-.Ft "int"
-.Fn "ber_get_null" "struct ber_element *root"
-.Ft "struct ber_element *"
-.Fn "ber_add_eoc" "struct ber_element *prev"
-.Ft "int"
-.Fn "ber_get_eoc" "struct ber_element *root"
-.Ft "struct ber_element *"
-.Fn "ber_add_oid" "struct ber_element *prev" "struct ber_oid *oid"
-.Ft "struct ber_element *"
-.Fn "ber_add_noid" "struct ber_element *prev" "struct ber_oid *oid" "int n"
-.Ft "struct ber_element *"
-.Fn "ber_add_oidstring" "struct ber_element *prev" "const char *string"
-.Ft "int"
-.Fn "ber_get_oid" "struct ber_element *root" "struct ber_oid *oid"
-.Ft "size_t"
-.Fn "ber_oid2ber" "struct ber_oid *oid" "u_int8_t *buf" "size_t size"
-.Ft "int"
-.Fn "ber_string2oid" "const char *string" "struct ber_oid *oid"
-.Ft "int"
-.Fn "ber_oid_cmp" "struct ber_oid *oid" "struct ber_oid *oid"
-.Ft "struct ber_element *"
-.Fn "ber_printf_elements" "struct ber_element *prev" "char *format" "..."
-.Ft "int"
-.Fn "ber_scanf_elements" "struct ber_element *root" "char *format" "..."
-.Ft "ssize_t"
-.Fn "ber_get_writebuf" "struct ber *ber" "void **buf"
-.Ft "ssize_t"
-.Fn "ber_write_elements" "struct ber *ber" "struct ber_element *root"
-.Ft "void"
-.Fn "ber_set_readbuf" "struct ber *ber" "void *buf" "size_t len"
-.Ft "struct ber_element *"
-.Fn "ber_read_elements" "struct ber *ber" "struct ber_element *root"
-.Ft off_t
-.Fn "ber_getpos" "struct ber_element *elm"
-.Ft "void"
-.Fn "ber_free_element" "struct ber_element *root"
-.Ft "void"
-.Fn "ber_free_elements" "struct ber_element *root"
-.Ft "size_t"
-.Fn "ber_calc_len" "struct ber_element *root"
-.Ft "void"
-.Fo "ber_set_application"
-.Fa "struct ber *ber"
-.Fa "unsigned int (*cb)(struct ber_element *)"
-.Fc
-.Ft "void"
-.Fo "ber_set_writecallback"
-.Fa "struct ber_element *elm"
-.Fa "void (*cb)(void *arg, size_t offs)"
-.Fa "void *arg"
-.Fc
-.Ft "void"
-.Fn "ber_free" "struct ber *ber"
-.Sh DESCRIPTION
-The
-.Nm ber
-API provides a mechanism to read and write ASN.1 streams and buffers using the
-Basic Encoding Rules.
-.Pp
-Encoded
-.Nm ber
-is stored in the following structure:
-.Bd -literal
-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 *);
-};
-.Ed
-.Pp
-.Fa br_rbuf
-and
-.Fa br_wbuf
-are the read and write buffers for a
-.Nm ber
-stream.
-These buffers are used when reading an existing byte stream (e.g. received from
-a TLS connection), or when writing a new byte stream in preparation for
-subsequent operations performed by the calling application (e.g. network
-transmission or export to a file).
-.Pp
-Intermediary storage of ber elements during decoding and encoding uses the
-following structure:
-.Bd -literal
-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
-};
-.Ed
-.Pp
-A linked list containing one or more
-.Vt ber_element
-is created during the decoding and encoding of
-.Vt ber .
-.Pp
-Once the
-.Vt ber
-and
-.Vt ber_element
-data structures have been declared,
-.Fn ber_set_readbuf
-may be called to initialize
-.Fa br_rbuf
-in preparation for decoding.
-It is assumed that a pointer to a ber byte stream is already available to the
-application, commonly obtained by
-.Xr read 2 ,
-.Xr recv 2 ,
-or
-.Xr tls_read 3 .
-.Fn ber_read_elements
-may then be called to parse, validate, and store the data stream into its
-consituent parts for subsequent processing.
-.Fn ber_read_elements
-returns a pointer to a fully populated list of one or more
-.Vt ber_element ,
-or
-.Dv NULL
-on a type mismatch or read error.
-.Pp
-The calling application must have explicit knowledge of the expected data
-types in order for correct decoding.
-.Fn ber_scanf_elements
-may be called to extract
-.Vt ber_element
-content into local variables.
-The
-.Fn ber_get_*
-functions extract the value of a single
-.Vt ber_element
-instance.
-.Fn ber_scanf_elements
-and the
-.Fn ber_get_*
-functions return 0 on success and -1 on failure.
-.Pp
-The first step when creating new ber is to populate
-.Vt ber_element
-with the desired content.
-This may be achieved using the
-.Fn ber_add_*
-and
-.Fn ber_printf_elements
-functions, each of which return a pointer to
-.Vt ber_element
-on success or
-.Dv NULL
-on failure.
-.Pp
-Once
-.Vt ber_element
-has been fully populated,
-.Fn ber_get_writebuf
-may be used to initialize
-.Fa br_wbuf
-for writing.
-.Fn ber_write_elements
-encodes
-.Vt ber_element
-into a compliant
-.Nm ber
-byte stream for subsequent use by the calling application, most commonly using
-.Xr send 2 ,
-.Xr write 2 ,
-or
-.Xr tls_write 3 .
-.Sh I/O OPERATIONS
-.Fn ber_get_writebuf ,
-.Fn ber_write_elements ,
-.Fn ber_set_readbuf ,
-.Fn ber_read_elements ,
-.Fn ber_getpos ,
-.Fn ber_free_element ,
-.Fn ber_free_elements ,
-.Fn ber_set_application ,
-.Fn ber_set_writecallback ,
-.Fn ber_free
-.Sh BER ELEMENTS
-.Fn ber_get_element ,
-.Fn ber_set_header ,
-.Fn ber_link_elements ,
-.Fn ber_unlink_elements ,
-.Fn ber_replace_elements ,
-.Fn ber_calc_len
-.Sh BER TYPES
-.Fn ber_add_sequence ,
-.Fn ber_add_set ,
-.Fn ber_add_integer ,
-.Fn ber_get_integer ,
-.Fn ber_add_enumerated ,
-.Fn ber_get_enumerated ,
-.Fn ber_add_boolean ,
-.Fn ber_get_boolean ,
-.Fn ber_add_string ,
-.Fn ber_add_nstring ,
-.Fn ber_add_ostring ,
-.Fn ber_add_bitstring ,
-.Fn ber_get_string ,
-.Fn ber_get_nstring ,
-.Fn ber_get_ostring ,
-.Fn ber_get_bitstring ,
-.Fn ber_add_null ,
-.Fn ber_get_null ,
-.Fn ber_add_eoc ,
-.Fn ber_get_eoc
-.Sh FORMAT STRINGS
-.Fn ber_printf_elements ,
-.Fn ber_scanf_elements
-.Sh OBJECT IDS
-Object Identifiers are commonly used in ASN.1-based protocols.
-These functions provide an interface to parse OIDs.
-For internal representation of OIDs, the following structure
-.Vt struct ber_oid
-is being used:
-.Bd -literal
-#define BER_MIN_OID_LEN 2
-#define BER_MAX_OID_LEN 32
-
-struct ber_oid {
- u_int32_t bo_id[BER_MAX_OID_LEN + 1];
- size_t bo_n;
-};
-.Ed
-.Pp
-.Fn ber_add_oid ,
-.Fn ber_add_noid ,
-.Fn ber_add_oidstring ,
-.Fn ber_get_oid ,
-.Fn ber_oid2ber ,
-.Fn ber_string2oid
-.Fn ber_oid_cmp ,
-.Sh RETURN VALUES
-Upon successful completion
-.Fn ber_get_integer ,
-.Fn ber_get_enumerated ,
-.Fn ber_get_boolean ,
-.Fn ber_get_string ,
-.Fn ber_get_nstring ,
-.Fn ber_get_ostring ,
-.Fn ber_get_bitstring ,
-.Fn ber_get_null ,
-.Fn ber_get_eoc ,
-.Fn ber_get_oid ,
-.Fn ber_string2oid
-and
-.Fn ber_scanf_elements
-return 0, while
-.Fn ber_write_elements
-returns the number of bytes written.
-Otherwise, \-1 is returned and the global variable errno is
-set to indicate the error.
-.Sh SEE ALSO
-.Xr read 2 ,
-.Xr recv 2 ,
-.Xr send 2 ,
-.Xr write 2 ,
-.Xr tls_read 3
-.Sh STANDARDS
-ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
-Information technology - ASN.1 encoding rules.
-.Sh HISTORY
-The
-.Nm ber
-manpage first appeared in
-.Ox 4.3 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm ber
-library was written by
-.An Claudio Jeker Aq Mt claudio@openbsd.org ,
-.An Marc Balmer Aq Mt marc@openbsd.org
-and
-.An Reyk Floeter Aq Mt reyk@openbsd.org .
-.Sh CAVEATS
-The
-.Nm ber
-API is subject to the following restrictions which are common to the
-Distinguished Encoding Rules as defined by X.690:
-.Pp
-.Bl -enum -compact
-.It
-Only the definite form of length encoding shall be used, encoded in the
-minimum number of octets.
-.It
-For bitstring, octetstring and restricted character string types, the
-constructed form of encoding shall not be used.
-.It
-If a boolean encoding represents the boolean value TRUE, its single contents
-octet shall have all eight bits set to one.
-.It
-Each unused bit in the final octet of the encoding of a bit string value shall
-be set to zero.
-.It
-If a bitstring value has no 1 bits, then an encoder shall encode the value with
-a length of 1 and an initial octet set to 0.
-.El
-.Pp
-In addition, set and sequence values are limited to a maximum of 65535 elements.
-No alternative encodings are permitted.
-.Pp
-.Do
-Whereas the basic encoding rules give the sender of an encoding various choices
-as to how data values may be encoded, the canonical and distinguished encoding
-rules select just one encoding from those allowed by the basic encoding rules.
-.Dc
-.Bq X.690
-.Pp
-The restrictions placed on this API avoid the ambiguity inherent in
-.Nm ber
-encoded ASN.1 thereby acting as a security mitigation.
-.Sh BUGS
-This manpage is a stub.
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"