This diff is a final synchronization of ber.c and ber.h.

It basically takes (2012) ber additions to snmpd and adds them back to ldap,
ldapd, and ypldap instances. See usr.sbin/snmpd/ber.c revision 1.24 commit
log for a summary of those changes (e.g. SNMPv2 traps, User-based Security
Model, callback for the USM HMAC calculations).

The ber code in this diff is not used by ldap, ldapd, or ypldap, but these
changes will make maintenance easier going forward.

The current (six) consumers of this ber implementation are as follows:
 - usr.bin/ldap
 - usr.sbin/ldapctl
 - usr.sbin/ldapd
 - usr.sbin/snmpctl
 - usr.sbin/snmpd
 - usr.sbin/ypldap

Ok?

Index: usr.bin/ldap/ber.c
===================================================================
RCS file: /cvs/src/usr.bin/ldap/ber.c,v
retrieving revision 1.6
diff -u -p -r1.6 ber.c
--- usr.bin/ldap/ber.c  29 Jun 2018 18:28:41 -0000      1.6
+++ usr.bin/ldap/ber.c  29 Jun 2018 19:41:59 -0000
@@ -631,10 +631,11 @@ ber_scanf_elements(struct ber_element *b
        va_list                  ap;
        int                     *d, level = -1;
        unsigned long           *t;
-       long long               *i;
+       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;
 
@@ -656,6 +657,13 @@ ber_scanf_elements(struct ber_element *b
                                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;
@@ -712,6 +720,11 @@ ber_scanf_elements(struct ber_element *b
                                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 &&
@@ -821,6 +834,12 @@ ber_read_elements(struct ber *ber, struc
        return root;
 }
 
+off_t
+ber_getpos(struct ber_element *elm)
+{
+       return elm->be_offs;
+}
+
 void
 ber_free_element(struct ber_element *root)
 {
@@ -893,6 +912,8 @@ ber_dump_element(struct ber *ber, struct
        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:
@@ -1101,6 +1122,7 @@ ber_read_element(struct ber *ber, struct
 
        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) {
@@ -1232,6 +1254,15 @@ ber_set_application(struct ber *b, unsig
 }
 
 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);
@@ -1258,5 +1289,33 @@ ber_read(struct ber *ber, void *buf, siz
                b += r;
                remain -= r;
        }
-       return (b - (u_char *)buf);
+       r = b - (u_char *)buf;
+       ber->br_offs += r;
+       return r;
+}
+
+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);
 }

Index: usr.bin/ldap/ber.h
===================================================================
RCS file: /cvs/src/usr.bin/ldap/ber.h,v
retrieving revision 1.3
diff -u -p -r1.3 ber.h
--- usr.bin/ldap/ber.h  29 Jun 2018 18:28:41 -0000      1.3
+++ usr.bin/ldap/ber.h  29 Jun 2018 19:41:59 -0000
@@ -17,13 +17,19 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifndef _BER_H
+#define _BER_H
+
 struct ber_element {
        struct ber_element      *be_next;
        unsigned long            be_type;
        unsigned long            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;
@@ -35,6 +41,7 @@ struct ber_element {
 };
 
 struct ber {
+       off_t    br_offs;
        u_char  *br_wbuf;
        u_char  *br_wptr;
        u_char  *br_wend;
@@ -119,10 +126,17 @@ ssize_t                    ber_get_writebuf(struct ber *
 int                     ber_write_elements(struct ber *, struct ber_element *);
 void                    ber_set_readbuf(struct ber *, void *, size_t);
 struct ber_element     *ber_read_elements(struct ber *, struct ber_element *);
+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 long (*)(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 */

Index: usr.sbin/ldapd/ber.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/ber.c,v
retrieving revision 1.16
diff -u -p -r1.16 ber.c
--- usr.sbin/ldapd/ber.c        29 Jun 2018 18:28:42 -0000      1.16
+++ usr.sbin/ldapd/ber.c        29 Jun 2018 19:42:09 -0000
@@ -631,10 +631,11 @@ ber_scanf_elements(struct ber_element *b
        va_list                  ap;
        int                     *d, level = -1;
        unsigned long           *t;
-       long long               *i;
+       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;
 
@@ -656,6 +657,13 @@ ber_scanf_elements(struct ber_element *b
                                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;
@@ -712,6 +720,11 @@ ber_scanf_elements(struct ber_element *b
                                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 &&
@@ -821,6 +834,12 @@ ber_read_elements(struct ber *ber, struc
        return root;
 }
 
+off_t
+ber_getpos(struct ber_element *elm)
+{
+       return elm->be_offs;
+}
+
 void
 ber_free_element(struct ber_element *root)
 {
@@ -893,6 +912,8 @@ ber_dump_element(struct ber *ber, struct
        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:
@@ -1101,6 +1122,7 @@ ber_read_element(struct ber *ber, struct
 
        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) {
@@ -1232,6 +1254,15 @@ ber_set_application(struct ber *b, unsig
 }
 
 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);
@@ -1258,5 +1289,33 @@ ber_read(struct ber *ber, void *buf, siz
                b += r;
                remain -= r;
        }
-       return (b - (u_char *)buf);
+       r = b - (u_char *)buf;
+       ber->br_offs += r;
+       return r;
+}
+
+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);
 }

Index: usr.sbin/ldapd/ber.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/ber.h,v
retrieving revision 1.4
diff -u -p -r1.4 ber.h
--- usr.sbin/ldapd/ber.h        29 Jun 2018 18:28:42 -0000      1.4
+++ usr.sbin/ldapd/ber.h        29 Jun 2018 19:42:09 -0000
@@ -17,13 +17,19 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifndef _BER_H
+#define _BER_H
+
 struct ber_element {
        struct ber_element      *be_next;
        unsigned long            be_type;
        unsigned long            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;
@@ -35,6 +41,7 @@ struct ber_element {
 };
 
 struct ber {
+       off_t    br_offs;
        u_char  *br_wbuf;
        u_char  *br_wptr;
        u_char  *br_wend;
@@ -119,10 +126,17 @@ ssize_t                    ber_get_writebuf(struct ber *
 int                     ber_write_elements(struct ber *, struct ber_element *);
 void                    ber_set_readbuf(struct ber *, void *, size_t);
 struct ber_element     *ber_read_elements(struct ber *, struct ber_element *);
+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 long (*)(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 */

Index: usr.sbin/ypldap/ber.c
===================================================================
RCS file: /cvs/src/usr.sbin/ypldap/ber.c,v
retrieving revision 1.18
diff -u -p -r1.18 ber.c
--- usr.sbin/ypldap/ber.c       29 Jun 2018 18:28:42 -0000      1.18
+++ usr.sbin/ypldap/ber.c       29 Jun 2018 19:42:19 -0000
@@ -631,10 +631,11 @@ ber_scanf_elements(struct ber_element *b
        va_list                  ap;
        int                     *d, level = -1;
        unsigned long           *t;
-       long long               *i;
+       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;
 
@@ -656,6 +657,13 @@ ber_scanf_elements(struct ber_element *b
                                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;
@@ -712,6 +720,11 @@ ber_scanf_elements(struct ber_element *b
                                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 &&
@@ -821,6 +834,12 @@ ber_read_elements(struct ber *ber, struc
        return root;
 }
 
+off_t
+ber_getpos(struct ber_element *elm)
+{
+       return elm->be_offs;
+}
+
 void
 ber_free_element(struct ber_element *root)
 {
@@ -893,6 +912,8 @@ ber_dump_element(struct ber *ber, struct
        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:
@@ -1101,6 +1122,7 @@ ber_read_element(struct ber *ber, struct
 
        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) {
@@ -1232,6 +1254,15 @@ ber_set_application(struct ber *b, unsig
 }
 
 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);
@@ -1258,5 +1289,33 @@ ber_read(struct ber *ber, void *buf, siz
                b += r;
                remain -= r;
        }
-       return (b - (u_char *)buf);
+       r = b - (u_char *)buf;
+       ber->br_offs += r;
+       return r;
+}
+
+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);
 }

Index: usr.sbin/ypldap/ber.h
===================================================================
RCS file: /cvs/src/usr.sbin/ypldap/ber.h,v
retrieving revision 1.5
diff -u -p -r1.5 ber.h
--- usr.sbin/ypldap/ber.h       29 Jun 2018 18:28:42 -0000      1.5
+++ usr.sbin/ypldap/ber.h       29 Jun 2018 19:42:19 -0000
@@ -17,13 +17,19 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifndef _BER_H
+#define _BER_H
+
 struct ber_element {
        struct ber_element      *be_next;
        unsigned long            be_type;
        unsigned long            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;
@@ -35,6 +41,7 @@ struct ber_element {
 };
 
 struct ber {
+       off_t    br_offs;
        u_char  *br_wbuf;
        u_char  *br_wptr;
        u_char  *br_wend;
@@ -119,10 +126,17 @@ ssize_t                    ber_get_writebuf(struct ber *
 int                     ber_write_elements(struct ber *, struct ber_element *);
 void                    ber_set_readbuf(struct ber *, void *, size_t);
 struct ber_element     *ber_read_elements(struct ber *, struct ber_element *);
+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 long (*)(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 */

Reply via email to