From 8420a36dc7fe72fb665e065b8673fa44ff1bbf21 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 5 Jul 2011 10:01:32 +1000 Subject: ldb: make ldb a top level library for Samba 4.0 Signed-off-by: Andrew Tridgell --- source4/lib/ldb/common/attrib_handlers.c | 496 ------------------------------- 1 file changed, 496 deletions(-) delete mode 100644 source4/lib/ldb/common/attrib_handlers.c (limited to 'source4/lib/ldb/common/attrib_handlers.c') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c deleted file mode 100644 index 2f4454c7b4..0000000000 --- a/source4/lib/ldb/common/attrib_handlers.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - ldb database library - - Copyright (C) Andrew Tridgell 2005 - Copyright (C) Andrew Bartlett 2006-2009 - - ** 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 3 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, see . -*/ -/* - attribute handlers for well known attribute types, selected by syntax OID - see rfc2252 -*/ - -#include "ldb_private.h" -#include "system/locale.h" -#include "ldb_handlers.h" - -/* - default handler that just copies a ldb_val. -*/ -int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out) -{ - *out = ldb_val_dup(mem_ctx, in); - if (in->length > 0 && out->data == NULL) { - ldb_oom(ldb); - return -1; - } - return 0; -} - -/* - a case folding copy handler, removing leading and trailing spaces and - multiple internal spaces - - We exploit the fact that utf8 never uses the space octet except for - the space itself -*/ -int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out) -{ - char *s, *t; - size_t l; - - if (!in || !out || !(in->data)) { - return -1; - } - - out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length); - if (out->data == NULL) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%.*s]", (int)in->length, (const char *)in->data); - return -1; - } - - s = (char *)(out->data); - - /* remove trailing spaces if any */ - l = strlen(s); - while (l > 0 && s[l - 1] == ' ') l--; - s[l] = '\0'; - - /* remove leading spaces if any */ - if (*s == ' ') { - for (t = s; *s == ' '; s++) ; - - /* remove leading spaces by moving down the string */ - memmove(t, s, l); - - s = t; - } - - /* check middle spaces */ - while ((t = strchr(s, ' ')) != NULL) { - for (s = t; *s == ' '; s++) ; - - if ((s - t) > 1) { - l = strlen(s); - - /* remove all spaces but one by moving down the string */ - memmove(t + 1, s, l); - } - } - - out->length = strlen((char *)out->data); - return 0; -} - -/* length limited conversion of a ldb_val to a int32_t */ -static int val_to_int64(const struct ldb_val *in, int64_t *v) -{ - char *end; - char buf[64]; - - /* make sure we don't read past the end of the data */ - if (in->length > sizeof(buf)-1) { - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - } - strncpy(buf, (char *)in->data, in->length); - buf[in->length] = 0; - - /* We've to use "strtoll" here to have the intended overflows. - * Otherwise we may get "LONG_MAX" and the conversion is wrong. */ - *v = (int64_t) strtoll(buf, &end, 0); - if (*end != 0) { - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - } - return LDB_SUCCESS; -} - - -/* - canonicalise a ldap Integer - rfc2252 specifies it should be in decimal form -*/ -static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out) -{ - int64_t i; - int ret; - - ret = val_to_int64(in, &i); - if (ret != LDB_SUCCESS) { - return ret; - } - out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i); - if (out->data == NULL) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - out->length = strlen((char *)out->data); - return 0; -} - -/* - compare two Integers -*/ -static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - int64_t i1=0, i2=0; - val_to_int64(v1, &i1); - val_to_int64(v2, &i2); - if (i1 == i2) return 0; - return i1 > i2? 1 : -1; -} - -/* - canonicalise a ldap Boolean - rfc2252 specifies it should be either "TRUE" or "FALSE" -*/ -static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out) -{ - if (strncasecmp((char *)in->data, "TRUE", in->length) == 0) { - out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE"); - out->length = 4; - } else if (strncasecmp((char *)in->data, "FALSE", in->length) == 0) { - out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE"); - out->length = 4; - } else { - return -1; - } - return 0; -} - -/* - compare two Booleans -*/ -static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - if (v1->length != v2->length) { - return v1->length - v2->length; - } - return strncasecmp((char *)v1->data, (char *)v2->data, v1->length); -} - - -/* - compare two binary blobs -*/ -int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx, - 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 whitespaces - and leading and trailing whitespaces - see rfc2252 section 8.1 - - try to optimize for the ascii case, - but if we find out an utf8 codepoint revert to slower but correct function -*/ -int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - const char *s1=(const char *)v1->data, *s2=(const char *)v2->data; - size_t n1 = v1->length, n2 = v2->length; - char *b1, *b2; - const char *u1, *u2; - int ret; - while (n1 && *s1 == ' ') { s1++; n1--; }; - while (n2 && *s2 == ' ') { s2++; n2--; }; - - while (n1 && n2 && *s1 && *s2) { - /* the first 127 (0x7F) chars are ascii and utf8 guarantes they - * never appear in multibyte sequences */ - if (((unsigned char)s1[0]) & 0x80) goto utf8str; - if (((unsigned char)s2[0]) & 0x80) goto utf8str; - if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2)) - break; - if (*s1 == ' ') { - while (n1 && s1[0] == s1[1]) { s1++; n1--; } - while (n2 && s2[0] == s2[1]) { s2++; n2--; } - } - s1++; s2++; - n1--; n2--; - } - - /* check for trailing spaces only if the other pointers has - * reached the end of the strings otherwise we can - * mistakenly match. ex. "domain users" <-> - * "domainUpdates" - */ - if (n1 && *s1 == ' ' && (!n2 || !*s2)) { - while (n1 && *s1 == ' ') { s1++; n1--; } - } - if (n2 && *s2 == ' ' && (!n1 || !*s1)) { - while (n2 && *s2 == ' ') { s2++; n2--; } - } - if (n1 == 0 && n2 != 0) { - return -(int)toupper(*s2); - } - if (n2 == 0 && n1 != 0) { - return (int)toupper(*s1); - } - if (n2 == 0 && n2 == 0) { - return 0; - } - return (int)toupper(*s1) - (int)toupper(*s2); - -utf8str: - /* no need to recheck from the start, just from the first utf8 char found */ - b1 = ldb_casefold(ldb, mem_ctx, s1, n1); - b2 = ldb_casefold(ldb, mem_ctx, s2, n2); - - if (!b1 || !b2) { - /* One of the strings was not UTF8, so we have no - * options but to do a binary compare */ - talloc_free(b1); - talloc_free(b2); - ret = memcmp(s1, s2, MIN(n1, n2)); - if (ret == 0) { - if (n1 == n2) return 0; - if (n1 > n2) { - return (int)toupper(s1[n2]); - } else { - return -(int)toupper(s2[n1]); - } - } - return ret; - } - - u1 = b1; - u2 = b2; - - while (*u1 & *u2) { - if (*u1 != *u2) - break; - if (*u1 == ' ') { - while (u1[0] == u1[1]) u1++; - while (u2[0] == u2[1]) u2++; - } - u1++; u2++; - } - if (! (*u1 && *u2)) { - while (*u1 == ' ') u1++; - while (*u2 == ' ') u2++; - } - ret = (int)(*u1 - *u2); - - talloc_free(b1); - talloc_free(b2); - - return ret; -} - - -/* - canonicalise a attribute in DN format -*/ -static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out) -{ - struct ldb_dn *dn; - int ret = -1; - - out->length = 0; - out->data = NULL; - - dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in); - if ( ! ldb_dn_validate(dn)) { - return LDB_ERR_INVALID_DN_SYNTAX; - } - - out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn); - if (out->data == NULL) { - goto done; - } - out->length = strlen((char *)out->data); - - ret = 0; - -done: - talloc_free(dn); - - return ret; -} - -/* - compare two dns -*/ -static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - struct ldb_dn *dn1 = NULL, *dn2 = NULL; - int ret; - - dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1); - if ( ! ldb_dn_validate(dn1)) return -1; - - dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2); - if ( ! ldb_dn_validate(dn2)) { - talloc_free(dn1); - return -1; - } - - ret = ldb_dn_compare(dn1, dn2); - - talloc_free(dn1); - talloc_free(dn2); - return ret; -} - -/* - compare two utc time values. 1 second resolution -*/ -static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - time_t t1=0, t2=0; - ldb_val_to_time(v1, &t1); - ldb_val_to_time(v2, &t2); - if (t1 == t2) return 0; - return t1 > t2? 1 : -1; -} - -/* - canonicalise a utc time -*/ -static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out) -{ - time_t t; - int ret; - ret = ldb_val_to_time(in, &t); - if (ret != LDB_SUCCESS) { - return ret; - } - out->data = (uint8_t *)ldb_timestring(mem_ctx, t); - if (out->data == NULL) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - out->length = strlen((char *)out->data); - return 0; -} - -/* - table of standard attribute handlers -*/ -static const struct ldb_schema_syntax ldb_standard_syntaxes[] = { - { - .name = LDB_SYNTAX_INTEGER, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_canonicalise_Integer, - .comparison_fn = ldb_comparison_Integer - }, - { - .name = LDB_SYNTAX_OCTET_STRING, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_handler_copy, - .comparison_fn = ldb_comparison_binary - }, - { - .name = LDB_SYNTAX_DIRECTORY_STRING, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_handler_fold, - .comparison_fn = ldb_comparison_fold - }, - { - .name = LDB_SYNTAX_DN, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_canonicalise_dn, - .comparison_fn = ldb_comparison_dn - }, - { - .name = LDB_SYNTAX_OBJECTCLASS, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_handler_fold, - .comparison_fn = ldb_comparison_fold - }, - { - .name = LDB_SYNTAX_UTC_TIME, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_canonicalise_utctime, - .comparison_fn = ldb_comparison_utctime - }, - { - .name = LDB_SYNTAX_BOOLEAN, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_canonicalise_Boolean, - .comparison_fn = ldb_comparison_Boolean - }, -}; - - -/* - return the attribute handlers for a given syntax name -*/ -const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb, - const char *syntax) -{ - unsigned int i; - unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]); - /* TODO: should be replaced with a binary search */ - for (i=0;i