mirror of
https://github.com/samba-team/samba.git
synced 2025-02-09 09:57:48 +03:00
r13324: From now on check attribute names obey rfc2251
Also add a way to provide utf8 compliant functions by registering them with ldb_set_utf8_fns() Next comes code to register samba internal utf8 functions. Simo.
This commit is contained in:
parent
c170079184
commit
ac9b8a41ff
@ -188,7 +188,7 @@ endif
|
||||
test: $(BINS) test-tdb test-ldap test-sqlite3 test-schema
|
||||
|
||||
install: all
|
||||
cp include/ldb.h $(includedir)
|
||||
cp include/ldb.h include/ldb_errors.h $(includedir)
|
||||
cp $(LDB_LIB) $(libdir)
|
||||
cp $(BINS) $(bindir)
|
||||
cp ldb.pc $(libdir)/pkgconfig
|
||||
|
@ -50,6 +50,8 @@ struct ldb_context *ldb_init(void *mem_ctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ldb_set_utf8_default(ldb);
|
||||
|
||||
return ldb;
|
||||
}
|
||||
|
||||
|
@ -55,23 +55,6 @@ int ldb_dn_check_special(const struct ldb_dn *dn, const char *check)
|
||||
return ! strcmp((char *)dn->components[0].value.data, check);
|
||||
}
|
||||
|
||||
static int ldb_dn_is_valid_attribute_name(const char *name)
|
||||
{
|
||||
if (name == NULL) return 0;
|
||||
|
||||
while (*name) {
|
||||
if (! isascii(*name)) {
|
||||
return 0;
|
||||
}
|
||||
if (! (isalnum((unsigned char)*name) || *name == '-')) {
|
||||
return 0;
|
||||
}
|
||||
name++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
|
||||
{
|
||||
const char *p, *s, *src;
|
||||
@ -301,7 +284,7 @@ static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw
|
||||
if (!dc.name)
|
||||
return dc;
|
||||
|
||||
if (! ldb_dn_is_valid_attribute_name(dc.name)) {
|
||||
if (! ldb_valid_attr_name(dc.name)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -519,7 +502,8 @@ int ldb_dn_compare_base(struct ldb_context *ldb,
|
||||
const struct ldb_attrib_handler *h;
|
||||
|
||||
/* compare names (attribute names are guaranteed to be ASCII only) */
|
||||
ret = ldb_caseless_cmp(base->components[n0].name,
|
||||
ret = ldb_caseless_cmp(ldb,
|
||||
base->components[n0].name,
|
||||
dn->components[n1].name);
|
||||
if (ret) {
|
||||
return ret;
|
||||
@ -598,7 +582,7 @@ struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn
|
||||
struct ldb_dn_component dc;
|
||||
const struct ldb_attrib_handler *h;
|
||||
|
||||
dc.name = ldb_casefold(cedn, edn->components[i].name);
|
||||
dc.name = ldb_casefold(ldb, cedn, edn->components[i].name);
|
||||
LDB_DN_NULL_FAILED(dc.name);
|
||||
|
||||
h = ldb_attrib_handler(ldb, dc.name);
|
||||
@ -761,7 +745,7 @@ struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
|
||||
const struct ldb_dn *base)
|
||||
{
|
||||
struct ldb_dn *new;
|
||||
if (! ldb_dn_is_valid_attribute_name(attr)) return NULL;
|
||||
if (! ldb_valid_attr_name(attr)) return NULL;
|
||||
if (value == NULL || value == '\0') return NULL;
|
||||
|
||||
if (base != NULL) {
|
||||
|
@ -498,40 +498,6 @@ void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
|
||||
talloc_free(ldif);
|
||||
}
|
||||
|
||||
/*
|
||||
add an empty element
|
||||
*/
|
||||
static int msg_add_empty(struct ldb_context *ldb,
|
||||
struct ldb_message *msg, const char *name, unsigned flags)
|
||||
{
|
||||
struct ldb_message_element *el2, *el;
|
||||
|
||||
el2 = talloc_realloc(msg, msg->elements,
|
||||
struct ldb_message_element, msg->num_elements+1);
|
||||
if (!el2) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg->elements = el2;
|
||||
|
||||
el = &msg->elements[msg->num_elements];
|
||||
|
||||
el->name = talloc_strdup(msg->elements, name);
|
||||
el->num_values = 0;
|
||||
el->values = NULL;
|
||||
el->flags = flags;
|
||||
|
||||
if (!el->name) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg->num_elements++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
read from a LDIF source, creating a ldb_message
|
||||
*/
|
||||
@ -630,7 +596,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
if (msg_add_empty(ldb, msg, (char *)value.data, flags) != 0) {
|
||||
if (ldb_msg_add_empty(msg, (char *)value.data, flags) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
continue;
|
||||
|
@ -123,6 +123,10 @@ int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
|
||||
{
|
||||
struct ldb_message_element *els;
|
||||
|
||||
if (! ldb_valid_attr_name(attr_name)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
els = talloc_realloc(msg, msg->elements,
|
||||
struct ldb_message_element, msg->num_elements+1);
|
||||
if (!els) {
|
||||
@ -135,6 +139,7 @@ int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
|
||||
els[msg->num_elements].flags = flags;
|
||||
els[msg->num_elements].name = talloc_strdup(els, attr_name);
|
||||
if (!els[msg->num_elements].name) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -35,11 +35,29 @@
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
|
||||
|
||||
/*
|
||||
TODO:
|
||||
a simple case folding function - will be replaced by a UTF8 aware function later
|
||||
this allow the user to pass in a caseless comparison
|
||||
function to handle utf8 caseless comparisons
|
||||
*/
|
||||
void ldb_set_utf8_fns(struct ldb_context *ldb,
|
||||
void *context,
|
||||
int (*cmp)(void *, const char *, const char *),
|
||||
char *(*casefold)(void *, void *, const char *))
|
||||
{
|
||||
if (context)
|
||||
ldb->utf8_fns.context = context;
|
||||
if (cmp)
|
||||
ldb->utf8_fns.caseless_cmp = cmp;
|
||||
if (casefold)
|
||||
ldb->utf8_fns.casefold = casefold;
|
||||
}
|
||||
|
||||
/*
|
||||
a simple case folding function
|
||||
NOTE: does not handle UTF8
|
||||
*/
|
||||
char *ldb_casefold(void *mem_ctx, const char *s)
|
||||
char *ldb_casefold_default(void *context, void *mem_ctx, const char *s)
|
||||
{
|
||||
int i;
|
||||
char *ret = talloc_strdup(mem_ctx, s);
|
||||
@ -55,20 +73,69 @@ char *ldb_casefold(void *mem_ctx, const char *s)
|
||||
|
||||
/*
|
||||
a caseless compare, optimised for 7 bit
|
||||
TODO: doesn't yet handle UTF8
|
||||
NOTE: doesn't handle UTF8
|
||||
*/
|
||||
int ldb_caseless_cmp(const char *s1, const char *s2)
|
||||
|
||||
int ldb_caseless_cmp_default(void *context, const char *s1, const char *s2)
|
||||
{
|
||||
return strcasecmp(s1, s2);
|
||||
return strcasecmp(s1,s2);
|
||||
}
|
||||
|
||||
void ldb_set_utf8_default(struct ldb_context *ldb)
|
||||
{
|
||||
ldb_set_utf8_fns(ldb, NULL, ldb_caseless_cmp_default, ldb_casefold_default);
|
||||
}
|
||||
|
||||
char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s)
|
||||
{
|
||||
return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s);
|
||||
}
|
||||
|
||||
int ldb_caseless_cmp(struct ldb_context *ldb, const char *s1, const char *s2)
|
||||
{
|
||||
return ldb->utf8_fns.caseless_cmp(ldb->utf8_fns.context, s1, s2);
|
||||
}
|
||||
|
||||
/*
|
||||
check the attribute name is valid according to rfc2251
|
||||
returns 1 if the name is ok
|
||||
*/
|
||||
|
||||
int ldb_valid_attr_name(const char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!s || !s[0])
|
||||
return 0;
|
||||
|
||||
/* handle special ldb_tdb wildcard */
|
||||
if (strcmp(s, "*") == 0) return 1;
|
||||
|
||||
for (i = 0; s[i]; i++) {
|
||||
if (! isascii(s[i])) {
|
||||
return 0;
|
||||
}
|
||||
if (i == 0) { /* first char must be an alpha (or our special '@' identifier) */
|
||||
if (! (isalpha(s[i]) || (s[i] == '@'))) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (! (isalnum(s[i]) || (s[i] == '-'))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
compare two attribute names
|
||||
attribute names are restricted by rfc2251 so using strcasecmp here is ok.
|
||||
return 0 for match
|
||||
*/
|
||||
int ldb_attr_cmp(const char *attr1, const char *attr2)
|
||||
{
|
||||
return ldb_caseless_cmp(attr1, attr2);
|
||||
return strcasecmp(attr1, attr2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -208,6 +208,16 @@ struct ldb_debug_ops {
|
||||
void *context;
|
||||
};
|
||||
|
||||
/**
|
||||
The user can optionally supply a custom utf8 functions,
|
||||
to handle comparisons and casefolding.
|
||||
*/
|
||||
struct ldb_utf8_fns {
|
||||
void *context;
|
||||
int (*caseless_cmp)(void *context, const char *s1, const char *s2);
|
||||
char *(*casefold)(void *context, void *mem_ctx, const char *s);
|
||||
};
|
||||
|
||||
/**
|
||||
Flag value for database connection mode.
|
||||
|
||||
@ -718,30 +728,48 @@ int ldb_transaction_cancel(struct ldb_context *ldb);
|
||||
*/
|
||||
const char *ldb_errstring(struct ldb_context *ldb);
|
||||
|
||||
/**
|
||||
setup the default utf8 functions
|
||||
FIXME: these functions do not yet handle utf8
|
||||
*/
|
||||
void ldb_set_utf8_default(struct ldb_context *ldb);
|
||||
|
||||
/**
|
||||
Casefold a string
|
||||
|
||||
\param ldb the ldb context
|
||||
\param mem_ctx the memory context to allocate the result string
|
||||
memory from.
|
||||
\param s the string that is to be folded
|
||||
\return a copy of the string, converted to upper case
|
||||
|
||||
\todo This function should be UTF8 aware, but currently is not.
|
||||
\note The default function is not yet UTF8 aware. Provide your own
|
||||
set of functions through ldb_set_utf8_fns()
|
||||
*/
|
||||
char *ldb_casefold(void *mem_ctx, const char *s);
|
||||
char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s);
|
||||
|
||||
/**
|
||||
Compare two strings, without regard to case.
|
||||
|
||||
\param ldb the ldb context
|
||||
\param s1 the first string to compare
|
||||
\param s2 the second string to compare
|
||||
|
||||
\return 0 if the strings are the same, non-zero if there are any
|
||||
differences except for case.
|
||||
|
||||
\note This function is not UTF8 aware.
|
||||
\note The default function is not yet UTF8 aware. Provide your own
|
||||
set of functions through ldb_set_utf8_fns()
|
||||
*/
|
||||
int ldb_caseless_cmp(const char *s1, const char *s2);
|
||||
int ldb_caseless_cmp(struct ldb_context *ldb, const char *s1, const char *s2);
|
||||
|
||||
/**
|
||||
Check the attribute name is valid according to rfc2251
|
||||
\param s tthe string to check
|
||||
|
||||
\return 1 if the name is ok
|
||||
*/
|
||||
int ldb_valid_attr_name(const char *s);
|
||||
|
||||
/*
|
||||
ldif manipulation functions
|
||||
|
@ -90,6 +90,9 @@ struct ldb_context {
|
||||
/* debugging operations */
|
||||
struct ldb_debug_ops debug_ops;
|
||||
|
||||
/* custom utf8 functions */
|
||||
struct ldb_utf8_fns utf8_fns;
|
||||
|
||||
/* backend specific opaque parameters */
|
||||
struct ldb_opaque {
|
||||
struct ldb_opaque *next;
|
||||
@ -191,4 +194,8 @@ int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
|
||||
struct ldb_control *get_control_from_list(struct ldb_control **controls, const char *oid);
|
||||
int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver);
|
||||
int check_critical_controls(struct ldb_control **controls);
|
||||
|
||||
/* The following definitions come from lib/ldb/common/ldb_utf8.c */
|
||||
char *ldb_casefold_default(void *context, void *mem_ctx, const char *s);
|
||||
int ldb_caseless_cmp_default(void *context, const char *s1, const char *s2);
|
||||
#endif
|
||||
|
@ -289,7 +289,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
|
||||
* For simple searches, we want to retrieve the list of EIDs that
|
||||
* match the criteria.
|
||||
*/
|
||||
attr = ldb_casefold(mem_ctx, t->u.equality.attr);
|
||||
attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
|
||||
if (attr == NULL) return NULL;
|
||||
h = ldb_attrib_handler(module->ldb, attr);
|
||||
|
||||
@ -353,7 +353,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
|
||||
wild_card_string[strlen(wild_card_string) - 1] = '\0';
|
||||
}
|
||||
|
||||
attr = ldb_casefold(mem_ctx, t->u.substring.attr);
|
||||
attr = ldb_casefold(module->ldb, mem_ctx, t->u.substring.attr);
|
||||
if (attr == NULL) return NULL;
|
||||
h = ldb_attrib_handler(module->ldb, attr);
|
||||
|
||||
@ -374,7 +374,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
|
||||
value.data);
|
||||
|
||||
case LDB_OP_GREATER:
|
||||
attr = ldb_casefold(mem_ctx, t->u.equality.attr);
|
||||
attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
|
||||
if (attr == NULL) return NULL;
|
||||
h = ldb_attrib_handler(module->ldb, attr);
|
||||
|
||||
@ -393,7 +393,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
|
||||
attr);
|
||||
|
||||
case LDB_OP_LESS:
|
||||
attr = ldb_casefold(mem_ctx, t->u.equality.attr);
|
||||
attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
|
||||
if (attr == NULL) return NULL;
|
||||
h = ldb_attrib_handler(module->ldb, attr);
|
||||
|
||||
@ -416,7 +416,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
|
||||
return talloc_strdup(mem_ctx, "SELECT eid FROM ldb_entry");
|
||||
}
|
||||
|
||||
attr = ldb_casefold(mem_ctx, t->u.present.attr);
|
||||
attr = ldb_casefold(module->ldb, mem_ctx, t->u.present.attr);
|
||||
if (attr == NULL) return NULL;
|
||||
|
||||
return lsqlite3_tprintf(mem_ctx,
|
||||
@ -425,7 +425,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
|
||||
attr);
|
||||
|
||||
case LDB_OP_APPROX:
|
||||
attr = ldb_casefold(mem_ctx, t->u.equality.attr);
|
||||
attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
|
||||
if (attr == NULL) return NULL;
|
||||
h = ldb_attrib_handler(module->ldb, attr);
|
||||
|
||||
@ -715,26 +715,8 @@ static int lsqlite3_search_callback(void *result, int col_num, char **cols, char
|
||||
if (!found) return 0;
|
||||
}
|
||||
|
||||
msg->elements = talloc_realloc(msg,
|
||||
msg->elements,
|
||||
struct ldb_message_element,
|
||||
msg->num_elements + 1);
|
||||
if (msg->elements == NULL) return SQLITE_ABORT;
|
||||
|
||||
msg->elements[msg->num_elements].flags = 0;
|
||||
msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, cols[2]);
|
||||
if (msg->elements[msg->num_elements].name == NULL) return SQLITE_ABORT;
|
||||
|
||||
msg->elements[msg->num_elements].num_values = 1;
|
||||
msg->elements[msg->num_elements].values = talloc_array(msg->elements,
|
||||
struct ldb_val, 1);
|
||||
if (msg->elements[msg->num_elements].values == NULL) return SQLITE_ABORT;
|
||||
|
||||
msg->elements[msg->num_elements].values[0].length = strlen(cols[3]);
|
||||
msg->elements[msg->num_elements].values[0].data = talloc_strdup(msg->elements, cols[3]);
|
||||
if (msg->elements[msg->num_elements].values[0].data == NULL) return SQLITE_ABORT;
|
||||
|
||||
msg->num_elements++;
|
||||
if (ldb_msg_add_string(msg, cols[2], cols[3]) != 0)
|
||||
return SQLITE_ABORT;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -1076,7 +1058,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
|
||||
int j;
|
||||
|
||||
/* Get a case-folded copy of the attribute name */
|
||||
attr = ldb_casefold(local_ctx, el->name);
|
||||
attr = ldb_casefold(module->ldb, local_ctx, el->name);
|
||||
if (attr == NULL) {
|
||||
ret = LDB_ERR_OTHER;
|
||||
goto failed;
|
||||
@ -1175,7 +1157,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
|
||||
int j;
|
||||
|
||||
/* Get a case-folded copy of the attribute name */
|
||||
attr = ldb_casefold(local_ctx, el->name);
|
||||
attr = ldb_casefold(module->ldb, local_ctx, el->name);
|
||||
if (attr == NULL) {
|
||||
ret = LDB_ERR_OTHER;
|
||||
goto failed;
|
||||
|
@ -106,7 +106,7 @@ static struct ldb_dn *ldb_dn_key(struct ldb_context *ldb,
|
||||
const struct ldb_attrib_handler *h;
|
||||
char *attr_folded;
|
||||
|
||||
attr_folded = ldb_casefold(ldb, attr);
|
||||
attr_folded = ldb_casefold(ldb, ldb, attr);
|
||||
if (!attr_folded) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ static void add_records(struct ldb_context *ldb,
|
||||
el[2].name = talloc_strdup(tmp_ctx, "uid");
|
||||
el[2].num_values = 1;
|
||||
el[2].values = vals[2];
|
||||
vals[2][0].data = (uint8_t *)ldb_casefold(tmp_ctx, name);
|
||||
vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name);
|
||||
vals[2][0].length = strlen((char *)vals[2][0].data);
|
||||
|
||||
el[3].flags = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user