diff options
| author | 2010-09-03 09:39:17 +0000 | |
|---|---|---|
| committer | 2010-09-03 09:39:17 +0000 | |
| commit | 7c686fcd9cf377b5ee91139b18e7fcc653fa77fd (patch) | |
| tree | bdbb4cb2685bb5c75ab1dc2cf4fb822e852ba80c /usr.sbin/ldapd/syntax.c | |
| parent | Make 'file' an argument in -f description. (diff) | |
| download | wireguard-openbsd-7c686fcd9cf377b5ee91139b18e7fcc653fa77fd.tar.xz wireguard-openbsd-7c686fcd9cf377b5ee91139b18e7fcc653fa77fd.zip | |
Implement attribute syntaxes from RFC4517. This adds validation to the most
common attribute types. Specialized attribute types like Delivery Method or
Teletex Terminal Identifier are recognized for completeness, but not
validated.
Diffstat (limited to 'usr.sbin/ldapd/syntax.c')
| -rw-r--r-- | usr.sbin/ldapd/syntax.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/usr.sbin/ldapd/syntax.c b/usr.sbin/ldapd/syntax.c new file mode 100644 index 00000000000..69a46388015 --- /dev/null +++ b/usr.sbin/ldapd/syntax.c @@ -0,0 +1,351 @@ +/* $OpenBSD: syntax.c,v 1.1 2010/09/03 09:39:17 martinh Exp $ */ + +/* + * Copyright (c) 2010 Martin Hedenfalk <martin@bzero.se> + * + * 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 <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "schema.h" +#include "uuid.h" + +#define SYNTAX_DECL(TYPE) \ + static int syntax_is_##TYPE(struct schema *schema, char *value, size_t len) + +SYNTAX_DECL(bit_string); +SYNTAX_DECL(boolean); +SYNTAX_DECL(country); +SYNTAX_DECL(directory_string); +SYNTAX_DECL(dn); +SYNTAX_DECL(gentime); +SYNTAX_DECL(ia5_string); +SYNTAX_DECL(integer); +SYNTAX_DECL(numeric_string); +SYNTAX_DECL(octet_string); +SYNTAX_DECL(oid); +SYNTAX_DECL(printable_string); +SYNTAX_DECL(utctime); +SYNTAX_DECL(uuid); + +static struct syntax syntaxes[] = { + /* + * Keep these sorted. + */ + { "1.3.6.1.1.1.0.0", "NIS netgroup triple", NULL }, + { "1.3.6.1.1.1.0.1", "Boot parameter", NULL }, + { "1.3.6.1.1.16.1", "UUID", syntax_is_uuid }, + { "1.3.6.1.4.1.1466.115.121.1.11", "Country String", syntax_is_country }, + { "1.3.6.1.4.1.1466.115.121.1.12", "DN", syntax_is_dn }, + { "1.3.6.1.4.1.1466.115.121.1.14", "Delivery Method", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.15", "Directory String", syntax_is_directory_string }, + { "1.3.6.1.4.1.1466.115.121.1.16", "DIT Content Rule Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.17", "DIT Structure Rule Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.21", "Enhanced Guide", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.22", "Facsimile Telephone Number", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.23", "Fax", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.24", "Generalized Time", syntax_is_gentime }, + { "1.3.6.1.4.1.1466.115.121.1.25", "Guide", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.26", "IA5 String", syntax_is_ia5_string }, + { "1.3.6.1.4.1.1466.115.121.1.27", "INTEGER", syntax_is_integer }, + { "1.3.6.1.4.1.1466.115.121.1.28", "JPEG", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.3", "Attribute Type Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.30", "Matching Rule Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.31", "Matching Rule Use Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.34", "Name And Optional UID", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.35", "Name Form Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.36", "Numeric String", syntax_is_numeric_string }, + { "1.3.6.1.4.1.1466.115.121.1.37", "Object Class Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.38", "OID", syntax_is_oid }, + { "1.3.6.1.4.1.1466.115.121.1.39", "Other Mailbox", syntax_is_ia5_string }, + { "1.3.6.1.4.1.1466.115.121.1.40", "Octet String", syntax_is_octet_string }, + { "1.3.6.1.4.1.1466.115.121.1.41", "Postal Address", syntax_is_directory_string }, + { "1.3.6.1.4.1.1466.115.121.1.44", "Printable String", syntax_is_printable_string }, + { "1.3.6.1.4.1.1466.115.121.1.45", "Subtree Specification", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.5", "Binary", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.50", "Telephone Number", syntax_is_printable_string }, + { "1.3.6.1.4.1.1466.115.121.1.51", "Teletex Terminal Identifier", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.52", "Telex Number", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.53", "UTC Time", syntax_is_utctime }, + { "1.3.6.1.4.1.1466.115.121.1.54", "LDAP Syntax Description", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.58", "Substring Assertion", NULL }, + { "1.3.6.1.4.1.1466.115.121.1.6", "Bit String", syntax_is_bit_string }, + { "1.3.6.1.4.1.1466.115.121.1.7", "Boolean", syntax_is_boolean }, + { "1.3.6.1.4.1.1466.115.121.1.8", "Certificate", NULL }, + +}; + +static int +syntax_cmp(const void *k, const void *e) +{ + return (strcmp(k, ((const struct syntax *)e)->oid)); +} + +const struct syntax * +syntax_lookup(const char *oid) +{ + return bsearch(oid, syntaxes, sizeof(syntaxes)/sizeof(syntaxes[0]), + sizeof(syntaxes[0]), syntax_cmp); +} + +/* + * A value of the Octet String syntax is a sequence of zero, one, or + * more arbitrary octets. + */ +static int +syntax_is_octet_string(struct schema *schema, char *value, size_t len) +{ + return 1; +} + +/* + * A string of one or more arbitrary UTF-8 characters. + */ +static int +syntax_is_directory_string(struct schema *schema, char *value, size_t len) +{ + /* FIXME: validate UTF-8 characters. */ + return len >= 1 && *value != '\0'; +} + +/* + * A value of the Printable String syntax is a string of one or more + * latin alphabetic, numeric, and selected punctuation characters as + * specified by the <PrintableCharacter> rule in Section 3.2. + * + * PrintableCharacter = ALPHA / DIGIT / SQUOTE / LPAREN / RPAREN / + * PLUS / COMMA / HYPHEN / DOT / EQUALS / + * SLASH / COLON / QUESTION / SPACE + */ +static int +syntax_is_printable_string(struct schema *schema, char *value, size_t len) +{ + static char *special = "'()+,-.=/:? "; + char *p; + + for (p = value; len > 0 && *p != '\0'; p++, len--) { + if (!isalnum(*p) && strchr(special, *p) == NULL) + return 0; + } + + return (p != value); +} + +/* + * A value of the IA5 String syntax is a string of zero, one, or more + * characters from International Alphabet 5 (IA5). + * IA5String = *(%x00-7F) + */ +static int +syntax_is_ia5_string(struct schema *schema, char *value, size_t len) +{ + char *p; + + for (p = value; *p != '\0'; p++) { + if ((unsigned char)*p > 0x7F) + return 0; + } + + return 1; +} + +/* + * A value of the Integer syntax is a whole number of unlimited magnitude. + * Integer = ( HYPHEN LDIGIT *DIGIT ) / number + * number = DIGIT / ( LDIGIT 1*DIGIT ) + */ +static int +syntax_is_integer(struct schema *schema, char *value, size_t len) +{ + if (*value == '-') + value++; + if (*value == '0') + return value[1] == '\0'; + for (value++; *value != '\0'; value++) + if (!isdigit(*value)) + return 0; + return 1; +} + +static int +syntax_is_dn(struct schema *schema, char *value, size_t len) +{ + if (!syntax_is_directory_string(schema, value, len)) + return 0; + + /* FIXME: DN syntax not implemented */ + + return 1; +} + +static int +syntax_is_oid(struct schema *schema, char *value, size_t len) +{ + char *symoid = NULL; + + if (len == 0 || *value == '\0') + return 0; + if (is_oidstr(value)) + return 1; + + /* + * Check for a symbolic OID: object class, attribute type or symoid. + */ + if (lookup_object_by_name(schema, value) != NULL || + lookup_attribute_by_name(schema, value) != NULL || + (symoid = lookup_symbolic_oid(schema, value)) != NULL) { + free(symoid); + return 1; + } + + return 0; +} + +static int +syntax_is_uuid(struct schema *schema, char *value, size_t len) +{ + int i; + + if (len != 36) + return 0; + +#define IS_XDIGITS(n, c) \ + do { \ + for (i = 0; i < (n); i++) \ + if (!isxdigit(*value++)) \ + return 0; \ + if (*value++ != (c)) \ + return 0; \ + } while(0) + + IS_XDIGITS(8, '-'); + IS_XDIGITS(4, '-'); + IS_XDIGITS(4, '-'); + IS_XDIGITS(4, '-'); + IS_XDIGITS(12, '\0'); + + return 1; +} + +/* + * NumericString = 1*(DIGIT / SPACE) + */ +static int +syntax_is_numeric_string(struct schema *schema, char *value, size_t len) +{ + char *p; + + for (p = value; *p != '\0'; p++) + if (!isdigit(*p) || *p != ' ') + return 0; + + return p != value; +} + +static int +syntax_is_time(struct schema *schema, char *value, size_t len, int gen) +{ + int n; + char *p = value; + +#define CHECK_RANGE(min, max) \ + if (!isdigit(p[0]) || !isdigit(p[1])) \ + return 0; \ + n = (p[0] - '0') * 10 + (p[1] - '0'); \ + if (n < min || n > max) \ + return 0; \ + p += 2; + + if (gen) + CHECK_RANGE(0, 99) /* century */ + CHECK_RANGE(0, 99) /* year */ + CHECK_RANGE(1, 12) /* month */ + CHECK_RANGE(1, 31) /* day */ + /* FIXME: should check number of days in month */ + CHECK_RANGE(0, 23); /* hour */ + + if (!gen || isdigit(*p)) { + CHECK_RANGE(0, 59); /* minute */ + if (!gen && isdigit(*p)) + CHECK_RANGE(0, 59+gen); /* second or leap-second */ + if (*p == '\0') + return 1; + } + /* fraction */ + if (!gen && ((*p == ',' || *p == '.') && !isdigit(*++p))) + return 0; + + if (*p == '-' || *p == '+') { + ++p; + CHECK_RANGE(0, 23); /* hour */ + if (!gen || isdigit(*p)) + CHECK_RANGE(0, 59); /* minute */ + } else if (*p++ != 'Z') + return 0; + + return *p == '\0'; +} + +static int +syntax_is_gentime(struct schema *schema, char *value, size_t len) +{ + return syntax_is_time(schema, value, len, 1); +} + +static int +syntax_is_utctime(struct schema *schema, char *value, size_t len) +{ + return syntax_is_time(schema, value, len, 0); +} + +static int +syntax_is_country(struct schema *schema, char *value, size_t len) +{ + if (len != 2) + return 0; + return syntax_is_printable_string(schema, value, len); +} + +static int +syntax_is_bit_string(struct schema *schema, char *value, size_t len) +{ + if (*value++ != '\'') + return 0; + + for (; *value != '\0'; value++) { + if (*value == '\'') + break; + if (*value != '0' && *value != '1') + return 0; + } + + if (++*value != 'B') + return 0; + + return *value == '\0'; +} + +static int +syntax_is_boolean(struct schema *schema, char *value, size_t len) +{ + return strcmp(value, "TRUE") == 0 || strcmp(value, "FALSE") == 0; +} + |
