mirror of
https://github.com/samba-team/samba.git
synced 2025-01-12 09:18:10 +03:00
parent
322f0df3f1
commit
a6717fae68
@ -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);
|
||||
char *end);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
struct ldb_dn * pExplodedDN;
|
||||
struct ldb_context * ldb = module->ldb;
|
||||
// struct lsqlite3_private * lsqlite3 = module->private_data;
|
||||
|
||||
/* 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 ***"
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user