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