1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

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.
This commit is contained in:
Andrew Tridgell 2009-04-02 16:42:21 +11:00
parent 1bc9c39235
commit 9539e2b508
17 changed files with 432 additions and 154 deletions

View File

@ -91,6 +91,7 @@ struct dsdb_attribute {
/* internal stuff */
const struct dsdb_syntax *syntax;
const struct ldb_schema_attribute *ldb_schema_attribute;
};
struct dsdb_class {
@ -156,6 +157,21 @@ struct dsdb_schema {
struct dsdb_attribute *attributes;
struct dsdb_class *classes;
/* lists of classes sorted by various attributes, for faster
access */
uint32_t num_classes;
struct dsdb_class **classes_by_lDAPDisplayName;
struct dsdb_class **classes_by_governsID_id;
struct dsdb_class **classes_by_governsID_oid;
struct dsdb_class **classes_by_cn;
/* lists of attributes sorted by various fields */
uint32_t num_attributes;
struct dsdb_attribute **attributes_by_lDAPDisplayName;
struct dsdb_attribute **attributes_by_attributeID_id;
struct dsdb_attribute **attributes_by_attributeID_oid;
struct dsdb_attribute **attributes_by_linkID;
struct {
bool we_are_master;
struct ldb_dn *master_dn;

View File

@ -28,6 +28,7 @@
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "param/param.h"
#include "lib/ldb/include/ldb_module.h"
struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience)
{
@ -582,6 +583,48 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
return WERR_OK;
}
/*
setup the ldb_schema_attribute field for a dsdb_attribute
*/
static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
struct dsdb_attribute *attr)
{
const char *syntax = attr->syntax->ldb_syntax;
const struct ldb_schema_syntax *s;
struct ldb_schema_attribute *a;
if (!syntax) {
syntax = attr->syntax->ldap_oid;
}
s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName);
if (s == NULL) {
s = ldb_samba_syntax_by_name(ldb, syntax);
}
if (s == NULL) {
s = ldb_standard_syntax_by_name(ldb, syntax);
}
if (s == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute);
if (attr->ldb_schema_attribute == NULL) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
a->name = attr->lDAPDisplayName;
a->flags = 0;
a->syntax = s;
return LDB_SUCCESS;
}
#define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
(p)->elem = samdb_result_string(msg, attr, NULL);\
if (strict && (p)->elem == NULL) { \
@ -676,7 +719,8 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
}\
} while (0)
WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema,
WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb,
const struct dsdb_schema *schema,
struct ldb_message *msg,
TALLOC_CTX *mem_ctx,
struct dsdb_attribute *attr)
@ -745,6 +789,10 @@ WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema,
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
return WERR_OK;
}
@ -866,7 +914,7 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
return LDB_ERR_OPERATIONS_ERROR;
}
status = dsdb_attribute_from_ldb(schema, attrs_res->msgs[i], sa, sa);
status = dsdb_attribute_from_ldb(ldb, schema, attrs_res->msgs[i], sa, sa);
if (!W_ERROR_IS_OK(status)) {
*error_string = talloc_asprintf(mem_ctx,
"schema_fsmo_init: failed to load attribute definition: %s:%s",
@ -1274,7 +1322,8 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb
}\
} while (0)
WERROR dsdb_attribute_from_drsuapi(struct dsdb_schema *schema,
WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb,
struct dsdb_schema *schema,
struct drsuapi_DsReplicaObject *r,
TALLOC_CTX *mem_ctx,
struct dsdb_attribute *attr)
@ -1333,6 +1382,10 @@ WERROR dsdb_attribute_from_drsuapi(struct dsdb_schema *schema,
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
return WERR_OK;
}

View File

