1/* $NetBSD: unique.c,v 1.3 2021/08/14 16:15:02 christos Exp $ */ 2 3/* unique.c - attribute uniqueness module */ 4/* $OpenLDAP$ */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2004-2021 The OpenLDAP Foundation. 8 * Portions Copyright 2004,2006-2007 Symas Corporation. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19/* ACKNOWLEDGEMENTS: 20 * This work was initially developed by Symas Corporation for 21 * inclusion in OpenLDAP Software, with subsequent enhancements by 22 * Emily Backes at Symas Corporation. This work was sponsored by 23 * Hewlett-Packard. 24 */ 25 26#include <sys/cdefs.h> 27__RCSID("$NetBSD: unique.c,v 1.3 2021/08/14 16:15:02 christos Exp $"); 28 29#include "portable.h" 30 31#ifdef SLAPD_OVER_UNIQUE 32 33#include <stdio.h> 34 35#include <ac/string.h> 36#include <ac/socket.h> 37 38#include "slap.h" 39#include "slap-config.h" 40 41#define UNIQUE_DEFAULT_URI ("ldap:///??sub") 42 43static slap_overinst unique; 44 45typedef struct unique_attrs_s { 46 struct unique_attrs_s *next; /* list of attrs */ 47 AttributeDescription *attr; 48} unique_attrs; 49 50typedef struct unique_domain_uri_s { 51 struct unique_domain_uri_s *next; 52 struct berval dn; 53 struct berval ndn; 54 struct berval filter; 55 Filter *f; 56 struct unique_attrs_s *attrs; 57 int scope; 58} unique_domain_uri; 59 60typedef struct unique_domain_s { 61 struct unique_domain_s *next; 62 struct berval domain_spec; 63 struct unique_domain_uri_s *uri; 64 char ignore; /* polarity of attributes */ 65 char strict; /* null considered unique too */ 66 char serial; /* serialize execution */ 67} unique_domain; 68 69typedef struct unique_data_s { 70 struct unique_domain_s *domains; 71 struct unique_domain_s *legacy; 72 char legacy_strict_set; 73 ldap_pvt_thread_mutex_t serial_mutex; 74} unique_data; 75 76typedef struct unique_counter_s { 77 struct berval *ndn; 78 int count; 79} unique_counter; 80 81enum { 82 UNIQUE_BASE = 1, 83 UNIQUE_IGNORE, 84 UNIQUE_ATTR, 85 UNIQUE_STRICT, 86 UNIQUE_URI, 87}; 88 89static ConfigDriver unique_cf_base; 90static ConfigDriver unique_cf_attrs; 91static ConfigDriver unique_cf_strict; 92static ConfigDriver unique_cf_uri; 93 94static ConfigTable uniquecfg[] = { 95 { "unique_base", "basedn", 2, 2, 0, ARG_DN|ARG_QUOTE|ARG_MAGIC|UNIQUE_BASE, 96 unique_cf_base, "( OLcfgOvAt:10.1 NAME 'olcUniqueBase' " 97 "DESC 'Subtree for uniqueness searches' " 98 "EQUALITY distinguishedNameMatch " 99 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, 100 { "unique_ignore", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_IGNORE, 101 unique_cf_attrs, "( OLcfgOvAt:10.2 NAME 'olcUniqueIgnore' " 102 "DESC 'Attributes for which uniqueness shall not be enforced' " 103 "EQUALITY caseIgnoreMatch " 104 "ORDERING caseIgnoreOrderingMatch " 105 "SUBSTR caseIgnoreSubstringsMatch " 106 "SYNTAX OMsDirectoryString )", NULL, NULL }, 107 { "unique_attributes", "attribute...", 2, 0, 0, ARG_MAGIC|UNIQUE_ATTR, 108 unique_cf_attrs, "( OLcfgOvAt:10.3 NAME 'olcUniqueAttribute' " 109 "DESC 'Attributes for which uniqueness shall be enforced' " 110 "EQUALITY caseIgnoreMatch " 111 "ORDERING caseIgnoreOrderingMatch " 112 "SUBSTR caseIgnoreSubstringsMatch " 113 "SYNTAX OMsDirectoryString )", NULL, NULL }, 114 { "unique_strict", "on|off", 1, 2, 0, ARG_MAGIC|UNIQUE_STRICT, 115 unique_cf_strict, "( OLcfgOvAt:10.4 NAME 'olcUniqueStrict' " 116 "DESC 'Enforce uniqueness of null values' " 117 "EQUALITY booleanMatch " 118 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 119 { "unique_uri", "ldapuri", 2, 3, 0, ARG_MAGIC|UNIQUE_URI, 120 unique_cf_uri, "( OLcfgOvAt:10.5 NAME 'olcUniqueURI' " 121 "DESC 'List of keywords and LDAP URIs for a uniqueness domain' " 122 "EQUALITY caseExactMatch " 123 "ORDERING caseExactOrderingMatch " 124 "SUBSTR caseExactSubstringsMatch " 125 "SYNTAX OMsDirectoryString )", NULL, NULL }, 126 { NULL, NULL, 0, 0, 0, ARG_IGNORED } 127}; 128 129static ConfigOCs uniqueocs[] = { 130 { "( OLcfgOvOc:10.1 " 131 "NAME 'olcUniqueConfig' " 132 "DESC 'Attribute value uniqueness configuration' " 133 "SUP olcOverlayConfig " 134 "MAY ( olcUniqueBase $ olcUniqueIgnore $ " 135 "olcUniqueAttribute $ olcUniqueStrict $ " 136 "olcUniqueURI ) )", 137 Cft_Overlay, uniquecfg }, 138 { NULL, 0, NULL } 139}; 140 141static void 142unique_free_domain_uri ( unique_domain_uri *uri ) 143{ 144 unique_domain_uri *next_uri = NULL; 145 unique_attrs *attr, *next_attr = NULL; 146 147 while ( uri ) { 148 next_uri = uri->next; 149 ch_free ( uri->dn.bv_val ); 150 ch_free ( uri->ndn.bv_val ); 151 ch_free ( uri->filter.bv_val ); 152 filter_free( uri->f ); 153 attr = uri->attrs; 154 while ( attr ) { 155 next_attr = attr->next; 156 ch_free (attr); 157 attr = next_attr; 158 } 159 ch_free ( uri ); 160 uri = next_uri; 161 } 162} 163 164/* free an entire stack of domains */ 165static void 166unique_free_domain ( unique_domain *domain ) 167{ 168 unique_domain *next_domain = NULL; 169 170 while ( domain ) { 171 next_domain = domain->next; 172 ch_free ( domain->domain_spec.bv_val ); 173 unique_free_domain_uri ( domain->uri ); 174 ch_free ( domain ); 175 domain = next_domain; 176 } 177} 178 179static int 180unique_new_domain_uri ( unique_domain_uri **urip, 181 const LDAPURLDesc *url_desc, 182 ConfigArgs *c ) 183{ 184 int i, rc = LDAP_SUCCESS; 185 unique_domain_uri *uri; 186 struct berval bv = {0, NULL}; 187 BackendDB *be = (BackendDB *)c->be; 188 char ** attr_str; 189 AttributeDescription * ad; 190 const char * text; 191 192 uri = ch_calloc ( 1, sizeof ( unique_domain_uri ) ); 193 194 if ( url_desc->lud_host && url_desc->lud_host[0] ) { 195 snprintf( c->cr_msg, sizeof( c->cr_msg ), 196 "host <%s> not allowed in URI", 197 url_desc->lud_host ); 198 rc = ARG_BAD_CONF; 199 goto exit; 200 } 201 202 if ( url_desc->lud_dn && url_desc->lud_dn[0] ) { 203 ber_str2bv( url_desc->lud_dn, 0, 0, &bv ); 204 rc = dnPrettyNormal( NULL, 205 &bv, 206 &uri->dn, 207 &uri->ndn, 208 NULL ); 209 if ( rc != LDAP_SUCCESS ) { 210 snprintf( c->cr_msg, sizeof( c->cr_msg ), 211 "<%s> invalid DN %d (%s)", 212 url_desc->lud_dn, rc, ldap_err2string( rc )); 213 rc = ARG_BAD_CONF; 214 goto exit; 215 } 216 217 if ( be->be_nsuffix == NULL ) { 218 snprintf( c->cr_msg, sizeof( c->cr_msg ), 219 "suffix must be set" ); 220 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 221 c->cr_msg ); 222 rc = ARG_BAD_CONF; 223 goto exit; 224 } 225 226 if ( !dnIsSuffix ( &uri->ndn, &be->be_nsuffix[0] ) ) { 227 snprintf( c->cr_msg, sizeof( c->cr_msg ), 228 "dn <%s> is not a suffix of backend base dn <%s>", 229 uri->dn.bv_val, 230 be->be_nsuffix[0].bv_val ); 231 rc = ARG_BAD_CONF; 232 goto exit; 233 } 234 235 if ( BER_BVISNULL( &be->be_rootndn ) || BER_BVISEMPTY( &be->be_rootndn ) ) { 236 Debug( LDAP_DEBUG_ANY, 237 "slapo-unique needs a rootdn; " 238 "backend <%s> has none, YMMV.\n", 239 be->be_nsuffix[0].bv_val ); 240 } 241 } 242 243 attr_str = url_desc->lud_attrs; 244 if ( attr_str ) { 245 for ( i=0; attr_str[i]; ++i ) { 246 unique_attrs * attr; 247 ad = NULL; 248 if ( slap_str2ad ( attr_str[i], &ad, &text ) 249 == LDAP_SUCCESS) { 250 attr = ch_calloc ( 1, 251 sizeof ( unique_attrs ) ); 252 attr->attr = ad; 253 attr->next = uri->attrs; 254 uri->attrs = attr; 255 } else { 256 snprintf( c->cr_msg, sizeof( c->cr_msg ), 257 "unique: attribute: %s: %s", 258 attr_str[i], text ); 259 rc = ARG_BAD_CONF; 260 goto exit; 261 } 262 } 263 } 264 265 uri->scope = url_desc->lud_scope; 266 if ( !uri->scope ) { 267 snprintf( c->cr_msg, sizeof( c->cr_msg ), 268 "unique: uri with base scope will always be unique"); 269 rc = ARG_BAD_CONF; 270 goto exit; 271 } 272 273 if (url_desc->lud_filter) { 274 char *ptr; 275 uri->f = str2filter( url_desc->lud_filter ); 276 if ( !uri->f ) { 277 snprintf( c->cr_msg, sizeof( c->cr_msg ), 278 "unique: bad filter"); 279 rc = ARG_BAD_CONF; 280 goto exit; 281 } 282 /* make sure the strfilter is in normal form (ITS#5581) */ 283 filter2bv( uri->f, &uri->filter ); 284 ptr = strstr( uri->filter.bv_val, "(?=" /*)*/ ); 285 if ( ptr != NULL && ptr <= ( uri->filter.bv_val - STRLENOF( "(?=" /*)*/ ) + uri->filter.bv_len ) ) 286 { 287 snprintf( c->cr_msg, sizeof( c->cr_msg ), 288 "unique: bad filter"); 289 rc = ARG_BAD_CONF; 290 goto exit; 291 } 292 } 293exit: 294 uri->next = *urip; 295 *urip = uri; 296 if ( rc ) { 297 Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 298 "%s: %s\n", c->log, c->cr_msg ); 299 unique_free_domain_uri ( uri ); 300 *urip = NULL; 301 } 302 return rc; 303} 304 305static int 306unique_new_domain_uri_basic ( unique_domain_uri **urip, 307 ConfigArgs *c ) 308{ 309 LDAPURLDesc *url_desc = NULL; 310 int rc; 311 312 rc = ldap_url_parse ( UNIQUE_DEFAULT_URI, &url_desc ); 313 if ( rc ) return rc; 314 rc = unique_new_domain_uri ( urip, url_desc, c ); 315 ldap_free_urldesc ( url_desc ); 316 return rc; 317} 318 319/* if *domain is non-null, it's pushed down the stack. 320 * note that the entire stack is freed if there is an error, 321 * so build added domains in a separate stack before adding them 322 * 323 * domain_specs look like 324 * 325 * [strict ][ignore ][serialize ]uri[[ uri]...] 326 * e.g. "ldap:///ou=foo,o=bar?uid?sub ldap:///ou=baz,o=bar?uid?sub" 327 * "strict ldap:///ou=accounts,o=bar?uid,uidNumber?one" 328 * etc 329 * 330 * so finally strictness is per-domain 331 * but so is ignore-state, and that would be better as a per-url thing 332 */ 333static int 334unique_new_domain ( unique_domain **domainp, 335 char *domain_spec, 336 ConfigArgs *c ) 337{ 338 char *uri_start; 339 int rc = LDAP_SUCCESS; 340 int uri_err = 0; 341 unique_domain * domain; 342 LDAPURLDesc *url_desc, *url_descs = NULL; 343 344 Debug(LDAP_DEBUG_TRACE, "==> unique_new_domain <%s>\n", 345 domain_spec ); 346 347 domain = ch_calloc ( 1, sizeof (unique_domain) ); 348 ber_str2bv( domain_spec, 0, 1, &domain->domain_spec ); 349 350 uri_start = domain_spec; 351 if ( strncasecmp ( uri_start, "ignore ", 352 STRLENOF( "ignore " ) ) == 0 ) { 353 domain->ignore = 1; 354 uri_start += STRLENOF( "ignore " ); 355 } 356 if ( strncasecmp ( uri_start, "serialize ", 357 STRLENOF( "serialize " ) ) == 0 ) { 358 domain->serial = 1; 359 uri_start += STRLENOF( "serialize " ); 360 } 361 if ( strncasecmp ( uri_start, "strict ", 362 STRLENOF( "strict " ) ) == 0 ) { 363 domain->strict = 1; 364 uri_start += STRLENOF( "strict " ); 365 if ( !domain->ignore 366 && strncasecmp ( uri_start, "ignore ", 367 STRLENOF( "ignore " ) ) == 0 ) { 368 domain->ignore = 1; 369 uri_start += STRLENOF( "ignore " ); 370 } 371 } 372 rc = ldap_url_parselist_ext ( &url_descs, uri_start, " ", 0 ); 373 if ( rc ) { 374 snprintf( c->cr_msg, sizeof( c->cr_msg ), 375 "<%s> invalid ldap urilist", 376 uri_start ); 377 rc = ARG_BAD_CONF; 378 goto exit; 379 } 380 381 for ( url_desc = url_descs; 382 url_desc; 383 url_desc = url_desc->lud_next ) { 384 rc = unique_new_domain_uri ( &domain->uri, 385 url_desc, 386 c ); 387 if ( rc ) { 388 rc = ARG_BAD_CONF; 389 uri_err = 1; 390 goto exit; 391 } 392 } 393 394exit: 395 if ( url_descs ) ldap_free_urldesc ( url_descs ); 396 domain->next = *domainp; 397 *domainp = domain; 398 if ( rc ) { 399 Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 400 "%s: %s\n", c->log, c->cr_msg ); 401 unique_free_domain ( domain ); 402 *domainp = NULL; 403 } 404 return rc; 405} 406 407static int 408unique_cf_base( ConfigArgs *c ) 409{ 410 BackendDB *be = (BackendDB *)c->be; 411 slap_overinst *on = (slap_overinst *)c->bi; 412 unique_data *private = (unique_data *) on->on_bi.bi_private; 413 unique_domain *domains = private->domains; 414 unique_domain *legacy = private->legacy; 415 int rc = ARG_BAD_CONF; 416 417 switch ( c->op ) { 418 case SLAP_CONFIG_EMIT: 419 rc = 0; 420 if ( legacy && legacy->uri && legacy->uri->dn.bv_val ) { 421 rc = value_add_one ( &c->rvalue_vals, 422 &legacy->uri->dn ); 423 if ( rc ) return rc; 424 rc = value_add_one ( &c->rvalue_nvals, 425 &legacy->uri->ndn ); 426 if ( rc ) return rc; 427 } 428 break; 429 case LDAP_MOD_DELETE: 430 assert ( legacy && legacy->uri && legacy->uri->dn.bv_val ); 431 rc = 0; 432 ch_free ( legacy->uri->dn.bv_val ); 433 ch_free ( legacy->uri->ndn.bv_val ); 434 BER_BVZERO( &legacy->uri->dn ); 435 BER_BVZERO( &legacy->uri->ndn ); 436 if ( !legacy->uri->attrs ) { 437 unique_free_domain_uri ( legacy->uri ); 438 legacy->uri = NULL; 439 } 440 if ( !legacy->uri && !private->legacy_strict_set ) { 441 unique_free_domain ( legacy ); 442 private->legacy = legacy = NULL; 443 } 444 break; 445 case LDAP_MOD_ADD: 446 case SLAP_CONFIG_ADD: 447 if ( domains ) { 448 snprintf( c->cr_msg, sizeof( c->cr_msg ), 449 "cannot set legacy attrs when URIs are present" ); 450 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 451 c->cr_msg ); 452 rc = ARG_BAD_CONF; 453 break; 454 } 455 if ( be->be_nsuffix == NULL ) { 456 snprintf( c->cr_msg, sizeof( c->cr_msg ), 457 "suffix must be set" ); 458 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 459 c->cr_msg ); 460 rc = ARG_BAD_CONF; 461 break; 462 } 463 if ( !dnIsSuffix ( &c->value_ndn, 464 &be->be_nsuffix[0] ) ) { 465 snprintf( c->cr_msg, sizeof( c->cr_msg ), 466 "dn is not a suffix of backend base" ); 467 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 468 c->cr_msg ); 469 rc = ARG_BAD_CONF; 470 break; 471 } 472 if ( !legacy ) { 473 unique_new_domain ( &private->legacy, 474 UNIQUE_DEFAULT_URI, 475 c ); 476 legacy = private->legacy; 477 } 478 if ( !legacy->uri ) 479 unique_new_domain_uri_basic ( &legacy->uri, c ); 480 ch_free ( legacy->uri->dn.bv_val ); 481 ch_free ( legacy->uri->ndn.bv_val ); 482 legacy->uri->dn = c->value_dn; 483 legacy->uri->ndn = c->value_ndn; 484 rc = 0; 485 break; 486 default: 487 abort(); 488 } 489 490 if ( rc ) { 491 ch_free( c->value_dn.bv_val ); 492 BER_BVZERO( &c->value_dn ); 493 ch_free( c->value_ndn.bv_val ); 494 BER_BVZERO( &c->value_ndn ); 495 } 496 497 return rc; 498} 499 500static int 501unique_cf_attrs( ConfigArgs *c ) 502{ 503 slap_overinst *on = (slap_overinst *)c->bi; 504 unique_data *private = (unique_data *) on->on_bi.bi_private; 505 unique_domain *domains = private->domains; 506 unique_domain *legacy = private->legacy; 507 unique_attrs *new_attrs = NULL; 508 unique_attrs *attr, *next_attr, *reverse_attrs; 509 unique_attrs **attrp; 510 int rc = ARG_BAD_CONF; 511 int i; 512 513 switch ( c->op ) { 514 case SLAP_CONFIG_EMIT: 515 if ( legacy 516 && (c->type == UNIQUE_IGNORE) == legacy->ignore 517 && legacy->uri ) 518 for ( attr = legacy->uri->attrs; 519 attr; 520 attr = attr->next ) 521 value_add_one( &c->rvalue_vals, 522 &attr->attr->ad_cname ); 523 rc = 0; 524 break; 525 case LDAP_MOD_DELETE: 526 if ( legacy 527 && (c->type == UNIQUE_IGNORE) == legacy->ignore 528 && legacy->uri 529 && legacy->uri->attrs) { 530 if ( c->valx < 0 ) { /* delete all */ 531 for ( attr = legacy->uri->attrs; 532 attr; 533 attr = next_attr ) { 534 next_attr = attr->next; 535 ch_free ( attr ); 536 } 537 legacy->uri->attrs = NULL; 538 } else { /* delete by index */ 539 attrp = &legacy->uri->attrs; 540 for ( i=0; i < c->valx; ++i ) 541 attrp = &(*attrp)->next; 542 attr = *attrp; 543 *attrp = attr->next; 544 ch_free (attr); 545 } 546 if ( !legacy->uri->attrs 547 && !legacy->uri->dn.bv_val ) { 548 unique_free_domain_uri ( legacy->uri ); 549 legacy->uri = NULL; 550 } 551 if ( !legacy->uri && !private->legacy_strict_set ) { 552 unique_free_domain ( legacy ); 553 private->legacy = legacy = NULL; 554 } 555 } 556 rc = 0; 557 break; 558 case LDAP_MOD_ADD: 559 case SLAP_CONFIG_ADD: 560 if ( domains ) { 561 snprintf( c->cr_msg, sizeof( c->cr_msg ), 562 "cannot set legacy attrs when URIs are present" ); 563 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 564 c->cr_msg ); 565 rc = ARG_BAD_CONF; 566 break; 567 } 568 if ( legacy 569 && legacy->uri 570 && legacy->uri->attrs 571 && (c->type == UNIQUE_IGNORE) != legacy->ignore ) { 572 snprintf( c->cr_msg, sizeof( c->cr_msg ), 573 "cannot set both attrs and ignore-attrs" ); 574 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 575 c->cr_msg ); 576 rc = ARG_BAD_CONF; 577 break; 578 } 579 if ( !legacy ) { 580 unique_new_domain ( &private->legacy, 581 UNIQUE_DEFAULT_URI, 582 c ); 583 legacy = private->legacy; 584 } 585 if ( !legacy->uri ) 586 unique_new_domain_uri_basic ( &legacy->uri, c ); 587 rc = 0; 588 for ( i=1; c->argv[i]; ++i ) { 589 AttributeDescription * ad = NULL; 590 const char * text; 591 if ( slap_str2ad ( c->argv[i], &ad, &text ) 592 == LDAP_SUCCESS) { 593 594 attr = ch_calloc ( 1, 595 sizeof ( unique_attrs ) ); 596 attr->attr = ad; 597 attr->next = new_attrs; 598 new_attrs = attr; 599 } else { 600 snprintf( c->cr_msg, sizeof( c->cr_msg ), 601 "unique: attribute: %s: %s", 602 c->argv[i], text ); 603 for ( attr = new_attrs; 604 attr; 605 attr=next_attr ) { 606 next_attr = attr->next; 607 ch_free ( attr ); 608 } 609 rc = ARG_BAD_CONF; 610 break; 611 } 612 } 613 if ( rc ) break; 614 615 /* (nconc legacy->uri->attrs (nreverse new_attrs)) */ 616 reverse_attrs = NULL; 617 for ( attr = new_attrs; 618 attr; 619 attr = next_attr ) { 620 next_attr = attr->next; 621 attr->next = reverse_attrs; 622 reverse_attrs = attr; 623 } 624 for ( attrp = &legacy->uri->attrs; 625 *attrp; 626 attrp = &(*attrp)->next ) ; 627 *attrp = reverse_attrs; 628 629 legacy->ignore = ( c->type == UNIQUE_IGNORE ); 630 break; 631 default: 632 abort(); 633 } 634 635 if ( rc ) { 636 Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 637 "%s: %s\n", c->log, c->cr_msg ); 638 } 639 return rc; 640} 641 642static int 643unique_cf_strict( ConfigArgs *c ) 644{ 645 slap_overinst *on = (slap_overinst *)c->bi; 646 unique_data *private = (unique_data *) on->on_bi.bi_private; 647 unique_domain *domains = private->domains; 648 unique_domain *legacy = private->legacy; 649 int rc = ARG_BAD_CONF; 650 651 switch ( c->op ) { 652 case SLAP_CONFIG_EMIT: 653 /* We process the boolean manually instead of using 654 * ARG_ON_OFF so that we can three-state it; 655 * olcUniqueStrict is either TRUE, FALSE, or missing, 656 * and missing is necessary to add olcUniqueURIs... 657 */ 658 if ( private->legacy_strict_set ) { 659 struct berval bv = legacy->strict ? slap_true_bv : slap_false_bv; 660 value_add_one ( &c->rvalue_vals, &bv ); 661 } 662 rc = 0; 663 break; 664 case LDAP_MOD_DELETE: 665 if ( legacy ) { 666 legacy->strict = 0; 667 if ( ! legacy->uri ) { 668 unique_free_domain ( legacy ); 669 private->legacy = NULL; 670 } 671 } 672 private->legacy_strict_set = 0; 673 rc = 0; 674 break; 675 case LDAP_MOD_ADD: 676 case SLAP_CONFIG_ADD: 677 if ( domains ) { 678 snprintf( c->cr_msg, sizeof( c->cr_msg ), 679 "cannot set legacy attrs when URIs are present" ); 680 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 681 c->cr_msg ); 682 rc = ARG_BAD_CONF; 683 break; 684 } 685 if ( ! legacy ) { 686 unique_new_domain ( &private->legacy, 687 UNIQUE_DEFAULT_URI, 688 c ); 689 legacy = private->legacy; 690 } 691 /* ... not using ARG_ON_OFF makes this necessary too */ 692 assert ( c->argc == 2 ); 693 legacy->strict = (strcasecmp ( c->argv[1], "TRUE" ) == 0); 694 private->legacy_strict_set = 1; 695 rc = 0; 696 break; 697 default: 698 abort(); 699 } 700 701 return rc; 702} 703 704static int 705unique_cf_uri( ConfigArgs *c ) 706{ 707 slap_overinst *on = (slap_overinst *)c->bi; 708 unique_data *private = (unique_data *) on->on_bi.bi_private; 709 unique_domain *domains = private->domains; 710 unique_domain *legacy = private->legacy; 711 unique_domain *domain = NULL, **domainp = NULL; 712 int rc = ARG_BAD_CONF; 713 int i; 714 715 switch ( c->op ) { 716 case SLAP_CONFIG_EMIT: 717 for ( domain = domains; 718 domain; 719 domain = domain->next ) { 720 rc = value_add_one ( &c->rvalue_vals, 721 &domain->domain_spec ); 722 if ( rc ) break; 723 } 724 break; 725 case LDAP_MOD_DELETE: 726 if ( c->valx < 0 ) { /* delete them all! */ 727 unique_free_domain ( domains ); 728 private->domains = NULL; 729 } else { /* delete just one */ 730 domainp = &private->domains; 731 for ( i=0; i < c->valx && *domainp; ++i ) 732 domainp = &(*domainp)->next; 733 734 /* If *domainp is null, we walked off the end 735 * of the list. This happens when back-config 736 * and the overlay are out-of-sync, like when 737 * rejecting changes before ITS#4752 gets 738 * fixed. 739 * 740 * This should never happen, but will appear 741 * if you backport this version of 742 * slapo-unique without the config-undo fixes 743 * 744 * test024 Will hit this case in such a 745 * situation. 746 */ 747 assert (*domainp != NULL); 748 749 domain = *domainp; 750 *domainp = domain->next; 751 domain->next = NULL; 752 unique_free_domain ( domain ); 753 } 754 rc = 0; 755 break; 756 757 case SLAP_CONFIG_ADD: /* fallthru */ 758 case LDAP_MOD_ADD: 759 if ( legacy ) { 760 snprintf( c->cr_msg, sizeof( c->cr_msg ), 761 "cannot set Uri when legacy attrs are present" ); 762 Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n", 763 c->cr_msg ); 764 rc = ARG_BAD_CONF; 765 break; 766 } 767 rc = 0; 768 if ( c->line ) rc = unique_new_domain ( &domain, c->line, c ); 769 else rc = unique_new_domain ( &domain, c->argv[1], c ); 770 if ( rc ) break; 771 assert ( domain->next == NULL ); 772 for ( domainp = &private->domains; 773 *domainp; 774 domainp = &(*domainp)->next ) ; 775 *domainp = domain; 776 777 break; 778 779 default: 780 abort (); 781 } 782 783 return rc; 784} 785 786/* 787** allocate new unique_data; 788** initialize, copy basedn; 789** store in on_bi.bi_private; 790** 791*/ 792 793static int 794unique_db_init( 795 BackendDB *be, 796 ConfigReply *cr 797) 798{ 799 slap_overinst *on = (slap_overinst *)be->bd_info; 800 unique_data *private; 801 802 Debug(LDAP_DEBUG_TRACE, "==> unique_db_init\n" ); 803 804 private = ch_calloc ( 1, sizeof ( unique_data ) ); 805 ldap_pvt_thread_mutex_init( &private->serial_mutex ); 806 on->on_bi.bi_private = private; 807 808 return 0; 809} 810 811static int 812unique_db_destroy( 813 BackendDB *be, 814 ConfigReply *cr 815) 816{ 817 slap_overinst *on = (slap_overinst *)be->bd_info; 818 unique_data *private = on->on_bi.bi_private; 819 820 Debug(LDAP_DEBUG_TRACE, "==> unique_db_destroy\n" ); 821 822 if ( private ) { 823 unique_domain *domains = private->domains; 824 unique_domain *legacy = private->legacy; 825 826 unique_free_domain ( domains ); 827 unique_free_domain ( legacy ); 828 ldap_pvt_thread_mutex_destroy( &private->serial_mutex ); 829 ch_free ( private ); 830 on->on_bi.bi_private = NULL; 831 } 832 833 return 0; 834} 835 836 837/* 838** search callback 839** if this is a REP_SEARCH, count++; 840** 841*/ 842 843static int count_attr_cb( 844 Operation *op, 845 SlapReply *rs 846) 847{ 848 unique_counter *uc; 849 850 /* because you never know */ 851 if(!op || !rs) return(0); 852 853 /* Only search entries are interesting */ 854 if(rs->sr_type != REP_SEARCH) return(0); 855 856 uc = op->o_callback->sc_private; 857 858 /* Ignore the current entry */ 859 if ( dn_match( uc->ndn, &rs->sr_entry->e_nname )) return(0); 860 861 Debug(LDAP_DEBUG_TRACE, "==> count_attr_cb <%s>\n", 862 rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN" ); 863 864 uc->count++; 865 866 return(0); 867} 868 869/* count the length of one attribute ad 870 * (and all of its values b) 871 * in the proposed filter 872 */ 873static int 874count_filter_len( 875 unique_domain *domain, 876 unique_domain_uri *uri, 877 AttributeDescription *ad, 878 BerVarray b 879) 880{ 881 unique_attrs *attr; 882 int i; 883 int ks = 0; 884 885 while ( !is_at_operational( ad->ad_type ) ) { 886 if ( uri->attrs ) { 887 for ( attr = uri->attrs; attr; attr = attr->next ) { 888 if ( ad == attr->attr ) { 889 break; 890 } 891 } 892 if ( ( domain->ignore && attr ) 893 || (!domain->ignore && !attr )) { 894 break; 895 } 896 } 897 if ( b && b[0].bv_val ) { 898 for (i = 0; b[i].bv_val; i++ ) { 899 /* note: make room for filter escaping... */ 900 ks += ( 3 * b[i].bv_len ) + ad->ad_cname.bv_len + STRLENOF( "(=)" ); 901 } 902 } else if ( domain->strict ) { 903 ks += ad->ad_cname.bv_len + STRLENOF( "(=*)" ); /* (attr=*) */ 904 } 905 break; 906 } 907 908 return ks; 909} 910 911static char * 912build_filter( 913 unique_domain *domain, 914 unique_domain_uri *uri, 915 AttributeDescription *ad, 916 BerVarray b, 917 char *kp, 918 int ks, 919 void *ctx 920) 921{ 922 unique_attrs *attr; 923 int i; 924 925 while ( !is_at_operational( ad->ad_type ) ) { 926 if ( uri->attrs ) { 927 for ( attr = uri->attrs; attr; attr = attr->next ) { 928 if ( ad == attr->attr ) { 929 break; 930 } 931 } 932 if ( ( domain->ignore && attr ) 933 || (!domain->ignore && !attr )) { 934 break; 935 } 936 } 937 if ( b && b[0].bv_val ) { 938 for ( i = 0; b[i].bv_val; i++ ) { 939 struct berval bv; 940 int len; 941 942 ldap_bv2escaped_filter_value_x( &b[i], &bv, 1, ctx ); 943 if (!b[i].bv_len) 944 bv.bv_val = b[i].bv_val; 945 len = snprintf( kp, ks, "(%s=%s)", ad->ad_cname.bv_val, bv.bv_val ); 946 assert( len >= 0 && len < ks ); 947 kp += len; 948 if ( bv.bv_val != b[i].bv_val ) { 949 ber_memfree_x( bv.bv_val, ctx ); 950 } 951 } 952 } else if ( domain->strict ) { 953 int len; 954 len = snprintf( kp, ks, "(%s=*)", ad->ad_cname.bv_val ); 955 assert( len >= 0 && len < ks ); 956 kp += len; 957 } 958 break; 959 } 960 return kp; 961} 962 963static int 964unique_search( 965 Operation *op, 966 Operation *nop, 967 struct berval * dn, 968 int scope, 969 SlapReply *rs, 970 struct berval *key 971) 972{ 973 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 974 SlapReply nrs = { REP_RESULT }; 975 slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */ 976 unique_counter uq = { NULL, 0 }; 977 int rc; 978 char *errmsg; 979 int errmsgsize; 980 981 Debug(LDAP_DEBUG_TRACE, "==> unique_search %s\n", key->bv_val ); 982 983 nop->ors_filter = str2filter_x(nop, key->bv_val); 984 if(nop->ors_filter == NULL) { 985 op->o_bd->bd_info = (BackendInfo *) on->on_info; 986 send_ldap_error(op, rs, LDAP_OTHER, 987 "unique_search invalid filter"); 988 return(rs->sr_err); 989 } 990 991 nop->ors_filterstr = *key; 992 993 cb.sc_response = (slap_response*)count_attr_cb; 994 cb.sc_private = &uq; 995 nop->o_callback = &cb; 996 nop->o_tag = LDAP_REQ_SEARCH; 997 nop->ors_scope = scope; 998 nop->ors_deref = LDAP_DEREF_NEVER; 999 nop->ors_limit = NULL; 1000 nop->ors_slimit = SLAP_NO_LIMIT; 1001 nop->ors_tlimit = SLAP_NO_LIMIT; 1002 nop->ors_attrs = slap_anlist_no_attrs; 1003 nop->ors_attrsonly = 1; 1004 1005 uq.ndn = &op->o_req_ndn; 1006 1007 nop->o_req_ndn = *dn; 1008 nop->o_ndn = op->o_bd->be_rootndn; 1009 1010 nop->o_bd = on->on_info->oi_origdb; 1011 rc = nop->o_bd->be_search(nop, &nrs); 1012 filter_free_x(nop, nop->ors_filter, 1); 1013 1014 if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) { 1015 op->o_bd->bd_info = (BackendInfo *) on->on_info; 1016 send_ldap_error(op, rs, rc, "unique_search failed"); 1017 rc = rs->sr_err; 1018 } else if(uq.count) { 1019 Debug(LDAP_DEBUG_TRACE, "=> unique_search found %d records\n", uq.count ); 1020 1021 errmsgsize = sizeof("non-unique attributes found with ") + key->bv_len; 1022 errmsg = op->o_tmpalloc(errmsgsize, op->o_tmpmemctx); 1023 snprintf( errmsg, errmsgsize, "non-unique attributes found with %s", key->bv_val ); 1024 op->o_bd->bd_info = (BackendInfo *) on->on_info; 1025 send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, errmsg); 1026 op->o_tmpfree(errmsg, op->o_tmpmemctx); 1027 rc = rs->sr_err; 1028 } else { 1029 Debug(LDAP_DEBUG_TRACE, "=> unique_search found no records\n" ); 1030 rc = SLAP_CB_CONTINUE; 1031 } 1032 1033 op->o_tmpfree( key->bv_val, op->o_tmpmemctx ); 1034 1035 return(rc); 1036} 1037 1038static int 1039unique_unlock( 1040 Operation *op, 1041 SlapReply *rs 1042) 1043{ 1044 slap_callback *sc = op->o_callback; 1045 unique_data *private = sc->sc_private; 1046 1047 ldap_pvt_thread_mutex_unlock( &private->serial_mutex ); 1048 op->o_callback = sc->sc_next; 1049 op->o_tmpfree( sc, op->o_tmpmemctx ); 1050 return 0; 1051} 1052 1053static int 1054unique_add( 1055 Operation *op, 1056 SlapReply *rs 1057) 1058{ 1059 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 1060 unique_data *private = (unique_data *) on->on_bi.bi_private; 1061 unique_domain *domains = private->domains; 1062 unique_domain *legacy = private->legacy; 1063 unique_domain *domain; 1064 Operation nop = *op; 1065 Attribute *a; 1066 char *key, *kp; 1067 struct berval bvkey; 1068 int rc = SLAP_CB_CONTINUE; 1069 int locked = 0; 1070 1071 Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n", 1072 op->o_req_dn.bv_val ); 1073 1074 if ( SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) || ( 1075 get_relax(op) > SLAP_CONTROL_IGNORED 1076 && access_allowed( op, op->ora_e, 1077 slap_schema.si_ad_entry, NULL, 1078 ACL_MANAGE, NULL ) ) ) { 1079 return rc; 1080 } 1081 1082 for ( domain = legacy ? legacy : domains; 1083 domain; 1084 domain = domain->next ) 1085 { 1086 unique_domain_uri *uri; 1087 1088 for ( uri = domain->uri; 1089 uri; 1090 uri = uri->next ) 1091 { 1092 int len; 1093 int ks = 0; 1094 1095 if ( uri->ndn.bv_val 1096 && !dnIsSuffix( &op->o_req_ndn, &uri->ndn )) 1097 continue; 1098 1099 if ( uri->f ) { 1100 if ( test_filter( NULL, op->ora_e, uri->f ) 1101 == LDAP_COMPARE_FALSE ) 1102 { 1103 Debug( LDAP_DEBUG_TRACE, 1104 "==> unique_add_skip<%s>\n", 1105 op->o_req_dn.bv_val ); 1106 continue; 1107 } 1108 } 1109 1110 if(!(a = op->ora_e->e_attrs)) { 1111 op->o_bd->bd_info = (BackendInfo *) on->on_info; 1112 send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, 1113 "unique_add() got null op.ora_e.e_attrs"); 1114 rc = rs->sr_err; 1115 break; 1116 1117 } else { 1118 for(; a; a = a->a_next) { 1119 ks += count_filter_len ( domain, 1120 uri, 1121 a->a_desc, 1122 a->a_vals); 1123 } 1124 } 1125 1126 /* skip this domain-uri if it isn't involved */ 1127 if ( !ks ) continue; 1128 1129 if ( domain->serial && !locked ) { 1130 ldap_pvt_thread_mutex_lock( &private->serial_mutex ); 1131 locked = 1; 1132 } 1133 1134 /* terminating NUL */ 1135 ks += sizeof("(|)"); 1136 1137 if ( uri->filter.bv_val && uri->filter.bv_len ) 1138 ks += uri->filter.bv_len + STRLENOF ("(&)"); 1139 kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx); 1140 1141 if ( uri->filter.bv_val && uri->filter.bv_len ) { 1142 len = snprintf (kp, ks, "(&%s", uri->filter.bv_val); 1143 assert( len >= 0 && len < ks ); 1144 kp += len; 1145 } 1146 len = snprintf(kp, ks - (kp - key), "(|"); 1147 assert( len >= 0 && len < ks - (kp - key) ); 1148 kp += len; 1149 1150 for(a = op->ora_e->e_attrs; a; a = a->a_next) 1151 kp = build_filter(domain, 1152 uri, 1153 a->a_desc, 1154 a->a_vals, 1155 kp, 1156 ks - ( kp - key ), 1157 op->o_tmpmemctx); 1158 1159 len = snprintf(kp, ks - (kp - key), ")"); 1160 assert( len >= 0 && len < ks - (kp - key) ); 1161 kp += len; 1162 if ( uri->filter.bv_val && uri->filter.bv_len ) { 1163 len = snprintf(kp, ks - (kp - key), ")"); 1164 assert( len >= 0 && len < ks - (kp - key) ); 1165 kp += len; 1166 } 1167 bvkey.bv_val = key; 1168 bvkey.bv_len = kp - key; 1169 1170 rc = unique_search ( op, 1171 &nop, 1172 uri->ndn.bv_val ? 1173 &uri->ndn : 1174 &op->o_bd->be_nsuffix[0], 1175 uri->scope, 1176 rs, 1177 &bvkey); 1178 1179 if ( rc != SLAP_CB_CONTINUE ) break; 1180 } 1181 if ( rc != SLAP_CB_CONTINUE ) break; 1182 } 1183 1184 if ( locked ) { 1185 if ( rc != SLAP_CB_CONTINUE ) { 1186 ldap_pvt_thread_mutex_unlock( &private->serial_mutex ); 1187 } else { 1188 slap_callback *cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); 1189 cb->sc_cleanup = unique_unlock; 1190 cb->sc_private = private; 1191 cb->sc_next = op->o_callback; 1192 op->o_callback = cb; 1193 } 1194 } 1195 return rc; 1196} 1197 1198 1199static int 1200unique_modify( 1201 Operation *op, 1202 SlapReply *rs 1203) 1204{ 1205 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 1206 unique_data *private = (unique_data *) on->on_bi.bi_private; 1207 unique_domain *domains = private->domains; 1208 unique_domain *legacy = private->legacy; 1209 unique_domain *domain; 1210 Operation nop = *op; 1211 Modifications *m; 1212 Entry *e = NULL; 1213 char *key, *kp; 1214 struct berval bvkey; 1215 int rc = SLAP_CB_CONTINUE; 1216 int locked = 0; 1217 1218 Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n", 1219 op->o_req_dn.bv_val ); 1220 1221 if ( !op->orm_modlist ) { 1222 Debug(LDAP_DEBUG_TRACE, "unique_modify: got empty modify op\n" ); 1223 return rc; 1224 } 1225 1226 if ( SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) || ( 1227 get_relax(op) > SLAP_CONTROL_IGNORED 1228 && overlay_entry_get_ov(op, &op->o_req_ndn, NULL, NULL, 0, &e, on) == LDAP_SUCCESS 1229 && e 1230 && access_allowed( op, e, 1231 slap_schema.si_ad_entry, NULL, 1232 ACL_MANAGE, NULL ) ) ) { 1233 overlay_entry_release_ov( op, e, 0, on ); 1234 return rc; 1235 } 1236 if ( e ) { 1237 overlay_entry_release_ov( op, e, 0, on ); 1238 } 1239 1240 for ( domain = legacy ? legacy : domains; 1241 domain; 1242 domain = domain->next ) 1243 { 1244 unique_domain_uri *uri; 1245 1246 for ( uri = domain->uri; 1247 uri; 1248 uri = uri->next ) 1249 { 1250 int len; 1251 int ks = 0; 1252 1253 if ( uri->ndn.bv_val 1254 && !dnIsSuffix( &op->o_req_ndn, &uri->ndn )) 1255 continue; 1256 1257 for ( m = op->orm_modlist; m; m = m->sml_next) 1258 if ( (m->sml_op & LDAP_MOD_OP) 1259 != LDAP_MOD_DELETE ) 1260 ks += count_filter_len 1261 ( domain, 1262 uri, 1263 m->sml_desc, 1264 m->sml_values); 1265 1266 /* skip this domain-uri if it isn't involved */ 1267 if ( !ks ) continue; 1268 1269 if ( domain->serial && !locked ) { 1270 ldap_pvt_thread_mutex_lock( &private->serial_mutex ); 1271 locked = 1; 1272 } 1273 1274 /* terminating NUL */ 1275 ks += sizeof("(|)"); 1276 1277 if ( uri->filter.bv_val && uri->filter.bv_len ) 1278 ks += uri->filter.bv_len + STRLENOF ("(&)"); 1279 kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx); 1280 1281 if ( uri->filter.bv_val && uri->filter.bv_len ) { 1282 len = snprintf(kp, ks, "(&%s", uri->filter.bv_val); 1283 assert( len >= 0 && len < ks ); 1284 kp += len; 1285 } 1286 len = snprintf(kp, ks - (kp - key), "(|"); 1287 assert( len >= 0 && len < ks - (kp - key) ); 1288 kp += len; 1289 1290 for(m = op->orm_modlist; m; m = m->sml_next) 1291 if ( (m->sml_op & LDAP_MOD_OP) 1292 != LDAP_MOD_DELETE ) 1293 kp = build_filter ( domain, 1294 uri, 1295 m->sml_desc, 1296 m->sml_values, 1297 kp, 1298 ks - (kp - key), 1299 op->o_tmpmemctx ); 1300 1301 len = snprintf(kp, ks - (kp - key), ")"); 1302 assert( len >= 0 && len < ks - (kp - key) ); 1303 kp += len; 1304 if ( uri->filter.bv_val && uri->filter.bv_len ) { 1305 len = snprintf (kp, ks - (kp - key), ")"); 1306 assert( len >= 0 && len < ks - (kp - key) ); 1307 kp += len; 1308 } 1309 bvkey.bv_val = key; 1310 bvkey.bv_len = kp - key; 1311 1312 rc = unique_search ( op, 1313 &nop, 1314 uri->ndn.bv_val ? 1315 &uri->ndn : 1316 &op->o_bd->be_nsuffix[0], 1317 uri->scope, 1318 rs, 1319 &bvkey); 1320 1321 if ( rc != SLAP_CB_CONTINUE ) break; 1322 } 1323 if ( rc != SLAP_CB_CONTINUE ) break; 1324 } 1325 1326 if ( locked ) { 1327 if ( rc != SLAP_CB_CONTINUE ) { 1328 ldap_pvt_thread_mutex_unlock( &private->serial_mutex ); 1329 } else { 1330 slap_callback *cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); 1331 cb->sc_cleanup = unique_unlock; 1332 cb->sc_private = private; 1333 cb->sc_next = op->o_callback; 1334 op->o_callback = cb; 1335 } 1336 } 1337 return rc; 1338} 1339 1340 1341static int 1342unique_modrdn( 1343 Operation *op, 1344 SlapReply *rs 1345) 1346{ 1347 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 1348 unique_data *private = (unique_data *) on->on_bi.bi_private; 1349 unique_domain *domains = private->domains; 1350 unique_domain *legacy = private->legacy; 1351 unique_domain *domain; 1352 Operation nop = *op; 1353 Entry *e = NULL; 1354 char *key, *kp; 1355 struct berval bvkey; 1356 LDAPRDN newrdn; 1357 struct berval bv[2]; 1358 int rc = SLAP_CB_CONTINUE; 1359 int locked = 0; 1360 1361 Debug(LDAP_DEBUG_TRACE, "==> unique_modrdn <%s> <%s>\n", 1362 op->o_req_dn.bv_val, op->orr_newrdn.bv_val ); 1363 1364 if ( SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) || ( 1365 get_relax(op) > SLAP_CONTROL_IGNORED 1366 && overlay_entry_get_ov(op, &op->o_req_ndn, NULL, NULL, 0, &e, on) == LDAP_SUCCESS 1367 && e 1368 && access_allowed( op, e, 1369 slap_schema.si_ad_entry, NULL, 1370 ACL_MANAGE, NULL ) ) ) { 1371 overlay_entry_release_ov( op, e, 0, on ); 1372 return rc; 1373 } 1374 if ( e ) { 1375 overlay_entry_release_ov( op, e, 0, on ); 1376 } 1377 1378 for ( domain = legacy ? legacy : domains; 1379 domain; 1380 domain = domain->next ) 1381 { 1382 unique_domain_uri *uri; 1383 1384 for ( uri = domain->uri; 1385 uri; 1386 uri = uri->next ) 1387 { 1388 int i, len; 1389 int ks = 0; 1390 1391 if ( uri->ndn.bv_val 1392 && !dnIsSuffix( &op->o_req_ndn, &uri->ndn ) 1393 && (!op->orr_nnewSup 1394 || !dnIsSuffix( op->orr_nnewSup, &uri->ndn ))) 1395 continue; 1396 1397 if ( ldap_bv2rdn_x ( &op->oq_modrdn.rs_newrdn, 1398 &newrdn, 1399 (char **)&rs->sr_text, 1400 LDAP_DN_FORMAT_LDAP, 1401 op->o_tmpmemctx ) ) { 1402 op->o_bd->bd_info = (BackendInfo *) on->on_info; 1403 send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, 1404 "unknown type(s) used in RDN"); 1405 rc = rs->sr_err; 1406 break; 1407 } 1408 1409 rc = SLAP_CB_CONTINUE; 1410 for ( i=0; newrdn[i]; i++) { 1411 AttributeDescription *ad = NULL; 1412 if ( slap_bv2ad( &newrdn[i]->la_attr, &ad, &rs->sr_text )) { 1413 ldap_rdnfree_x( newrdn, op->o_tmpmemctx ); 1414 rs->sr_err = LDAP_INVALID_SYNTAX; 1415 send_ldap_result( op, rs ); 1416 rc = rs->sr_err; 1417 break; 1418 } 1419 newrdn[i]->la_private = ad; 1420 } 1421 if ( rc != SLAP_CB_CONTINUE ) break; 1422 1423 bv[1].bv_val = NULL; 1424 bv[1].bv_len = 0; 1425 1426 for ( i=0; newrdn[i]; i++ ) { 1427 bv[0] = newrdn[i]->la_value; 1428 ks += count_filter_len ( domain, 1429 uri, 1430 newrdn[i]->la_private, 1431 bv); 1432 } 1433 1434 /* skip this domain if it isn't involved */ 1435 if ( !ks ) continue; 1436 1437 if ( domain->serial && !locked ) { 1438 ldap_pvt_thread_mutex_lock( &private->serial_mutex ); 1439 locked = 1; 1440 } 1441 1442 /* terminating NUL */ 1443 ks += sizeof("(|)"); 1444 1445 if ( uri->filter.bv_val && uri->filter.bv_len ) 1446 ks += uri->filter.bv_len + STRLENOF ("(&)"); 1447 kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx); 1448 1449 if ( uri->filter.bv_val && uri->filter.bv_len ) { 1450 len = snprintf(kp, ks, "(&%s", uri->filter.bv_val); 1451 assert( len >= 0 && len < ks ); 1452 kp += len; 1453 } 1454 len = snprintf(kp, ks - (kp - key), "(|"); 1455 assert( len >= 0 && len < ks - (kp - key) ); 1456 kp += len; 1457 1458 for ( i=0; newrdn[i]; i++) { 1459 bv[0] = newrdn[i]->la_value; 1460 kp = build_filter ( domain, 1461 uri, 1462 newrdn[i]->la_private, 1463 bv, 1464 kp, 1465 ks - (kp - key ), 1466 op->o_tmpmemctx); 1467 } 1468 1469 len = snprintf(kp, ks - (kp - key), ")"); 1470 assert( len >= 0 && len < ks - (kp - key) ); 1471 kp += len; 1472 if ( uri->filter.bv_val && uri->filter.bv_len ) { 1473 len = snprintf (kp, ks - (kp - key), ")"); 1474 assert( len >= 0 && len < ks - (kp - key) ); 1475 kp += len; 1476 } 1477 bvkey.bv_val = key; 1478 bvkey.bv_len = kp - key; 1479 1480 rc = unique_search ( op, 1481 &nop, 1482 uri->ndn.bv_val ? 1483 &uri->ndn : 1484 &op->o_bd->be_nsuffix[0], 1485 uri->scope, 1486 rs, 1487 &bvkey); 1488 1489 if ( rc != SLAP_CB_CONTINUE ) break; 1490 } 1491 if ( rc != SLAP_CB_CONTINUE ) break; 1492 } 1493 1494 if ( locked ) { 1495 if ( rc != SLAP_CB_CONTINUE ) { 1496 ldap_pvt_thread_mutex_unlock( &private->serial_mutex ); 1497 } else { 1498 slap_callback *cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); 1499 cb->sc_cleanup = unique_unlock; 1500 cb->sc_private = private; 1501 cb->sc_next = op->o_callback; 1502 op->o_callback = cb; 1503 } 1504 } 1505 return rc; 1506} 1507 1508/* 1509** init_module is last so the symbols resolve "for free" -- 1510** it expects to be called automagically during dynamic module initialization 1511*/ 1512 1513int 1514unique_initialize() 1515{ 1516 int rc; 1517 1518 /* statically declared just after the #includes at top */ 1519 memset (&unique, 0, sizeof(unique)); 1520 1521 unique.on_bi.bi_type = "unique"; 1522 unique.on_bi.bi_flags = SLAPO_BFLAG_SINGLE; 1523 unique.on_bi.bi_db_init = unique_db_init; 1524 unique.on_bi.bi_db_destroy = unique_db_destroy; 1525 unique.on_bi.bi_op_add = unique_add; 1526 unique.on_bi.bi_op_modify = unique_modify; 1527 unique.on_bi.bi_op_modrdn = unique_modrdn; 1528 1529 unique.on_bi.bi_cf_ocs = uniqueocs; 1530 rc = config_register_schema( uniquecfg, uniqueocs ); 1531 if ( rc ) return rc; 1532 1533 return(overlay_register(&unique)); 1534} 1535 1536#if SLAPD_OVER_UNIQUE == SLAPD_MOD_DYNAMIC && defined(PIC) 1537int init_module(int argc, char *argv[]) { 1538 return unique_initialize(); 1539} 1540#endif 1541 1542#endif /* SLAPD_OVER_UNIQUE */ 1543