Skip to content

Commit

Permalink
Update to freebsd 13-stable code from oct 28
Browse files Browse the repository at this point in the history
  • Loading branch information
laffer1 committed Nov 7, 2024
1 parent f083041 commit ade7165
Show file tree
Hide file tree
Showing 24 changed files with 19,721 additions and 104 deletions.
76 changes: 47 additions & 29 deletions contrib/bsnmp/lib/asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ asn_get_header(struct asn_buf *b, u_char *type, asn_len_t *len)
return (ASN_ERR_EOBUF);
}
*type = *b->asn_cptr;
if ((*type & ASN_TYPE_MASK) > 0x30) {
asn_error(b, "types > 0x30 not supported (%u)",
if ((*type & ASN_TYPE_MASK) > 0x1e) {
asn_error(b, "tags > 0x1e not supported (%#x)",
*type & ASN_TYPE_MASK);
return (ASN_ERR_FAILED);
}
Expand Down Expand Up @@ -100,11 +100,19 @@ asn_get_header(struct asn_buf *b, u_char *type, asn_len_t *len)
*len = *b->asn_cptr++;
b->asn_len--;
}

#ifdef BOGUS_CVE_2019_5610_FIX
/*
* This is the fix from CVE-2019-5610.
*
* This is the wrong place. Each of the asn functions should check
* that it has enough info for its own work.
*/
if (*len > b->asn_len) {
asn_error(b, "len %u exceeding asn_len %u", *len, b->asn_len);
asn_error(b, "lenen %u exceeding asn_len %u", *len, b->asn_len);
return (ASN_ERR_EOBUF);
}
#endif
return (ASN_ERR_OK);
}

Expand Down Expand Up @@ -147,7 +155,7 @@ asn_put_len(u_char *ptr, asn_len_t len)

/*
* Write a header (tag and length fields).
* Tags are restricted to one byte tags (value <= 0x30) and the
* Tags are restricted to one byte tags (value <= 0x1e) and the
* lenght field to 16-bit. All errors stop the encoding.
*/
enum asn_err
Expand All @@ -156,8 +164,8 @@ asn_put_header(struct asn_buf *b, u_char type, asn_len_t len)
u_int lenlen;

