summaryrefslogtreecommitdiff
path: root/usr.sbin/ldapd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ldapd')
-rw-r--r--usr.sbin/ldapd/schema.c239
-rw-r--r--usr.sbin/ldapd/schema.h8
-rw-r--r--usr.sbin/ldapd/search.c57
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;