summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/common/attrib_handlers.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb/common/attrib_handlers.c')
-rw-r--r--source4/lib/ldb/common/attrib_handlers.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c
new file mode 100644
index 0000000000..fcff4113b4
--- /dev/null
+++ b/source4/lib/ldb/common/attrib_handlers.c
@@ -0,0 +1,335 @@
+/*
+ ldb database library
+
+ Copyright (C) Andrew Tridgell 2005
+
+ ** NOTE! The following LGPL license applies to the ldb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ attribute handlers for well known attribute types, selected by syntax OID
+ see rfc2252
+*/
+
+#include "includes.h"
+#include "ldb/include/ldb.h"
+#include "ldb/include/ldb_private.h"
+#include <ctype.h>
+
+/*
+ default handler that just copies a ldb_val.
+*/
+int ldb_handler_copy(struct ldb_context *ldb,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ *out = ldb_val_dup(ldb, in);
+ if (out->data == NULL) {
+ ldb_oom(ldb);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ a case folding copy handler, removing leading and trailing spaces and
+ multiple internal spaces
+*/
+static int ldb_handler_fold(struct ldb_context *ldb,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ uint8_t *s1, *s2;
+ out->data = talloc_size(ldb, strlen(in->data)+1);
+ if (out->data == NULL) {
+ ldb_oom(ldb);
+ return -1;
+ }
+ s1 = in->data;
+ s2 = out->data;
+ while (*s1 == ' ') s1++;
+ while (*s1) {
+ *s2 = toupper(*s1);
+ if (s1[0] == ' ') {
+ while (s1[0] == s1[1]) s1++;
+ }
+ s2++; s1++;
+ }
+ *s2 = 0;
+ out->length = strlen(out->data);
+ return 0;
+}
+
+
+/*
+ a case folding copy handler, removing leading and trailing spaces and
+ multiple internal spaces, and checking for wildcard characters
+*/
+static int ldb_handler_fold_wildcard(struct ldb_context *ldb,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ if (strchr(in->data, '*')) {
+ return -1;
+ }
+ return ldb_handler_fold(ldb, in, out);
+}
+
+/*
+ canonicalise a ldap Integer
+ rfc2252 specifies it should be in decimal form
+*/
+static int ldb_canonicalise_Integer(struct ldb_context *ldb,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ char *end;
+ long long i = strtoll(in->data, &end, 0);
+ if (*end != 0) {
+ return -1;
+ }
+ out->data = talloc_asprintf(ldb, "%lld", i);
+ if (out->data == NULL) {
+ return -1;
+ }
+ out->length = strlen(out->data);
+ return 0;
+}
+
+/*
+ compare two Integers
+*/
+static int ldb_comparison_Integer(struct ldb_context *ldb,
+ const struct ldb_val *v1, const struct ldb_val *v2)
+{
+ return strtoll(v1->data, NULL, 0) - strtoll(v2->data, NULL, 0);
+}
+
+/*
+ compare two binary blobs
+*/
+int ldb_comparison_binary(struct ldb_context *ldb,
+ const struct ldb_val *v1, const struct ldb_val *v2)
+{
+ if (v1->length != v2->length) {
+ return v1->length - v2->length;
+ }
+ return memcmp(v1->data, v2->data, v1->length);
+}
+
+/*
+ compare two case insensitive strings, ignoring multiple whitespace
+ and leading and trailing whitespace
+ see rfc2252 section 8.1
+*/
+static int ldb_comparison_fold(struct ldb_context *ldb,
+ const struct ldb_val *v1, const struct ldb_val *v2)
+{
+ const char *s1=v1->data, *s2=v2->data;
+ while (*s1 == ' ') s1++;
+ while (*s2 == ' ') s2++;
+ /* TODO: make utf8 safe, possibly with helper function from application */
+ while (*s1 && *s2) {
+ if (toupper(*s1) != toupper(*s2)) break;
+ if (*s1 == ' ') {
+ while (s1[0] == s1[1]) s1++;
+ while (s2[0] == s2[1]) s2++;
+ }
+ s1++; s2++;
+ }
+ while (*s1 == ' ') s1++;
+ while (*s2 == ' ') s2++;
+ return (int)(*s1) - (int)(*s2);
+}
+
+/*
+ compare two case insensitive strings, ignoring multiple whitespace
+ and leading and trailing whitespace
+ see rfc2252 section 8.1
+ handles wildcards
+*/
+static int ldb_comparison_fold_wildcard(struct ldb_context *ldb,
+ const struct ldb_val *v1,
+ const struct ldb_val *v2)
+{
+ const char *s1=v1->data, *s2=v2->data;
+ while (*s1 == ' ') s1++;
+ while (*s2 == ' ') s2++;
+ /* TODO: make utf8 safe, possibly with helper function from application */
+ while (*s1 && *s2) {
+ if (s1[0] == '*' && s1[1] == 0) {
+ return 0;
+ }
+ if (toupper(*s1) != toupper(*s2)) break;
+ if (*s1 == ' ') {
+ while (s1[0] == s1[1]) s1++;
+ while (s2[0] == s2[1]) s2++;
+ }
+ s1++; s2++;
+ }
+ while (*s1 == ' ') s1++;
+ while (*s2 == ' ') s2++;
+ return (int)(*s1) - (int)(*s2);
+}
+
+
+/*
+ canonicalise a attribute in DN format
+*/
+static int ldb_canonicalise_dn(struct ldb_context *ldb,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ struct ldb_dn *dn2=NULL, *dn1 = ldb_dn_explode(ldb, in->data);
+ out->data = NULL;
+ if (dn1 == NULL) {
+ goto failed;
+ }
+ dn2 = ldb_dn_casefold(ldb, dn1);
+ if (dn2 == NULL) goto failed;
+
+ out->data = ldb_dn_linearize(ldb, dn2);
+ if (out->data == NULL) goto failed;
+
+ talloc_free(dn1);
+ talloc_free(dn2);
+ return 0;
+
+failed:
+ talloc_free(dn1);
+ talloc_free(dn2);
+ return -1;
+}
+
+/*
+ compare two dns
+*/
+static int ldb_comparison_dn(struct ldb_context *ldb,
+ const struct ldb_val *v1, const struct ldb_val *v2)
+{
+ struct ldb_val cv1, cv2;
+ int ret;
+ if (ldb_canonicalise_dn(ldb, v1, &cv1) != 0 ||
+ ldb_canonicalise_dn(ldb, v2, &cv2) != 0) {
+ goto failed;
+ }
+ ret = strcmp(cv1.data, cv2.data);
+ talloc_free(cv1.data);
+ talloc_free(cv2.data);
+ return ret;
+failed:
+ talloc_free(cv1.data);
+ talloc_free(cv2.data);
+ return -1;
+}
+
+/*
+ compare two objectclasses, looking at subclasses
+*/
+static int ldb_comparison_objectclass(struct ldb_context *ldb,
+ const struct ldb_val *v1, const struct ldb_val *v2)
+{
+ int ret, i;
+ const char **subclasses;
+ ret = ldb_comparison_fold(ldb, v1, v2);
+ if (ret == 0) {
+ return 0;
+ }
+ fprintf(stderr, "looing for %s %s\n", v1->data, v2->data);
+ subclasses = ldb_subclass_list(ldb, v1->data);
+ if (subclasses == NULL) {
+ return ret;
+ }
+ for (i=0;subclasses[i];i++) {
+ struct ldb_val vs;
+ vs.data = discard_const(subclasses[i]);
+ vs.length = strlen(subclasses[i]);
+ if (ldb_comparison_objectclass(ldb, &vs, v2) == 0) {
+ return 0;
+ }
+ }
+ return ret;
+}
+
+/*
+ table of standard attribute handlers
+*/
+static const struct ldb_attrib_handler ldb_standard_attribs[] = {
+ {
+ .attr = LDB_SYNTAX_INTEGER,
+ .flags = 0,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldb_handler_copy,
+ .canonicalise_fn = ldb_canonicalise_Integer,
+ .comparison_fn = ldb_comparison_Integer
+ },
+ {
+ .attr = LDB_SYNTAX_OCTET_STRING,
+ .flags = 0,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldb_handler_copy,
+ .canonicalise_fn = ldb_handler_copy,
+ .comparison_fn = ldb_comparison_binary
+ },
+ {
+ .attr = LDB_SYNTAX_DIRECTORY_STRING,
+ .flags = 0,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldb_handler_copy,
+ .canonicalise_fn = ldb_handler_fold,
+ .comparison_fn = ldb_comparison_fold
+ },
+ {
+ .attr = LDB_SYNTAX_WILDCARD,
+ .flags = LDB_ATTR_FLAG_WILDCARD,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldb_handler_copy,
+ .canonicalise_fn = ldb_handler_fold_wildcard,
+ .comparison_fn = ldb_comparison_fold_wildcard
+ },
+ {
+ .attr = LDB_SYNTAX_DN,
+ .flags = 0,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldb_handler_copy,
+ .canonicalise_fn = ldb_canonicalise_dn,
+ .comparison_fn = ldb_comparison_dn
+ },
+ {
+ .attr = LDB_SYNTAX_OBJECTCLASS,
+ .flags = 0,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldb_handler_copy,
+ .canonicalise_fn = ldb_handler_fold,
+ .comparison_fn = ldb_comparison_objectclass
+ }
+};
+
+
+/*
+ return the attribute handlers for a given syntax name
+*/
+const struct ldb_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb,
+ const char *syntax)
+{
+ int i;
+ unsigned num_handlers = sizeof(ldb_standard_attribs)/sizeof(ldb_standard_attribs[0]);
+ /* TODO: should be replaced with a binary search */
+ for (i=0;i<num_handlers;i++) {
+ if (strcmp(ldb_standard_attribs[i].attr, syntax) == 0) {
+ return &ldb_standard_attribs[i];
+ }
+ }
+ return NULL;
+}
+