diff options
author | Martin Hedenfal <martinh@cvs.openbsd.org> | 2010-07-02 05:23:41 +0000 |
---|---|---|
committer | Martin Hedenfal <martinh@cvs.openbsd.org> | 2010-07-02 05:23:41 +0000 |
commit | feee5618724608016262d9d30337d44e8defc5f3 (patch) | |
tree | 9b91b7714389c1b10dbef1a902a264cafe713aa4 /usr.sbin/ldapd | |
parent | e096f67c64cdf963cf9b5a033b0065be2f5c2f68 (diff) |
Dump parsed schema to buffer and send in requests for the cn=schema
subschema namespace. Only do this if 'objectClasses' and 'attributeTypes'
are expicitly requested. This allows clients to for example present custom
editing forms.
Diffstat (limited to 'usr.sbin/ldapd')
-rw-r--r-- | usr.sbin/ldapd/schema.c | 239 | ||||
-rw-r--r-- | usr.sbin/ldapd/schema.h | 8 | ||||
-rw-r--r-- | usr.sbin/ldapd/search.c | 57 |
3 files changed, 290 insertions, 14 deletions
diff --git a/usr.sbin/ldapd/schema.c b/usr.sbin/ldapd/schema.c index 0bfeb38f554..f8ce78d898a 100644 --- a/usr.sbin/ldapd/schema.c +++ b/usr.sbin/ldapd/schema.c @@ -1,4 +1,4 @@ -/* $OpenBSD: schema.c,v 1.7 2010/07/02 00:42:50 martinh Exp $ */ +/* $OpenBSD: schema.c,v 1.8 2010/07/02 05:23:40 martinh Exp $ */ /* * Copyright (c) 2010 Martin Hedenfalk <martinh@openbsd.org> @@ -681,6 +681,7 @@ schema_parse_attributetype(struct schema *schema) log_warn("calloc"); goto fail; } + attr->usage = USAGE_USER_APP; if (is_oidstr(kw)) attr->oid = kw; @@ -999,3 +1000,239 @@ schema_parse(struct schema *schema, const char *filename) return ret; } +static int +schema_dump_names(const char *desc, struct name_list *nlist, + char *buf, size_t size) +{ + struct name *name; + + if (nlist == NULL || SLIST_EMPTY(nlist)) + return 0; + + if (strlcat(buf, " ", size) >= size || + strlcat(buf, desc, size) >= size) + return -1; + + name = SLIST_FIRST(nlist); + if (SLIST_NEXT(name, next) == NULL) { + /* single name, no parenthesis */ + if (strlcat(buf, " '", size) >= size || + strlcat(buf, name->name, size) >= size || + strlcat(buf, "'", size) >= size) + return -1; + } else { + if (strlcat(buf, " ( ", size) >= size) + return -1; + SLIST_FOREACH(name, nlist, next) + if (strlcat(buf, "'", size) >= size || + strlcat(buf, name->name, size) >= size || + strlcat(buf, "' ", size) >= size) + return -1; + if (strlcat(buf, ")", size) >= size) + return -1; + } + + return 0; +} + +static int +schema_dump_attrlist(const char *desc, struct attr_list *alist, + char *buf, size_t size) +{ + struct attr_ptr *aptr; + + if (alist == NULL || SLIST_EMPTY(alist)) + return 0; + + if (strlcat(buf, " ", size) >= size || + strlcat(buf, desc, size) >= size) + return -1; + + aptr = SLIST_FIRST(alist); + if (SLIST_NEXT(aptr, next) == NULL) { + /* single attribute, no parenthesis */ + if (strlcat(buf, " ", size) >= size || + strlcat(buf, ATTR_NAME(aptr->attr_type), size) >= size) + return -1; + } else { + if (strlcat(buf, " ( ", size) >= size) + return -1; + SLIST_FOREACH(aptr, alist, next) { + if (strlcat(buf, ATTR_NAME(aptr->attr_type), + size) >= size || + strlcat(buf, " ", size) >= size) + return -1; + if (SLIST_NEXT(aptr, next) != NULL && + strlcat(buf, "$ ", size) >= size) + return -1; + } + if (strlcat(buf, ")", size) >= size) + return -1; + } + + return 0; +} + +static int +schema_dump_objlist(const char *desc, struct obj_list *olist, + char *buf, size_t size) +{ + struct obj_ptr *optr; + + if (olist == NULL || SLIST_EMPTY(olist)) + return 0; + + if (strlcat(buf, " ", size) >= size || + strlcat(buf, desc, size) >= size) + return -1; + + optr = SLIST_FIRST(olist); + if (SLIST_NEXT(optr, next) == NULL) { + /* single attribute, no parenthesis */ + if (strlcat(buf, " ", size) >= size || + strlcat(buf, OBJ_NAME(optr->object), size) >= size) + return -1; + } else { + if (strlcat(buf, " ( ", size) >= size) + return -1; + SLIST_FOREACH(optr, olist, next) { + if (strlcat(buf, OBJ_NAME(optr->object), size) >= size || + strlcat(buf, " ", size) >= size) + return -1; + if (SLIST_NEXT(optr, next) != NULL && + strlcat(buf, "$ ", size) >= size) + return -1; + } + if (strlcat(buf, ")", size) >= size) + return -1; + } + + return 0; +} + +int +schema_dump_object(struct object *obj, char *buf, size_t size) +{ + if (strlcpy(buf, "( ", size) >= size || + strlcat(buf, obj->oid, size) >= size) + return -1; + + if (schema_dump_names("NAME", obj->names, buf, size) != 0) + return -1; + + if (obj->desc != NULL) + if (strlcat(buf, " DESC '", size) >= size || + strlcat(buf, obj->desc, size) >= size || + strlcat(buf, "'", size) >= size) + return -1; + + switch (obj->kind) { + case KIND_STRUCTURAL: + if (strlcat(buf, " STRUCTURAL", size) >= size) + return -1; + break; + case KIND_ABSTRACT: + if (strlcat(buf, " ABSTRACT", size) >= size) + return -1; + break; + case KIND_AUXILIARY: + if (strlcat(buf, " AUXILIARY", size) >= size) + return -1; + break; + } + + if (schema_dump_objlist("SUP", obj->sup, buf, size) != 0) + return -1; + + if (obj->obsolete && strlcat(buf, " OBSOLETE", size) >= size) + return -1; + + if (schema_dump_attrlist("MUST", obj->must, buf, size) != 0) + return -1; + + if (schema_dump_attrlist("MAY", obj->may, buf, size) != 0) + return -1; + + if (strlcat(buf, " )", size) >= size) + return -1; + + return 0; +} + +int +schema_dump_attribute(struct attr_type *at, char *buf, size_t size) +{ + if (strlcpy(buf, "( ", size) >= size || + strlcat(buf, at->oid, size) >= size) + return -1; + + if (schema_dump_names("NAME", at->names, buf, size) != 0) + return -1; + + if (at->desc != NULL) + if (strlcat(buf, " DESC ", size) >= size || + strlcat(buf, at->desc, size) >= size || + strlcat(buf, "'", size) >= size) + return -1; + + if (at->obsolete && strlcat(buf, " OBSOLETE", size) >= size) + return -1; + + if (at->sup != NULL) + if (strlcat(buf, " SUP ", size) >= size || + strlcat(buf, ATTR_NAME(at->sup), size) >= size) + return -1; + + if (at->equality != NULL) + if (strlcat(buf, " EQUALITY ", size) >= size || + strlcat(buf, at->equality, size) >= size) + return -1; + + if (at->ordering != NULL) + if (strlcat(buf, " ORDERING ", size) >= size || + strlcat(buf, at->ordering, size) >= size) + return -1; + + if (at->substr != NULL) + if (strlcat(buf, " SUBSTR ", size) >= size || + strlcat(buf, at->substr, size) >= size) + return -1; + + if (at->syntax != NULL) + if (strlcat(buf, " SYNTAX ", size) >= size || + strlcat(buf, at->syntax, size) >= size) + return -1; + + if (at->single && strlcat(buf, " SINGLE-VALUE", size) >= size) + return -1; + + if (at->collective && strlcat(buf, " COLLECTIVE", size) >= size) + return -1; + + if (at->immutable && strlcat(buf, " NO-USER-MODIFICATION", size) >= size) + return -1; + + switch (at->usage) { + case USAGE_USER_APP: + /* User application usage is the default. */ + break; + case USAGE_DIR_OP: + if (strlcat(buf, " USAGE directoryOperation", size) >= size) + return -1; + break; + case USAGE_DIST_OP: + if (strlcat(buf, " USAGE distributedOperation", size) >= size) + return -1; + break; + case USAGE_DSA_OP: + if (strlcat(buf, " USAGE dSAOperation", size) >= size) + return -1; + break; + } + + if (strlcat(buf, " )", size) >= size) + return -1; + + return 0; +} + diff --git a/usr.sbin/ldapd/schema.h b/usr.sbin/ldapd/schema.h index 91e6d748c6a..d00dfaa14e3 100644 --- a/usr.sbin/ldapd/schema.h +++ b/usr.sbin/ldapd/schema.h @@ -1,4 +1,4 @@ -/* $OpenBSD: schema.h,v 1.3 2010/07/01 18:37:12 martinh Exp $ */ +/* $OpenBSD: schema.h,v 1.4 2010/07/02 05:23:40 martinh Exp $ */ /* * Copyright (c) 2010 Martin Hedenfalk <martinh@openbsd.org> @@ -117,7 +117,7 @@ struct schema struct oidname_tree attr_names; struct object_tree objects; struct oidname_tree object_names; - struct symoid_tree symbolic_oids; + struct symoid_tree symbolic_oids; FILE *fp; const char *filename; @@ -130,6 +130,10 @@ struct schema struct schema *schema_new(void); int schema_parse(struct schema *schema, const char *filename); +int schema_dump_object(struct object *obj, + char *buf, size_t size); +int schema_dump_attribute(struct attr_type *obj, + char *buf, size_t size); struct attr_type *lookup_attribute_by_oid(struct schema *schema, char *oid); struct attr_type *lookup_attribute_by_name(struct schema *schema, char *name); diff --git a/usr.sbin/ldapd/search.c b/usr.sbin/ldapd/search.c index bdcaaafc4ef..a6dcd63808d 100644 --- a/usr.sbin/ldapd/search.c +++ b/usr.sbin/ldapd/search.c @@ -1,4 +1,4 @@ -/* $OpenBSD: search.c,v 1.9 2010/07/01 02:19:11 martinh Exp $ */ +/* $OpenBSD: search.c,v 1.10 2010/07/02 05:23:40 martinh Exp $ */ /* * Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se> @@ -65,14 +65,11 @@ is_operational(char *adesc) /* Return true if attr should be included in search entry. */ static int -should_include_attribute(struct ber_element *attr, struct search *search) +should_include_attribute(char *adesc, struct search *search, int explicit) { - char *adesc, *fdesc; + char *fdesc; struct ber_element *elm; - if (ber_get_string(attr->be_sub, &adesc) != 0) - return 0; - if (search->attrlist->be_sub->be_encoding == BER_TYPE_EOC) { /* An empty list with no attributes requests the return of * all user attributes. */ @@ -86,7 +83,8 @@ should_include_attribute(struct ber_element *attr, struct search *search) return 1; if (strcmp(fdesc, "*") == 0 && !is_operational(adesc)) return 1; - if (strcmp(fdesc, "+") == 0 && is_operational(adesc)) + if (strcmp(fdesc, "+") == 0 && is_operational(adesc) && + !explicit) return 1; } @@ -101,6 +99,7 @@ search_result(const char *dn, size_t dnlen, struct ber_element *attrs, struct conn *conn = search->conn; struct ber_element *root, *elm, *filtered_attrs = NULL, *link, *a; struct ber_element *prev, *next; + char *adesc; void *buf; if ((root = ber_add_sequence(NULL)) == NULL) @@ -111,7 +110,9 @@ search_result(const char *dn, size_t dnlen, struct ber_element *attrs, link = filtered_attrs; for (prev = NULL, a = attrs->be_sub; a; a = next) { - if (should_include_attribute(a, search)) { + if (ber_get_string(a->be_sub, &adesc) != 0) + goto fail; + if (should_include_attribute(adesc, search, 0)) { next = a->be_next; if (prev != NULL) prev->be_next = a->be_next; /* unlink a */ @@ -525,7 +526,11 @@ ldap_search_root_dse(struct search *search) static void ldap_search_subschema(struct search *search) { + char buf[1024]; struct ber_element *root, *elm, *key, *val; + struct object *obj; + struct attr_type *at; + int rc; if ((root = ber_add_sequence(NULL)) == NULL) { return; @@ -552,10 +557,41 @@ ldap_search_subschema(struct search *search) val = ber_add_set(key); ber_add_string(val, "cn=schema"); + if (should_include_attribute("objectClasses", search, 1)) { + elm = ber_add_sequence(elm); + key = ber_add_string(elm, "objectClasses"); + val = ber_add_set(key); + + RB_FOREACH(obj, object_tree, &conf->schema->objects) { + if (schema_dump_object(obj, buf, sizeof(buf)) != 0) { + rc = LDAP_OTHER; + goto done; + } + val = ber_add_string(val, buf); + } + } + + if (should_include_attribute("attributeTypes", search, 1)) { + elm = ber_add_sequence(elm); + key = ber_add_string(elm, "attributeTypes"); + val = ber_add_set(key); + + RB_FOREACH(at, attr_type_tree, &conf->schema->attr_types) { + if (schema_dump_attribute(at, buf, sizeof(buf)) != 0) { + rc = LDAP_OTHER; + goto done; + } + val = ber_add_string(val, buf); + } + } + search_result("cn=schema", 9, root, search); + rc = LDAP_SUCCESS; + +done: ber_free_elements(root); send_ldap_result(search->conn, search->req->msgid, - LDAP_RES_SEARCH_RESULT, LDAP_SUCCESS); + LDAP_RES_SEARCH_RESULT, rc); search_close(search); } @@ -734,8 +770,7 @@ ldap_search(struct request *req) &search->tmlim, &search->typesonly, &search->filter, - &search->attrlist) != 0) - { + &search->attrlist) != 0) { log_warnx("failed to parse search request"); reason = LDAP_PROTOCOL_ERROR; goto done; |