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);