1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00

r7408: added DN explode function, based on simo's ldap_parse_dn() function. simo, when you get a chance, please change your license so this can be linked with ldb.

This commit is contained in:
Derrell Lipman 2005-06-08 19:49:49 +00:00 committed by Gerald (Jerry) Carter
parent a7f7ec6cfe
commit 588a1d1451
4 changed files with 542 additions and 15 deletions

View File

@ -51,7 +51,8 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \
COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \
common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \
common/ldb_debug.o common/ldb_modules.o
common/ldb_debug.o common/ldb_modules.o \
common/ldb_explode_dn.o
MODULES_OBJ=modules/timestamps.o modules/schema.o

View File

@ -0,0 +1,461 @@
/*
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.
*/
#include "includes.h"
#include "ldb/include/ldb.h"
#include "ldb/include/ldb_explode_dn.h"
#define LDB_PARSE_DN_INVALID(x) do { \
if (x) { \
goto failed; \
} \
} while(0)
static char
octet_from_hex(char * p,
char * ret)
{
unsigned char low_char;
unsigned char high_char;
unsigned char low_binary;
unsigned char high_binary;
if (p[0] == '\0' || p[1] == '\0') {
return -1;
}
high_char = p[0];
low_char = p[1];
if (high_char >= '0' && high_char <= '9') {
high_binary = high_char - '0';
} else if (high_char >= 'A' && high_char <= 'F') {
high_binary = 10 + (high_char - 'A');
} else if (high_char >= 'a' && high_char <= 'f') {
high_binary = 10 + (high_char - 'a');
} else {
return -1;
}
if (low_char >= '0' && low_char <= '9') {
low_binary = low_char - '0';
} else if (low_char >= 'A' && low_char <= 'F') {
low_binary = 10 + (low_char - 'A');
} else if (low_char >= 'a' && low_char <= 'f') {
low_binary = 10 + (low_char - 'a');
} else {
return -1;
}
*ret = (char) ((high_binary << 4) | low_binary);
return 0;
}
static char *
parse_slash(char *p,
char *end)
{
switch (*(p + 1)) {
case ',':
case '=':
case '\n':
case '+':
case '<':
case '>':
case '#':
case ';':
case '\\':
case '"':
memmove(p, p + 1, end - (p + 1));
return (end - 1);
default:
if (*(p + 1) != '\0' && *(p + 2) != '\0') {
if (octet_from_hex(p + 1, p) < 0) {
return NULL;
}
memmove(p + 1, p + 3, end - (p + 3));
return (end - 2);
} else {
return NULL;
}
}
}
struct ldb_dn *
ldb_explode_dn(void *mem_ctx,
const char *orig_dn)
{
struct ldb_dn * dn;
struct ldb_dn_component * component;
struct ldb_dn_attribute * attribute;
char * p;
char * start;
char * separator;
char * src;
char * dest;
char * dn_copy;
char * dn_end;
int i;
int size;
int orig_len;
/* Allocate a structure to hold the exploded DN */
if ((dn = talloc(mem_ctx, struct ldb_dn)) == NULL) {
return NULL;
}
/* Initially there are no components */
dn->comp_num = 0;
/* Allocate the component array, with space for one component */
if ((dn->components =
talloc_array(dn, struct ldb_dn_component *, 1)) == NULL) {
goto failed;
}
/* Allocate the first component */
if ((component = talloc(dn, struct ldb_dn_component)) == NULL) {
goto failed;
}
/* This component has no attributes yet */
component->attr_num = 0;
/* Get the length of the provided DN */
if ((orig_len = strlen(orig_dn)) == 0) {
/* We found a zero-length DN. Return it. */
if ((dn->dn = talloc_strdup(dn, orig_dn)) == NULL) {
goto failed;
}
return dn;
}
/* Copy the provided DN so we can manipulate it */
if ((dn_copy = p = talloc_strdup(mem_ctx, orig_dn)) == NULL) {
goto failed;
}
/* Our copy may end shorter than the original as we unescape chars */
dn_end = dn_copy + orig_len + 1;
/* For each attribute/value pair... */
do {
/* Allocate an array to hold the attributes, initially len 1 */
if ((component->attributes =
talloc_array(component,
struct ldb_dn_attribute *, 1)) == NULL) {
goto failed;
}
/* Allocate this attribute */
if ((attribute =
talloc(component, struct ldb_dn_attribute)) == NULL) {
goto failed;
}
/* skip white space */
while (*p == ' ' || *p == '\n') {
p++;
}
/* start parsing this component */
do {
/* Save pointer to beginning of attribute name */
start = p;
/* find our attribute/value separator '=' */
while (*p != '\0' && *p != '=') {
if (*p == '\\') {
if ((dn_end =
parse_slash(p, dn_end)) == NULL) {
goto failed;
}
}
p++;
}
/* Ensure we found the attribute/value separator */
if (*p != '=') {
goto failed;
}
/* Save pointer to separator */
separator = p;
/* remove trailing white space from attribute name */
while (p > start &&
(*(p - 1) == ' ' || *(p - 1) == '\n')) {
p--;
}
LDB_PARSE_DN_INVALID((p - start) < 1);
/* save attribute name */
if ((attribute->name =
talloc_strndup(attribute,
start,
p - start)) == NULL) {
goto failed;
}
ldb_debug(mem_ctx,
LDB_DEBUG_TRACE,
"attribute name: [%s]\n", attribute->name);
/* skip white space after the separator */
p = separator + 1;
p += strspn(p, " \n");
/* ensure there's a value here */
if (*p == '\0') {
goto failed;
}
/* check if the value is enclosed in QUOTATION */
if (*p == '"') {
/* save pointer to beginning of attr value */
start = p + 1;
/* find the trailing QUOTE */
while (*p != '\0' && *p != '"') {
if (*p == '\\') {
if ((dn_end =
parse_slash(p, dn_end)) == NULL) {
goto failed;
}
}
p++;
}
/* skip spaces until the separator */
if (*p == '\0') {
/* We're already at end of string */
separator = p;
} else {
/* Skip spaces */
separator = p + 1 + strspn(p+1, " \n");
}
/* must be end of string or a separator here */
if (*separator != '\0' &&
*separator != ',' &&
*separator != ';' &&
*separator != '+') {
/* Error Malformed DN */
goto failed;
}
} else {
/*
* Value is not quouted.
*/
/* save pointer to beginning of value */
start = p;
/* find end of value */
while (*p != '\0' &&
*p != ',' &&
*p != ';' &&
*p != '+') {
if (*p == '\\') {
if ((dn_end =
parse_slash(p, dn_end)) == NULL) {
goto failed;
}
}
p++;
}
/* save pointer to the terminating separator */
separator = p;
/* remove trailing whitespace */
while (p > start &&
(*(p - 1) == ' ' ||
*(p - 1) == '\n')) {
p--;
}
}
LDB_PARSE_DN_INVALID((p - start) < 1);
/* save the value */
if ((attribute->value =
talloc_strndup(attribute,
start,
p - start)) == NULL) {
goto failed;
}
ldb_debug(mem_ctx,
LDB_DEBUG_TRACE,
"attribute value: [%s]\n", attribute->value);
/* save the entire RDN */
if ((attribute->rdn =
talloc_asprintf(attribute,
"%s=%s",
attribute->name,
attribute->value)) == NULL) {
goto failed;
}
ldb_debug(mem_ctx,
LDB_DEBUG_TRACE,
"attribute: [%s]\n", attribute->rdn);
/* add this attribute to the attribute list */
component->attributes[component->attr_num] = attribute;
component->attr_num++;
/* is this a multi-valued attribute? */
if (*separator == '+') {
/* Yup. prepare for the next value. */
if ((component->attributes =
talloc_realloc(component,
component->attributes,
struct ldb_dn_attribute *,
component->attr_num + 1)) == NULL) {
goto failed;
}
/* allocate new attribute structure */
if ((attribute =
talloc(component,
struct ldb_dn_attribute)) == NULL) {
goto failed;
}
}
/* if we're not at end of string, skip white space */
if (*separator != '\0') {
/* skip spaces past the separator */
p = separator + 1;
p += strspn(p, " \n");
}
} while (*separator == '+');
/* find total length of all attributes */
for (i = 0, size = 0; i < component->attr_num; i++) {
size += strlen(component->attributes[i]->rdn) + 1;
}
/*
* rebuild the normalized component
*/
/* allocate space for the normalized component */
if ((component->component =
dest = talloc_size(component, size)) == NULL) {
goto failed;
}
/* copy each of the attributes to the normalized component */
for (i = 0; i < component->attr_num; i++) {
if (i != 0) {
*dest = '+';
dest++;
}
src = component->attributes[i]->rdn;
do {
*(dest++) = *(src++);
} while(*src);
*dest = '\0';
}
ldb_debug(mem_ctx,
LDB_DEBUG_TRACE,
"component: [%s]\n", component->component);
/* insert the component into the component list */
dn->components[dn->comp_num] = component;
dn->comp_num++;
/* if there are additional components... */
if (*separator == ',' || *separator == ';') {
/* ... then prepare to parse them */
if ((dn->components =
talloc_realloc(dn,
dn->components,
struct ldb_dn_component *,
dn->comp_num + 1)) == NULL ||
(component =
talloc(dn, struct ldb_dn_component)) == NULL) {
goto failed;
}
component->attr_num = 0;
}
/* update pointer to after the separator */
p = separator + 1;
} while(*separator == ',' || *separator == ';');
/* find total length of all components */
for (i = 0, size = 0; i < dn->comp_num; i++) {
size = size + strlen(dn->components[i]->component) + 1;
}
/* rebuild the normalized DN */
if ((dn->dn = dest = talloc_size(dn, size)) == NULL) {
goto failed;
}
/* copy the normalized components into the DN */
for (i = 0; i < dn->comp_num; i++) {
if (i != 0) {
*dest = ',';
dest++;
}
src = dn->components[i]->component;
do {
*(dest++) = *(src++);
} while(*src);
*dest = '\0';
}
ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn);
/* we don't need the copy of the DN any more */
talloc_free(dn_copy);
/* give 'em what they came for! */
return dn;
failed:
/* something went wrong. free memory and tell 'em it failed */
talloc_free(dn);
ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn);
return NULL;
}

