From 9539e2b508b3340b49575e5022c365ec382b2097 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Apr 2009 16:42:21 +1100 Subject: major upgrade to the ldb attribute handling This is all working towards supporting the full WSPP schema without a major performance penalty. We now use binary searches when looking up classes and attributes. We also avoid the loop loading the attributes into ldb, by adding a hook to override the ldb attribute search function in a module. The attributes can thus be loaded once, and then saved as part of the global schema. Also added support for a few more key attribute syntaxes, as needed for the full schema. --- source4/lib/ldb/common/attrib_handlers.c | 53 +++++++++++++++++++++++++++----- source4/lib/ldb/common/ldb_attributes.c | 21 +++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) (limited to 'source4/lib/ldb/common') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 80725ec04f..4869e3289c 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -105,7 +105,7 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, canonicalise a ldap Integer rfc2252 specifies it should be in decimal form */ -int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, +static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { char *end; @@ -124,12 +124,44 @@ int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, /* compare two Integers */ -int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx, +static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0); } +/* + canonicalise a ldap Boolean + rfc2252 specifies it should be either "TRUE" or "FALSE" +*/ +static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + if (strncasecmp((char *)in->data, "TRUE", in->length) == 0) { + out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE"); + out->length = 4; + } else if (strncasecmp((char *)in->data, "FALSE", in->length) == 0) { + out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE"); + out->length = 4; + } else { + return -1; + } + return 0; +} + +/* + compare two Booleans +*/ +static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) { + return v1->length - v2->length; + } + return strncasecmp((char *)v1->data, (char *)v2->data, v1->length); +} + + /* compare two binary blobs */ @@ -231,7 +263,7 @@ utf8str: /* canonicalise a attribute in DN format */ -int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, +static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { struct ldb_dn *dn; @@ -262,7 +294,7 @@ done: /* compare two dns */ -int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, +static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { struct ldb_dn *dn1 = NULL, *dn2 = NULL; @@ -287,7 +319,7 @@ int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, /* compare two utc time values. 1 second resolution */ -int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx, +static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { time_t t1, t2; @@ -299,7 +331,7 @@ int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx, /* canonicalise a utc time */ -int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx, +static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { time_t t = ldb_string_to_time((char *)in->data); @@ -356,7 +388,14 @@ static const struct ldb_schema_syntax ldb_standard_syntaxes[] = { .ldif_write_fn = ldb_handler_copy, .canonicalise_fn = ldb_canonicalise_utctime, .comparison_fn = ldb_comparison_utctime - } + }, + { + .name = LDB_SYNTAX_BOOLEAN, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_Boolean, + .comparison_fn = ldb_comparison_Boolean + }, }; diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c index 9fa0fb2ccd..cf45e8ef28 100644 --- a/source4/lib/ldb/common/ldb_attributes.c +++ b/source4/lib/ldb/common/ldb_attributes.c @@ -124,6 +124,16 @@ const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_conte int i, e, b = 0, r; const struct ldb_schema_attribute *def = &ldb_attribute_default; + if (ldb->schema.attribute_handler_override) { + const struct ldb_schema_attribute *ret = + ldb->schema.attribute_handler_override(ldb, + ldb->schema.attribute_handler_override_private, + name); + if (ret) { + return ret; + } + } + /* as handlers are sorted, '*' must be the first if present */ if (strcmp(ldb->schema.attributes[0].name, "*") == 0) { def = &ldb->schema.attributes[0]; @@ -273,3 +283,14 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c return NULL; } +/* + set an attribute handler override function - used to delegate schema handling + to external code + */ +void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb, + ldb_attribute_handler_override_fn_t override, + void *private_data) +{ + ldb->schema.attribute_handler_override_private = private_data; + ldb->schema.attribute_handler_override = override; +} -- cgit