1
0
mirror of https://github.com/samba-team/samba.git synced 2025-09-18 09:44:19 +03:00

r8082: large rewite of ldb_dn.c

- we do not support multpiple attribute components anymore, makes code a lot easier
  they will be readded later if we found out they are really used, so far my tests
  show w2k3 do not handle them as well

- fix escaping issues, move component value to be in an ldb_val structure
  still need to handle binary values case

- make cononicalize functions leak less memory by giving a specific memory context

- fix tests scripts so that test-ldap can start
- make test not delete databases on completion so that I can inspect them
(This used to be commit 624a73148d)
This commit is contained in:
Simo Sorce
2005-07-02 17:30:03 +00:00
committed by Gerald (Jerry) Carter
parent 2e419725b0
commit 1c5105065a
15 changed files with 284 additions and 345 deletions

View File

@@ -34,10 +34,10 @@
/* /*
default handler that just copies a ldb_val. default handler that just copies a ldb_val.
*/ */
int ldb_handler_copy(struct ldb_context *ldb, int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
*out = ldb_val_dup(ldb, in); *out = ldb_val_dup(mem_ctx, in);
if (out->data == NULL) { if (out->data == NULL) {
ldb_oom(ldb); ldb_oom(ldb);
return -1; return -1;
@@ -49,11 +49,11 @@ int ldb_handler_copy(struct ldb_context *ldb,
a case folding copy handler, removing leading and trailing spaces and a case folding copy handler, removing leading and trailing spaces and
multiple internal spaces multiple internal spaces
*/ */
static int ldb_handler_fold(struct ldb_context *ldb, static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
uint8_t *s1, *s2; uint8_t *s1, *s2;
out->data = talloc_size(ldb, strlen(in->data)+1); out->data = talloc_size(mem_ctx, strlen(in->data)+1);
if (out->data == NULL) { if (out->data == NULL) {
ldb_oom(ldb); ldb_oom(ldb);
return -1; return -1;
@@ -78,20 +78,20 @@ static int ldb_handler_fold(struct ldb_context *ldb,
a case folding copy handler, removing leading and trailing spaces and a case folding copy handler, removing leading and trailing spaces and
multiple internal spaces, and checking for wildcard characters multiple internal spaces, and checking for wildcard characters
*/ */
static int ldb_handler_fold_wildcard(struct ldb_context *ldb, static int ldb_handler_fold_wildcard(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
if (strchr(in->data, '*')) { if (strchr(in->data, '*')) {
return -1; return -1;
} }
return ldb_handler_fold(ldb, in, out); return ldb_handler_fold(ldb, mem_ctx, in, out);
} }
/* /*
canonicalise a ldap Integer canonicalise a ldap Integer
rfc2252 specifies it should be in decimal form rfc2252 specifies it should be in decimal form
*/ */
static int ldb_canonicalise_Integer(struct ldb_context *ldb, static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
char *end; char *end;
@@ -99,7 +99,7 @@ static int ldb_canonicalise_Integer(struct ldb_context *ldb,
if (*end != 0) { if (*end != 0) {
return -1; return -1;
} }
out->data = talloc_asprintf(ldb, "%lld", i); out->data = talloc_asprintf(mem_ctx, "%lld", i);
if (out->data == NULL) { if (out->data == NULL) {
return -1; return -1;
} }
@@ -110,7 +110,7 @@ static int ldb_canonicalise_Integer(struct ldb_context *ldb,
/* /*
compare two Integers compare two Integers
*/ */
static int ldb_comparison_Integer(struct ldb_context *ldb, static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2) const struct ldb_val *v1, const struct ldb_val *v2)
{ {
return strtoll(v1->data, NULL, 0) - strtoll(v2->data, NULL, 0); return strtoll(v1->data, NULL, 0) - strtoll(v2->data, NULL, 0);
@@ -119,7 +119,7 @@ static int ldb_comparison_Integer(struct ldb_context *ldb,
/* /*
compare two binary blobs compare two binary blobs
*/ */
int ldb_comparison_binary(struct ldb_context *ldb, int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2) const struct ldb_val *v1, const struct ldb_val *v2)
{ {
if (v1->length != v2->length) { if (v1->length != v2->length) {
@@ -133,7 +133,7 @@ int ldb_comparison_binary(struct ldb_context *ldb,
and leading and trailing whitespace and leading and trailing whitespace
see rfc2252 section 8.1 see rfc2252 section 8.1
*/ */
static int ldb_comparison_fold(struct ldb_context *ldb, static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2) const struct ldb_val *v1, const struct ldb_val *v2)
{ {
const char *s1=v1->data, *s2=v2->data; const char *s1=v1->data, *s2=v2->data;
@@ -159,7 +159,8 @@ static int ldb_comparison_fold(struct ldb_context *ldb,
see rfc2252 section 8.1 see rfc2252 section 8.1
handles wildcards handles wildcards
*/ */
static int ldb_comparison_fold_wildcard(struct ldb_context *ldb, static int ldb_comparison_fold_wildcard(struct ldb_context *ldb,
void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v1,
const struct ldb_val *v2) const struct ldb_val *v2)
{ {
@@ -187,40 +188,49 @@ static int ldb_comparison_fold_wildcard(struct ldb_context *ldb,
/* /*
canonicalise a attribute in DN format canonicalise a attribute in DN format
*/ */
static int ldb_canonicalise_dn(struct ldb_context *ldb, static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
struct ldb_dn *dn2=NULL, *dn1 = ldb_dn_explode(ldb, in->data); struct ldb_dn *dn1, *dn2;
int ret = -1;
out->length = 0;
out->data = NULL; out->data = NULL;
dn1 = ldb_dn_explode(mem_ctx, in->data);
if (dn1 == NULL) { if (dn1 == NULL) {
goto failed; return -1;
} }
dn2 = ldb_dn_casefold(ldb, dn1); dn2 = ldb_dn_casefold(ldb, dn1);
if (dn2 == NULL) goto failed; if (dn2 == NULL) {
goto done;
}
out->data = ldb_dn_linearize(ldb, dn2); out->data = ldb_dn_linearize(mem_ctx, dn2);
if (out->data == NULL) goto failed; if (out->data == NULL) {
goto done;
}
out->length = strlen(out->data);
ret = 0;
done:
talloc_free(dn1); talloc_free(dn1);
talloc_free(dn2); talloc_free(dn2);
return 0;
failed: return ret;
talloc_free(dn1);
talloc_free(dn2);
return -1;
} }
/* /*
compare two dns compare two dns
*/ */
static int ldb_comparison_dn(struct ldb_context *ldb, static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2) const struct ldb_val *v1, const struct ldb_val *v2)
{ {
struct ldb_val cv1, cv2; struct ldb_val cv1, cv2;
int ret; int ret;
if (ldb_canonicalise_dn(ldb, v1, &cv1) != 0 || if (ldb_canonicalise_dn(ldb, mem_ctx, v1, &cv1) != 0 ||
ldb_canonicalise_dn(ldb, v2, &cv2) != 0) { ldb_canonicalise_dn(ldb, mem_ctx, v2, &cv2) != 0) {
goto failed; goto failed;
} }
ret = strcmp(cv1.data, cv2.data); ret = strcmp(cv1.data, cv2.data);
@@ -236,12 +246,12 @@ failed:
/* /*
compare two objectclasses, looking at subclasses compare two objectclasses, looking at subclasses
*/ */
static int ldb_comparison_objectclass(struct ldb_context *ldb, static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2) const struct ldb_val *v1, const struct ldb_val *v2)
{ {
int ret, i; int ret, i;
const char **subclasses; const char **subclasses;
ret = ldb_comparison_fold(ldb, v1, v2); ret = ldb_comparison_fold(ldb, mem_ctx, v1, v2);
if (ret == 0) { if (ret == 0) {
return 0; return 0;
} }
@@ -253,7 +263,7 @@ static int ldb_comparison_objectclass(struct ldb_context *ldb,
struct ldb_val vs; struct ldb_val vs;
vs.data = discard_const(subclasses[i]); vs.data = discard_const(subclasses[i]);
vs.length = strlen(subclasses[i]); vs.length = strlen(subclasses[i]);
if (ldb_comparison_objectclass(ldb, &vs, v2) == 0) { if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) {
return 0; return 0;
} }
} }

View File

@@ -60,10 +60,16 @@ int ldb_set_attrib_handlers(struct ldb_context *ldb,
default function for read/write/canonicalise default function for read/write/canonicalise
*/ */
static int ldb_default_copy(struct ldb_context *ldb, static int ldb_default_copy(struct ldb_context *ldb,
void *mem_ctx,
const struct ldb_val *in, const struct ldb_val *in,
struct ldb_val *out) struct ldb_val *out)
{ {
*out = *in; *out = ldb_val_dup(mem_ctx, in);
if (out->length == 0) {
return -1;
}
return 0; return 0;
} }
@@ -71,6 +77,7 @@ static int ldb_default_copy(struct ldb_context *ldb,
default function for comparison default function for comparison
*/ */
static int ldb_default_cmp(struct ldb_context *ldb, static int ldb_default_cmp(struct ldb_context *ldb,
void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v1,
const struct ldb_val *v2) const struct ldb_val *v2)
{ {

View File

@@ -37,63 +37,74 @@
#include "includes.h" #include "includes.h"
#include "ldb/include/ldb.h" #include "ldb/include/ldb.h"
#include "ldb/include/ldb_private.h" #include "ldb/include/ldb_private.h"
#include "ldb/include/ldb_dn.h"
#define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
static char *escape_string(void *mem_ctx, const char *src) static char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
{ {
const char *p, *s; const char *p, *s, *src;
char *d, *dst=NULL; char *d, *dst;
int len;
LDB_DN_NULL_FAILED(src); if (!value.length)
return NULL;
p = s = src = (const char *)value.data;
len = value.length;
/* allocate destination string, it will be at most 3 times the source */ /* allocate destination string, it will be at most 3 times the source */
dst = d = talloc_array(mem_ctx, char, strlen(src) * 3 + 1); dst = d = talloc_array(mem_ctx, char, len * 3 + 1);
LDB_DN_NULL_FAILED(dst); LDB_DN_NULL_FAILED(dst);
p = s = src; while (p - src < len) {
while (*p) {
p += strcspn(p, ",=\n+<>#;\\\""); p += strcspn(p, ",=\n+<>#;\\\"");
if (*p == '\0') /* no special s found, all ok */
if (p - src == len) /* found no escapable chars */
break; break;
if (*p) { /* copy part of the string and escape */ memcpy(d, s, p - s); /* copy the part of the string before the stop */
memcpy(d, s, p - s); d += (p - s); /* move to current position */
d += (p - s);
if (*p) { /* it is a normal escapable character */
*d++ = '\\'; *d++ = '\\';
*d++ = *p++; *d++ = *p++;
s = p; } else { /* we have a zero byte in the string */
strncpy(d, "\00", 3); /* escape the zero */
d = d + 3;
p++; /* skip the zero */
} }
s = p; /* move forward */
} }
/* copy the last part (with zero) and return */ /* copy the last part (with zero) and return */
memcpy(d, s, &src[strlen(src)] - s + 1); memcpy(d, s, &src[len] - s + 1);
return dst; return dst;
failed: failed:
talloc_free(dst); talloc_free(dst);
return NULL; return NULL;
} }
static char *unescape_string(void *mem_ctx, const char *src) static struct ldb_val ldb_dn_unescape_value(void *mem_ctx, const char *src)
{ {
struct ldb_val value;
unsigned x; unsigned x;
char *p, *dst=NULL, *end; char *p, *dst = NULL, *end;
value.length = 0;
LDB_DN_NULL_FAILED(src); LDB_DN_NULL_FAILED(src);
dst = p = talloc_strdup(mem_ctx, src); dst = p = talloc_memdup(mem_ctx, src, strlen(src) + 1);
LDB_DN_NULL_FAILED(dst); LDB_DN_NULL_FAILED(dst);
end = &dst[strlen(dst)]; end = &dst[strlen(dst)];
while (*p) { while (*p) {
p += strcspn(p, ",=\n+<>#;\\\""); p += strcspn(p, ",=\n+<>#;\\\"");
if (*p == '\0') /* no escapes or specials found, all ok */
return dst;
if (*p == '\\') { if (*p == '\\') {
if (strchr(",=\n+<>#;\\\"", p[1])) { if (strchr(",=\n+<>#;\\\"", p[1])) {
@@ -112,31 +123,41 @@ static char *unescape_string(void *mem_ctx, const char *src)
} }
} }
/* a string with not escaped specials is invalid */ /* a string with not escaped specials is invalid (tested) */
if (*p != '\0') {
return NULL; goto failed;
}
} }
return dst; value.length = end - dst;
value.data = dst;
return value;
failed: failed:
talloc_free(dst); talloc_free(dst);
return NULL; return value;
} }
static char *seek_to_separator(char *string, const char *separator) /* check if the string contains quotes
* skips leading and trailing spaces
* - returns 0 if no quotes found
* - returns 1 if quotes are found and put their position
* in *quote_start and *quote_end parameters
* - return -1 if there are open quotes
*/
static int get_quotes_position(const char *source, int *quote_start, int *quote_end)
{ {
char *p; const char *p;
p = strchr(string, '='); p = source;
LDB_DN_NULL_FAILED(p);
p++;
/* check if there are quotes surrounding the value */ /* check if there are quotes surrounding the value */
p += strspn(p, " \n"); /* skip white spaces after '=' */ p += strspn(p, " \n"); /* skip white spaces */
if (*p == '\"') { if (*p == '\"') {
*quote_start = p - source;
p++; p++;
while (*p != '\"') { while (*p != '\"') {
p = strchr(p, '\"'); p = strchr(p, '\"');
@@ -145,11 +166,50 @@ static char *seek_to_separator(char *string, const char *separator)
if (*(p - 1) == '\\') if (*(p - 1) == '\\')
p++; p++;
} }
*quote_end = p - source;
return 1;
} }
p += strcspn(p, separator); return 0;
return p; failed:
return -1;
}
static char *seek_to_separator(char *string, const char *separators)
{
char *p;
int ret, qs, qe;
p = strchr(string, '=');
LDB_DN_NULL_FAILED(p);
p++;
/* check if there are quotes surrounding the value */
ret = get_quotes_position(p, &qs, &qe);
if (ret == -1)
return NULL;
if (ret == 1) { /* quotes found */
p += qe; /* positioning after quotes */
p += strspn(p, " \n"); /* skip white spaces after the quote */
if (strcspn(p, separators) != 0) /* if there are characters between quotes */
return NULL; /* and separators, the dn is invalid */
return p; /* return on the separator */
}
/* no quotes found seek to separators */
ret = strcspn(p, separators);
if (ret == 0) /* no separators ?! bail out */
return NULL;
return p + ret;
failed: failed:
return NULL; return NULL;
@@ -172,132 +232,53 @@ static char *ldb_dn_trim_string(char *string, const char *edge)
return s; return s;
} }
static struct ldb_dn_attribute *ldb_dn_explode_attribute(void *mem_ctx, char *raw_attribute) /* we choosed to not support multpile valued components */
static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw_component)
{ {
struct ldb_dn_attribute *at; struct ldb_dn_component dc;
char *p; char *p;
int ret, qs, qe;
at = talloc(mem_ctx, struct ldb_dn_attribute); /* find attribute type/value separator */
LDB_DN_NULL_FAILED(at); p = strchr(raw_component, '=');
p = strchr(raw_attribute, '=');
LDB_DN_NULL_FAILED(p); LDB_DN_NULL_FAILED(p);
*p = '\0'; *p++ = '\0'; /* terminate name and point to value */
at->name = talloc_strdup(at, ldb_dn_trim_string(raw_attribute, " \n")); /* copy and trim name in the component */
LDB_DN_NULL_FAILED(at->name); dc.name = talloc_strdup(mem_ctx, ldb_dn_trim_string(raw_component, " \n"));
if (!dc.name)
return dc;
p++; ret = get_quotes_position(p, &qs, &qe);
p = ldb_dn_trim_string(p, " \n"); switch (ret) {
case 0: /* no quotes trim the string */
p = ldb_dn_trim_string(p, " \n");
dc.value = ldb_dn_unescape_value(mem_ctx, p);
break;
if (*p == '\"') { /* quotes at start means there must be quotes at the end */ case 1: /* quotes found get the unquoted string */
if (p[strlen(p) - 1] != '\"') /* malformed value */ p[qe] = '\0';
return NULL; p = p + qs + 1;
dc.value.length = strlen(p);
p++; dc.value.data = talloc_memdup(mem_ctx, p, dc.value.length + 1);
p[strlen(p) - 1] = '\0'; break;
at->value = talloc_strdup(at, p);
return at; default: /* mismatched quotes ot other error, bail out */
goto failed;
} }
/* no quotes means we must unescape the string */
at->value = unescape_string(at, p);
LDB_DN_NULL_FAILED(at->value);
return at; if (dc.value.length == 0) {
goto failed;
failed: }
talloc_free(at);
return NULL;
}
static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_component)
{
struct ldb_dn_component *dc;
char *p;
dc = talloc(mem_ctx, struct ldb_dn_component);
LDB_DN_NULL_FAILED(dc);
dc->attr_num = 0;
dc->attributes = NULL;
p = raw_component;
/* get the components */
do {
char *t;
/* terminate the current attribute and return pointer to the next one */
t = seek_to_separator(p, "+");
LDB_DN_NULL_FAILED(t);
if (*t) { /* here there is a separator */
*t = '\0'; /*terminate */
t++; /* a separtor means there's another attribute that follows */
}
/* allocate attributes pointer */
dc->attributes = talloc_realloc(dc, dc->attributes,
struct ldb_dn_attribute *,
dc->attr_num + 1);
LDB_DN_NULL_FAILED(dc->attributes);
/* store the exploded attirbute in the main structure */
dc->attributes[dc->attr_num] = ldb_dn_explode_attribute(dc->attributes, p);
LDB_DN_NULL_FAILED(dc->attributes[dc->attr_num]);
dc->attr_num++;
/* jump to the next attribute if any */
p = t;
} while(*p);
return dc; return dc;
failed: failed:
talloc_free(dc); talloc_free(dc.name);
return NULL; dc.name = NULL;
} return dc;
/* FIXME: currently consider a dn composed of only case insensitive attributes
this is not correct and need to be fixed soon */
static void ldb_dn_sort_attributes(struct ldb_dn *edn)
{
struct ldb_dn_attribute *at0, *at1;
int i, j, k, l;
for (i = 0; i < edn->comp_num; i++) {
if (edn->components[i]->attr_num > 1) {
/* it is very unlikely that there is a multivalued RDN. In that
unlikely case it is very unlikely you will find more than 2
values. So the use of bubble sort here seem to be acceptable */
for (j = 0; (j + 1) < edn->components[i]->attr_num; j++) {
for (k = j; k >= 0; k--) {
at0 = edn->components[i]->attributes[k];
at1 = edn->components[i]->attributes[k + 1];
l = ldb_caseless_cmp(at0->name, at1->name);
if (l > 0) {
/* already sorted, so no bubbles to move exit inner loop */
break;
}
if (l == 0) {
if (ldb_caseless_cmp(at0->value, at1->value) >= 0) {
/* already sorted, so no bubbles to move exit inner loop */
break;
}
}
edn->components[i]->attributes[k] = at1;
edn->components[i]->attributes[k + 1] = at0;
}
}
}
}
} }
struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
@@ -305,6 +286,8 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
struct ldb_dn *edn; /* the exploded dn */ struct ldb_dn *edn; /* the exploded dn */
char *pdn, *p; char *pdn, *p;
pdn = NULL;
/* Allocate a structure to hold the exploded DN */ /* Allocate a structure to hold the exploded DN */
edn = talloc(mem_ctx, struct ldb_dn); edn = talloc(mem_ctx, struct ldb_dn);
LDB_DN_NULL_FAILED(edn); LDB_DN_NULL_FAILED(edn);
@@ -314,8 +297,7 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
edn->components = NULL; edn->components = NULL;
pdn = p = talloc_strdup(edn, dn); pdn = p = talloc_strdup(edn, dn);
if (!pdn) LDB_DN_NULL_FAILED(pdn);
goto failed;
/* get the components */ /* get the components */
do { do {
@@ -323,25 +305,23 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
/* terminate the current component and return pointer to the next one */ /* terminate the current component and return pointer to the next one */
t = seek_to_separator(p, ",;"); t = seek_to_separator(p, ",;");
if (t == NULL) LDB_DN_NULL_FAILED(t);
goto failed;
if (*t) { /* here there is a separator */ if (*t) { /* here there is a separator */
*t = '\0'; /*terminate */ *t = '\0'; /*terminate */
t++; /* a separtor means there's another component that follows */ t++; /* a separtor means another component follows */
} }
/* allocate space to hold the dn component */ /* allocate space to hold the dn component */
edn->components = talloc_realloc(edn, edn->components, edn->components = talloc_realloc(edn, edn->components,
struct ldb_dn_component *, struct ldb_dn_component,
edn->comp_num + 1); edn->comp_num + 1);
if (edn->components == NULL) if (edn->components == NULL)
goto failed; goto failed;
/* store the exploded component in the main structure */ /* store the exploded component in the main structure */
edn->components[edn->comp_num] = explode_component(edn->components, p); edn->components[edn->comp_num] = ldb_dn_explode_component(edn, p);
if (edn->components[edn->comp_num] == NULL) LDB_DN_NULL_FAILED(edn->components[edn->comp_num].name);
goto failed;
edn->comp_num++; edn->comp_num++;
@@ -350,87 +330,71 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
} while(*p); } while(*p);
/* sort attributes if there's any multivalued component */
ldb_dn_sort_attributes(edn);
talloc_free(pdn); talloc_free(pdn);
return edn; return edn;
failed: failed:
talloc_free(pdn);
talloc_free(edn); talloc_free(edn);
return NULL; return NULL;
} }
char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn) char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn)
{ {
char *dn, *ename, *evalue; char *dn, *value;
const char *format; const char *format = "%s=%s";
int i, j; int i;
dn = talloc_strdup(mem_ctx, ""); dn = talloc_strdup(mem_ctx, "");
LDB_DN_NULL_FAILED(dn); LDB_DN_NULL_FAILED(dn);
for (i = 0; i < edn->comp_num; i++) { for (i = 0; i < edn->comp_num; i++) {
if (i != 0) { if (i != 0) {
dn = talloc_append_string(mem_ctx, dn, ","); format = ",%s=%s";
} }
for (j = 0; j < edn->components[i]->attr_num; j++) {
if (j == 0) {
format = "%s=%s";
} else {
format = "+%s=%s";
}
ename = escape_string(dn, edn->components[i]->attributes[j]->name); value = ldb_dn_escape_value(dn, edn->components[i].value);
LDB_DN_NULL_FAILED(ename); LDB_DN_NULL_FAILED(value);
evalue = escape_string(dn, edn->components[i]->attributes[j]->value); dn = talloc_asprintf_append(dn, format, edn->components[i].name, value);
LDB_DN_NULL_FAILED(evalue); LDB_DN_NULL_FAILED(dn);
dn = talloc_asprintf_append(dn, format, ename, evalue); talloc_free(value);
LDB_DN_NULL_FAILED(dn);
talloc_free(ename);
talloc_free(evalue);
}
} }
return dn; return dn;
failed: failed:
talloc_free(dn); talloc_free(dn);
return NULL; return NULL;
} }
/* FIXME: currently consider a dn composed of only case insensitive attributes /* compare DNs using casefolding compare functions */
this is not correct and need to be fixed soon */ int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1)
int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1)
{ {
struct ldb_dn_attribute *at0, *at1; int i, ret;
int i, j, k;
/* if the number of components doesn't match they differ */ /* if the number of components doesn't match they differ */
if (edn0->comp_num != edn1->comp_num) if (edn0->comp_num != edn1->comp_num)
return (edn1->comp_num - edn0->comp_num); return (edn1->comp_num - edn0->comp_num);
for (i = 0; i < edn0->comp_num; i++) { for (i = 0; i < edn0->comp_num; i++) {
const struct ldb_attrib_handler *h;
/* if the number of attributes per component doesn't match they differ */ /* compare names (attribute names are guaranteed to be ASCII only) */
if (edn0->components[i]->attr_num != edn1->components[i]->attr_num) ret = ldb_caseless_cmp(edn0->components[i].name,
return (edn1->components[i]->attr_num - edn0->components[i]->attr_num); edn1->components[i].name);
if (ret) {
return ret;
}
for (j = 0; j < edn0->components[i]->attr_num; j++) { /* names match, compare values */
at0 = edn0->components[i]->attributes[j]; h = ldb_attrib_handler(ldb, edn0->components[i].name);
at1 = edn1->components[i]->attributes[j]; ret = h->comparison_fn(ldb, ldb, &(edn0->components[i].value),
&(edn1->components[i].value));
/* compare names */ if (ret) {
k = ldb_caseless_cmp(at0->name, at1->name); return ret;
if (k)
return k;
/* names match, compare values */
k = ldb_caseless_cmp(at0->value, at1->value);
if (k)
return k;
} }
} }
@@ -438,55 +402,31 @@ int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1)
} }
/* /*
casefold a dn. We need to uppercase the attribute names, and the casefold a dn. We need to casefold the attribute names, and canonicalize
attribute values of case insensitive attributes. We also need to remove attribute values of case insensitive attributes.
extraneous spaces between elements
*/ */
struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn) struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn)
{ {
struct ldb_dn *cedn; struct ldb_dn *cedn;
int i, j; int i;
cedn = talloc(ldb, struct ldb_dn); cedn = talloc(ldb, struct ldb_dn);
LDB_DN_NULL_FAILED(cedn); LDB_DN_NULL_FAILED(cedn);
cedn->comp_num = edn->comp_num; cedn->comp_num = edn->comp_num;
cedn->components = talloc_array(cedn, struct ldb_dn_component *, edn->comp_num); cedn->components = talloc_array(cedn, struct ldb_dn_component, edn->comp_num);
LDB_DN_NULL_FAILED(cedn->components); LDB_DN_NULL_FAILED(cedn->components);
for (i = 0; i < edn->comp_num; i++) { for (i = 0; i < edn->comp_num; i++) {
struct ldb_dn_component *dc; struct ldb_dn_component dc;
const struct ldb_attrib_handler *h;
dc = talloc(cedn->components, struct ldb_dn_component); dc.name = ldb_casefold(cedn, edn->components[i].name);
LDB_DN_NULL_FAILED(dc); LDB_DN_NULL_FAILED(dc.name);
dc->attr_num = edn->components[i]->attr_num; h = ldb_attrib_handler(ldb, dc.name);
dc->attributes = edn->components[i]->attributes; if (h->canonicalise_fn(ldb, cedn, &(edn->components[i].value), &(dc.value)) != 0) {
LDB_DN_NULL_FAILED(dc->attributes); goto failed;
for (j = 0; j < edn->components[i]->attr_num; j++) {
struct ldb_dn_attribute *at;
struct ldb_val v0, v;
const struct ldb_attrib_handler *h;
at = talloc(dc->attributes, struct ldb_dn_attribute);
LDB_DN_NULL_FAILED(at);
at->name = ldb_casefold(at, edn->components[i]->attributes[j]->name);
LDB_DN_NULL_FAILED(at->name);
h = ldb_attrib_handler(ldb, at->name);
/* at->value should be a ldb_val, work around
this for now .... */
v0.data = edn->components[i]->attributes[j]->value;
v0.length = strlen(v0.data);
if (h->canonicalise_fn(ldb, &v0, &v) != 0) {
return NULL;
}
talloc_steal(at, v.data);
at->value = v.data;
dc->attributes[j] = at;
} }
cedn->components[i] = dc; cedn->components[i] = dc;

View File

@@ -317,7 +317,7 @@ int ldb_ldif_write(struct ldb_context *ldb,
for (j=0;j<msg->elements[i].num_values;j++) { for (j=0;j<msg->elements[i].num_values;j++) {
struct ldb_val v; struct ldb_val v;
ret = h->ldif_write_fn(ldb, &msg->elements[i].values[j], &v); ret = h->ldif_write_fn(ldb, ldb, &msg->elements[i].values[j], &v);
CHECK_RET; CHECK_RET;
if (ldb_should_b64_encode(&v)) { if (ldb_should_b64_encode(&v)) {
ret = fprintf_fn(private_data, "%s:: ", ret = fprintf_fn(private_data, "%s:: ",
@@ -647,7 +647,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
if (!el->values) { if (!el->values) {
goto failed; goto failed;
} }
ret = h->ldif_read_fn(ldb, &value, &el->values[el->num_values]); ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[el->num_values]);
if (ret != 0) { if (ret != 0) {
goto failed; goto failed;
} }
@@ -671,7 +671,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
goto failed; goto failed;
} }
el->num_values = 1; el->num_values = 1;
ret = h->ldif_read_fn(ldb, &value, &el->values[0]); ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[0]);
if (ret != 0) { if (ret != 0) {
goto failed; goto failed;
} }

View File

@@ -120,7 +120,7 @@ static int ldb_match_leaf(struct ldb_context *ldb,
h = ldb_attrib_handler(ldb, el->name); h = ldb_attrib_handler(ldb, el->name);
for (i=0;i<el->num_values;i++) { for (i=0;i<el->num_values;i++) {
if (h->comparison_fn(ldb, &tree->u.simple.value, if (h->comparison_fn(ldb, ldb, &tree->u.simple.value,
&el->values[i]) == 0) { &el->values[i]) == 0) {
return 1; return 1;
} }

View File

@@ -188,8 +188,8 @@ char *ldb_binary_encode(void *ctx, struct ldb_val val);
/* /*
functions for controlling attribute handling functions for controlling attribute handling
*/ */
typedef int (*ldb_attr_handler_t)(struct ldb_context *, const struct ldb_val *, struct ldb_val *); typedef int (*ldb_attr_handler_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, struct ldb_val *);
typedef int (*ldb_attr_comparison_t)(struct ldb_context *, const struct ldb_val *, const struct ldb_val *); typedef int (*ldb_attr_comparison_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, const struct ldb_val *);
struct ldb_attrib_handler { struct ldb_attrib_handler {
const char *attr; const char *attr;

View File

@@ -1,41 +0,0 @@
/*
Unix SMB/CIFS implementation.
LDAP server
Copyright (C) Simo Sorce 2004
Copyright (C) Derrell Lipman 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct ldb_dn_attribute {
char *name;
char *value;
};
struct ldb_dn_component {
int attr_num;
struct ldb_dn_attribute **attributes;
};
struct ldb_dn {
int comp_num;
struct ldb_dn_component **components;
};
struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn);
char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn);
int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1);
struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn);

View File

@@ -1,8 +1,9 @@
/* /*
ldb database library ldb database library
Copyright (C) Andrew Tridgell 2004 Copyright (C) Andrew Tridgell 2004
Copyright (C) Stefan Metzmacher 2004 Copyright (C) Stefan Metzmacher 2004
Copyright (C) Simo Sorce 2004
** NOTE! The following LGPL license applies to the ldb ** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released ** library. This does NOT imply that all of Samba is released
@@ -105,6 +106,16 @@ struct ldb_context {
struct ldb_schema schema; struct ldb_schema schema;
}; };
/* internal ldb exploded dn structures */
struct ldb_dn_component {
char *name;
struct ldb_val value;
};
struct ldb_dn {
int comp_num;
struct ldb_dn_component *components;
};
/* the modules init function */ /* the modules init function */
typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, const char *options[]); typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, const char *options[]);
@@ -178,17 +189,22 @@ int ldb_set_attrib_handlers(struct ldb_context *ldb,
unsigned num_handlers); unsigned num_handlers);
int ldb_setup_wellknown_attributes(struct ldb_context *ldb); int ldb_setup_wellknown_attributes(struct ldb_context *ldb);
/* The following definitions come from lib/ldb/common/ldb_dn.c */
struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn);
char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn); char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn);
int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1); int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1);
struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn); struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn);
/* The following definitions come from lib/ldb/common/ldb_attributes.c */
const char **ldb_subclass_list(struct ldb_context *ldb, const char *class); const char **ldb_subclass_list(struct ldb_context *ldb, const char *class);
void ldb_subclass_remove(struct ldb_context *ldb, const char *class); void ldb_subclass_remove(struct ldb_context *ldb, const char *class);
int ldb_subclass_add(struct ldb_context *ldb, const char *class, const char *subclass); int ldb_subclass_add(struct ldb_context *ldb, const char *class, const char *subclass);
int ldb_handler_copy(struct ldb_context *ldb, int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out); const struct ldb_val *in, struct ldb_val *out);
int ldb_comparison_binary(struct ldb_context *ldb, int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2); const struct ldb_val *v1, const struct ldb_val *v2);
#endif #endif

View File

@@ -111,7 +111,7 @@ static char *ldb_dn_key(struct ldb_context *ldb,
} }
h = ldb_attrib_handler(ldb, attr); h = ldb_attrib_handler(ldb, attr);
if (h->canonicalise_fn(ldb, value, &v) != 0) { if (h->canonicalise_fn(ldb, ldb, value, &v) != 0) {
/* canonicalisation can be refused. For example, /* canonicalisation can be refused. For example,
a attribute that takes wildcards will refuse to canonicalise a attribute that takes wildcards will refuse to canonicalise
if the value contains a wildcard */ if the value contains a wildcard */

View File

@@ -38,7 +38,6 @@
#include "includes.h" #include "includes.h"
#include "ldb/include/ldb.h" #include "ldb/include/ldb.h"
#include "ldb/include/ldb_private.h" #include "ldb/include/ldb_private.h"
#include "ldb/include/ldb_dn.h"
#include "ldb/ldb_tdb/ldb_tdb.h" #include "ldb/ldb_tdb/ldb_tdb.h"
#define LDBLOCK "@INT_LDBLOCK" #define LDBLOCK "@INT_LDBLOCK"
@@ -531,7 +530,7 @@ static int msg_delete_element(struct ldb_module *module,
h = ldb_attrib_handler(ldb, el->name); h = ldb_attrib_handler(ldb, el->name);
for (i=0;i<el->num_values;i++) { for (i=0;i<el->num_values;i++) {
if (h->comparison_fn(ldb, &el->values[i], val) == 0) { if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
if (i<el->num_values-1) { if (i<el->num_values-1) {
memmove(&el->values[i], &el->values[i+1], memmove(&el->values[i], &el->values[i+1],
sizeof(el->values[i])*(el->num_values-(i+1))); sizeof(el->values[i])*(el->num_values-(i+1)));

View File

@@ -30,16 +30,16 @@
/* /*
convert a ldif formatted objectSid to a NDR formatted blob convert a ldif formatted objectSid to a NDR formatted blob
*/ */
static int ldif_read_objectSid(struct ldb_context *ldb, const struct ldb_val *in, static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
struct dom_sid *sid; struct dom_sid *sid;
NTSTATUS status; NTSTATUS status;
sid = dom_sid_parse_talloc(ldb, in->data); sid = dom_sid_parse_talloc(mem_ctx, in->data);
if (sid == NULL) { if (sid == NULL) {
return -1; return -1;
} }
status = ndr_push_struct_blob(out, ldb, sid, status = ndr_push_struct_blob(out, mem_ctx, sid,
(ndr_push_flags_fn_t)ndr_push_dom_sid); (ndr_push_flags_fn_t)ndr_push_dom_sid);
talloc_free(sid); talloc_free(sid);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
@@ -51,12 +51,12 @@ static int ldif_read_objectSid(struct ldb_context *ldb, const struct ldb_val *in
/* /*
convert a NDR formatted blob to a ldif formatted objectSid convert a NDR formatted blob to a ldif formatted objectSid
*/ */
static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *in, static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
struct dom_sid *sid; struct dom_sid *sid;
NTSTATUS status; NTSTATUS status;
sid = talloc(ldb, struct dom_sid); sid = talloc(mem_ctx, struct dom_sid);
if (sid == NULL) { if (sid == NULL) {
return -1; return -1;
} }
@@ -66,7 +66,7 @@ static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *i
talloc_free(sid); talloc_free(sid);
return -1; return -1;
} }
out->data = dom_sid_string(ldb, sid); out->data = dom_sid_string(mem_ctx, sid);
talloc_free(sid); talloc_free(sid);
if (out->data == NULL) { if (out->data == NULL) {
return -1; return -1;
@@ -78,7 +78,7 @@ static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *i
/* /*
compare two objectSids compare two objectSids
*/ */
static int ldb_comparison_objectSid(struct ldb_context *ldb, static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2) const struct ldb_val *v1, const struct ldb_val *v2)
{ {
if (strncmp(v1->data, "S-", 2) == 0 && if (strncmp(v1->data, "S-", 2) == 0 &&
@@ -88,26 +88,26 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb,
if (strncmp(v1->data, "S-", 2) == 0) { if (strncmp(v1->data, "S-", 2) == 0) {
struct ldb_val v; struct ldb_val v;
int ret; int ret;
if (ldif_read_objectSid(ldb, v1, &v) != 0) { if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
return -1; return -1;
} }
ret = ldb_comparison_binary(ldb, &v, v2); ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
talloc_free(v.data); talloc_free(v.data);
return ret; return ret;
} }
return ldb_comparison_binary(ldb, v1, v2); return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
} }
/* /*
canonicalise a objectSid canonicalise a objectSid
*/ */
static int ldb_canonicalise_objectSid(struct ldb_context *ldb, const struct ldb_val *in, static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
if (strncmp(in->data, "S-", 2) == 0) { if (strncmp(in->data, "S-", 2) == 0) {
return ldif_read_objectSid(ldb, in, out); return ldif_read_objectSid(ldb, mem_ctx, in, out);
} }
return ldb_handler_copy(ldb, in, out); return ldb_handler_copy(ldb, mem_ctx, in, out);
} }

View File

@@ -2,7 +2,7 @@
echo "Running extended search tests" echo "Running extended search tests"
rm -f $LDB_URL mv $LDB_URL $LDB_URL.1
cat <<EOF | bin/ldbadd || exit 1 cat <<EOF | bin/ldbadd || exit 1
dn: cn=testrec1,cn=TEST dn: cn=testrec1,cn=TEST
@@ -67,4 +67,3 @@ checkcount 1 '(i1:1.2.840.113556.1.4.804:=8388608)'
# this is one that w2k gives # this is one that w2k gives
checkcount 3 '(|(|(&(!(groupType:1.2.840.113556.1.4.803:=1))(groupType:1.2.840.113556.1.4.803:=2147483648)(groupType:1.2.840.113556.1.4.804:=10))(samAccountType=805306368))(samAccountType=805306369))' checkcount 3 '(|(|(&(!(groupType:1.2.840.113556.1.4.803:=1))(groupType:1.2.840.113556.1.4.803:=2147483648)(groupType:1.2.840.113556.1.4.804:=10))(samAccountType=805306368))(samAccountType=805306369))'
rm -f $LDB_URL

View File

@@ -24,9 +24,17 @@ for f in $SCHEMA_NEEDED; do
fi fi
done done
tests/init_slapd.sh
tests/start_slapd.sh
export LDB_URL=`tests/ldapi_url.sh` export LDB_URL=`tests/ldapi_url.sh`
. tests/test-generic.sh PATH=bin:$PATH
export PATH
if [ -z "$LDBDIR" ]; then
LDBDIR="."
export LDBDIR
fi
. $LDBDIR/tests/init_slapd.sh
. $LDBDIR/tests/start_slapd.sh
. $LDBDIR/tests/test-generic.sh

View File

@@ -2,7 +2,7 @@
echo "Running tdb feature tests" echo "Running tdb feature tests"
rm -f $LDB_URL mv $LDB_URL $LDB_URL.2
checkcount() { checkcount() {
count=$1 count=$1
@@ -128,4 +128,3 @@ checkcount 1 '(test=foo)'
checkcount 0 '(test=FOO)' checkcount 0 '(test=FOO)'
checkcount 0 '(test=fo*)' checkcount 0 '(test=fo*)'
rm -f $LDB_URL

View File

@@ -7,6 +7,8 @@ PATH=bin:$PATH
export PATH export PATH
rm -f tdbtest.ldb rm -f tdbtest.ldb
rm -f tdbtest.ldb.1
rm -f tdbtest.ldb.2
if [ -z "$LDBDIR" ]; then if [ -z "$LDBDIR" ]; then
LDBDIR="." LDBDIR="."