/* tag field */
if ((type & ASN_TYPE_MASK) > 0x30) {
asn_error(NULL, "types > 0x30 not supported (%u)",
if ((type & ASN_TYPE_MASK) > 0x1e) {
asn_error(NULL, "types > 0x1e not supported (%#x)",
type & ASN_TYPE_MASK);
return (ASN_ERR_FAILED);
}
Expand Down Expand Up @@ -251,9 +259,10 @@ asn_get_real_integer(struct asn_buf *b, asn_len_t len, int64_t *vp)
return (ASN_ERR_BADLEN);
}
err = ASN_ERR_OK;
if (len > 8)
if (len > 8) {
asn_error(b, "integer too long");
err = ASN_ERR_RANGE;
else if (len > 1 &&
} else if (len > 1 &&
((*b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) ||
(*b->asn_cptr == 0xff && (b->asn_cptr[1] & 0x80) == 0x80))) {
asn_error(b, "non-minimal integer");
Expand Down Expand Up @@ -331,27 +340,35 @@ asn_put_real_integer(struct asn_buf *b, u_char type, int64_t ival)
static enum asn_err
asn_get_real_unsigned(struct asn_buf *b, asn_len_t len, uint64_t *vp)
{
enum asn_err err;

*vp = 0;
if (b->asn_len < len) {
asn_error(b, "truncated integer");
return (ASN_ERR_EOBUF);
}
if (len == 0) {
/* X.690: 8.3.1 */
asn_error(b, "zero-length integer");
*vp = 0;
return (ASN_ERR_BADLEN);
}
err = ASN_ERR_OK;
*vp = 0;
if ((*b->asn_cptr & 0x80) || (len == 9 && *b->asn_cptr != 0)) {
if (len > 1 && *b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) {
/* X.690: 8.3.2 */
asn_error(b, "non-minimal unsigned");
b->asn_cptr += len;
b->asn_len -= len;
return (ASN_ERR_BADLEN);

}

enum asn_err err = ASN_ERR_OK;

if ((*b->asn_cptr & 0x80) || len > 9 ||
(len == 9 && *b->asn_cptr != 0)) {
/* negative integer or too larger */
*vp = 0xffffffffffffffffULL;
err = ASN_ERR_RANGE;
} else if (len > 1 &&
*b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) {
asn_error(b, "non-minimal unsigned");
err = ASN_ERR_BADLEN;
asn_error(b, "unsigned too large or negative");
b->asn_cptr += len;
b->asn_len -= len;
return (ASN_ERR_RANGE);
}

while (len--) {
Expand Down Expand Up @@ -405,11 +422,14 @@ asn_get_integer_raw(struct asn_buf *b, asn_len_t len, int32_t *vp)
enum asn_err ret;

if ((ret = asn_get_real_integer(b, len, &val)) == ASN_ERR_OK) {
if (len > 4)
if (len > 4) {
asn_error(b, "integer too long");
ret = ASN_ERR_BADLEN;
else if (val > INT32_MAX || val < INT32_MIN)
} else if (val > INT32_MAX || val < INT32_MIN) {
/* may not happen */
asn_error(b, "integer out of range");
ret = ASN_ERR_RANGE;
}
*vp = (int32_t)val;
}
return (ret);
Expand Down Expand Up @@ -589,7 +609,7 @@ asn_get_objid_raw(struct asn_buf *b, asn_len_t len, struct asn_oid *oid)
return (ASN_ERR_EOBUF);
}
if (subid > (ASN_MAXID >> 7)) {
asn_error(b, "OBID subid too larger");
asn_error(b, "OID subid too larger");
err = ASN_ERR_RANGE;
}
subid = (subid << 7) | (*b->asn_cptr & 0x7f);
Expand Down Expand Up @@ -645,7 +665,7 @@ asn_put_objid(struct asn_buf *b, const struct asn_oid *oid)
oidlen = 2;
} else if (oid->len == 1) {
/* illegal */
asn_error(b, "short oid");
asn_error(NULL, "short oid");
if (oid->subs[0] > 2)
asn_error(NULL, "oid[0] too large (%u)", oid->subs[0]);
err = ASN_ERR_RANGE;
Expand All @@ -657,7 +677,8 @@ asn_put_objid(struct asn_buf *b, const struct asn_oid *oid)
err = ASN_ERR_RANGE;
}
if (oid->subs[0] > 2 ||
(oid->subs[0] < 2 && oid->subs[1] >= 40)) {
(oid->subs[0] < 2 && oid->subs[1] >= 40) ||
(oid->subs[0] == 2 && oid->subs[1] > ASN_MAXID - 2 * 40)) {
asn_error(NULL, "oid out of range (%u,%u)",
oid->subs[0], oid->subs[1]);
err = ASN_ERR_RANGE;
Expand Down Expand Up @@ -814,10 +835,7 @@ asn_get_uint32_raw(struct asn_buf *b, asn_len_t len, uint32_t *vp)
enum asn_err err;

if ((err = asn_get_real_unsigned(b, len, &v)) == ASN_ERR_OK) {
if (len > 5) {
asn_error(b, "uint32 too long %u", len);
err = ASN_ERR_BADLEN;
} else if (v > UINT32_MAX) {
if (v > UINT32_MAX) {
asn_error(b, "uint32 too large %llu", v);
err = ASN_ERR_RANGE;
}
Expand Down
59 changes: 52 additions & 7 deletions contrib/bsnmp/lib/bsnmpclient.3
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
.\"
.\" $Begemot: bsnmp/lib/bsnmpclient.3,v 1.12 2005/10/04 08:46:50 brandt_h Exp $
.\"
.Dd December 31, 2016
.Dd March 31, 2020
.Dt BSNMPCLIENT 3
.Os
.Sh NAME
Expand Down Expand Up @@ -177,7 +177,9 @@ If it is
a local stream socket is used.
For
.Dv SNMP_TRANS_UDP
a UDP socket is created.
a UDPv4 socket and for
.Dv SNMP_TRANS_UDP6
a UDPv6 socket is created.
It uses the
.Va chost
field as the path to the server's socket for local sockets.
Expand Down Expand Up @@ -675,7 +677,12 @@ The syntax of a server specification is
.Pp
where
.Va trans
is the transport name (one of udp, stream or dgram),
is the transport name (one of
.Qq udp ,
.Qq udp6 ,
.Qq stream
or
.Qq dgram ) ,
.Va community
is the string to be used for both the read and the write community,
.Va server
Expand All @@ -685,13 +692,51 @@ of a local socket, and
is the port in case of UDP transport.
The function returns 0 in the case of success and return -1 and sets
the error string in case of an error.
.Pp
The function
.Fn snmp_parse_serverr
fills the transport, the port number and the community strings with
reasonable default values when they are not specified.
The default transport
is
.Dv SNMP_TRANS_UDP .
If the host name contains a slash the default is modified to
.Dv SNMP_TRANS_LOC_DGRAM .
If the host name looks like a numeric IPv6 address the default is
.Dv SNMP_TRANS_UDP6 .
For numeric IPv6 addresses the transport name udp is automatically
translated as
.Dv SNMP_TRANS_UDP6 .
The default port number (for
.Dv udp
or
.Dv udp6 )
is
.Qq snmp .
The default read community is
.Qq public
and the default write community
.Qq private .
.Pp
.Fn snmp_parse_server
recognizes path names, host names and numerical IPv4 and IPv6 addresses.
A string consisting of digits and periods is assumed to be an IPv4 address
and must be parseable by
.Fn inet_aton 3 .
An IPv6 address is any string enclosed in square brackets.
It must be parseable with
.Fn gethostinfo 3 .
.Pp
The port number for
.Fn snmp_parse_server
can be specified numerically or symbolically.
It is ignored for local sockets.
.Sh DIAGNOSTICS
If an error occurs in any of the function an error indication as described
If an error occurs in any of the functions an error indication as described
above is returned.
Additionally the function sets a printable error string
in the
Additionally the function sets a printable error string in the
.Va error
filed of
field of
.Va snmp_client .
.Sh SEE ALSO
.Xr gensnmptree 1 ,
Expand Down
45 changes: 29 additions & 16 deletions contrib/bsnmp/lib/snmpclient.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005,2018
* Copyright (c) 2004-2005,2018-2019
* Hartmut Brandt.
* All rights reserved.
* Copyright (c) 2001-2003
Expand Down Expand Up @@ -930,7 +930,7 @@ open_client_udp(const char *host, const char *port)
/* open connection */
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = snmp_client.trans == SNMP_TRANS_UDP ? AF_INET:
hints.ai_family = snmp_client.trans == SNMP_TRANS_UDP ? AF_INET :
AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
Expand Down Expand Up @@ -1884,7 +1884,8 @@ static const char *const trans_list[] = {
/**
* Try to get a transport identifier which is a leading alphanumeric string
* terminated by a double colon. The string may not be empty. The transport
* identifier is optional.
* identifier is optional. Unknown transport identifiers are reject.
* Be careful: a double colon can also occur in a numeric IPv6 address.
*
* \param sc client struct to set errors
* \param strp possible start of transport; updated to point to
Expand All @@ -1899,22 +1900,30 @@ get_transp(struct snmp_client *sc, const char **strp)
size_t i;

for (i = 0; i < nitems(trans_list); i++) {
if (trans_list[i] == NULL || *trans_list[i] == '\0')
continue;
p = strstr(*strp, trans_list[i]);
if (p == *strp) {
*strp += strlen(trans_list[i]);
return ((int)i);
}
}

p = *strp;
if (p[0] == ':' && p[1] == ':') {
p = strstr(*strp, "::");
if (p == *strp) {
seterr(sc, "empty transport specifier");
return (-1);
}
/* by default assume UDP */
return (SNMP_TRANS_UDP);
if (p == NULL)
/* by default assume UDP */
return (SNMP_TRANS_UDP);

/* ignore :: after [ */
const char *ob = strchr(*strp, '[');
if (ob != NULL && p > ob)
/* by default assume UDP */
return (SNMP_TRANS_UDP);

seterr(sc, "unknown transport specifier '%.*s'", p - *strp, *strp);
return (-1);
}

/**
Expand Down Expand Up @@ -2153,12 +2162,14 @@ int
snmp_parse_server(struct snmp_client *sc, const char *str)
{
const char *const orig = str;

/* parse input */
int i, trans = get_transp(sc, &str);
int def_trans = 0, trans = get_transp(sc, &str);
if (trans < 0)
return (-1);
/* choose automatically */
i = orig == str ? -1: trans;
if (orig == str)
def_trans = 1;

const char *const comm[2] = {
str,
Expand Down Expand Up @@ -2204,7 +2215,7 @@ snmp_parse_server(struct snmp_client *sc, const char *str)
}

#if DEBUG_PARSE
printf("transp: %u\n", trans);
printf("transp: %d (def=%d)\n", trans, def_trans);
printf("comm: %zu %zu\n", comm[0] - orig, comm[1] - orig);
printf("ipv6: %zu %zu\n", ipv6[0] - orig, ipv6[1] - orig);
printf("ipv4: %zu %zu\n", ipv4[0] - orig, ipv4[1] - orig);
Expand All @@ -2218,18 +2229,19 @@ snmp_parse_server(struct snmp_client *sc, const char *str)
if (ipv6[0] != ipv6[1]) {
if ((chost = save_str(sc, ipv6)) == NULL)
return (-1);
if (i == -1 || trans == SNMP_TRANS_UDP)
if (def_trans || trans == SNMP_TRANS_UDP)
/* assume the user meant udp6:: */
trans = SNMP_TRANS_UDP6;
} else if (ipv4[0] != ipv4[1]) {
if ((chost = save_str(sc, ipv4)) == NULL)
return (-1);
if (i == -1)
if (def_trans)
trans = SNMP_TRANS_UDP;
} else {
if ((chost = save_str(sc, host)) == NULL)
return (-1);

if (i == -1) {
if (def_trans) {
/*
* Default transport is UDP unless the host contains
* a slash in which case we default to DGRAM.
Expand Down Expand Up @@ -2258,6 +2270,7 @@ snmp_parse_server(struct snmp_client *sc, const char *str)

/* commit */
sc->trans = trans;

/*
* If community string was specified and it is empty, overwrite it.
* If it was not specified, use default.
Expand All @@ -2276,7 +2289,7 @@ snmp_parse_server(struct snmp_client *sc, const char *str)

#if DEBUG_PARSE
printf("Committed values:\n");
printf("trans: %u\n", sc->trans);
printf("trans: %d\n", sc->trans);
printf("comm: '%s'/'%s'\n", sc->read_community, sc->write_community);
printf("host: '%s'\n", sc->chost);
printf("port: '%s'\n", sc->cport);
Expand Down
Loading

0 comments on commit ade7165

Please sign in to comment.