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 +++++++++++++ source4/lib/ldb/configure.ac | 2 +- source4/lib/ldb/include/ldb.h | 9 ++++++ source4/lib/ldb/include/ldb_handlers.h | 29 ++--------------- source4/lib/ldb/include/ldb_module.h | 7 +++++ source4/lib/ldb/include/ldb_private.h | 3 ++ 7 files changed, 89 insertions(+), 35 deletions(-) (limited to 'source4/lib/ldb') 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; +} diff --git a/source4/lib/ldb/configure.ac b/source4/lib/ldb/configure.ac index b98cc88537..3e1a96018b 100644 --- a/source4/lib/ldb/configure.ac +++ b/source4/lib/ldb/configure.ac @@ -11,7 +11,7 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_DEFUN([SMB_EXT_LIB], [echo -n ""]) AC_DEFUN([SMB_ENABLE], [echo -n ""]) -AC_INIT(ldb, 0.9.4) +AC_INIT(ldb, 0.9.5) AC_CONFIG_SRCDIR([common/ldb.c]) AC_LIBREPLACE_ALL_CHECKS diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index be41151409..1b6b41aa43 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -402,6 +402,15 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c */ #define LDB_SYNTAX_INTEGER "1.3.6.1.4.1.1466.115.121.1.27" +/** + LDAP attribute syntax for a boolean + + This is the well-known LDAP attribute syntax for a boolean. + + See RFC 2252, Section 4.3.2 +*/ +#define LDB_SYNTAX_BOOLEAN "1.3.6.1.4.1.1466.115.121.1.7" + /** LDAP attribute syntax for an octet string diff --git a/source4/lib/ldb/include/ldb_handlers.h b/source4/lib/ldb/include/ldb_handlers.h index e1c14e679b..21fbcc33f8 100644 --- a/source4/lib/ldb/include/ldb_handlers.h +++ b/source4/lib/ldb/include/ldb_handlers.h @@ -31,37 +31,12 @@ * Author: Simo Sorce */ - int ldb_handler_copy( struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out); - -int ldb_handler_fold( struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out); - -int ldb_canonicalise_Integer( struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out); - -int ldb_comparison_Integer( struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2); - int ldb_comparison_binary( struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2); - -int ldb_comparison_fold( struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2); - -int ldb_canonicalise_dn( struct ldb_context *ldb, void *mem_ctx, +int db_handler_fold( struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out); - -int ldb_comparison_dn( struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2); - -int ldb_comparison_objectclass( struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2); - -int ldb_comparison_utctime( struct ldb_context *ldb, void *mem_ctx, +int ldb_comparison_fold( struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2); -int ldb_canonicalise_utctime( struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out); - diff --git a/source4/lib/ldb/include/ldb_module.h b/source4/lib/ldb/include/ldb_module.h index e07fd43e27..d9950d6649 100644 --- a/source4/lib/ldb/include/ldb_module.h +++ b/source4/lib/ldb/include/ldb_module.h @@ -89,6 +89,13 @@ int ldb_schema_attribute_add(struct ldb_context *ldb, const char *syntax); void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name); +/* we allow external code to override the name -> schema_attribute function */ +typedef const struct ldb_schema_attribute *(*ldb_attribute_handler_override_fn_t)(struct ldb_context *, void *, const char *); + +void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb, + ldb_attribute_handler_override_fn_t override, + void *private_data); + /* The following definitions come from lib/ldb/common/ldb_controls.c */ 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); diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 2e8da9941c..6946ca2182 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -65,6 +65,9 @@ struct ldb_module { schema related information needed for matching rules */ struct ldb_schema { + void *attribute_handler_override_private; + ldb_attribute_handler_override_fn_t attribute_handler_override; + /* attribute handling table */ unsigned num_attributes; struct ldb_schema_attribute *attributes; -- cgit