Hi,

I found a crash on ldapd while parsing schema file, and wrote a fix for
the crash. It's first time for me to send a patch to OpenBSD, so if
there's any problem please let me know.

The crash is found on -CURRENT, and the patch is written based on latest
CVS version. nis.schema from -CURRENT and additional sshkey.schema file
is needed to reproduce the crash.

Here's content of sshkey.schema
--
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
    EQUALITY octetStringMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )

objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey'
    SUP top
    AUXILIARY
    MUST ( sshPublicKey $ uid )
    )
--

Here's first ldapd.conf file which crashes ldapd
--
schema "/etc/ldap/nis.schema"
schema "sshkey.schema"
schema "/etc/ldap/nis.schema"
schema "sshkey.schema"
--

Here's second ldapd.conf file, similar with the first one but crashed on
different point
--
schema "/etc/ldap/nis.schema"
schema "sshkey.schema"
namespace "d=a"
schema "sshkey.schema"
namespace "d=a"
schema "/etc/ldap/nis.schema"
--

Finally, here's the patch.


Index: usr.sbin/ldapd/schema.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/schema.c,v
retrieving revision 1.16
diff -u -p -r1.16 schema.c
--- usr.sbin/ldapd/schema.c     16 Nov 2014 19:04:40 -0000      1.16
+++ usr.sbin/ldapd/schema.c     18 Jan 2015 12:58:48 -0000
@@ -453,6 +453,18 @@ schema_err(struct schema *schema, const 
        schema->error++;
 }
 
+static void
+schema_unlink_attr_name(struct schema *schema, const char *name, struct 
attr_type *attr)
+{
+       struct oidname          find, *oidname;
+
+       find.on_name = name;
+       oidname = RB_FIND(oidname_tree, &schema->attr_names, &find);
+       if (oidname != NULL) {
+               RB_REMOVE(oidname_tree, &schema->attr_names, oidname);
+       }
+}
+
 static int
 schema_link_attr_name(struct schema *schema, const char *name, struct 
attr_type *attr)
 {
@@ -490,6 +502,16 @@ schema_link_attr_names(struct schema *sc
 }
 
 static int
+schema_unlink_attr_names(struct schema *schema, struct attr_type *attr)
+{
+       struct name     *name;
+
+       SLIST_FOREACH(name, attr->names, next) {
+               schema_unlink_attr_name(schema, name->name, attr);
+       }
+}
+
+static int
 schema_link_obj_name(struct schema *schema, const char *name, struct object 
*obj)
 {
        struct oidname          *oidname, *prev;
@@ -513,6 +535,18 @@ schema_link_obj_name(struct schema *sche
        return 0;
 }
 
+static void
+schema_unlink_obj_name(struct schema *schema, const char *name, struct object 
*obj)
+{
+       struct oidname          find, *oidname;
+
+       find.on_name = name;
+       oidname = RB_FIND(oidname_tree, &schema->object_names, &find);
+       if(oidname != NULL) {
+               RB_REMOVE(oidname_tree, &schema->object_names, oidname);
+       }
+}
+
 static int
 schema_link_obj_names(struct schema *schema, struct object *obj)
 {
@@ -525,6 +559,16 @@ schema_link_obj_names(struct schema *sch
        return 0;
 }
 
+static void
+schema_unlink_obj_names(struct schema *schema, struct object *obj)
+{
+       struct name     *name;
+
+       SLIST_FOREACH(name, obj->names, next) {
+               schema_unlink_obj_name(schema, name->name, obj);
+       }
+}
+
 static struct name_list *
 schema_parse_names(struct schema *schema)
 {
@@ -879,6 +923,9 @@ schema_parse_attributetype(struct schema
 fail:
        free(kw);
        if (attr != NULL) {
+               if(attr->names != NULL) {
+                       schema_unlink_attr_names(schema, attr);
+               }
                if (attr->oid != NULL) {
                        RB_REMOVE(attr_type_tree, &schema->attr_types, attr);
                        free(attr->oid);
@@ -1013,6 +1060,9 @@ schema_parse_objectclass(struct schema *
 fail:
        free(kw);
        if (obj != NULL) {
+               if (obj->names != NULL) {
+                       schema_unlink_obj_names(schema, obj);
+               }
                if (obj->oid != NULL) {
                        RB_REMOVE(object_tree, &schema->objects, obj);
                        free(obj->oid);

Reply via email to