View File

@ -0,0 +1,38 @@
/*
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 * rdn;
char * name;
char * value;
};
struct ldb_dn_component {
char * component;
int attr_num;
struct ldb_dn_attribute ** attributes;
};
struct ldb_dn {
char *dn;
int comp_num;
struct ldb_dn_component ** components;
};

View File

@ -569,23 +569,52 @@ lsqlite3_search(struct ldb_module * module,
"SELECT entry.entry_data\n"
" FROM ldb_entry AS entry\n"
" WHERE entry.eid IN\n"
" (SELECT ldb_entry.eid\n"
" (SELECT DISTINCT ldb_entry.eid\n"
" FROM ldb_entry,\n"
" ldb_descendants,\n"
" %q\n"
" WHERE ldb_descendants.aeid = %lld\n"
" AND ldb_entry.eid = ldb_descendants.deid\n"
" AND ldap_entry.eid IN\n"
"%s);",
"%s"
");",
table_list,
eid,
sql_constraints);
break;
#warning "scope BASE and ONLEVEL not yet implemented"
case LDB_SCOPE_BASE:
sql = sqlite3_mprintf(
"SELECT entry.entry_data\n"
" FROM ldb_entry AS entry\n"
" WHERE entry.eid IN\n"
" (SELECT DISTINCT ldb_entry.eid\n"
" FROM %q\n"
" WHERE ldb_entry.eid = %lld\n"
" AND ldb_entry.eid IN\n"
"%s"
");",
table_list,
eid,
sql_constraints);
break;
case LDB_SCOPE_ONELEVEL:
sql = sqlite3_mprintf(
"SELECT entry.entry_data\n"
" FROM ldb_entry AS entry\n"
" WHERE entry.eid IN\n"
" (SELECT DISTINCT ldb_entry.eid\n"
" FROM ldb_entry AS pchild, "
" %q\n"
" WHERE ldb_entry.eid = pchild.eid "
" AND pchild.peid = %lld "
" AND ldb_entry.eid IN\n"
"%s"
");",
table_list,
eid,
sql_constraints);
break;
}
@ -599,9 +628,7 @@ lsqlite3_new_attr(struct ldb_module * module,
{
struct lsqlite3_private * lsqlite3 = module->private_data;
/* Get a case-folded copy of the attribute name */
pAttrName = ldb_casefold((struct ldb_context *) module, pAttrName);
/* NOTE: pAttrName is assumed to already be case-folded here! */
QUERY_NOROWS(lsqlite3,
FALSE,
"CREATE TABLE ldb_attr_%q "
@ -639,9 +666,13 @@ lsqlite3_msg_to_sql(struct ldb_module * module,
flags = el->flags & LDB_FLAG_MOD_MASK;
}
/* Get a case-folded copy of the attribute name */
pAttrName = ldb_casefold((struct ldb_context *) module,
el->name);
if (flags == LDB_FLAG_MOD_ADD) {
/* Create the attribute table if it doesn't exist */
if (lsqlite3_new_attr(module, el->name) != 0) {
if (lsqlite3_new_attr(module, pAttrName) != 0) {
return -1;
}
}
@ -649,10 +680,6 @@ lsqlite3_msg_to_sql(struct ldb_module * module,
/* For each value of the specified attribute name... */
for (j = 0; j < el->num_values; j++) {
/* Get a case-folded copy of the attribute name */
pAttrName = ldb_casefold((struct ldb_context *) module,
el->name);
/* ... bind the attribute value, if necessary */
switch (flags) {
case LDB_FLAG_MOD_ADD:
@ -725,7 +752,7 @@ lsqlite3_msg_to_sql(struct ldb_module * module,
static int
lsqlite3_new_dn(struct ldb_module *module,
lsqlite3_new_dn(struct ldb_module * module,
char * pDN,
long long * pEID)
{
@ -738,10 +765,10 @@ lsqlite3_new_dn(struct ldb_module *module,
/* Parse the DN into its constituent components */
#warning "this simple parse of DN ignores escaped '=' and ','. fix it."
while (pDN != NULL) {
pName = strsep(&pDN, ",");
pName = strsep(&pValue, "=");
if (pDN == NULL) {
/* Attribute name with value? Should not occur. */
/* Attribute name without value? Should not occur. */
return -1;
}