1/* dynid.c */ 2/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/dynid.c,v 1.1.2.4 2006/06/20 17:28:43 sjones Exp $ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted only as authorized by the OpenLDAP 8 * Public License. 9 * 10 * A copy of this license is available in the file LICENSE in the 11 * top-level directory of the distribution or, alternatively, at 12 * <http://www.OpenLDAP.org/license.html>. 13 */ 14 15#include "portable.h" 16 17#ifdef SLAPD_OVER_DYNID 18#include "overlayutils.h" 19 20#include <stdio.h> 21#include <uuid/uuid.h> 22 23#include <ac/string.h> 24#include <ac/ctype.h> 25#include "slap.h" 26#include "ldif.h" 27#include "config.h" 28 29#define DYNID_BACK_CONFIG 1 30static slap_overinst dynid; 31 32static AttributeDescription *dynid_memberships = NULL; 33static AttributeDescription *dynid_uuid = NULL; 34 35typedef struct dynid_objmap { 36 AttributeDescription *owneruuidAttr; 37 AttributeDescription *uuidAttr; 38 AttributeDescription *idAttr; 39 unsigned long max; 40 unsigned long min; 41 unsigned long lastid; 42 int generateuuid; 43 struct berval override_dn; 44 BerValue target_dn; 45 struct dynid_objmap *next; 46} dynid_objmap; 47 48typedef struct dynid_data { 49 struct dynid_objmap *map; 50} dynid_data; 51 52typedef struct dynid_unique_counter_s { 53 struct berval *ndn; 54 int count; 55} dynid_unique_counter; 56 57typedef struct dynid_ismember_t { 58 int found; 59} dynid_ismember_t; 60 61static int dynid_count_attr_cb( 62 Operation *op, 63 SlapReply *rs 64) 65{ 66 dynid_unique_counter *uc; 67 68 /* because you never know */ 69 if(!op || !rs) return(0); 70 71 /* Only search entries are interesting */ 72 if(rs->sr_type != REP_SEARCH) return(0); 73 74 uc = op->o_callback->sc_private; 75 76 /* Ignore the current entry */ 77 if ( dn_match( uc->ndn, &rs->sr_entry->e_nname )) return(0); 78 79 Debug(LDAP_DEBUG_TRACE, "==> count_attr_cb <%s>\n", 80 rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0); 81 82 uc->count++; 83 84 return(0); 85} 86 87static int dynid_search( 88 Operation *op, 89 Operation *nop, 90 char *key, 91 struct berval *searchbase 92) 93{ 94 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 95// unique_data *ud = on->on_bi.bi_private; 96 SlapReply nrs = { REP_RESULT }; 97 slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */ 98 dynid_unique_counter uq = { NULL, 0 }; 99 int rc; 100 101 nop->ors_filter = str2filter_x(nop, key); 102 ber_str2bv(key, 0, 0, &nop->ors_filterstr); 103 104 cb.sc_response = (slap_response*)dynid_count_attr_cb; 105 cb.sc_private = &uq; 106 nop->o_callback = &cb; 107 nop->o_tag = LDAP_REQ_SEARCH; 108 nop->ors_scope = LDAP_SCOPE_SUBTREE; 109 nop->ors_deref = LDAP_DEREF_NEVER; 110 nop->ors_limit = NULL; 111 nop->ors_slimit = SLAP_NO_LIMIT; 112 nop->ors_tlimit = SLAP_NO_LIMIT; 113 nop->ors_attrs = slap_anlist_no_attrs; 114 nop->ors_attrsonly = 1; 115 116 uq.ndn = &op->o_req_ndn; 117 118 nop->o_req_dn = *searchbase; 119 nop->o_req_ndn = *searchbase; 120 nop->o_ndn = op->o_bd->be_rootndn; 121 122 nop->o_bd = on->on_info->oi_origdb; 123 rc = nop->o_bd->be_search(nop, &nrs); 124 125 if (rc == LDAP_NO_SUCH_OBJECT) { 126 Debug(LDAP_DEBUG_TRACE, "=> dynid_search LDAP_NO_SUCH_OBJECT\n", 0, 0, 0); 127 return (0); 128 } 129 if(rc != LDAP_SUCCESS) { 130 op->o_bd->bd_info = (BackendInfo *) on->on_info; 131 Debug(LDAP_DEBUG_TRACE, "=> dynid_search failed (%ld)\n", rc, 0, 0); 132 return(-1); 133 } 134 135 Debug(LDAP_DEBUG_TRACE, "=> dynid_search found %d records\n", uq.count, 0, 0); 136 137 if(uq.count) { 138 op->o_bd->bd_info = (BackendInfo *) on->on_info; 139 Debug(LDAP_DEBUG_TRACE, "=> dynid_search not unique - count(%d)\n", uq.count, 0, 0); 140 return(-1); 141 } 142 143 return(0); 144} 145 146static __attribute__ ((noinline)) int dynid_addownerguid(Operation *op, SlapReply *rs) 147{ 148 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 149 dynid_data *ad = on->on_bi.bi_private; 150 dynid_objmap *ddmap = ad->map; 151 int rc = -1; 152 Entry *e = NULL; 153 154 int cache = op->o_do_not_cache; 155 struct berval op_dn = op->o_dn, 156 op_ndn = op->o_ndn; 157 BackendDB *op_bd = op->o_bd; 158 BackendDB *target_bd = NULL; 159 struct berval *target_ndn = NULL; 160 Attribute *owneruuidAttr = NULL; 161 162 if (!ddmap->owneruuidAttr || !ddmap->uuidAttr || BER_BVISNULL(&op->o_ndn)) { 163 goto cleanup; 164 }; 165 166 target_bd = select_backend( &op->o_req_ndn, 0); 167 target_ndn = &op_ndn; 168 169 if (target_bd) { 170 //op->o_do_not_cache = 1; 171 op->o_dn = op->o_bd->be_rootdn; 172 op->o_ndn = op->o_bd->be_rootndn; 173 op->o_bd = target_bd; 174 175 if (op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { 176 Debug(LDAP_DEBUG_TRACE, "=> dynid_addownerguid CURRENT Authenticated PROXY User\n", 0, 0, 0); 177 rc = attr_merge_one( op->oq_add.rs_e, ddmap->owneruuidAttr, &op->o_conn->c_authz.c_sai_krb5_pac_id, NULL ); 178 } else { 179 rc = be_entry_get_rw( op, target_ndn, NULL, ddmap->uuidAttr, 0, &e ); 180 if ( e != NULL ) { 181 dump_slap_entry(e); 182 183 owneruuidAttr = attr_find( op->oq_add.rs_e->e_attrs, ddmap->owneruuidAttr ); 184 if (owneruuidAttr) { 185 Debug(LDAP_DEBUG_TRACE, "=> dynid_addownerguid SUGGESTED Owner\n", 0, 0, 0); 186 dump_slap_attr(owneruuidAttr); 187 rc = attr_delete(&(op->oq_add.rs_e->e_attrs), ddmap->owneruuidAttr ); 188 owneruuidAttr = NULL; 189 } 190 owneruuidAttr = attr_find( e->e_attrs, ddmap->uuidAttr ); 191 if (owneruuidAttr) { 192 Debug(LDAP_DEBUG_TRACE, "=> dynid_addownerguid CURRENT Authenticated User\n", 0, 0, 0); 193 dump_slap_attr(owneruuidAttr); 194 195 rc = attr_merge_one( op->oq_add.rs_e, ddmap->owneruuidAttr, owneruuidAttr->a_vals, NULL ); 196 } 197 be_entry_release_rw( op, e, 0 ); 198 } 199 } 200 op->o_do_not_cache = cache; 201 op->o_dn = op_dn; 202 op->o_ndn = op_ndn; 203 op->o_bd = op_bd; 204 } 205 if(rc != LDAP_SUCCESS) { 206 Debug(LDAP_DEBUG_TRACE, "=> dynid_addownerguid be_entry_get_rw failed (%ld)\n", rc, 0, 0); 207 return(rc); 208 } 209 210cleanup: 211 return rc; 212} 213 214static __attribute__ ((noinline)) int dynid_addownerguidextended(Operation *op, SlapReply *rs) 215{ 216 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 217 dynid_data *ad = on->on_bi.bi_private; 218 dynid_objmap *ddmap = ad->map; 219 int rc = -1; 220 Entry *e = NULL; 221 222 int cache = op->o_do_not_cache; 223 struct berval op_dn = op->o_dn, 224 op_ndn = op->o_ndn; 225 BackendDB *op_bd = op->o_bd; 226 BackendDB *target_bd = NULL; 227 struct berval *target_ndn = NULL; 228 Attribute *owneruuidAttr = NULL; 229 230 if (!ddmap->owneruuidAttr || !ddmap->uuidAttr || BER_BVISNULL(&op->o_ndn)) { 231 goto cleanup; 232 }; 233 234 target_bd = select_backend( &op->o_req_ndn, 0); 235 target_ndn = &op->o_ndn; 236 237 if (target_bd) { 238 rc = be_entry_get_rw( op, target_ndn, NULL, ddmap->uuidAttr, 0, &e ); 239 if ( e != NULL ) { 240 dump_slap_entry(e); 241 242 owneruuidAttr = attr_find( op->oq_add.rs_e->e_attrs, ddmap->owneruuidAttr ); 243 if (owneruuidAttr) { 244 Debug(LDAP_DEBUG_TRACE, "=> dynid_addownerguid SUGGESTED Owner\n", 0, 0, 0); 245 dump_slap_attr(owneruuidAttr); 246 rc = attr_delete(&(op->oq_add.rs_e->e_attrs), ddmap->owneruuidAttr ); 247 owneruuidAttr = NULL; 248 } 249 owneruuidAttr = attr_find( e->e_attrs, ddmap->uuidAttr ); 250 if (owneruuidAttr) { 251 Debug(LDAP_DEBUG_TRACE, "=> dynid_addownerguid CURRENT Authenticated User\n", 0, 0, 0); 252 dump_slap_attr(owneruuidAttr); 253 254 rc = attr_merge_one( op->oq_add.rs_e, ddmap->owneruuidAttr, owneruuidAttr->a_vals, NULL ); 255 } 256 be_entry_release_rw( op, e, 0 ); 257 } 258 259 } 260 if(rc != LDAP_SUCCESS) { 261 Debug(LDAP_DEBUG_TRACE, "=> dynid_addownerguid be_entry_get_rw failed (%ld)\n", rc, 0, 0); 262 return(rc); 263 } 264 265cleanup: 266 return rc; 267} 268 269static __attribute__ ((noinline)) int dynid_generate_id(Operation *op) 270{ 271 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 272 dynid_data *ad = on->on_bi.bi_private; 273 dynid_objmap *ddmap = ad->map; 274 Attribute *idNumber = NULL; 275 const char *text = NULL; 276 int rc = 0; 277 int isUnique = 1; 278 Operation nop = *op; 279 struct berval bv = {0}; 280 struct berval searchbase = {0}; 281 char tmp[150] = {0}; 282 283 if ( ddmap->lastid < ddmap->max) 284 { 285 for (ddmap->lastid++; (ddmap->lastid > ddmap->min) && (ddmap->lastid < ddmap->max) && !isUnique; ddmap->lastid++) 286 { 287 snprintf(tmp, sizeof(tmp),"(%s=%ld)",ddmap->idAttr->ad_cname.bv_val, ddmap->lastid); 288 } 289 } else { 290 Debug( LDAP_DEBUG_TRACE, "#####dynid_generate_id OUT OF IDs max[%d]#####\n", ddmap->lastid, 0, 0); 291 } 292 293 if (isUnique) 294 { 295 snprintf(tmp, sizeof(tmp), "%ld", ddmap->lastid); 296 Debug( LDAP_DEBUG_TRACE, "#####[NEW ID][%d][%s]#####\n", ddmap->lastid, tmp, 0); 297 ber_str2bv( tmp, 0, 0, &bv ); 298 dump_berval(&bv); 299 rc = attr_delete(&(op->oq_add.rs_e->e_attrs), ddmap->idAttr ); 300 rc = attr_merge_one( op->oq_add.rs_e, ddmap->idAttr, &bv, NULL ); 301 302 idNumber = attr_find( op->oq_add.rs_e->e_attrs, ddmap->idAttr ); 303 if (idNumber) 304 { 305 dump_slap_attr(idNumber); 306 } else { 307 Debug( LDAP_DEBUG_TRACE, "#####[idNumber - NOT FOUND]#####\n", 0, 0, 0); 308 } 309 } 310 311 op->o_tag = LDAP_REQ_ADD; 312 return rc; 313} 314static __attribute__ ((noinline)) int dynid_generate_uuid(Operation *op) 315{ 316 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 317 dynid_data *ad = on->on_bi.bi_private; 318 dynid_objmap *ddmap = ad->map; 319 struct berval bv; 320 Attribute *uuidAttr = NULL; 321 const char *text; 322 int rc = -1; 323 char uuidStr[512] = {0}; 324 uuid_t uu; 325 326 if (ddmap->uuidAttr) 327 { 328 uuidAttr = attr_find( op->oq_add.rs_e->e_attrs, ddmap->uuidAttr ); 329 if (uuidAttr) 330 { 331 dump_slap_attr(uuidAttr); 332 rc = attr_delete(&(op->oq_add.rs_e->e_attrs), ddmap->uuidAttr ); 333 } 334 335 uuid_generate(uu); 336 uuid_unparse(uu,uuidStr); 337 ber_str2bv( uuidStr, 0, 0, &bv ); 338 rc = attr_merge_one( op->oq_add.rs_e, ddmap->uuidAttr, &bv, NULL ); 339 } 340 341 return rc; 342} 343 344dynid_is_member_cb ( 345 Operation *op, 346 SlapReply *rs 347) 348{ 349 Debug(LDAP_DEBUG_TRACE, "dynid_is_member_cb sr_type[%d] sr_err[%d]\n", rs->sr_type, rs->sr_err, 0); 350 dynid_ismember_t *ismember = (dynid_ismember_t *)op->o_callback->sc_private; 351 352 if (rs->sr_err == LDAP_COMPARE_TRUE) 353 ismember->found = 1; 354 else 355 ismember->found = 0; 356 357 return 0; 358} 359 360 361static int __attribute__ ((noinline)) 362dynid_is_member ( 363 Operation *op, 364 struct berval* groupDN, 365 AttributeDescription *searchAttr, 366 struct berval* searchID, 367 int * result) 368{ 369 Operation nop = *op; 370 AttributeAssertion ava = { NULL, BER_BVNULL }; 371 SlapReply sreply = {REP_RESULT}; 372 slap_callback cb = { NULL, dynid_is_member_cb, NULL, NULL }; 373 BackendDB *target_bd = NULL; 374 dynid_ismember_t ismember = {0}; 375 int rc = 0; 376 377 target_bd = select_backend(&op->o_req_ndn, 0); 378 379 if (!target_bd || !target_bd->be_compare) 380 return LDAP_NOT_SUPPORTED; 381 382 sreply.sr_entry = NULL; 383 sreply.sr_nentries = 0; 384 385 nop.orc_ava = &ava; 386 nop.orc_ava->aa_desc = searchAttr; 387 nop.orc_ava->aa_value = *searchID; 388 389 nop.o_tag = LDAP_REQ_COMPARE; 390 nop.o_protocol = LDAP_VERSION3; 391 nop.o_callback = &cb; 392 nop.o_time = slap_get_time(); 393 nop.o_do_not_cache = 0; 394 nop.o_dn = target_bd->be_rootdn; 395 nop.o_ndn = target_bd->be_rootndn; 396 nop.o_bd = target_bd; 397 398 nop.o_req_dn = *groupDN; 399 nop.o_req_ndn = *groupDN; 400 cb.sc_private = &ismember; 401 402 rc = nop.o_bd->be_compare( &nop, &sreply ); 403 Debug(LDAP_DEBUG_TRACE, "dynid_is_member be_compare[%d] ismember[%d]\n", rc, ismember.found, 0); 404 if (ismember.found) 405 *result = 1; 406 else 407 *result = 0; 408 return 0; 409} 410 411static int __attribute__ ((noinline)) dynid_is_match(Operation *op) 412{ 413 Attribute *oc = NULL, *idNumber = NULL; 414 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 415 dynid_data *ad = on->on_bi.bi_private; 416 dynid_objmap *ddmap = ad->map; 417 const char *text = NULL; 418 Operation nop = *op; 419 Entry *theEntry = NULL; 420 int rc = LDAP_COMPARE_FALSE, entry_rc = -1; 421 struct berval op_dn = op->o_dn, 422 op_ndn = op->o_ndn; 423 BackendDB *op_bd = op->o_bd; 424 BackendDB *target_bd = NULL; 425 struct berval *target_ndn = NULL; 426 427 428 if (!BER_BVISNULL(&op->o_req_ndn) && !BER_BVISNULL(&ddmap->target_dn) && dnIsSuffix(&op->o_req_ndn, &ddmap->target_dn)) { 429 if (!BER_BVISNULL(&ddmap->override_dn) && !op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { 430 rc = LDAP_COMPARE_FALSE; 431 432 target_bd = select_backend( &op->o_req_ndn, 0); 433 target_ndn = &op_ndn; 434 435 if (target_bd && !BER_BVISNULL(&op_ndn)) { 436 op->o_dn = op->o_bd->be_rootdn; 437 op->o_ndn = op->o_bd->be_rootndn; 438 op->o_bd = target_bd; 439 440 entry_rc = be_entry_get_rw( op, &op_ndn, NULL , dynid_uuid, 0, &theEntry ); // user uuid 441 Debug( LDAP_DEBUG_TRACE, "#####dynid_is_match be_entry_get_rw [%d] [%s]#####\n", entry_rc, op_ndn.bv_val, 0); 442 443 if (entry_rc == LDAP_SUCCESS && theEntry) { 444 Attribute *uuidAttr = NULL; 445 int isMember = 0; 446 447 uuidAttr = attr_find( theEntry->e_attrs, dynid_uuid); 448 if (uuidAttr) { 449 dynid_is_member ( op, &ddmap->override_dn, dynid_memberships, uuidAttr->a_nvals , &isMember); 450 if (isMember) { // override 451 rc = LDAP_COMPARE_FALSE; 452 } else { 453 rc = LDAP_COMPARE_TRUE; 454 } 455 } 456 } 457 458 if (theEntry) 459 be_entry_release_r(op, theEntry); 460 461 462 op->o_dn = op_dn; 463 op->o_ndn = op_ndn; 464 op->o_bd = op_bd; 465 } 466 } else { 467 rc = LDAP_COMPARE_TRUE; 468 } 469 } else { 470 rc = LDAP_COMPARE_FALSE; 471 } 472 473 return rc; 474} 475 476 477static int dynid_add(Operation *op, SlapReply *rs) { 478 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 479 dynid_data *ad = on->on_bi.bi_private; 480 dynid_objmap *ddmap = ad->map; 481 482 if ( rs->sr_err != LDAP_SUCCESS ) return SLAP_CB_CONTINUE; 483 484 if ( !op->o_bd ) return SLAP_CB_CONTINUE; 485 486 switch(op->o_tag) { 487 case LDAP_REQ_ADD: 488 //Debug( LDAP_DEBUG_TRACE, "dynid: LDAP_REQ_ADD[%s]\n", op->o_req_dn.bv_val, 0, 0); 489 if (dynid_is_match(op) == LDAP_COMPARE_TRUE) 490 { 491 if (ddmap->idAttr) 492 { 493 dynid_generate_id(op); 494 } 495 if (ddmap->uuidAttr) 496 { 497 dynid_generate_uuid(op); 498 } 499 if (ddmap->owneruuidAttr) 500 { 501 dynid_addownerguid(op, rs); 502 } 503 } 504 break; 505 default: 506 return SLAP_CB_CONTINUE; 507 } 508 return SLAP_CB_CONTINUE; 509} 510 511static int 512dynid_db_init( 513 BackendDB *be 514) 515{ 516 slap_overinst *on = (slap_overinst *)be->bd_info; 517 dynid_data *dd = ch_calloc(1, sizeof(dynid_data)); 518 519 on->on_bi.bi_private = dd; 520 return 0; 521} 522 523static int 524dynid_db_close( 525 BackendDB *be 526) 527{ 528 slap_overinst *on = (slap_overinst *)be->bd_info; 529 dynid_data *dd = on->on_bi.bi_private; 530} 531 532static int 533dynid_db_destroy( 534 BackendDB *be 535) 536{ 537 slap_overinst *on = (slap_overinst *)be->bd_info; 538 dynid_data *dd = on->on_bi.bi_private; 539 540 if (dd) 541 free( dd ); 542} 543 544#ifdef DYNID_BACK_CONFIG 545 546enum { 547 DI_RANGE = 1, 548 DI_GUID, 549 DI_OWNERGUID, 550 DI_OVERRIDE, 551 DI_LAST 552}; 553 554static ConfigDriver di_cfgen; 555 556static ConfigTable dicfg[] = { 557 { "dynid-range", "dn> <attribute> <minimum> <maximum", 558 4, 5, 0, ARG_MAGIC|DI_RANGE, di_cfgen, 559 "( OLcfgOvAt:700.1 NAME 'olcDIRange' " 560 "DESC 'Dynamic ID Range: <dn>, <attributeDescription>, <minimum>, <maximum>' " 561 "EQUALITY caseIgnoreMatch " 562 "SYNTAX OMsDirectoryString )", 563 NULL, NULL }, 564 { "dynid-generateduid", "dn> <ad", 565 2, 3, 0, ARG_MAGIC|DI_GUID, di_cfgen, 566 "( OLcfgOvAt:700.2 NAME 'olcDIGUIDGen' " 567 "DESC 'Dynamic ID GUID Generation: <dn>, <attributeDescription>' " 568 "EQUALITY caseIgnoreMatch " 569 "SYNTAX OMsDirectoryString )", 570 NULL, NULL }, 571 { "dynid-owneruuid", "dn> <ad", 572 2, 3, 0, ARG_MAGIC|DI_OWNERGUID, di_cfgen, 573 "( OLcfgOvAt:700.3 NAME 'olcDIOwnerGUIDGen' " 574 "DESC 'Dynamic ID Owner GUID Generation: <dn>, <attributeDescription>' " 575 "EQUALITY caseIgnoreMatch " 576 "SYNTAX OMsDirectoryString )", 577 NULL, NULL }, 578 { "dynid-override", "dn> <override dn>", 579 2, 3, 0, ARG_MAGIC|DI_OVERRIDE, di_cfgen, 580 "( OLcfgOvAt:700.4 NAME 'olcDIOverride' " 581 "DESC 'Dynamic ID Override: <dn>, <override dn>' " 582 "EQUALITY caseIgnoreMatch " 583 "SYNTAX OMsDirectoryString )", 584 NULL, NULL }, 585 { NULL, NULL, 0, 0, 0, ARG_IGNORED } 586}; 587 588static ConfigOCs diocs[] = { 589 { "( OLcfgOvOc:700.1 " 590 "NAME 'olcDynamicID' " 591 "DESC 'Dynamic id configuration' " 592 "SUP olcOverlayConfig " 593 "MAY (olcDIRange $ olcDIGUIDGen $ olcDIOwnerGUIDGen $ olcDIOverride) )", 594 Cft_Overlay, dicfg, NULL, NULL }, 595 { NULL, 0, NULL } 596}; 597 598static int 599di_cfgen( ConfigArgs *c ) 600{ 601 slap_overinst *on = (slap_overinst *)c->bi; 602 dynid_data *dd = (dynid_data *)on->on_bi.bi_private; 603 dynid_objmap *ddmap = NULL; 604 const char *text = NULL; 605 606 int rc = 0, i; 607 608 if (dynid_memberships == NULL) { 609 rc = slap_str2ad( "apple-group-memberguid", &dynid_memberships, &text ); 610 if ( rc != LDAP_SUCCESS ) { 611 Debug(LDAP_DEBUG_CONFIG, "=> [%d]dynid_initialize apple-group-memberguid error\n", rc, 0, 0); 612 return rc; 613 } 614 } 615 616 if (dynid_uuid == NULL) { 617 rc = slap_str2ad( "apple-generateduid", &dynid_uuid, &text ); 618 if ( rc != LDAP_SUCCESS ) { 619 Debug(LDAP_DEBUG_CONFIG, "=> [%d]dynid_initialize apple-generateduid error\n", rc, 0, 0); 620 return rc; 621 } 622 } 623 624 if ( c->op == SLAP_CONFIG_EMIT ) { 625 switch( c->type ) { 626 case DI_RANGE: 627 if ( dd && dd->map && !BER_BVISNULL(&dd->map->target_dn) && dd->map->idAttr) { 628 struct berval bv; 629 bv.bv_len = sprintf( c->cr_msg, "%s %s %d %d", 630 dd->map->target_dn.bv_val, dd->map->idAttr->ad_cname.bv_val, dd->map->min, dd->map->max ); 631 bv.bv_val = c->cr_msg; 632 value_add_one( &c->rvalue_vals, &bv ); 633 Debug(LDAP_DEBUG_CONFIG, "[SLAP_CONFIG_EMIT] dynid-range dn (%s) AttributeDescription (%s)\n", dd->map->target_dn.bv_val, dd->map->idAttr->ad_cname.bv_val, 0); 634 Debug(LDAP_DEBUG_CONFIG, "[SLAP_CONFIG_EMIT] dynid-range minimum (%d) maximum (%d)\n", dd->map->min, dd->map->max, 0); 635 } else { 636 rc = 1; 637 } 638 break; 639 640 case DI_GUID: 641 if ( dd && dd->map && !BER_BVISNULL(&dd->map->target_dn) && dd->map->uuidAttr) { 642 struct berval bv; 643 bv.bv_len = sprintf( c->cr_msg, "%s %s", 644 dd->map->target_dn.bv_val, dd->map->uuidAttr->ad_cname.bv_val); 645 bv.bv_val = c->cr_msg; 646 value_add_one( &c->rvalue_vals, &bv ); 647 Debug(LDAP_DEBUG_CONFIG, "[SLAP_CONFIG_EMIT] dynid-generateuuid dn (%s) AttributeDescription (%s)\n", dd->map->target_dn.bv_val, dd->map->uuidAttr->ad_cname.bv_val, 0); 648 } else { 649 rc = 1; 650 } 651 break; 652 653 case DI_OWNERGUID: 654 if ( dd && dd->map && !BER_BVISNULL(&dd->map->target_dn) && dd->map->owneruuidAttr) { 655 struct berval bv; 656 bv.bv_len = sprintf( c->cr_msg, "%s %s", 657 dd->map->target_dn.bv_val, dd->map->owneruuidAttr->ad_cname.bv_val); 658 bv.bv_val = c->cr_msg; 659 value_add_one( &c->rvalue_vals, &bv ); 660 Debug(LDAP_DEBUG_CONFIG, "[SLAP_CONFIG_EMIT] dynid-owneruuid dn (%s) AttributeDescription (%s)\n", dd->map->target_dn.bv_val, dd->map->owneruuidAttr->ad_cname.bv_val, 0); 661 } else { 662 rc = 1; 663 } 664 break; 665 666 case DI_OVERRIDE: 667 if ( dd && dd->map && !BER_BVISNULL(&dd->map->target_dn) && !BER_BVISNULL(&dd->map->override_dn)) { 668 struct berval bv; 669 bv.bv_len = sprintf( c->cr_msg, "%s %s", dd->map->target_dn.bv_val, dd->map->override_dn.bv_val); 670 bv.bv_val = c->cr_msg; 671 value_add_one( &c->rvalue_vals, &bv ); 672 Debug(LDAP_DEBUG_CONFIG, "[SLAP_CONFIG_EMIT] dynid-override dn (%s)\n", dd->map->target_dn.bv_val, dd->map->override_dn.bv_val, 0); 673 } else { 674 rc = 1; 675 } 676 break; 677 678 default: 679 rc = 1; 680 break; 681 } 682 683 return rc; 684 685 } 686 687 switch( c->type ) { 688 case DI_RANGE: { 689 struct berval target = {0}; 690 AttributeDescription *ad = NULL, 691 *member_ad = NULL; 692 int minimum, maximum; 693 char *next; 694 const char *text; 695 696 ber_str2bv( c->argv[ 1 ], 0, 0, &target ); 697 if (BER_BVISNULL(&target)) { 698 Debug(LDAP_DEBUG_CONFIG, "=> dynid-range - target not defined\n", 0, 0, 0); 699 return ARG_BAD_CONF; 700 } 701 Debug(LDAP_DEBUG_CONFIG, "=> dynid-range dn(%s) [%s]\n", c->argv[ 1 ], target.bv_val, 0); 702 703 rc = slap_str2ad( c->argv[ 2 ], &ad, &text ); 704 if ( rc != LDAP_SUCCESS ) { 705 snprintf( c->cr_msg, sizeof( c->cr_msg ), 706 "\"dynid-range [<dn>] [<id attribute>] [minimum] [maximum]\": " 707 "unable to find AttributeDescription \"%s\"", 708 c->argv[ 2 ] ); 709 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 710 c->log, c->cr_msg, 0 ); 711 return ARG_BAD_CONF; 712 } 713 Debug(LDAP_DEBUG_CONFIG, "=> dynid-range AttributeDescription (%s)\n", ad->ad_cname.bv_val, 0, 0); 714 715 minimum = strtol(c->argv[ 3 ], &next, 10); 716 if ( next == NULL || next[0] != '\0' ) { 717 snprintf( c->cr_msg, sizeof( c->cr_msg ), 718 "\"dynid-range [<dn>] [<id attribute>] [minimum] [maximum]\": " 719 "unable to parse minimum id \"%s\"\n", 720 c->argv[ 3 ] ); 721 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 722 c->log, c->cr_msg, 0 ); 723 return 1; 724 } 725 Debug(LDAP_DEBUG_CONFIG, "=> dynid-range minimum (%d)\n", minimum, 0, 0); 726 727 maximum = strtol(c->argv[4], &next, 10); 728 if ( next == NULL || next[0] != '\0' ) { 729 snprintf( c->cr_msg, sizeof( c->cr_msg ), 730 "\"dynid-range [<dn>] [<id attribute>] [minimum] [maximum]\": " 731 "unable to parse maximum id \"%s\"\n", 732 c->argv[ 4 ] ); 733 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 734 c->log, c->cr_msg, 0 ); 735 return ARG_BAD_CONF; 736 } 737 Debug(LDAP_DEBUG_CONFIG, "=> dynid-range maximum (%d)\n", maximum, 0, 0); 738 739 for ( ddmap = dd->map; ddmap != NULL; ddmap = ddmap->next ) 740 { 741 if ( dn_match(&ddmap->target_dn, &target) ) { 742 snprintf( c->cr_msg, sizeof( c->cr_msg ), 743 "\"dynid-range \": " 744 "dn \"%s\" already mapped (reuse).\n", 745 ddmap->target_dn.bv_val ); 746 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 747 c->log, c->cr_msg, 0 ); 748 break; 749 } 750 } 751 752 if (!ddmap) 753 { 754 ddmap = (dynid_objmap *)ch_calloc( 1, sizeof( dynid_objmap ) ); 755 ber_dupbv (&ddmap->target_dn, &target); 756 ddmap->next = dd->map; 757 dd->map = ddmap; 758 } 759 760 ddmap->idAttr = ad; 761 ddmap->min = minimum; 762 ddmap->max = maximum; 763 ddmap->lastid = minimum; 764 765 } break; 766 767 case DI_GUID: { 768 struct berval target = {0}; 769 AttributeDescription *uuidAd = NULL; 770 const char *text; 771 772 ber_str2bv( c->argv[ 1 ], 0, 0, &target ); 773 if (BER_BVISNULL(&target)) { 774 Debug(LDAP_DEBUG_CONFIG, "=> dynid-generateuuid - target not defined\n", 0, 0, 0); 775 return ARG_BAD_CONF; 776 } 777 Debug(LDAP_DEBUG_CONFIG, "=> dynid-generateuuid dn(%s) [%s]\n", c->argv[ 1 ], target.bv_val, 0); 778 779 rc = slap_str2ad( c->argv[ 2 ], &uuidAd, &text ); 780 if ( rc != LDAP_SUCCESS ) { 781 snprintf( c->cr_msg, sizeof( c->cr_msg ), 782 "\"dynid-generateuuid [<oc>] [<id attribute>]\": " 783 "unable to find AttributeDescription \"%s\"", 784 c->argv[ 2 ] ); 785 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 786 c->log, c->cr_msg, 0 ); 787 return ARG_BAD_CONF; 788 } 789 Debug(LDAP_DEBUG_CONFIG, "=> dynid-generateuuid AttributeDescription (%s)\n", uuidAd->ad_cname.bv_val, 0, 0); 790 791 for ( ddmap = dd->map; ddmap != NULL; ddmap = ddmap->next ) 792 { 793 if ( dn_match(&ddmap->target_dn, &target) ) { 794 snprintf( c->cr_msg, sizeof( c->cr_msg ), 795 "\"dynid-generateuuid \": " 796 "dn \"%s\" already mapped (reuse).\n", 797 ddmap->target_dn.bv_val ); 798 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 799 c->log, c->cr_msg, 0 ); 800 break; 801 } 802 } 803 804 if (!ddmap) 805 { 806 ddmap = (dynid_objmap *)ch_calloc( 1, sizeof( dynid_objmap ) ); 807 ber_dupbv (&ddmap->target_dn, &target); 808 ddmap->next = dd->map; 809 dd->map = ddmap; 810 } 811 812 ddmap->uuidAttr = uuidAd; 813 814 815 } break; 816 817 case DI_OWNERGUID: { 818 struct berval target = {0}; 819 AttributeDescription *owneruuidAd = NULL; 820 const char *text; 821 822 ber_str2bv( c->argv[ 1 ], 0, 0, &target ); 823 if (BER_BVISNULL(&target)) { 824 Debug(LDAP_DEBUG_CONFIG, "=> dynid-owneruuid - target not defined\n", 0, 0, 0); 825 return ARG_BAD_CONF; 826 } 827 Debug(LDAP_DEBUG_CONFIG, "=> dynid-owneruuid dn(%s) [%s]\n", c->argv[ 1 ], target.bv_val, 0); 828 829 rc = slap_str2ad( c->argv[ 2 ], &owneruuidAd, &text ); 830 if ( rc != LDAP_SUCCESS ) { 831 snprintf( c->cr_msg, sizeof( c->cr_msg ), 832 "\"dynid-owneruuid [<oc>] [<id attribute>]\": " 833 "unable to find AttributeDescription \"%s\"", 834 c->argv[ 2 ] ); 835 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 836 c->log, c->cr_msg, 0 ); 837 return ARG_BAD_CONF; 838 } 839 Debug(LDAP_DEBUG_CONFIG, "=> dynid-owneruuid AttributeDescription (%s)\n", owneruuidAd->ad_cname.bv_val, 0, 0); 840 841 for ( ddmap = dd->map; ddmap != NULL; ddmap = ddmap->next ) 842 { 843 if ( dn_match(&ddmap->target_dn, &target) ) { 844 snprintf( c->cr_msg, sizeof( c->cr_msg ), 845 "\"dynid-owneruuid \": " 846 "dn \"%s\" already mapped (reuse).\n", 847 ddmap->target_dn.bv_val ); 848 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 849 c->log, c->cr_msg, 0 ); 850 break; 851 } 852 } 853 854 if (!ddmap) 855 { 856 ddmap = (dynid_objmap *)ch_calloc( 1, sizeof( dynid_objmap ) ); 857 ber_dupbv (&ddmap->target_dn, &target); 858 ddmap->next = dd->map; 859 dd->map = ddmap; 860 } 861 862 ddmap->owneruuidAttr = owneruuidAd; 863 864 865 } break; 866 867 case DI_OVERRIDE: { 868 struct berval target = {0}; 869 struct berval override = {0}; 870 AttributeDescription *owneruuidAd = NULL; 871 const char *text; 872 873 ber_str2bv( c->argv[ 1 ], 0, 0, &target ); 874 if (BER_BVISNULL(&target)) { 875 Debug(LDAP_DEBUG_CONFIG, "=> dynid-override - target not defined\n", 0, 0, 0); 876 return ARG_BAD_CONF; 877 } 878 Debug(LDAP_DEBUG_CONFIG, "=> dynid-override target dn(%s) [%s]\n", c->argv[ 1 ], target.bv_val, 0); 879 880 ber_str2bv( c->argv[ 2 ], 0, 0, &override ); 881 if (BER_BVISNULL(&override)) { 882 Debug(LDAP_DEBUG_CONFIG, "=> dynid-override - override not defined\n", 0, 0, 0); 883 return ARG_BAD_CONF; 884 } 885 Debug(LDAP_DEBUG_CONFIG, "=> dynid-override override dn(%s) [%s]\n", c->argv[ 2 ], override.bv_val, 0); 886 887 for ( ddmap = dd->map; ddmap != NULL; ddmap = ddmap->next ) 888 { 889 if ( dn_match(&ddmap->target_dn, &target) ) { 890 snprintf( c->cr_msg, sizeof( c->cr_msg ), 891 "\"dynid-override \": " 892 "dn \"%s\" already mapped (reuse).\n", 893 ddmap->target_dn.bv_val ); 894 Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", 895 c->log, c->cr_msg, 0 ); 896 break; 897 } 898 } 899 900 if (!ddmap) 901 { 902 ddmap = (dynid_objmap *)ch_calloc( 1, sizeof( dynid_objmap ) ); 903 ber_dupbv (&ddmap->target_dn, &target); 904 ddmap->next = dd->map; 905 dd->map = ddmap; 906 } 907 908 ber_dupbv (&ddmap->override_dn, &override); 909 } break; 910 911 default: 912 rc = 1; 913 break; 914 } 915 916 return rc; 917} 918#endif 919int dynid_initialize() { 920 int rc = 0; 921 922 memset( &dynid, 0, sizeof( slap_overinst ) ); 923 924 dynid.on_bi.bi_type = "dynid"; 925 dynid.on_bi.bi_db_init = dynid_db_init; 926 dynid.on_bi.bi_op_add = dynid_add; 927 dynid.on_bi.bi_db_close = dynid_db_close; 928 dynid.on_bi.bi_db_destroy = dynid_db_destroy; 929 930 dynid.on_bi.bi_db_config = config_generic_wrapper; 931 dynid.on_bi.bi_cf_ocs = diocs; 932 933 rc = config_register_schema( dicfg, diocs ); 934 if ( rc ) { 935 return rc; 936 } 937 938 return overlay_register(&dynid); 939} 940 941#if SLAPD_OVER_dynid == SLAPD_MOD_DYNAMIC && defined(PIC) 942int 943init_module( int argc, char *argv[] ) 944{ 945 return dynid_initialize(); 946} 947#endif 948 949#endif /* SLAPD_OVER_DYNID */ 950