summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Hedenfal <martinh@cvs.openbsd.org>2010-11-03 14:17:02 +0000
committerMartin Hedenfal <martinh@cvs.openbsd.org>2010-11-03 14:17:02 +0000
commit0e45dd2311703ce1d77c9129358ac7bd6724fd31 (patch)
tree52c46d74a50fe1c5297e22a0776e157a4bd14c57
parent04bce8357ba512d76a70e072606f6fae4370e22e (diff)
Validate matching rules against attribute syntaxes. All matching rules from
RFC 4517 are recognized, except the optional wordMatch and keywordMatch. Requires a current core.schema file.
-rw-r--r--usr.sbin/ldapctl/Makefile4
-rw-r--r--usr.sbin/ldapd/Makefile4
-rw-r--r--usr.sbin/ldapd/matching.c144
-rw-r--r--usr.sbin/ldapd/schema.c66
-rw-r--r--usr.sbin/ldapd/schema.h27
5 files changed, 230 insertions, 15 deletions
diff --git a/usr.sbin/ldapctl/Makefile b/usr.sbin/ldapctl/Makefile
index fcb5c7e9dc5..5807416f72b 100644
--- a/usr.sbin/ldapctl/Makefile
+++ b/usr.sbin/ldapctl/Makefile
@@ -1,11 +1,11 @@
-# $OpenBSD: Makefile,v 1.4 2010/09/03 14:34:02 martinh Exp $
+# $OpenBSD: Makefile,v 1.5 2010/11/03 14:17:01 martinh Exp $
.PATH: ${.CURDIR}/../ldapd
PROG= ldapctl
MAN= ldapctl.8
SRCS= ldapctl.c parse.y btree.c log.c ber.c util.c \
- index.c attributes.c schema.c syntax.c
+ index.c attributes.c schema.c syntax.c matching.c
LDADD= -levent -lcrypto -lz -lutil
DPADD= ${LIBEVENT} ${LIBCRYPTO} ${LIBZ} ${LIBUTIL}
diff --git a/usr.sbin/ldapd/Makefile b/usr.sbin/ldapd/Makefile
index f3ee37b6df2..f89a57e244e 100644
--- a/usr.sbin/ldapd/Makefile
+++ b/usr.sbin/ldapd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.8 2010/09/03 09:39:17 martinh Exp $
+# $OpenBSD: Makefile,v 1.9 2010/11/03 14:17:01 martinh Exp $
PROG= ldapd
MAN= ldapd.8 ldapd.conf.5
@@ -6,7 +6,7 @@ SRCS= ber.c log.c control.c \
util.c ldapd.c ldape.c conn.c attributes.c namespace.c \
btree.c filter.c search.c parse.y \
auth.c modify.c index.c ssl.c ssl_privsep.c \
- validate.c uuid.c schema.c imsgev.c syntax.c
+ validate.c uuid.c schema.c imsgev.c syntax.c matching.c
LDADD= -levent -lssl -lcrypto -lz -lutil
DPADD= ${LIBEVENT} ${LIBCRYPTO} ${LIBSSL} ${LIBZ} ${LIBUTIL}
diff --git a/usr.sbin/ldapd/matching.c b/usr.sbin/ldapd/matching.c
new file mode 100644
index 00000000000..eb8f4fbf4e9
--- /dev/null
+++ b/usr.sbin/ldapd/matching.c
@@ -0,0 +1,144 @@
+/* $OpenBSD: matching.c,v 1.1 2010/11/03 14:17:01 martinh Exp $ */
+
+/*
+ * Copyright (c) 2010 Martin Hedenfalk <martinh@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "schema.h"
+
+#ifndef nitems
+# define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+static const char *ia5string_syntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.26",
+ NULL
+};
+
+static const char *dir_string_syntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.15",
+ "1.3.6.1.4.1.1466.115.121.1.44",
+ "1.3.6.1.4.1.1466.115.121.1.11",
+ "1.3.6.1.4.1.1466.115.121.1.50",
+ "1.3.6.1.4.1.1466.115.121.1.26",
+ NULL
+};
+
+static const char *num_string_syntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.36",
+ NULL
+};
+
+static const char *telephone_syntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.50",
+ NULL
+};
+
+static const char *dir_string_sequence_syntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.41",
+ NULL
+};
+
+static const char *int_first_component_syntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.17",
+ NULL
+};
+
+static const char *oid_first_component_syntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.3",
+ "1.3.6.1.4.1.1466.115.121.1.16",
+ "1.3.6.1.4.1.1466.115.121.1.54",
+ "1.3.6.1.4.1.1466.115.121.1.30",
+ "1.3.6.1.4.1.1466.115.121.1.31",
+ "1.3.6.1.4.1.1466.115.121.1.35",
+ "1.3.6.1.4.1.1466.115.121.1.37",
+ NULL
+};
+
+static struct match_rule match_rules[] = {
+
+ { "1.3.6.1.1.16.2", "uuidMatch", MATCH_EQUALITY, NULL, "1.3.6.1.1.16.1", NULL },
+ { "1.3.6.1.1.16.3", "uuidOrderingMatch", MATCH_ORDERING, NULL, "1.3.6.1.1.16.1", NULL },
+ { "1.3.6.1.4.1.1466.109.114.1", "caseExactIA5Match", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.26", ia5string_syntaxes },
+ { "1.3.6.1.4.1.1466.109.114.2", "caseIgnoreIA5Match", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.26", ia5string_syntaxes },
+ { "1.3.6.1.4.1.1466.109.114.3", "caseIgnoreIA5SubstringsMatch", MATCH_SUBSTR, NULL, "1.3.6.1.4.1.1466.115.121.1.58", ia5string_syntaxes },
+ { "2.5.13.0", "objectIdentifierMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.38", NULL },
+ { "2.5.13.1", "distinguishedNameMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.12", NULL },
+ { "2.5.13.10", "numericStringSubstringsMatch", MATCH_SUBSTR, NULL, "1.3.6.1.4.1.1466.115.121.1.58", num_string_syntaxes },
+ { "2.5.13.11", "caseIgnoreListMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.41", NULL },
+ { "2.5.13.12", "caseIgnoreListSubstringsMatch", MATCH_SUBSTR, NULL, "1.3.6.1.4.1.1466.115.121.1.58", dir_string_sequence_syntaxes },
+ { "2.5.13.13", "booleanMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.7", NULL },
+ { "2.5.13.14", "integerMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.27", NULL },
+ { "2.5.13.15", "integerOrderingMatch", MATCH_ORDERING, NULL, "1.3.6.1.4.1.1466.115.121.1.27", NULL },
+ { "2.5.13.16", "bitStringMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.6", NULL },
+ { "2.5.13.17", "octetStringMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.40", NULL },
+ { "2.5.13.18", "octetStringOrderingMatch", MATCH_ORDERING, NULL, "1.3.6.1.4.1.1466.115.121.1.40", NULL },
+ { "2.5.13.2", "caseIgnoreMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.15", dir_string_syntaxes },
+ { "2.5.13.20", "telephoneNumberMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.50", NULL },
+ { "2.5.13.21", "telephoneNumberSubstringsMatch", MATCH_SUBSTR, NULL, "1.3.6.1.4.1.1466.115.121.1.58", telephone_syntaxes },
+ { "2.5.13.23", "uniqueMemberMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.34", NULL },
+ { "2.5.13.27", "generalizedTimeMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.24", NULL },
+ { "2.5.13.28", "generalizedTimeOrderingMatch", MATCH_ORDERING, NULL, "1.3.6.1.4.1.1466.115.121.1.24", NULL },
+ { "2.5.13.29", "integerFirstComponentMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.27", int_first_component_syntaxes },
+ { "2.5.13.3", "caseIgnoreOrderingMatch", MATCH_ORDERING, NULL, "1.3.6.1.4.1.1466.115.121.1.15", dir_string_syntaxes },
+ { "2.5.13.30", "objectIdentifierFirstComponentMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.38", oid_first_component_syntaxes },
+ { "2.5.13.31", "directoryStringFirstComponentMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.15", NULL },
+ { "2.5.13.4", "caseIgnoreSubstringsMatch", MATCH_SUBSTR, NULL, "1.3.6.1.4.1.1466.115.121.1.58", dir_string_syntaxes },
+ { "2.5.13.5", "caseExactMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.15", NULL },
+ { "2.5.13.6", "caseExactOrderingMatch", MATCH_ORDERING, NULL, "1.3.6.1.4.1.1466.115.121.1.15", NULL },
+ { "2.5.13.7", "caseExactSubstringsMatch", MATCH_SUBSTR, NULL, "1.3.6.1.4.1.1466.115.121.1.58", dir_string_syntaxes },
+ { "2.5.13.8", "numericStringMatch", MATCH_EQUALITY, NULL, "1.3.6.1.4.1.1466.115.121.1.36", NULL },
+ { "2.5.13.9", "numericStringOrderingMatch", MATCH_ORDERING, NULL, "1.3.6.1.4.1.1466.115.121.1.36", NULL },
+
+#if 0
+ { "2.5.13.32", "wordMatch", "1.3.6.1.4.1.1466.115.121.1.15", MATCH_EQUALITY, NULL },
+ { "2.5.13.33", "keywordMatch", "1.3.6.1.4.1.1466.115.121.1.15", MATCH_EQUALITY, NULL },
+#endif
+};
+
+static struct match_rule_alias {
+ char *name;
+ char *oid;
+} aliases[] = {
+ { "caseExactIA5SubstringsMatch", "caseExactSubstringsMatch" },
+};
+
+const struct match_rule *
+match_rule_lookup(const char *oid_or_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < nitems(match_rules); i++) {
+ if (strcasecmp(oid_or_name, match_rules[i].name) == 0 ||
+ strcmp(oid_or_name, match_rules[i].oid) == 0)
+ return &match_rules[i];
+ }
+
+ for (i = 0; i < nitems(aliases); i++) {
+ if (strcasecmp(oid_or_name, aliases[i].name) == 0)
+ return match_rule_lookup(aliases[i].oid);
+ }
+
+ return NULL;
+}
+
diff --git a/usr.sbin/ldapd/schema.c b/usr.sbin/ldapd/schema.c
index 0fdedf5519f..57548b59478 100644
--- a/usr.sbin/ldapd/schema.c
+++ b/usr.sbin/ldapd/schema.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: schema.c,v 1.12 2010/09/21 10:41:32 martinh Exp $ */
+/* $OpenBSD: schema.c,v 1.13 2010/11/03 14:17:01 martinh Exp $ */
/*
* Copyright (c) 2010 Martin Hedenfalk <martinh@openbsd.org>
@@ -665,6 +665,35 @@ fail:
}
static int
+schema_validate_match_rule(struct schema *schema, struct attr_type *at,
+ const struct match_rule *mrule, enum match_rule_type type)
+{
+ int i;
+
+ if (mrule == NULL)
+ return 0;
+
+ if ((mrule->type & type) != type) {
+ schema_err(schema, "%s: bad matching rule '%s'",
+ ATTR_NAME(at), mrule->name);
+ return -1;
+ }
+
+ /* Is this matching rule compatible with the attribute syntax? */
+ if (strcmp(mrule->syntax_oid, at->syntax->oid) == 0)
+ return 0;
+
+ /* Check any alternative syntaxes for compatibility. */
+ for (i = 0; mrule->alt_syntax_oids && mrule->alt_syntax_oids[i]; i++)
+ if (strcmp(mrule->alt_syntax_oids[i], at->syntax->oid) == 0)
+ return 0;
+
+ schema_err(schema, "%s: inappropriate matching rule '%s' for syntax [%s]",
+ ATTR_NAME(at), mrule->name, at->syntax->oid);
+ return -1;
+}
+
+static int
schema_parse_attributetype(struct schema *schema)
{
struct attr_type *attr = NULL, *prev, *sup;
@@ -725,14 +754,32 @@ schema_parse_attributetype(struct schema *schema)
}
free(arg);
} else if (strcasecmp(kw, "EQUALITY") == 0) {
- if (schema_lex(schema, &attr->equality) != STRING)
+ if (schema_lex(schema, &arg) != STRING)
goto fail;
+ if ((attr->equality = match_rule_lookup(arg)) == NULL) {
+ schema_err(schema, "%s: unknown matching rule",
+ arg);
+ goto fail;
+ }
+ free(arg);
} else if (strcasecmp(kw, "ORDERING") == 0) {
- if (schema_lex(schema, &attr->ordering) != STRING)
+ if (schema_lex(schema, &arg) != STRING)
goto fail;
+ if ((attr->ordering = match_rule_lookup(arg)) == NULL) {
+ schema_err(schema, "%s: unknown matching rule",
+ arg);
+ goto fail;
+ }
+ free(arg);
} else if (strcasecmp(kw, "SUBSTR") == 0) {
- if (schema_lex(schema, &attr->substr) != STRING)
+ if (schema_lex(schema, &arg) != STRING)
+ goto fail;
+ if ((attr->substr = match_rule_lookup(arg)) == NULL) {
+ schema_err(schema, "%s: unknown matching rule",
+ arg);
goto fail;
+ }
+ free(arg);
} else if (strcasecmp(kw, "SYNTAX") == 0) {
if (schema_lex(schema, &arg) != STRING ||
!is_oidstr(arg))
@@ -820,6 +867,11 @@ schema_parse_attributetype(struct schema *schema)
sup = sup->sup;
}
+ if (schema_validate_match_rule(schema, attr, attr->equality, MATCH_EQUALITY) != 0 ||
+ schema_validate_match_rule(schema, attr, attr->ordering, MATCH_ORDERING) != 0 ||
+ schema_validate_match_rule(schema, attr, attr->substr, MATCH_SUBSTR) != 0)
+ goto fail;
+
return 0;
fail:
@@ -1230,17 +1282,17 @@ schema_dump_attribute(struct attr_type *at, char *buf, size_t size)
if (at->equality != NULL)
if (strlcat(buf, " EQUALITY ", size) >= size ||
- strlcat(buf, at->equality, size) >= size)
+ strlcat(buf, at->equality->name, size) >= size)
return -1;
if (at->ordering != NULL)
if (strlcat(buf, " ORDERING ", size) >= size ||
- strlcat(buf, at->ordering, size) >= size)
+ strlcat(buf, at->ordering->name, size) >= size)
return -1;
if (at->substr != NULL)
if (strlcat(buf, " SUBSTR ", size) >= size ||
- strlcat(buf, at->substr, size) >= size)
+ strlcat(buf, at->substr->name, size) >= size)
return -1;
if (at->syntax != NULL)
diff --git a/usr.sbin/ldapd/schema.h b/usr.sbin/ldapd/schema.h
index e5c305d0dcd..750c5eb3abf 100644
--- a/usr.sbin/ldapd/schema.h
+++ b/usr.sbin/ldapd/schema.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: schema.h,v 1.5 2010/09/03 09:39:17 martinh Exp $ */
+/* $OpenBSD: schema.h,v 1.6 2010/11/03 14:17:01 martinh Exp $ */
/*
* Copyright (c) 2010 Martin Hedenfalk <martinh@openbsd.org>
@@ -30,6 +30,12 @@ enum usage {
USAGE_DSA_OP /* operational attribute */
};
+enum match_rule_type {
+ MATCH_EQUALITY,
+ MATCH_ORDERING,
+ MATCH_SUBSTR,
+};
+
struct name {
SLIST_ENTRY(name) next;
char *name;
@@ -44,6 +50,16 @@ struct syntax {
size_t len);
};
+struct match_rule
+{
+ char *oid;
+ char *name;
+ enum match_rule_type type;
+ int (*prepare)(char *value, size_t len);
+ const char *syntax_oid;
+ const char **alt_syntax_oids;
+};
+
struct attr_type {
RB_ENTRY(attr_type) link;
char *oid;
@@ -51,9 +67,9 @@ struct attr_type {
char *desc;
int obsolete;
struct attr_type *sup;
- char *equality;
- char *ordering;
- char *substr;
+ const struct match_rule *equality;
+ const struct match_rule *ordering;
+ const struct match_rule *substr;
const struct syntax *syntax;
int single;
int collective;
@@ -155,5 +171,8 @@ int is_oidstr(const char *oidstr);
/* syntax.c */
const struct syntax *syntax_lookup(const char *oid);
+/* matching.c */
+const struct match_rule *match_rule_lookup(const char *oid);
+
#endif