X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Funique.c;h=54414823f9e440484690bbc1da9454b22b8f54a0;hb=2317211a8f7b1a50862bd16c29d208b62fbb387b;hp=d1df4dbb3ea234acc71bd6bafd7cf6b16cc9c827;hpb=44e920962914bb3ca73ace6b1f222f399497f97d;p=openldap diff --git a/servers/slapd/overlays/unique.c b/servers/slapd/overlays/unique.c index d1df4dbb3e..54414823f9 100644 --- a/servers/slapd/overlays/unique.c +++ b/servers/slapd/overlays/unique.c @@ -2,8 +2,8 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2005 The OpenLDAP Foundation. - * Portions Copyright 2004 Symas Corporation. + * Copyright 2004-2008 The OpenLDAP Foundation. + * Portions Copyright 2004,2006-2007 Symas Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -14,9 +14,11 @@ * top-level directory of the distribution or, alternatively, at * . */ -/* ACKNOWLEDGEMENTS: - * This work was initially developed by Symas Corp. for inclusion in - * OpenLDAP Software. This work was sponsored by Hewlett-Packard. +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Symas Corporation for + * inclusion in OpenLDAP Software, with subsequent enhancements by + * Matthew Backes at Symas Corporation. This work was sponsored by + * Hewlett-Packard. */ #include "portable.h" @@ -29,20 +31,38 @@ #include #include "slap.h" +#include "config.h" + +#define UNIQUE_DEFAULT_URI ("ldap:///??sub") static slap_overinst unique; typedef struct unique_attrs_s { - struct unique_attrs_s *next; /* list of attrs */ + struct unique_attrs_s *next; /* list of attrs */ AttributeDescription *attr; } unique_attrs; +typedef struct unique_domain_uri_s { + struct unique_domain_uri_s *next; + struct berval *dn; + struct berval *ndn; + struct berval *filter; + struct unique_attrs_s *attrs; + int scope; +} unique_domain_uri; + +typedef struct unique_domain_s { + struct unique_domain_s *next; + struct berval *domain_spec; + struct unique_domain_uri_s *uri; + char ignore; /* polarity of attributes */ + char strict; /* null considered unique too */ +} unique_domain; + typedef struct unique_data_s { - const char *message; /* breadcrumbs */ - struct unique_attrs_s *attrs; /* list of known attrs */ - struct unique_attrs_s *ignore; /* list of ignored attrs */ - BerValue dn; /* base of "unique tree" */ - char strict; /* null considered unique too */ + struct unique_domain_s *domains; + struct unique_domain_s *legacy; + char legacy_strict_set; } unique_data; typedef struct unique_counter_s { @@ -50,174 +70,754 @@ typedef struct unique_counter_s { int count; } unique_counter; -/* -** allocate new unique_data; -** initialize, copy basedn; -** store in on_bi.bi_private; -** -*/ +enum { + UNIQUE_BASE = 1, + UNIQUE_IGNORE, + UNIQUE_ATTR, + UNIQUE_STRICT, + UNIQUE_URI +}; + +static ConfigDriver unique_cf_base; +static ConfigDriver unique_cf_attrs; +static ConfigDriver unique_cf_strict; +static ConfigDriver unique_cf_uri; + +static ConfigTable uniquecfg[] = { + { "unique_base", "basedn", 2, 2, 0, ARG_DN|ARG_MAGIC|UNIQUE_BASE, + unique_cf_base, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' " + "DESC 'Subtree for uniqueness searches' " + "EQUALITY distinguishedNameMatch " + "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, + { "unique_ignore", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_IGNORE, + unique_cf_attrs, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' " + "DESC 'Attributes for which uniqueness shall not be enforced' " + "EQUALITY caseIgnoreMatch " + "ORDERING caseIgnoreOrderingMatch " + "SUBSTR caseIgnoreSubstringsMatch " + "SYNTAX OMsDirectoryString )", NULL, NULL }, + { "unique_attributes", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_ATTR, + unique_cf_attrs, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' " + "DESC 'Attributes for which uniqueness shall be enforced' " + "EQUALITY caseIgnoreMatch " + "ORDERING caseIgnoreOrderingMatch " + "SUBSTR caseIgnoreSubstringsMatch " + "SYNTAX OMsDirectoryString )", NULL, NULL }, + { "unique_strict", "on|off", 1, 2, 0, ARG_MAGIC|UNIQUE_STRICT, + unique_cf_strict, "( OLcfgOvAt:10.4 NAME 'olcUniqueStrict' " + "DESC 'Enforce uniqueness of null values' " + "EQUALITY booleanMatch " + "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, + { "unique_uri", "ldapuri", 2, 3, 0, ARG_MAGIC|UNIQUE_URI, + unique_cf_uri, "( OLcfgOvAt:10.5 NAME 'olcUniqueURI' " + "DESC 'List of keywords and LDAP URIs for a uniqueness domain' " + "EQUALITY caseExactMatch " + "ORDERING caseExactOrderingMatch " + "SUBSTR caseExactSubstringsMatch " + "SYNTAX OMsDirectoryString )", NULL, NULL }, + { NULL, NULL, 0, 0, 0, ARG_IGNORED } +}; + +static ConfigOCs uniqueocs[] = { + { "( OLcfgOvOc:10.1 " + "NAME 'olcUniqueConfig' " + "DESC 'Attribute value uniqueness configuration' " + "SUP olcOverlayConfig " + "MAY ( olcUniqueBase $ olcUniqueIgnore $ " + "olcUniqueAttribute $ olcUniqueStrict $ " + "olcUniqueURI ) )", + Cft_Overlay, uniquecfg }, + { NULL, 0, NULL } +}; + +static void +unique_free_domain_uri ( unique_domain_uri *uri ) +{ + unique_domain_uri *next_uri = NULL; + unique_attrs *attr, *next_attr = NULL; + + while ( uri ) { + next_uri = uri->next; + ber_bvfree ( uri->dn ); + ber_bvfree ( uri->ndn ); + ber_bvfree ( uri->filter ); + attr = uri->attrs; + while ( attr ) { + next_attr = attr->next; + ch_free (attr); + attr = next_attr; + } + ch_free ( uri ); + uri = next_uri; + } +} -static int unique_db_init( - BackendDB *be -) +/* free an entire stack of domains */ +static void +unique_free_domain ( unique_domain *domain ) { - slap_overinst *on = (slap_overinst *)be->bd_info; - unique_data *ud = ch_malloc(sizeof(unique_data)); + unique_domain *next_domain = NULL; + + while ( domain ) { + next_domain = domain->next; + ber_bvfree ( domain->domain_spec ); + unique_free_domain_uri ( domain->uri ); + ch_free ( domain ); + domain = next_domain; + } +} - /* Debug(LDAP_DEBUG_TRACE, "==> unique_init\n", 0, 0, 0); */ +static int +unique_new_domain_uri ( unique_domain_uri **urip, + const LDAPURLDesc *url_desc, + ConfigArgs *c ) +{ + int i, rc = LDAP_SUCCESS; + unique_domain_uri *uri; + struct berval bv = {0, NULL}; + BackendDB *be = (BackendDB *)c->be; + char ** attr_str; + AttributeDescription * ad; + const char * text; + + uri = ch_calloc ( 1, sizeof ( unique_domain_uri ) ); + + if ( url_desc->lud_dn && url_desc->lud_dn[0] ) { + ber_str2bv( url_desc->lud_dn, 0, 1, &bv ); + rc = dnPrettyNormal( NULL, + &bv, + uri->dn, + uri->ndn, + NULL ); + if ( rc != LDAP_SUCCESS ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "<%s> invalid DN %d (%s)", + url_desc->lud_dn, rc, ldap_err2string( rc )); + rc = ARG_BAD_CONF; + goto exit; + } - ud->message = "_init"; - ud->attrs = NULL; - ud->ignore = NULL; - ud->strict = 0; + if ( !dnIsSuffix ( uri->ndn, &be->be_nsuffix[0] ) ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "dn <%s> is not a suffix of backend base dn <%s>", + uri->dn->bv_val, + be->be_nsuffix[0].bv_val ); + rc = ARG_BAD_CONF; + goto exit; + } + } - /* default to the base of our configured database */ - ber_dupbv(&ud->dn, &be->be_nsuffix[0]); - on->on_bi.bi_private = ud; + attr_str = url_desc->lud_attrs; + if ( attr_str ) { + for ( i=0; attr_str[i]; ++i ) { + unique_attrs * attr; + ad = NULL; + if ( slap_str2ad ( attr_str[i], &ad, &text ) + == LDAP_SUCCESS) { + attr = ch_calloc ( 1, + sizeof ( unique_attrs ) ); + attr->attr = ad; + attr->next = uri->attrs; + uri->attrs = attr; + } else { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "unique: attribute: %s: %s", + attr_str[i], text ); + rc = ARG_BAD_CONF; + goto exit; + } + } + } - return 0; + uri->scope = url_desc->lud_scope; + if ( !uri->scope ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "unique: uri with base scope will always be unique"); + rc = ARG_BAD_CONF; + goto exit; + } + + if (url_desc->lud_filter) { + Filter * f; + uri->filter = ber_str2bv( url_desc->lud_filter, 0, 1, NULL); + f = str2filter( uri->filter->bv_val ); + if ( !f ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "unique: bad filter"); + rc = ARG_BAD_CONF; + goto exit; + } + filter_free( f ); + } +exit: + if ( bv.bv_val ) ber_memfree ( bv.bv_val ); + uri->next = *urip; + *urip = uri; + if ( rc ) { + Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + unique_free_domain_uri ( uri ); + *urip = NULL; + } + return rc; } +static int +unique_new_domain_uri_basic ( unique_domain_uri **urip, + ConfigArgs *c ) +{ + LDAPURLDesc *url_desc = NULL; + int rc; -/* -** if command = attributes: -** foreach argument: -** convert to attribute; -** add to configured attribute list; -** elseif command = base: -** set our basedn to argument; -** else complain about invalid directive; -** -*/ + rc = ldap_url_parse ( UNIQUE_DEFAULT_URI, &url_desc ); + if ( rc ) return rc; + rc = unique_new_domain_uri ( urip, url_desc, c ); + ldap_free_urldesc ( url_desc ); + return rc; +} -static int unique_config( - BackendDB *be, - const char *fname, - int lineno, - int argc, - char **argv -) +/* if *domain is non-null, it's pushed down the stack. + * note that the entire stack is freed if there is an error, + * so build added domains in a separate stack before adding them + * + * domain_specs look like + * + * [strict ][ignore ]uri[[ uri]...] + * e.g. "ldap:///ou=foo,o=bar?uid?sub ldap:///ou=baz,o=bar?uid?sub" + * "strict ldap:///ou=accounts,o=bar?uid,uidNumber?one" + * etc + * + * so finally strictness is per-domain + * but so is ignore-state, and that would be better as a per-url thing + */ +static int +unique_new_domain ( unique_domain **domainp, + char *domain_spec, + ConfigArgs *c ) +{ + char *uri_start; + int rc = LDAP_SUCCESS; + int uri_err = 0; + unique_domain * domain; + LDAPURLDesc *url_desc, *url_descs = NULL; + + Debug(LDAP_DEBUG_TRACE, "==> unique_new_domain <%s>\n", + domain_spec, 0, 0); + + domain = ch_calloc ( 1, sizeof (unique_domain) ); + domain->domain_spec = ber_str2bv( domain_spec, 0, 1, NULL ); + + uri_start = domain_spec; + if ( strncasecmp ( uri_start, "ignore ", + STRLENOF( "ignore " ) ) == 0 ) { + domain->ignore = 1; + uri_start += STRLENOF( "ignore " ); + } + if ( strncasecmp ( uri_start, "strict ", + STRLENOF( "strict " ) ) == 0 ) { + domain->strict = 1; + uri_start += STRLENOF( "strict " ); + if ( !domain->ignore + && strncasecmp ( uri_start, "ignore ", + STRLENOF( "ignore " ) ) == 0 ) { + domain->ignore = 1; + uri_start += STRLENOF( "ignore " ); + } + } + rc = ldap_url_parselist_ext ( &url_descs, uri_start, " ", 0 ); + if ( rc ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "<%s> invalid ldap urilist", + uri_start ); + rc = ARG_BAD_CONF; + goto exit; + } + + for ( url_desc = url_descs; + url_desc; + url_desc = url_descs->lud_next ) { + rc = unique_new_domain_uri ( &domain->uri, + url_desc, + c ); + if ( rc ) { + rc = ARG_BAD_CONF; + uri_err = 1; + goto exit; + } + } + +exit: + if ( url_descs ) ldap_free_urldesc ( url_descs ); + domain->next = *domainp; + *domainp = domain; + if ( rc ) { + Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + unique_free_domain ( domain ); + *domainp = NULL; + } + return rc; +} + +static int +unique_cf_base( ConfigArgs *c ) { - slap_overinst *on = (slap_overinst *) be->bd_info; - unique_data *ud = on->on_bi.bi_private; - unique_attrs *up; - const char *text; - AttributeDescription *ad; + BackendDB *be = (BackendDB *)c->be; + slap_overinst *on = (slap_overinst *)c->bi; + unique_data *private = (unique_data *) on->on_bi.bi_private; + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + int rc = ARG_BAD_CONF; + + switch ( c->op ) { + case SLAP_CONFIG_EMIT: + rc = 0; + if ( legacy && legacy->uri && legacy->uri->dn ) { + rc = value_add_one ( &c->rvalue_vals, + legacy->uri->dn ); + if ( rc ) return rc; + rc = value_add_one ( &c->rvalue_nvals, + legacy->uri->ndn ); + if ( rc ) return rc; + } + break; + case LDAP_MOD_DELETE: + assert ( legacy && legacy->uri && legacy->uri->dn ); + rc = 0; + ber_bvfree ( legacy->uri->dn ); + ber_bvfree ( legacy->uri->ndn ); + legacy->uri->dn = NULL; + legacy->uri->ndn = NULL; + if ( !legacy->uri->attrs + && !legacy->uri->dn ) { + unique_free_domain_uri ( legacy->uri ); + legacy->uri = NULL; + } + if ( !legacy->uri && !private->legacy_strict_set ) { + unique_free_domain ( legacy ); + private->legacy = legacy = NULL; + } + break; + case LDAP_MOD_ADD: + case SLAP_CONFIG_ADD: + if ( domains ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot set legacy attrs when URIs are present" ); + Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", + c->cr_msg, NULL, NULL ); + rc = ARG_BAD_CONF; + break; + } + if ( !dnIsSuffix ( &c->value_ndn, + &be->be_nsuffix[0] ) ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "dn is not a suffix of backend base" ); + Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", + c->cr_msg, NULL, NULL ); + rc = ARG_BAD_CONF; + break; + } + if ( !legacy ) { + unique_new_domain ( &private->legacy, + UNIQUE_DEFAULT_URI, + c ); + legacy = private->legacy; + } + if ( !legacy->uri ) + unique_new_domain_uri_basic ( &legacy->uri, c ); + ber_bvfree ( legacy->uri->dn ); + ber_bvfree ( legacy->uri->ndn ); + legacy->uri->dn = ber_bvdup ( &c->value_dn ); + legacy->uri->ndn = ber_bvdup ( &c->value_ndn ); + rc = 0; + break; + default: + abort(); + } + + return rc; +} + +static int +unique_cf_attrs( ConfigArgs *c ) +{ + slap_overinst *on = (slap_overinst *)c->bi; + unique_data *private = (unique_data *) on->on_bi.bi_private; + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + unique_attrs *new_attrs = NULL; + unique_attrs *attr, *next_attr, *reverse_attrs; + unique_attrs **attrp; + int rc = ARG_BAD_CONF; int i; - ud->message = "_config"; - Debug(LDAP_DEBUG_TRACE, "==> unique_config\n", 0, 0, 0); - - if(!strcasecmp(*argv, "unique_attributes") || - !strcasecmp(*argv, "unique_ignore")) { - for(i = 1; i < argc; i++) { - for(up = ud->attrs; up; up = up->next) - if(!strcmp(argv[i], up->attr->ad_cname.bv_val)) { - Debug(LDAP_DEBUG_ANY, - "%s: line %d: duplicate attribute <%s>, ignored\n", - fname, lineno, argv[i]); - continue; + switch ( c->op ) { + case SLAP_CONFIG_EMIT: + if ( legacy + && (c->type == UNIQUE_IGNORE) == legacy->ignore + && legacy->uri ) + for ( attr = legacy->uri->attrs; + attr; + attr = attr->next ) + value_add_one( &c->rvalue_vals, + &attr->attr->ad_cname ); + rc = 0; + break; + case LDAP_MOD_DELETE: + if ( legacy + && (c->type == UNIQUE_IGNORE) == legacy->ignore + && legacy->uri + && legacy->uri->attrs) { + if ( c->valx < 0 ) { /* delete all */ + for ( attr = legacy->uri->attrs; + attr; + attr = next_attr ) { + next_attr = attr->next; + ch_free ( attr ); + } + legacy->uri->attrs = NULL; + } else { /* delete by index */ + attrp = &legacy->uri->attrs; + for ( i=0; i < c->valx; ++i ) + attrp = &(*attrp)->next; + attr = *attrp; + *attrp = attr->next; + ch_free (attr); } - ad = NULL; - if(slap_str2ad(argv[i], &ad, &text) != LDAP_SUCCESS) { - Debug(LDAP_DEBUG_ANY, - "%s: line %d: bad attribute <%s>, ignored\n", - fname, lineno, text); - continue; /* XXX */ - } else if(ad->ad_next) { - Debug(LDAP_DEBUG_ANY, - "%s: line %d: multiple attributes match <%s>, ignored\n", - fname, lineno, argv[i]); - continue; + if ( !legacy->uri->attrs + && !legacy->uri->dn ) { + unique_free_domain_uri ( legacy->uri ); + legacy->uri = NULL; + } + if ( !legacy->uri && !private->legacy_strict_set ) { + unique_free_domain ( legacy ); + private->legacy = legacy = NULL; } - up = ch_malloc(sizeof(unique_attrs)); - up->attr = ad; - if(!strcasecmp(*argv, "unique_ignore")) { - up->next = ud->ignore; - ud->ignore = up; + } + rc = 0; + break; + case LDAP_MOD_ADD: + case SLAP_CONFIG_ADD: + if ( domains ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot set legacy attrs when URIs are present" ); + Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", + c->cr_msg, NULL, NULL ); + rc = ARG_BAD_CONF; + break; + } + if ( legacy + && legacy->uri + && legacy->uri->attrs + && (c->type == UNIQUE_IGNORE) != legacy->ignore ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot set both attrs and ignore-attrs" ); + Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", + c->cr_msg, NULL, NULL ); + rc = ARG_BAD_CONF; + break; + } + if ( !legacy ) { + unique_new_domain ( &private->legacy, + UNIQUE_DEFAULT_URI, + c ); + legacy = private->legacy; + } + if ( !legacy->uri ) + unique_new_domain_uri_basic ( &legacy->uri, c ); + rc = 0; + for ( i=1; c->argv[i]; ++i ) { + AttributeDescription * ad = NULL; + const char * text; + if ( slap_str2ad ( c->argv[i], &ad, &text ) + == LDAP_SUCCESS) { + + attr = ch_calloc ( 1, + sizeof ( unique_attrs ) ); + attr->attr = ad; + attr->next = new_attrs; + new_attrs = attr; } else { - up->next = ud->attrs; - ud->attrs = up; + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "unique: attribute: %s: %s", + c->argv[i], text ); + for ( attr = new_attrs; + attr; + attr=next_attr ) { + next_attr = attr->next; + ch_free ( attr ); + } + rc = ARG_BAD_CONF; + break; + } + } + if ( rc ) break; + + /* (nconc legacy->uri->attrs (nreverse new_attrs)) */ + reverse_attrs = NULL; + for ( attr = new_attrs; + attr; + attr = next_attr ) { + next_attr = attr->next; + attr->next = reverse_attrs; + reverse_attrs = attr; + } + for ( attrp = &legacy->uri->attrs; + *attrp; + attrp = &(*attrp)->next ) ; + *attrp = reverse_attrs; + + legacy->ignore = ( c->type == UNIQUE_IGNORE ); + break; + default: + abort(); + } + + if ( rc ) { + Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + } + return rc; +} + +static int +unique_cf_strict( ConfigArgs *c ) +{ + slap_overinst *on = (slap_overinst *)c->bi; + unique_data *private = (unique_data *) on->on_bi.bi_private; + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + int rc = ARG_BAD_CONF; + + switch ( c->op ) { + case SLAP_CONFIG_EMIT: + /* We process the boolean manually instead of using + * ARG_ON_OFF so that we can three-state it; + * olcUniqueStrict is either TRUE, FALSE, or missing, + * and missing is necessary to add olcUniqueURIs... + */ + if ( private->legacy_strict_set ) { + struct berval bv; + bv.bv_val = legacy->strict ? "TRUE" : "FALSE"; + bv.bv_len = legacy->strict ? + STRLENOF("TRUE") : + STRLENOF("FALSE"); + value_add_one ( &c->rvalue_vals, &bv ); + } + rc = 0; + break; + case LDAP_MOD_DELETE: + if ( legacy ) { + legacy->strict = 0; + if ( ! legacy->uri ) { + unique_free_domain ( legacy ); + private->legacy = NULL; } - Debug(LDAP_DEBUG_CONFIG, "%s: line %d: new attribute <%s>\n", - fname, lineno, argv[i]); - } - } else if(!strcasecmp(*argv, "unique_strict")) { - ud->strict = 1; - } else if(!strcasecmp(*argv, "unique_base")) { - struct berval bv; - ber_str2bv( argv[1], 0, 0, &bv ); - ch_free(ud->dn.bv_val); - dnNormalize(0, NULL, NULL, &bv, &ud->dn, NULL); - Debug(LDAP_DEBUG_CONFIG, "%s: line %d: new base dn <%s>\n", - fname, lineno, argv[1]); - } else { - return(SLAP_CONF_UNKNOWN); + } + private->legacy_strict_set = 0; + rc = 0; + break; + case LDAP_MOD_ADD: + case SLAP_CONFIG_ADD: + if ( domains ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot set legacy attrs when URIs are present" ); + Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", + c->cr_msg, NULL, NULL ); + rc = ARG_BAD_CONF; + break; + } + if ( ! legacy ) { + unique_new_domain ( &private->legacy, + UNIQUE_DEFAULT_URI, + c ); + legacy = private->legacy; + } + /* ... not using ARG_ON_OFF makes this necessary too */ + assert ( c->argc == 2 ); + legacy->strict = (strcasecmp ( c->argv[1], "TRUE" ) == 0); + private->legacy_strict_set = 1; + rc = 0; + break; + default: + abort(); } - return(0); + return rc; } +static int +unique_cf_uri( ConfigArgs *c ) +{ + slap_overinst *on = (slap_overinst *)c->bi; + unique_data *private = (unique_data *) on->on_bi.bi_private; + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + unique_domain *domain = NULL, **domainp = NULL; + int rc = ARG_BAD_CONF; + int i; + + switch ( c->op ) { + case SLAP_CONFIG_EMIT: + for ( domain = domains; + domain; + domain = domain->next ) { + rc = value_add_one ( &c->rvalue_vals, + domain->domain_spec ); + if ( rc ) break; + rc = value_add_one ( &c->rvalue_nvals, + domain->domain_spec ); + if ( rc ) break; + } + break; + case LDAP_MOD_DELETE: + if ( c->valx < 0 ) { /* delete them all! */ + unique_free_domain ( domains ); + private->domains = NULL; + } else { /* delete just one */ + domainp = &private->domains; + for ( i=0; i < c->valx && *domainp; ++i ) + domainp = &(*domainp)->next; + + /* If *domainp is null, we walked off the end + * of the list. This happens when back-config + * and the overlay are out-of-sync, like when + * rejecting changes before ITS#4752 gets + * fixed. + * + * This should never happen, but will appear + * if you backport this version of + * slapo-unique without the config-undo fixes + * + * test024 Will hit this case in such a + * situation. + */ + assert (*domainp != NULL); + + domain = *domainp; + *domainp = domain->next; + domain->next = NULL; + unique_free_domain ( domain ); + } + rc = 0; + break; + + case SLAP_CONFIG_ADD: /* fallthrough */ + case LDAP_MOD_ADD: + if ( legacy ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot set Uri when legacy attrs are present" ); + Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", + c->cr_msg, NULL, NULL ); + rc = ARG_BAD_CONF; + break; + } + rc = 0; + if ( c->line ) rc = unique_new_domain ( &domain, c->line, c ); + else rc = unique_new_domain ( &domain, c->argv[1], c ); + if ( rc ) break; + assert ( domain->next == NULL ); + for ( domainp = &private->domains; + *domainp; + domainp = &(*domainp)->next ) ; + *domainp = domain; + + break; + + default: + abort (); + } + + return rc; +} /* -** mostly, just print the init message; +** allocate new unique_data; +** initialize, copy basedn; +** store in on_bi.bi_private; ** */ static int -unique_open( - BackendDB *be +unique_db_init( + BackendDB *be, + ConfigReply *cr ) { - slap_overinst *on = (slap_overinst *)be->bd_info; - unique_data *ud = on->on_bi.bi_private; - ud->message = "_open"; + slap_overinst *on = (slap_overinst *)be->bd_info; + unique_data **privatep = (unique_data **) &on->on_bi.bi_private; + + Debug(LDAP_DEBUG_TRACE, "==> unique_db_init\n", 0, 0, 0); + + *privatep = ch_calloc ( 1, sizeof ( unique_data ) ); + + return 0; +} + +static int +unique_db_destroy( + BackendDB *be, + ConfigReply *cr +) +{ + slap_overinst *on = (slap_overinst *)be->bd_info; + unique_data **privatep = (unique_data **) &on->on_bi.bi_private; + unique_data *private = *privatep; + + Debug(LDAP_DEBUG_TRACE, "==> unique_db_destroy\n", 0, 0, 0); + + if ( private ) { + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + + unique_free_domain ( domains ); + unique_free_domain ( legacy ); + ch_free ( private ); + *privatep = NULL; + } + + return 0; +} +static int +unique_open( + BackendDB *be, + ConfigReply *cr +) +{ Debug(LDAP_DEBUG_TRACE, "unique_open: overlay initialized\n", 0, 0, 0); - return(0); + return 0; } /* -** foreach configured attribute: -** free it; -** free our basedn; -** (do not) free ud->message; -** reset on_bi.bi_private; -** free our config data; +** Leave unique_data but wipe out config ** */ static int unique_close( - BackendDB *be + BackendDB *be, + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *) be->bd_info; - unique_data *ud = on->on_bi.bi_private; - unique_attrs *ii, *ij; - ud->message = "_close"; + unique_data **privatep = (unique_data **) &on->on_bi.bi_private; + unique_data *private = *privatep; Debug(LDAP_DEBUG_TRACE, "==> unique_close\n", 0, 0, 0); - for(ii = ud->attrs; ii; ii = ij) { - ij = ii->next; - ch_free(ii); - } + if ( private ) { + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; - for(ii = ud->ignore; ii; ii = ij) { - ij = ii->next; - ch_free(ii); + unique_free_domain ( domains ); + unique_free_domain ( legacy ); + memset ( private, 0, sizeof ( unique_data ) ); } - ch_free(ud->dn.bv_val); - - on->on_bi.bi_private = NULL; /* XXX */ - - ch_free(ud); - - return(0); + return ( 0 ); } @@ -253,80 +853,116 @@ static int count_attr_cb( return(0); } -static int count_filter_len( - unique_data *ud, +/* count the length of one attribute ad + * (and all of its values b) + * in the proposed filter + */ +static int +count_filter_len( + unique_domain *domain, + unique_domain_uri *uri, AttributeDescription *ad, - BerVarray b, - int ks + BerVarray b ) { - unique_attrs *up; + unique_attrs *attr; int i; - - while(!is_at_operational(ad->ad_type)) { - if(ud->ignore) { - for(up = ud->ignore; up; up = up->next) - if(ad == up->attr) break; - if(up) break; - } - if(ud->attrs) { - for(up = ud->attrs; up; up = up->next) - if(ad == up->attr) break; - if(!up) break; + int ks = 0; + + while ( !is_at_operational( ad->ad_type ) ) { + if ( uri->attrs ) { + for ( attr = uri->attrs; attr; attr = attr->next ) { + if ( ad == attr->attr ) { + break; + } + } + if ( ( domain->ignore && attr ) + || (!domain->ignore && !attr )) { + break; + } } - if(b && b[0].bv_val) for(i = 0; b[i].bv_val; i++) - ks += b[i].bv_len + ad->ad_cname.bv_len + STRLENOF( "(=)" ); - else if(ud->strict) + if ( b && b[0].bv_val ) { + for (i = 0; b[i].bv_val; i++ ) { + /* note: make room for filter escaping... */ + ks += ( 3 * b[i].bv_len ) + ad->ad_cname.bv_len + STRLENOF( "(=)" ); + } + } else if ( domain->strict ) { ks += ad->ad_cname.bv_len + STRLENOF( "(=*)" ); /* (attr=*) */ + } break; } + return ks; } -static char *build_filter( - unique_data *ud, +static char * +build_filter( + unique_domain *domain, + unique_domain_uri *uri, AttributeDescription *ad, BerVarray b, - char *kp + char *kp, + int ks, + void *ctx ) { - unique_attrs *up; + unique_attrs *attr; int i; - while(!is_at_operational(ad->ad_type)) { - if(ud->ignore) { - for(up = ud->ignore; up; up = up->next) - if(ad == up->attr) break; - if(up) break; - } - if(ud->attrs) { - for(up = ud->attrs; up; up = up->next) - if(ad == up->attr) break; - if(!up) break; - } - if(b && b[0].bv_val) for(i = 0; b[i].bv_val; i++) - kp += sprintf(kp, "(%s=%s)", ad->ad_cname.bv_val, b[i].bv_val); - else if(ud->strict) - kp += sprintf(kp, "(%s=*)", ad->ad_cname.bv_val); + while ( !is_at_operational( ad->ad_type ) ) { + if ( uri->attrs ) { + for ( attr = uri->attrs; attr; attr = attr->next ) { + if ( ad == attr->attr ) { + break; + } + } + if ( ( domain->ignore && attr ) + || (!domain->ignore && !attr )) { + break; + } + } + if ( b && b[0].bv_val ) { + for ( i = 0; b[i].bv_val; i++ ) { + struct berval bv; + int len; + + ldap_bv2escaped_filter_value_x( &b[i], &bv, 1, ctx ); + len = snprintf( kp, ks, "(%s=%s)", ad->ad_cname.bv_val, bv.bv_val ); + assert( len >= 0 && len < ks ); + kp += len; + if ( bv.bv_val != b[i].bv_val ) { + ber_memfree_x( bv.bv_val, ctx ); + } + } + } else if ( domain->strict ) { + int len; + len = snprintf( kp, ks, "(%s=*)", ad->ad_cname.bv_val ); + assert( len >= 0 && len < ks ); + kp += len; + } break; } return kp; } -static int unique_search( +static int +unique_search( Operation *op, Operation *nop, + struct berval * dn, + int scope, SlapReply *rs, char *key ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; - unique_data *ud = on->on_bi.bi_private; SlapReply nrs = { REP_RESULT }; slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */ unique_counter uq = { NULL, 0 }; int rc; + Debug(LDAP_DEBUG_TRACE, "==> unique_search %s\n", key, 0, 0); + nop->ors_filter = str2filter_x(nop, key); ber_str2bv(key, 0, 0, &nop->ors_filterstr); @@ -334,7 +970,7 @@ static int unique_search( cb.sc_private = &uq; nop->o_callback = &cb; nop->o_tag = LDAP_REQ_SEARCH; - nop->ors_scope = LDAP_SCOPE_SUBTREE; + nop->ors_scope = scope; nop->ors_deref = LDAP_DEREF_NEVER; nop->ors_limit = NULL; nop->ors_slimit = SLAP_NO_LIMIT; @@ -344,13 +980,13 @@ static int unique_search( uq.ndn = &op->o_req_ndn; - nop->o_req_ndn = ud->dn; + nop->o_req_ndn = *dn; nop->o_ndn = op->o_bd->be_rootndn; nop->o_bd = on->on_info->oi_origdb; rc = nop->o_bd->be_search(nop, &nrs); filter_free_x(nop, nop->ors_filter); - ch_free( key ); + op->o_tmpfree( key, op->o_tmpmemctx ); if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) { op->o_bd->bd_info = (BackendInfo *) on->on_info; @@ -370,168 +1006,344 @@ static int unique_search( return(SLAP_CB_CONTINUE); } -static int unique_add( +static int +unique_add( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; - unique_data *ud = on->on_bi.bi_private; + unique_data *private = (unique_data *) on->on_bi.bi_private; + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + unique_domain *domain; Operation nop = *op; - Attribute *a; char *key, *kp; - int ks = 16; + int rc = SLAP_CB_CONTINUE; + + Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n", + op->o_req_dn.bv_val, 0, 0); + + for ( domain = legacy ? legacy : domains; + domain; + domain = domain->next ) + { + unique_domain_uri *uri; + int ks = 0; + + for ( uri = domain->uri; + uri; + uri = uri->next ) + { + int len; + + if ( uri->ndn + && !dnIsSuffix( &op->o_req_ndn, uri->ndn )) + continue; - Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n", op->o_req_dn.bv_val, 0, 0); + if(!(a = op->ora_e->e_attrs)) { + op->o_bd->bd_info = (BackendInfo *) on->on_info; + send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, + "unique_add() got null op.ora_e.e_attrs"); + rc = rs->sr_err; + break; - if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn )) - return SLAP_CB_CONTINUE; + } else { + for(; a; a = a->a_next) { + ks += count_filter_len ( domain, + uri, + a->a_desc, + a->a_vals); + } + } -/* -** count everything first; -** allocate some memory; -** write the search key; -** -*/ + /* skip this domain-uri if it isn't involved */ + if ( !ks ) continue; - if(!(a = op->ora_e->e_attrs)) { - op->o_bd->bd_info = (BackendInfo *) on->on_info; - send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, - "unique_add() got null op.ora_e.e_attrs"); - return(rs->sr_err); - } else for(; a; a = a->a_next) { - ks = count_filter_len(ud, a->a_desc, a->a_vals, ks); - } + if ( uri->filter && uri->filter->bv_len ) + ks += uri->filter->bv_len + STRLENOF ("(&)"); + kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx); - key = ch_malloc(ks); + if ( uri->filter && uri->filter->bv_len ) { + len = snprintf (kp, ks, "(&%s", uri->filter->bv_val); + assert( len >= 0 && len < ks ); + kp += len; + } + len = snprintf(kp, ks - (kp - key), "(|"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + + for(a = op->ora_e->e_attrs; a; a = a->a_next) + kp = build_filter(domain, + uri, + a->a_desc, + a->a_vals, + kp, + ks - ( kp - key ), + op->o_tmpmemctx); + + len = snprintf(kp, ks - (kp - key), ")"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + if ( uri->filter && uri->filter->bv_len ) { + len = snprintf(kp, ks - (kp - key), ")"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + } - kp = key + sprintf(key, "(|"); + rc = unique_search ( op, + &nop, + uri->ndn ? + uri->ndn : + &op->o_bd->be_nsuffix[0], + uri->scope, + rs, + key); - for(a = op->ora_e->e_attrs; a; a = a->a_next) { - kp = build_filter(ud, a->a_desc, a->a_vals, kp); + if ( rc != SLAP_CB_CONTINUE ) break; + } + if ( rc != SLAP_CB_CONTINUE ) break; } - sprintf(kp, ")"); - - Debug(LDAP_DEBUG_TRACE, "=> unique_add %s\n", key, 0, 0); - - return unique_search(op, &nop, rs, key); + return rc; } -static int unique_modify( +static int +unique_modify( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; - unique_data *ud = on->on_bi.bi_private; + unique_data *private = (unique_data *) on->on_bi.bi_private; + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + unique_domain *domain; Operation nop = *op; - Modifications *m; char *key, *kp; - int ks = 16; /* a handful of extra bytes */ - - Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n", op->o_req_dn.bv_val, 0, 0); - - if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn )) - return SLAP_CB_CONTINUE; - -/* -** count everything first; -** allocate some memory; -** write the search key; -** -*/ - - if(!(m = op->orm_modlist)) { - op->o_bd->bd_info = (BackendInfo *) on->on_info; - send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, - "unique_modify() got null op.orm_modlist"); - return(rs->sr_err); - } else for(; m; m = m->sml_next) { - if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue; - ks = count_filter_len(ud, m->sml_desc, m->sml_values, ks); - } + int rc = SLAP_CB_CONTINUE; + + Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n", + op->o_req_dn.bv_val, 0, 0); + + for ( domain = legacy ? legacy : domains; + domain; + domain = domain->next ) + { + unique_domain_uri *uri; + int ks = 0; + + for ( uri = domain->uri; + uri; + uri = uri->next ) + { + int len; + + if ( uri->ndn + && !dnIsSuffix( &op->o_req_ndn, uri->ndn )) + continue; - key = ch_malloc(ks); + if ( !(m = op->orm_modlist) ) { + op->o_bd->bd_info = (BackendInfo *) on->on_info; + send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, + "unique_modify() got null op.orm_modlist"); + rc = rs->sr_err; + break; + + } else + for ( ; m; m = m->sml_next) + if ( (m->sml_op & LDAP_MOD_OP) + != LDAP_MOD_DELETE ) + ks += count_filter_len + ( domain, + uri, + m->sml_desc, + m->sml_values); + + /* skip this domain-uri if it isn't involved */ + if ( !ks ) continue; + + if ( uri->filter && uri->filter->bv_len ) + ks += uri->filter->bv_len + STRLENOF ("(&)"); + kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx); + + if ( uri->filter && uri->filter->bv_len ) { + len = snprintf(kp, ks, "(&%s", uri->filter->bv_val); + assert( len >= 0 && len < ks ); + kp += len; + } + len = snprintf(kp, ks - (kp - key), "(|"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + + for(m = op->orm_modlist; m; m = m->sml_next) + if ( (m->sml_op & LDAP_MOD_OP) + != LDAP_MOD_DELETE ) + kp = build_filter ( domain, + uri, + m->sml_desc, + m->sml_values, + kp, + ks - (kp - key), + op->o_tmpmemctx ); + + len = snprintf(kp, ks - (kp - key), ")"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + if ( uri->filter && uri->filter->bv_len ) { + len = snprintf (kp, ks - (kp - key), ")"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + } - kp = key + sprintf(key, "(|"); + rc = unique_search ( op, + &nop, + uri->ndn ? + uri->ndn : + &op->o_bd->be_nsuffix[0], + uri->scope, + rs, + key); - for(m = op->orm_modlist; m; m = m->sml_next) { - if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue; - kp = build_filter(ud, m->sml_desc, m->sml_values, kp); + if ( rc != SLAP_CB_CONTINUE ) break; + } + if ( rc != SLAP_CB_CONTINUE ) break; } - sprintf(kp, ")"); - - Debug(LDAP_DEBUG_TRACE, "=> unique_modify %s\n", key, 0, 0); - - return unique_search(op, &nop, rs, key); + return rc; } -static int unique_modrdn( +static int +unique_modrdn( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; - unique_data *ud = on->on_bi.bi_private; + unique_data *private = (unique_data *) on->on_bi.bi_private; + unique_domain *domains = private->domains; + unique_domain *legacy = private->legacy; + unique_domain *domain; Operation nop = *op; - char *key, *kp; - int i, ks = 16; /* a handful of extra bytes */ LDAPRDN newrdn; struct berval bv[2]; + int rc = SLAP_CB_CONTINUE; Debug(LDAP_DEBUG_TRACE, "==> unique_modrdn <%s> <%s>\n", op->o_req_dn.bv_val, op->orr_newrdn.bv_val, 0); - if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ) && - (!op->orr_nnewSup || !dnIsSuffix( op->orr_nnewSup, &ud->dn ))) - return SLAP_CB_CONTINUE; + for ( domain = legacy ? legacy : domains; + domain; + domain = domain->next ) + { + unique_domain_uri *uri; + int ks = 0; + + for ( uri = domain->uri; + uri; + uri = uri->next ) + { + int i, len; + + if ( uri->ndn + && !dnIsSuffix( &op->o_req_ndn, uri->ndn ) + && (!op->orr_nnewSup + || !dnIsSuffix( op->orr_nnewSup, uri->ndn ))) + continue; - if(ldap_bv2rdn_x(&op->oq_modrdn.rs_newrdn, &newrdn, - (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx )) { - op->o_bd->bd_info = (BackendInfo *) on->on_info; - send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, - "unknown type(s) used in RDN"); - return(rs->sr_err); - } - for(i = 0; newrdn[i]; i++) { - AttributeDescription *ad = NULL; - if ( slap_bv2ad( &newrdn[i]->la_attr, &ad, &rs->sr_text )) { - ldap_rdnfree_x( newrdn, op->o_tmpmemctx ); - rs->sr_err = LDAP_INVALID_SYNTAX; - send_ldap_result( op, rs ); - return(rs->sr_err); - } - newrdn[i]->la_private = ad; - } + if ( ldap_bv2rdn_x ( &op->oq_modrdn.rs_newrdn, + &newrdn, + (char **)&rs->sr_text, + LDAP_DN_FORMAT_LDAP, + op->o_tmpmemctx ) ) { + op->o_bd->bd_info = (BackendInfo *) on->on_info; + send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, + "unknown type(s) used in RDN"); + rc = rs->sr_err; + break; + } - bv[1].bv_val = NULL; - bv[1].bv_len = 0; + rc = SLAP_CB_CONTINUE; + for ( i=0; newrdn[i]; i++) { + AttributeDescription *ad = NULL; + if ( slap_bv2ad( &newrdn[i]->la_attr, &ad, &rs->sr_text )) { + ldap_rdnfree_x( newrdn, op->o_tmpmemctx ); + rs->sr_err = LDAP_INVALID_SYNTAX; + send_ldap_result( op, rs ); + rc = rs->sr_err; + break; + } + newrdn[i]->la_private = ad; + } + if ( rc != SLAP_CB_CONTINUE ) break; - for(i = 0; newrdn[i]; i++) { - bv[0] = newrdn[i]->la_value; - ks = count_filter_len(ud, newrdn[i]->la_private, bv, ks); - } + bv[1].bv_val = NULL; + bv[1].bv_len = 0; - key = ch_malloc(ks); - kp = key + sprintf(key, "(|"); + for ( i=0; newrdn[i]; i++ ) { + bv[0] = newrdn[i]->la_value; + ks += count_filter_len ( domain, + uri, + newrdn[i]->la_private, + bv); + } - for(i = 0; newrdn[i]; i++) { - bv[0] = newrdn[i]->la_value; - kp = build_filter(ud, newrdn[i]->la_private, bv, kp); - } + /* skip this domain if it isn't involved */ + if ( !ks ) continue; + + if ( uri->filter && uri->filter->bv_len ) + ks += uri->filter->bv_len + STRLENOF ("(&)"); + kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx); + + if ( uri->filter && uri->filter->bv_len ) { + len = snprintf(kp, ks, "(&%s", uri->filter->bv_val); + assert( len >= 0 && len < ks ); + kp += len; + } + len = snprintf(kp, ks - (kp - key), "(|"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + + for ( i=0; newrdn[i]; i++) { + bv[0] = newrdn[i]->la_value; + kp = build_filter ( domain, + uri, + newrdn[i]->la_private, + bv, + kp, + ks - (kp - key ), + op->o_tmpmemctx); + } + + len = snprintf(kp, ks - (kp - key), ")"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + if ( uri->filter && uri->filter->bv_len ) { + len = snprintf (kp, ks - (kp - key), ")"); + assert( len >= 0 && len < ks - (kp - key) ); + kp += len; + } - sprintf(kp, ")"); + rc = unique_search ( op, + &nop, + uri->ndn ? + uri->ndn : + &op->o_bd->be_nsuffix[0], + uri->scope, + rs, + key); - Debug(LDAP_DEBUG_TRACE, "=> unique_modrdn %s\n", key, 0, 0); + if ( rc != SLAP_CB_CONTINUE ) break; + } + if ( rc != SLAP_CB_CONTINUE ) break; + } - return unique_search(op, &nop, rs, key); + return rc; } /* @@ -539,25 +1351,33 @@ static int unique_modrdn( ** it expects to be called automagically during dynamic module initialization */ -int unique_init() { +int +unique_initialize() +{ + int rc; /* statically declared just after the #includes at top */ + memset (&unique, 0, sizeof(unique)); + unique.on_bi.bi_type = "unique"; unique.on_bi.bi_db_init = unique_db_init; - unique.on_bi.bi_db_config = unique_config; + unique.on_bi.bi_db_destroy = unique_db_destroy; unique.on_bi.bi_db_open = unique_open; unique.on_bi.bi_db_close = unique_close; unique.on_bi.bi_op_add = unique_add; unique.on_bi.bi_op_modify = unique_modify; unique.on_bi.bi_op_modrdn = unique_modrdn; - unique.on_bi.bi_op_delete = NULL; + + unique.on_bi.bi_cf_ocs = uniqueocs; + rc = config_register_schema( uniquecfg, uniqueocs ); + if ( rc ) return rc; return(overlay_register(&unique)); } #if SLAPD_OVER_UNIQUE == SLAPD_MOD_DYNAMIC && defined(PIC) int init_module(int argc, char *argv[]) { - return unique_init(); + return unique_initialize(); } #endif