As per X.690, "the end-of-contents octets shall be present if the length is encoded as specified in 8.1.3.6, otherwise they shall not be present", i.e. only used with indefinite length encoding. Since we do not support indefinite length encoding, I thought it may make sense to remove some corresponding code from the ber api.
The end-of-content type under the universal class has a special meaning; if applications wish to make use of a similar, non-universal content value they are free to do so without assistance from the ber api. It would appear that ldap still wants to use the "eoc" functions, but I believe simply checking for a ber element length of zero should suffice in these cases (i.e. aldap.c). I think the RFC 2411 comment referenced in usr.sbin/ldapd/modify.c below should be referring to RFC 4511, but I will send a separate diff proposal for that. The ldapd and snmpd regression tests pass for me with these changes. I am only looking for feedback and testing at this time. I may be wrong with this approach, so feel free to correct me if you feel this is a misguided change. All such (DER like) restrictions enforced by the ber api will be clarified in an upcoming ber.3 diff. Regards, Rob Index: usr.bin/ldap/aldap.c =================================================================== RCS file: /cvs/src/usr.bin/ldap/aldap.c,v retrieving revision 1.4 diff -u -p -r1.4 aldap.c --- usr.bin/ldap/aldap.c 31 Jul 2018 11:37:18 -0000 1.4 +++ usr.bin/ldap/aldap.c 12 Aug 2018 17:39:52 -0000 @@ -568,7 +568,7 @@ aldap_count_attrs(struct aldap_message * return (-1); for (i = 0, a = msg->body.search.attrs; - a != NULL && ber_get_eoc(a) != 0; + a != NULL && a->be_len != 0; i++, a = a->be_next) ; @@ -616,7 +616,7 @@ aldap_next_attr(struct aldap_message *ms LDAP_DEBUG("attr", msg->body.search.iter); - if (ber_get_eoc(msg->body.search.iter) == 0) + if (msg->body.search.iter->be_len == 0) goto notfound; if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b) @@ -654,7 +654,7 @@ aldap_match_attr(struct aldap_message *m for (a = msg->body.search.attrs;;) { if (a == NULL) goto notfound; - if (ber_get_eoc(a) == 0) + if (a->be_len == 0) goto notfound; if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0) goto fail; Index: usr.bin/ldap/ber.c =================================================================== RCS file: /cvs/src/usr.bin/ldap/ber.c,v retrieving revision 1.18 diff -u -p -r1.18 ber.c --- usr.bin/ldap/ber.c 3 Aug 2018 01:51:28 -0000 1.18 +++ usr.bin/ldap/ber.c 12 Aug 2018 17:39:52 -0000 @@ -359,28 +359,6 @@ ber_get_null(struct ber_element *elm) 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) { @@ -629,11 +607,6 @@ ber_printf_elements(struct ber_element * case ')': ber = sub; break; - case '.': - if ((e = ber_add_eoc(ber)) == NULL) - goto fail; - ber = e; - break; default: break; } @@ -737,11 +710,6 @@ ber_scanf_elements(struct ber_element *b 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); @@ -990,7 +958,10 @@ ber_dump_element(struct ber *ber, struct ber_write(ber, root->be_val, root->be_len); break; case BER_TYPE_NULL: /* no payload */ + break; case BER_TYPE_EOC: + if (root->be_class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_SEQUENCE: case BER_TYPE_SET: @@ -1202,6 +1173,8 @@ ber_read_element(struct ber *ber, struct switch (elm->be_encoding) { case BER_TYPE_EOC: /* End-Of-Content */ + if (class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_BOOLEAN: case BER_TYPE_INTEGER: Index: usr.bin/ldap/ber.h =================================================================== RCS file: /cvs/src/usr.bin/ldap/ber.h,v retrieving revision 1.6 diff -u -p -r1.6 ber.h --- usr.bin/ldap/ber.h 3 Aug 2018 01:51:28 -0000 1.6 +++ usr.bin/ldap/ber.h 12 Aug 2018 17:39:52 -0000 @@ -113,8 +113,6 @@ int ber_get_bitstring(struct ber_elem 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 *); cvs server: Diffing usr.sbin cvs server: Diffing usr.sbin/ldapctl cvs server: Diffing usr.sbin/ldapd Index: usr.sbin/ldapd/ber.c =================================================================== RCS file: /cvs/src/usr.sbin/ldapd/ber.c,v retrieving revision 1.28 diff -u -p -r1.28 ber.c --- usr.sbin/ldapd/ber.c 3 Aug 2018 01:51:28 -0000 1.28 +++ usr.sbin/ldapd/ber.c 12 Aug 2018 17:39:53 -0000 @@ -359,28 +359,6 @@ ber_get_null(struct ber_element *elm) 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) { @@ -629,11 +607,6 @@ ber_printf_elements(struct ber_element * case ')': ber = sub; break; - case '.': - if ((e = ber_add_eoc(ber)) == NULL) - goto fail; - ber = e; - break; default: break; } @@ -737,11 +710,6 @@ ber_scanf_elements(struct ber_element *b 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); @@ -990,7 +958,10 @@ ber_dump_element(struct ber *ber, struct ber_write(ber, root->be_val, root->be_len); break; case BER_TYPE_NULL: /* no payload */ + break; case BER_TYPE_EOC: + if (root->be_class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_SEQUENCE: case BER_TYPE_SET: @@ -1202,6 +1173,8 @@ ber_read_element(struct ber *ber, struct switch (elm->be_encoding) { case BER_TYPE_EOC: /* End-Of-Content */ + if (class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_BOOLEAN: case BER_TYPE_INTEGER: Index: usr.sbin/ldapd/ber.h =================================================================== RCS file: /cvs/src/usr.sbin/ldapd/ber.h,v retrieving revision 1.7 diff -u -p -r1.7 ber.h --- usr.sbin/ldapd/ber.h 3 Aug 2018 01:51:28 -0000 1.7 +++ usr.sbin/ldapd/ber.h 12 Aug 2018 17:39:53 -0000 @@ -113,8 +113,6 @@ int ber_get_bitstring(struct ber_elem 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 *); Index: usr.sbin/ldapd/modify.c =================================================================== RCS file: /cvs/src/usr.sbin/ldapd/modify.c,v retrieving revision 1.21 diff -u -p -r1.21 modify.c --- usr.sbin/ldapd/modify.c 14 May 2018 07:53:47 -0000 1.21 +++ usr.sbin/ldapd/modify.c 12 Aug 2018 17:39:53 -0000 @@ -327,7 +327,7 @@ ldap_modify(struct request *req) /* * We're already in the "SET OF value * AttributeValue" (see RFC2411 section - * 4.1.7) have either EOC, so all values + * 4.1.7) have either no content, so all values * for the attribute gets deleted, or we * have a (first) octetstring (there is one * for each AttributeValue to be deleted) @@ -340,8 +340,8 @@ ldap_modify(struct request *req) } break; case LDAP_MOD_REPLACE: - if (vals->be_sub != NULL && - vals->be_sub->be_type != BER_TYPE_EOC) { + if (vals->be_sub && + vals->be_sub->be_len != 0) { if (a == NULL) { if (ldap_add_attribute(entry, attr, vals) != NULL) vals = NULL; Index: usr.sbin/ldapd/search.c =================================================================== RCS file: /cvs/src/usr.sbin/ldapd/search.c,v retrieving revision 1.23 diff -u -p -r1.23 search.c --- usr.sbin/ldapd/search.c 31 Jul 2018 11:01:00 -0000 1.23 +++ usr.sbin/ldapd/search.c 12 Aug 2018 17:39:54 -0000 @@ -72,7 +72,7 @@ should_include_attribute(char *adesc, st struct ber_element *elm; if (search->attrlist->be_sub == NULL || - search->attrlist->be_sub->be_encoding == BER_TYPE_EOC) { + search->attrlist->be_sub->be_len == 0) { /* An empty list with no attributes requests the return of * all user attributes. */ return !is_operational(adesc); cvs server: Diffing usr.sbin/ldapd/schema cvs server: Diffing usr.sbin/snmpctl cvs server: Diffing usr.sbin/snmpd Index: usr.sbin/snmpd/ber.3 =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/ber.3,v retrieving revision 1.17 diff -u -p -r1.17 ber.3 --- usr.sbin/snmpd/ber.3 31 Jul 2018 11:01:29 -0000 1.17 +++ usr.sbin/snmpd/ber.3 12 Aug 2018 17:39:54 -0000 @@ -39,8 +39,6 @@ .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 , @@ -107,10 +105,6 @@ .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" @@ -180,8 +174,6 @@ using the .Fn ber_get_bitstring , .Fn ber_add_null , .Fn ber_get_null , -.Fn ber_add_eoc , -.Fn ber_get_eoc .Sh OBJECT IDS Object Identifiers are commonly used in ASN.1-based protocols. These functions provide an interface to parse OIDs. @@ -228,7 +220,6 @@ Upon successful completion .Fn ber_get_nstring , .Fn ber_get_bitstring , .Fn ber_get_null , -.Fn ber_get_eoc , .Fn ber_get_oid , .Fn ber_string2oid and Index: usr.sbin/snmpd/ber.c =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/ber.c,v retrieving revision 1.47 diff -u -p -r1.47 ber.c --- usr.sbin/snmpd/ber.c 3 Aug 2018 01:51:28 -0000 1.47 +++ usr.sbin/snmpd/ber.c 12 Aug 2018 17:39:56 -0000 @@ -359,28 +359,6 @@ ber_get_null(struct ber_element *elm) 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) { @@ -629,11 +607,6 @@ ber_printf_elements(struct ber_element * case ')': ber = sub; break; - case '.': - if ((e = ber_add_eoc(ber)) == NULL) - goto fail; - ber = e; - break; default: break; } @@ -737,11 +710,6 @@ ber_scanf_elements(struct ber_element *b 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); @@ -990,7 +958,10 @@ ber_dump_element(struct ber *ber, struct ber_write(ber, root->be_val, root->be_len); break; case BER_TYPE_NULL: /* no payload */ + break; case BER_TYPE_EOC: + if (root->be_class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_SEQUENCE: case BER_TYPE_SET: @@ -1202,6 +1173,8 @@ ber_read_element(struct ber *ber, struct switch (elm->be_encoding) { case BER_TYPE_EOC: /* End-Of-Content */ + if (class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_BOOLEAN: case BER_TYPE_INTEGER: Index: usr.sbin/snmpd/ber.h =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/ber.h,v retrieving revision 1.13 diff -u -p -r1.13 ber.h --- usr.sbin/snmpd/ber.h 3 Aug 2018 01:51:28 -0000 1.13 +++ usr.sbin/snmpd/ber.h 12 Aug 2018 17:39:56 -0000 @@ -113,8 +113,6 @@ int ber_get_bitstring(struct ber_elem 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 *); cvs server: Diffing usr.sbin/ypldap Index: usr.sbin/ypldap/aldap.c =================================================================== RCS file: /cvs/src/usr.sbin/ypldap/aldap.c,v retrieving revision 1.42 diff -u -p -r1.42 aldap.c --- usr.sbin/ypldap/aldap.c 31 Jul 2018 11:37:18 -0000 1.42 +++ usr.sbin/ypldap/aldap.c 12 Aug 2018 17:40:03 -0000 @@ -568,7 +568,7 @@ aldap_count_attrs(struct aldap_message * return (-1); for (i = 0, a = msg->body.search.attrs; - a != NULL && ber_get_eoc(a) != 0; + a != NULL && a->be_len != 0; i++, a = a->be_next) ; @@ -616,7 +616,7 @@ aldap_next_attr(struct aldap_message *ms LDAP_DEBUG("attr", msg->body.search.iter); - if (ber_get_eoc(msg->body.search.iter) == 0) + if (msg->body.search.iter->be_len == 0) goto notfound; if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b) @@ -654,7 +654,7 @@ aldap_match_attr(struct aldap_message *m for (a = msg->body.search.attrs;;) { if (a == NULL) goto notfound; - if (ber_get_eoc(a) == 0) + if (a->be_len == 0) goto notfound; if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0) goto fail; Index: usr.sbin/ypldap/ber.c =================================================================== RCS file: /cvs/src/usr.sbin/ypldap/ber.c,v retrieving revision 1.30 diff -u -p -r1.30 ber.c --- usr.sbin/ypldap/ber.c 3 Aug 2018 01:51:28 -0000 1.30 +++ usr.sbin/ypldap/ber.c 12 Aug 2018 17:40:03 -0000 @@ -359,28 +359,6 @@ ber_get_null(struct ber_element *elm) 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) { @@ -629,11 +607,6 @@ ber_printf_elements(struct ber_element * case ')': ber = sub; break; - case '.': - if ((e = ber_add_eoc(ber)) == NULL) - goto fail; - ber = e; - break; default: break; } @@ -737,11 +710,6 @@ ber_scanf_elements(struct ber_element *b 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); @@ -990,7 +958,10 @@ ber_dump_element(struct ber *ber, struct ber_write(ber, root->be_val, root->be_len); break; case BER_TYPE_NULL: /* no payload */ + break; case BER_TYPE_EOC: + if (root->be_class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_SEQUENCE: case BER_TYPE_SET: @@ -1202,6 +1173,8 @@ ber_read_element(struct ber *ber, struct switch (elm->be_encoding) { case BER_TYPE_EOC: /* End-Of-Content */ + if (class == BER_CLASS_UNIVERSAL) + return -1; break; case BER_TYPE_BOOLEAN: case BER_TYPE_INTEGER: Index: usr.sbin/ypldap/ber.h =================================================================== RCS file: /cvs/src/usr.sbin/ypldap/ber.h,v retrieving revision 1.8 diff -u -p -r1.8 ber.h --- usr.sbin/ypldap/ber.h 3 Aug 2018 01:51:28 -0000 1.8 +++ usr.sbin/ypldap/ber.h 12 Aug 2018 17:40:05 -0000 @@ -113,8 +113,6 @@ int ber_get_bitstring(struct ber_elem 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 *);