From 3e2c696e45b24b0192ab7b1ddaf1dd4d79571609 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Sep 2006 02:49:04 +0000 Subject: r18866: Jeremy and Volker have given the go-ahead on the group mapping ldb code. Yay! This first commit copies lib/ldb/ from Samba4. A huge congratulations should go to Simo on this - he has put an enormous amount of work into ldb, and it's great to see it go into the Samba3 tree. (This used to be commit bbedf2e34315f5c420a3a05dfe22b1d5cf79f042) --- source3/lib/ldb/common/attrib_handlers.c | 392 +++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 source3/lib/ldb/common/attrib_handlers.c (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c new file mode 100644 index 0000000000..8e437964f4 --- /dev/null +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -0,0 +1,392 @@ +/* + 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/includes.h" +#include "system/locale.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 +*/ +static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + char *s, *t; + int l; + if (!in || !out || !(in->data)) { + return -1; + } + + out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data)); + if (out->data == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%s]", 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; +} + + + +/* + 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) +{ + char *end; + long long i = strtoll((char *)in->data, &end, 0); + if (*end != 0) { + return -1; + } + out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lld", i); + if (out->data == NULL) { + return -1; + } + 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) +{ + return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0); +} + +/* + 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 +*/ +static 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; + char *b1, *b2, *u1, *u2; + int ret; + while (*s1 == ' ') s1++; + while (*s2 == ' ') s2++; + /* TODO: make utf8 safe, possibly with helper function from application */ + while (*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 (s1[0] == s1[1]) s1++; + while (s2[0] == s2[1]) s2++; + } + s1++; s2++; + } + if (! (*s1 && *s2)) { + /* check for trailing spaces only if one of the pointers + * has reached the end of the strings otherwise we + * can mistakenly match. + * ex. "domain users" <-> "domainUpdates" + */ + while (*s1 == ' ') s1++; + while (*s2 == ' ') s2++; + } + return (int)(toupper(*s1)) - (int)(toupper(*s2)); + +utf8str: + /* non need to recheck from the start, just from the first utf8 char found */ + b1 = u1 = ldb_casefold(ldb, mem_ctx, s1); + b2 = u2 = ldb_casefold(ldb, mem_ctx, s2); + + 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_explode_casefold(ldb, (char *)in->data); + if (dn == NULL) { + return -1; + } + + out->data = (uint8_t *)ldb_dn_linearize(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_explode_casefold(mem_ctx, (char *)v1->data); + if (dn1 == NULL) return -1; + + dn2 = ldb_dn_explode_casefold(mem_ctx, (char *)v2->data); + if (dn2 == NULL) { + talloc_free(dn1); + return -1; + } + + ret = ldb_dn_compare(ldb, dn1, dn2); + + talloc_free(dn1); + talloc_free(dn2); + return ret; +} + +/* + compare two objectclasses, looking at subclasses +*/ +static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + int ret, i; + const char **subclasses; + ret = ldb_comparison_fold(ldb, mem_ctx, v1, v2); + if (ret == 0) { + return 0; + } + subclasses = ldb_subclass_list(ldb, (char *)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, mem_ctx, &vs, v2) == 0) { + return 0; + } + } + 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, t2; + t1 = ldb_string_to_time((char *)v1->data); + t2 = ldb_string_to_time((char *)v2->data); + return (int)t2 - (int)t1; +} + +/* + 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 = ldb_string_to_time((char *)in->data); + out->data = (uint8_t *)ldb_timestring(mem_ctx, t); + if (out->data == NULL) { + return -1; + } + out->length = strlen((char *)out->data); + return 0; +} + +/* + 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_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 + }, + { + .attr = LDB_SYNTAX_UTC_TIME, + .flags = 0, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_utctime, + .comparison_fn = ldb_comparison_utctime + } +}; + + +/* + 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 Date: Sat, 7 Oct 2006 10:24:16 +0000 Subject: r19163: pass always a mem_ctx to functions and a ldb_context where needed It would be nice if someone can merge that to samba4, otherwise I'll merge that to samba4 on monday metze (This used to be commit 6bc42f31ce294f2bd50ffbd536e1ee42607ef799) --- source3/lib/ldb/common/attrib_handlers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c index 8e437964f4..c4c83c52a6 100644 --- a/source3/lib/ldb/common/attrib_handlers.c +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -220,7 +220,7 @@ static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, out->length = 0; out->data = NULL; - dn = ldb_dn_explode_casefold(ldb, (char *)in->data); + dn = ldb_dn_explode_casefold(ldb, mem_ctx, (char *)in->data); if (dn == NULL) { return -1; } @@ -248,10 +248,10 @@ static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, struct ldb_dn *dn1 = NULL, *dn2 = NULL; int ret; - dn1 = ldb_dn_explode_casefold(mem_ctx, (char *)v1->data); + dn1 = ldb_dn_explode_casefold(ldb, mem_ctx, (char *)v1->data); if (dn1 == NULL) return -1; - dn2 = ldb_dn_explode_casefold(mem_ctx, (char *)v2->data); + dn2 = ldb_dn_explode_casefold(ldb, mem_ctx, (char *)v2->data); if (dn2 == NULL) { talloc_free(dn1); return -1; -- cgit From d63a3e05a23ffb016578c3daa8b48d6fc32e1e8c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Oct 2006 07:15:27 +0000 Subject: r19183: merge from samba4: don't crash on invalid utf8 chars metze (This used to be commit 71e1f8550f96eaaae7e4fc4d02eb36f1d894abc8) --- source3/lib/ldb/common/attrib_handlers.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c index c4c83c52a6..07a0ec6eb8 100644 --- a/source3/lib/ldb/common/attrib_handlers.c +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -184,10 +184,19 @@ static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, return (int)(toupper(*s1)) - (int)(toupper(*s2)); utf8str: - /* non need to recheck from the start, just from the first utf8 char found */ + /* no need to recheck from the start, just from the first utf8 char found */ b1 = u1 = ldb_casefold(ldb, mem_ctx, s1); b2 = u2 = ldb_casefold(ldb, mem_ctx, s2); - + + if (u1 && u2) { + /* Both strings converted correctly */ + } else { + /* One of the strings was not UTF8, so we have no options but to do a binary compare */ + + u1 = s1; + u2 = s2; + } + while (*u1 & *u2) { if (*u1 != *u2) break; @@ -202,9 +211,10 @@ utf8str: while (*u2 == ' ') u2++; } ret = (int)(*u1 - *u2); + talloc_free(b1); talloc_free(b2); - + return ret; } -- cgit From 5a77ccfbfc070ccb77004cb47e2a582883e4862c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 16 Nov 2006 11:11:09 +0000 Subject: r19741: fix compiler warnings metze (This used to be commit 18171cf54b22f9f2d73753db580934bd10e95e3d) --- source3/lib/ldb/common/attrib_handlers.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c index 07a0ec6eb8..cb1dfa105f 100644 --- a/source3/lib/ldb/common/attrib_handlers.c +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -154,7 +154,8 @@ static 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; - char *b1, *b2, *u1, *u2; + const char *u1, *u2; + char *b1, *b2; int ret; while (*s1 == ' ') s1++; while (*s2 == ' ') s2++; @@ -185,11 +186,14 @@ static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, utf8str: /* no need to recheck from the start, just from the first utf8 char found */ - b1 = u1 = ldb_casefold(ldb, mem_ctx, s1); - b2 = u2 = ldb_casefold(ldb, mem_ctx, s2); + b1 = ldb_casefold(ldb, mem_ctx, s1); + b2 = ldb_casefold(ldb, mem_ctx, s2); - if (u1 && u2) { + if (b1 && b2) { /* Both strings converted correctly */ + + u1 = b1; + u2 = b2; } else { /* One of the strings was not UTF8, so we have no options but to do a binary compare */ -- cgit From 847644bdac520a3cca7f30ffa50c0de3eeedf6d9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 27 Nov 2006 08:41:41 +0000 Subject: r19917: Fix warnings (This used to be commit cf4309b9048a8417104cac660421a3dcd2e96ffe) --- source3/lib/ldb/common/attrib_handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c index cb1dfa105f..a289f3c32a 100644 --- a/source3/lib/ldb/common/attrib_handlers.c +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -296,7 +296,7 @@ static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx, } for (i=0;subclasses[i];i++) { struct ldb_val vs; - vs.data = discard_const(subclasses[i]); + vs.data = (uint8 *)discard_const(subclasses[i]); vs.length = strlen(subclasses[i]); if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) { return 0; -- cgit From 762b86ff0deb072871081f2684f63778e36ad3ce Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Nov 2006 17:47:41 +0000 Subject: r19935: always use discard_const_p() in lib/ldb/ metze (This used to be commit 4a5da57306ad8cce5522ee72349cb85b447e295c) --- source3/lib/ldb/common/attrib_handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c index a289f3c32a..2b699aeaa8 100644 --- a/source3/lib/ldb/common/attrib_handlers.c +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -296,7 +296,7 @@ static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx, } for (i=0;subclasses[i];i++) { struct ldb_val vs; - vs.data = (uint8 *)discard_const(subclasses[i]); + vs.data = discard_const_p(uint8_t, subclasses[i]); vs.length = strlen(subclasses[i]); if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) { return 0; -- cgit From 2c09988e46d4e917b1c53c9bda3f81a48bba4952 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 01:44:42 +0000 Subject: r23790: LGPLv3+ conversion for our LGPLv2+ library code (This used to be commit 1b78cace504f60c0f525765fbf59d9cc6506cd4d) --- source3/lib/ldb/common/attrib_handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c index 2b699aeaa8..e646a45ae6 100644 --- a/source3/lib/ldb/common/attrib_handlers.c +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -10,7 +10,7 @@ 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. + 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 -- cgit From 9fa1c63578733077c0aaaeeb2fc97c3b191089cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 03:42:26 +0000 Subject: r23798: updated old Temple Place FSF addresses to new URL (This used to be commit c676a971142d7176fd5dbf21405fca14515a0a76) --- source3/lib/ldb/common/attrib_handlers.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/lib/ldb/common/attrib_handlers.c') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c index e646a45ae6..5f26db6776 100644 --- a/source3/lib/ldb/common/attrib_handlers.c +++ b/source3/lib/ldb/common/attrib_handlers.c @@ -18,8 +18,7 @@ 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 + License along with this library; if not, see . */ /* attribute handlers for well known attribute types, selected by syntax OID -- cgit