From a6717fae681f89cf427e282d645029ca0b3e4d44 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 9 Jun 2005 02:47:26 +0000 Subject: r7418: work in progress (This used to be commit 2a13e7655b1bce88694ddbb6a4d9349008ba42f0) --- source4/lib/ldb/common/ldb_explode_dn.c | 218 ++++++++++++++++++++---------- source4/lib/ldb/common/ldb_utf8.c | 4 +- source4/lib/ldb/include/ldb.h | 2 +- source4/lib/ldb/include/ldb_explode_dn.h | 7 +- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 58 ++++---- 5 files changed, 187 insertions(+), 102 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index 4e71bc70d1..d3f278c776 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -30,82 +30,67 @@ } while(0) +/* + * Forward declarations + */ 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; -} + char * ret); 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; - } - } -} - + char *end); + + + +/* + * Public functions + */ + +/* + * ldb_explode_dn() + * + * Explode, normalize, and optionally case-fold a DN string. The result is a + * structure containing arrays of the constituent RDNs. + * + * Parameters: + * mem_ctx - + * talloc context on which all allocated memory is hung + * + * orig_dn - + * The distinguished name, in string format, to be exploded + * + * hUserData - + * Data handle provided by the caller, and passed back to the caller in + * the case_fold_attr_fn callback function. This handle is not otherwise + * used within this function. + * + * case_fold_attr_fn - + * Pointer to a callback function which will be called to determine if a + * particular attribute type (name) requires case-folding of its values. + * If this function pointer is non-null, then attribute names will always + * be case-folded. Additionally, the function pointed to by + * case_fold_attr_fn will be called with the data handle (hUserData) and + * an attribute name as its parameters, and should return TRUE or FALSE to + * indicate whether values of that attribute type should be case-folded. + * + * If case_fold_attr_fn is null, then neither attribute names nor + * attribute values will be case-folded. + * + * Returns: + * Upon success, an ldb_dn structure pointer is returned, containing the + * exploded DN. + * + * If memory could not be allocated or if the DN was improperly formatted, + * NULL is returned. + */ struct ldb_dn * -ldb_explode_dn(void *mem_ctx, - const char *orig_dn) +ldb_explode_dn(void * mem_ctx, + const char * orig_dn, + void * hUserData, + int (*case_fold_attr_fn)(void * hUserData, + char * attr)) { struct ldb_dn * dn; struct ldb_dn_component * component; @@ -222,6 +207,14 @@ ldb_explode_dn(void *mem_ctx, goto failed; } + /* attribute names are always case-folded */ + p = attribute->name; + if ((attribute->name = + ldb_casefold(attribute, p)) == NULL) { + goto failed; + } + talloc_free(p); + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "attribute name: [%s]\n", attribute->name); @@ -314,6 +307,19 @@ ldb_explode_dn(void *mem_ctx, goto failed; } + /* see if this attribute value needs case folding */ + if (case_fold_attr_fn != NULL && + (* case_fold_attr_fn)(hUserData, + attribute->name)) { + /* yup, case-fold it. */ + p = attribute->value; + if ((attribute->value = + ldb_casefold(attribute, p)) == NULL) { + goto failed; + } + talloc_free(p); + } + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "attribute value: [%s]\n", attribute->value); @@ -460,3 +466,77 @@ failed: ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn); return NULL; } + + +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; + } + } +} + diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 9cbb5646dd..dc25d6cf13 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -41,10 +41,10 @@ TODO: a simple case folding function - will be replaced by a UTF8 aware function later */ -char *ldb_casefold(struct ldb_context *ldb, const char *s) +char *ldb_casefold(void *mem_ctx, const char *s) { int i; - char *ret = talloc_strdup(ldb, s); + char *ret = talloc_strdup(mem_ctx, s); if (!s) { errno = ENOMEM; return NULL; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 8ccf8967cb..91a826447a 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -203,7 +203,7 @@ const char *ldb_errstring(struct ldb_context *ldb); /* casefold a string (should be UTF8, but at the moment it isn't) */ -char *ldb_casefold(struct ldb_context *ldb, const char *s); +char *ldb_casefold(void *mem_ctx, const char *s); /* ldif manipulation functions diff --git a/source4/lib/ldb/include/ldb_explode_dn.h b/source4/lib/ldb/include/ldb_explode_dn.h index 78768ebb80..af9829ba40 100644 --- a/source4/lib/ldb/include/ldb_explode_dn.h +++ b/source4/lib/ldb/include/ldb_explode_dn.h @@ -39,5 +39,8 @@ struct ldb_dn { extern struct ldb_dn * -ldb_explode_dn(void *mem_ctx, - const char *orig_dn); +ldb_explode_dn(void * mem_ctx, + const char * orig_dn, + void * hUserData, + int (*case_fold_attr_fn)(void * hUserData, + char * attr)); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 147ee599a9..4f774efbae 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -37,6 +37,7 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/include/ldb_parse.h" +#include "ldb/include/ldb_explode_dn.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" #ifndef FALSE @@ -172,9 +173,11 @@ lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, callback function used in call to ldb_dn_fold() for determining whether an attribute type requires case folding. */ -static int lsqlite3_case_fold_attr_required(struct ldb_module *module, - char *attr) +static int lsqlite3_case_fold_attr_required(void * hUserData, + char *attr) { +// struct ldb_module * module = hUserData; + #warning "currently, all attributes require case folding" return TRUE; } @@ -184,9 +187,9 @@ static int lsqlite3_case_fold_attr_required(struct ldb_module *module, * rename a record */ static int -lsqlite3_rename(struct ldb_module *module, - const char *olddn, - const char *newdn) +lsqlite3_rename(struct ldb_module * module, + const char * olddn, + const char * newdn) { /* ignore ltdb specials */ if (olddn[0] == '@' ||newdn[0] == '@') { @@ -478,7 +481,7 @@ lsqlite3_search(struct ldb_module * module, { int ret; int bLoop; - long long eid; + long long eid = 0; char * sql; char * sql_constraints; char * table_list; @@ -509,7 +512,7 @@ lsqlite3_search(struct ldb_module * module, pTail, -1, &pStmt, - &pTail)) != SQLITE_OK) { + NULL)) != SQLITE_OK) { ret = -1; break; } @@ -541,17 +544,24 @@ lsqlite3_search(struct ldb_module * module, * Normal condition is only one time through loop. Loop is * rerun in error conditions, via "continue", above. */ + sqlite3_free(discard_const_p(char, pTail)); ret = 0; bLoop = FALSE; } + if (ret != 0) { + sqlite3_free(discard_const_p(char, pTail)); + return -1; + } + /* Parse the filter expression into a tree we can work with */ if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { + sqlite3_free(discard_const_p(char, pTail)); return -1; } /* Allocate a temporary talloc context */ - hTalloc = talloc_new(module); + hTalloc = talloc_new(module->ldb); /* Move the parse tree to our temporary context */ talloc_steal(hTalloc, pTree); @@ -756,28 +766,20 @@ lsqlite3_new_dn(struct ldb_module * module, char * pDN, long long * pEID) { - char * pName; - char * pValue; - - /* Normalize the distinguished name */ - pDN = ldb_dn_fold(module, pDN, lsqlite3_case_fold_attr_required); - - /* Parse the DN into its constituent components */ -#warning "this simple parse of DN ignores escaped '=' and ','. fix it." - while (pDN != NULL) { - pName = strsep(&pValue, "="); - - if (pDN == NULL) { - /* Attribute name without value? Should not occur. */ - return -1; - } - - pValue = pName; - strsep(&pValue, "="); - -#warning "*** lsqlite3_new_dn() not yet fully implemented ***" + struct ldb_dn * pExplodedDN; + struct ldb_context * ldb = module->ldb; +// struct lsqlite3_private * lsqlite3 = module->private_data; + + /* Explode and normalize the DN */ + if ((pExplodedDN = + ldb_explode_dn(ldb, + pDN, + ldb, + lsqlite3_case_fold_attr_required)) == NULL) { + return -1; } +#warning "*** lsqlite3_new_dn() not yet fully implemented ***" return -1; } -- cgit