@ -23,10 +23,44 @@
#include "includes.h"
#include "dsdb/samdb/samdb.h"
/* a binary array search, where the array is an array of pointers to structures,
and we want to find a match for 'target' on 'field' in those structures.
Inputs:
array: base pointer to an array of structures
arrray_size: number of elements in the array
field: the name of the field in the structure we are keying off
target: the field value we are looking for
comparison_fn: the comparison function
result: where the result of the search is put
if the element is found, then 'result' is set to point to the found array element. If not,
then 'result' is set to NULL.
The array is assumed to be sorted by the same comparison_fn as the
search (with, for example, qsort)
*/
#define BINARY_ARRAY_SEARCH(array, array_size, field, target, comparison_fn, result) do { \
int32_t _b, _e; \
(result) = NULL; \
for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \
int32_t _i = (_b+_e)/2; \
int _r = comparison_fn(target, array[_i]->field); \
if (_r == 0) { (result) = array[_i]; break; } \
if (_r < 0) _e = _i - 1; else _b = _i + 1; \
} } while (0)
static int uint32_cmp(uint32_t c1, uint32_t c2)
{
return c1 - c2;
}
const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
uint32_t id)
{
struct dsdb_attribute *cur;
struct dsdb_attribute *c;
/*
* 0xFFFFFFFF is used as value when no mapping table is available,
@ -34,69 +68,49 @@ const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_
*/
if (id == 0xFFFFFFFF) return NULL;
/* TODO: add binary search */
for (cur = schema->attributes; cur; cur = cur->next) {
if (cur->attributeID_id != id) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->attributes_by_attributeID_id,
schema->num_attributes, attributeID_id, id, uint32_cmp, c);
return c;
}
const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
const char *oid)
{
struct dsdb_attribute *cur;
struct dsdb_attribute *c;
if (!oid) return NULL;
/* TODO: add binary search */
for (cur = schema->attributes; cur; cur = cur->next) {
if (strcmp(cur->attributeID_oid, oid) != 0) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->attributes_by_attributeID_oid,
schema->num_attributes, attributeID_oid, oid, strcasecmp, c);
return c;
}
const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
const char *name)
{
struct dsdb_attribute *cur;
struct dsdb_attribute *c;
if (!name) return NULL;
/* TODO: add binary search */
for (cur = schema->attributes; cur; cur = cur->next) {
if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->attributes_by_lDAPDisplayName,
schema->num_attributes, lDAPDisplayName, name, strcasecmp, c);
return c;
}
const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
int linkID)
{
struct dsdb_attribute *cur;
struct dsdb_attribute *c;
/* TODO: add binary search */
for (cur = schema->attributes; cur; cur = cur->next) {
if (cur->linkID != linkID) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->attributes_by_linkID,
schema->num_attributes, linkID, linkID, uint32_cmp, c);
return c;
}
const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
uint32_t id)
{
struct dsdb_class *cur;
struct dsdb_class *c;
/*
* 0xFFFFFFFF is used as value when no mapping table is available,
@ -104,65 +118,39 @@ const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *sc
*/
if (id == 0xFFFFFFFF) return NULL;
/* TODO: add binary search */
for (cur = schema->classes; cur; cur = cur->next) {
if (cur->governsID_id != id) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->classes_by_governsID_id,
schema->num_classes, governsID_id, id, uint32_cmp, c);
return c;
}
const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
const char *oid)
{
struct dsdb_class *cur;
struct dsdb_class *c;
if (!oid) return NULL;
/* TODO: add binary search */
for (cur = schema->classes; cur; cur = cur->next) {
if (strcmp(cur->governsID_oid, oid) != 0) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->classes_by_governsID_oid,
schema->num_classes, governsID_oid, oid, strcasecmp, c);
return c;
}
const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
const char *name)
{
struct dsdb_class *cur;
struct dsdb_class *c;
if (!name) return NULL;
/* TODO: add binary search */
for (cur = schema->classes; cur; cur = cur->next) {
if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->classes_by_lDAPDisplayName,
schema->num_classes, lDAPDisplayName, name, strcasecmp, c);
return c;
}
const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
const char *cn)
{
struct dsdb_class *cur;
struct dsdb_class *c;
if (!cn) return NULL;
/* TODO: add binary search */
for (cur = schema->classes; cur; cur = cur->next) {
if (strcasecmp(cur->cn, cn) != 0) continue;
return cur;
}
return NULL;
BINARY_ARRAY_SEARCH(schema->classes_by_cn,
schema->num_classes, cn, cn, strcasecmp, c);
return c;
}
const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
@ -171,7 +159,6 @@ const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
const struct dsdb_attribute *a;
const struct dsdb_class *c;
/* TODO: add binary search */
a = dsdb_attribute_by_attributeID_id(schema, id);
if (a) {
return a->lDAPDisplayName;

View File

@ -26,6 +26,21 @@
#include "lib/ldb/include/ldb_module.h"
#include "param/param.h"
/*
override the name to attribute handler function
*/
const struct ldb_schema_attribute *dsdb_attribute_handler_override(struct ldb_context *ldb,
void *private_data,
const char *name)
{
struct dsdb_schema *schema = talloc_get_type_abort(private_data, struct dsdb_schema);
const struct dsdb_attribute *a = dsdb_attribute_by_lDAPDisplayName(schema, name);
if (a == NULL) {
/* this will fall back to ldb internal handling */
return NULL;
}
return a->ldb_schema_attribute;
}
static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes)
{
@ -34,11 +49,19 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
struct ldb_result *res_idx;
struct dsdb_attribute *attr;
struct ldb_message *mod_msg;
TALLOC_CTX *mem_ctx = talloc_new(ldb);
TALLOC_CTX *mem_ctx;
struct ldb_message *msg;
struct ldb_message *msg_idx;
/* setup our own attribute name to schema handler */
ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema);
if (!write_attributes) {
talloc_free(mem_ctx);
return ret;
}
mem_ctx = talloc_new(ldb);
if (!mem_ctx) {
return LDB_ERR_OPERATIONS_ERROR;
}
@ -46,27 +69,27 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
msg = ldb_msg_new(mem_ctx);
if (!msg) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
goto op_error;
}
msg_idx = ldb_msg_new(mem_ctx);
if (!msg_idx) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
goto op_error;
}
msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES");
if (!msg->dn) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
goto op_error;
}
msg_idx->dn = ldb_dn_new(msg, ldb, "@INDEXLIST");
if (!msg_idx->dn) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
goto op_error;
}
for (attr = schema->attributes; attr; attr = attr->next) {
const struct ldb_schema_syntax *s;
const char *syntax = attr->syntax->ldb_syntax;
if (!syntax) {
syntax = attr->syntax->ldap_oid;
}
@ -87,33 +110,13 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
break;
}
}
if (!attr->syntax) {
continue;
}
ret = ldb_schema_attribute_add(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED,
syntax);
if (ret != LDB_SUCCESS) {
s = ldb_samba_syntax_by_name(ldb, attr->syntax->ldap_oid);
if (s) {
ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED, s);
} else {
ret = LDB_SUCCESS; /* Nothing to do here */
}
}
if (ret != LDB_SUCCESS) {
break;
}
}
if (!write_attributes || ret != LDB_SUCCESS) {
if (ret != LDB_SUCCESS) {
talloc_free(mem_ctx);
return ret;
}
/* Try to avoid churning the attributes too much - we only want to do this if they have changed */
ret = ldb_search(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg->dn));
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
@ -165,6 +168,146 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
}
talloc_free(mem_ctx);
return ret;
op_error:
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class **c1, struct dsdb_class **c2)
{
return strcasecmp((*c1)->lDAPDisplayName, (*c2)->lDAPDisplayName);
}
static int dsdb_compare_class_by_governsID_id(struct dsdb_class **c1, struct dsdb_class **c2)
{
return (*c1)->governsID_id - (*c2)->governsID_id;
}
static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2)
{
return strcasecmp((*c1)->governsID_oid, (*c2)->governsID_oid);
}
static int dsdb_compare_class_by_cn(struct dsdb_class **c1, struct dsdb_class **c2)
{
return strcasecmp((*c1)->cn, (*c2)->cn);
}
static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
return strcasecmp((*a1)->lDAPDisplayName, (*a2)->lDAPDisplayName);
}
static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
return (*a1)->attributeID_id - (*a2)->attributeID_id;
}
static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
return strcasecmp((*a1)->attributeID_oid, (*a2)->attributeID_oid);
}
static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
return (*a1)->linkID - (*a2)->linkID;
}
/*
create the sorted accessor arrays for the schema
*/
static int dsdb_setup_sorted_accessors(struct ldb_context *ldb,
struct dsdb_schema *schema)
{
struct dsdb_class *cur;
struct dsdb_attribute *a;
uint32_t i;
talloc_free(schema->classes_by_lDAPDisplayName);
talloc_free(schema->classes_by_governsID_id);
talloc_free(schema->classes_by_governsID_oid);
talloc_free(schema->classes_by_cn);
/* count the classes */
for (i=0, cur=schema->classes; cur; i++, cur=cur->next) /* noop */ ;
schema->num_classes = i;
/* setup classes_by_* */
schema->classes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_class *, i);
schema->classes_by_governsID_id = talloc_array(schema, struct dsdb_class *, i);
schema->classes_by_governsID_oid = talloc_array(schema, struct dsdb_class *, i);
schema->classes_by_cn = talloc_array(schema, struct dsdb_class *, i);
if (schema->classes_by_lDAPDisplayName == NULL ||
schema->classes_by_governsID_id == NULL ||
schema->classes_by_governsID_oid == NULL ||
schema->classes_by_cn == NULL) {
goto failed;
}
for (i=0, cur=schema->classes; cur; i++, cur=cur->next) {
schema->classes_by_lDAPDisplayName[i] = cur;
schema->classes_by_governsID_id[i] = cur;
schema->classes_by_governsID_oid[i] = cur;
schema->classes_by_cn[i] = cur;
}
/* sort the arrays */
qsort(schema->classes_by_lDAPDisplayName, schema->num_classes,
sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_lDAPDisplayName);
qsort(schema->classes_by_governsID_id, schema->num_classes,
sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_governsID_id);
qsort(schema->classes_by_governsID_oid, schema->num_classes,
sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_governsID_oid);
qsort(schema->classes_by_cn, schema->num_classes,
sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_cn);
/* now build the attribute accessor arrays */
talloc_free(schema->attributes_by_lDAPDisplayName);
talloc_free(schema->attributes_by_attributeID_id);
talloc_free(schema->attributes_by_attributeID_oid);
talloc_free(schema->attributes_by_linkID);
/* count the attributes */
for (i=0, a=schema->attributes; a; i++, a=a->next) /* noop */ ;
schema->num_attributes = i;
/* setup attributes_by_* */
schema->attributes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_attribute *, i);
schema->attributes_by_attributeID_id = talloc_array(schema, struct dsdb_attribute *, i);
schema->attributes_by_attributeID_oid = talloc_array(schema, struct dsdb_attribute *, i);
schema->attributes_by_linkID = talloc_array(schema, struct dsdb_attribute *, i);
if (schema->attributes_by_lDAPDisplayName == NULL ||
schema->attributes_by_attributeID_id == NULL ||
schema->attributes_by_attributeID_oid == NULL ||
schema->attributes_by_linkID == NULL) {
goto failed;
}
for (i=0, a=schema->attributes; a; i++, a=a->next) {
schema->attributes_by_lDAPDisplayName[i] = a;
schema->attributes_by_attributeID_id[i] = a;
schema->attributes_by_attributeID_oid[i] = a;
schema->attributes_by_linkID[i] = a;
}
/* sort the arrays */
qsort(schema->attributes_by_lDAPDisplayName, schema->num_attributes,
sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_lDAPDisplayName);
qsort(schema->attributes_by_attributeID_id, schema->num_attributes,
sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_attributeID_id);
qsort(schema->attributes_by_attributeID_oid, schema->num_attributes,
sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_attributeID_oid);
qsort(schema->attributes_by_linkID, schema->num_attributes,
sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_linkID);
return LDB_SUCCESS;
failed:
schema->classes_by_lDAPDisplayName = NULL;
schema->classes_by_governsID_id = NULL;
schema->classes_by_governsID_oid = NULL;
schema->classes_by_cn = NULL;
schema->attributes_by_lDAPDisplayName = NULL;
schema->attributes_by_attributeID_id = NULL;
schema->attributes_by_attributeID_oid = NULL;
schema->attributes_by_linkID = NULL;
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
@ -177,6 +320,11 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
{
int ret;
ret = dsdb_setup_sorted_accessors(ldb, schema);
if (ret != LDB_SUCCESS) {
return ret;
}
ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
if (ret != LDB_SUCCESS) {
return ret;
@ -207,6 +355,7 @@ int dsdb_set_global_schema(struct ldb_context *ldb)
if (!global_schema) {
return LDB_SUCCESS;
}
ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
if (ret != LDB_SUCCESS) {
return ret;
@ -367,7 +516,7 @@ WERROR dsdb_attach_schema_from_ldif(struct ldb_context *ldb, const char *pf, con
goto nomem;
}
status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
status = dsdb_attribute_from_ldb(ldb, schema, msg, sa, sa);
if (!W_ERROR_IS_OK(status)) {
goto failed;
}

View File

@ -1227,7 +1227,7 @@ static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context
static const struct dsdb_syntax dsdb_syntaxes[] = {
{
.name = "Boolean",
.ldap_oid = "1.3.6.1.4.1.1466.115.121.1.7",
.ldap_oid = LDB_SYNTAX_BOOLEAN,
.oMSyntax = 1,
.attributeSyntax_oid = "2.5.5.8",
.drsuapi_to_ldb = dsdb_syntax_BOOL_drsuapi_to_ldb,
@ -1289,7 +1289,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
.ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
.equality = "numericStringMatch",
.substring = "numericStringSubstringsMatch",
.comment = "Numeric String"
.comment = "Numeric String",
.ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
},{
.name = "String(Printable)",
.ldap_oid = "1.3.6.1.4.1.1466.115.121.1.44",
@ -1297,6 +1298,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
.attributeSyntax_oid = "2.5.5.5",
.drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
.ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
.ldb_syntax = LDB_SYNTAX_OCTET_STRING,
},{
.name = "String(Teletex)",
.ldap_oid = "1.2.840.113556.1.4.905",
@ -1316,7 +1318,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
.drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
.ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
.equality = "caseExactIA5Match",
.comment = "Printable String"
.comment = "Printable String",
.ldb_syntax = LDB_SYNTAX_OCTET_STRING,
},{
.name = "String(UTC-Time)",
.ldap_oid = "1.3.6.1.4.1.1466.115.121.1.53",
@ -1423,7 +1426,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
.attributeSyntax_oid = "2.5.5.13",
.drsuapi_to_ldb = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
.ldb_to_drsuapi = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
.comment = "Presentation Address"
.comment = "Presentation Address",
.ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
},{
/* not used in w2k3 schema */
.name = "Object(Access-Point)",
@ -1433,6 +1437,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
.attributeSyntax_oid = "2.5.5.14",
.drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
.ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
.ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
},{
/* not used in w2k3 schema */
.name = "Object(DN-String)",

View File

@ -729,6 +729,20 @@ const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb
return s;
}
const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
{
uint32_t j;
const struct ldb_schema_syntax *s = NULL;
for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
if (strcmp(samba_attributes[j].name, name) == 0) {
s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
break;
}
}
return s;
}
/*
register the samba ldif handlers

View File

@ -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
},
};

View File

@ -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;
}

View File

@ -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

View File

@ -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 <a href="http://www.ietf.org/rfc/rfc2252.txt">RFC 2252</a>, 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

View File

@ -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 db_handler_fold( struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out);
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,
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,
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);

View File

@ -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);

View File

@ -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;

View File

@ -243,7 +243,7 @@ static NTSTATUS vampire_apply_schema(struct vampire_state *s,
sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
NT_STATUS_HAVE_NO_MEMORY(sa);
status = dsdb_attribute_from_drsuapi(s->self_made_schema, &cur->object, s, sa);
status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}

View File

@ -2,5 +2,5 @@
# if we use the ones installed in the system.
define(TDB_MIN_VERSION,1.1.4)
define(TALLOC_MIN_VERSION,1.3.0)
define(LDB_REQUIRED_VERSION,0.9.4)
define(LDB_REQUIRED_VERSION,0.9.5)
define(TEVENT_REQUIRED_VERSION,0.9.5)

View File

@ -223,7 +223,7 @@ static int test_add_attribute(void *ptr, struct ldb_context *ldb, struct ldb_mes
goto failed;
}
status = dsdb_attribute_from_ldb(schema, msg, attr, attr);
status = dsdb_attribute_from_ldb(ldb, schema, msg, attr, attr);
if (!W_ERROR_IS_OK(status)) {
goto failed;
}

View File

@ -231,7 +231,7 @@ static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
NT_STATUS_HAVE_NO_MEMORY(sa);
status = dsdb_attribute_from_drsuapi(s->self_made_schema, &cur->object, s, sa);
status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}