1/*	$NetBSD: rbac.c,v 1.2 2021/08/14 16:14:53 christos Exp $	*/
2
3/* rbac.c - RBAC main file */
4/* $OpenLDAP$ */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2013-2021 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18/* ACKNOWLEDGEMENTS:
19 */
20
21#include <sys/cdefs.h>
22__RCSID("$NetBSD: rbac.c,v 1.2 2021/08/14 16:14:53 christos Exp $");
23
24#include "portable.h"
25
26#include <stdio.h>
27
28#include <ac/string.h>
29
30#include "slap.h"
31#include "slap-config.h"
32#include "lutil.h"
33
34#include "rbac.h"
35
36#define RBAC_REQ 1
37
38static slap_overinst rbac;
39
40static struct berval slap_EXOP_CREATE_SESSION =
41		BER_BVC(LDAP_RBAC_EXOP_CREATE_SESSION);
42static struct berval slap_EXOP_CHECK_ACCESS =
43		BER_BVC(LDAP_RBAC_EXOP_CHECK_ACCESS);
44static struct berval slap_EXOP_ADD_ACTIVE_ROLE =
45		BER_BVC(LDAP_RBAC_EXOP_ADD_ACTIVE_ROLE);
46static struct berval slap_EXOP_DROP_ACTIVE_ROLE =
47		BER_BVC(LDAP_RBAC_EXOP_DROP_ACTIVE_ROLE);
48static struct berval slap_EXOP_DELETE_SESSION =
49		BER_BVC(LDAP_RBAC_EXOP_DELETE_SESSION);
50static struct berval slap_EXOP_SESSION_ROLES =
51		BER_BVC(LDAP_RBAC_EXOP_SESSION_ROLES);
52
53rbac_tenant_t rbac_tenants = {
54	{
55		.schema = &slap_rbac_jts_schema,
56	},
57	NULL
58};
59
60static ConfigDriver rbac_cf_gen;
61
62static ConfigTable rbaccfg[] = {
63	{ "rbac-default-users-base-dn", "usersDN", 2, 2, 0,
64		ARG_MAGIC|ARG_DN|RBAC_DEFAULT_USERS_BASE_DN,
65		rbac_cf_gen,
66		"(OLcfgCtAt:7.1 NAME 'olcRBACDefaultUsersBaseDn' "
67			"DESC 'default Base DN for RBAC users ' "
68			"SYNTAX OMsDirectoryString "
69			"SINGLE-VALUE )",
70		NULL, NULL
71	},
72	{ "rbac-default-roles-base-dn", "rolesDN", 2, 2, 0,
73		ARG_MAGIC|ARG_DN|RBAC_DEFAULT_ROLES_BASE_DN,
74		rbac_cf_gen,
75		"(OLcfgCtAt:7.2 NAME 'olcRBACDefaultRolesBaseDn' "
76			"DESC 'default base DN for RBAC roles ' "
77			"SYNTAX OMsDirectoryString "
78			"SINGLE-VALUE )",
79		NULL, NULL
80	},
81	{ "rbac-default-permissions-base-dn", "permissionsDN", 2, 2, 0,
82		ARG_MAGIC|ARG_DN|RBAC_DEFAULT_PERMISSIONS_BASE_DN,
83		rbac_cf_gen,
84		"(OLcfgCtAt:7.3 NAME 'olcRBACDefaultPermissionsBaseDn' "
85			"DESC 'default base DN for RBAC permissions ' "
86			"SYNTAX OMsDirectoryString "
87			"SINGLE-VALUE )",
88		NULL, NULL
89	},
90	{ "rbac-default-sessions-base-dn", "sessionsDN", 2, 2, 0,
91		ARG_MAGIC|ARG_DN|RBAC_DEFAULT_SESSIONS_BASE_DN,
92		rbac_cf_gen,
93		"(OLcfgCtAt:7.4 NAME 'olcRBACDefaultSessionsBaseDn' "
94			"DESC 'default base DN for RBAC permissions ' "
95			"SYNTAX OMsDirectoryString "
96			"SINGLE-VALUE )",
97		NULL, NULL
98	},
99	{ "rbac-admin", "adminDN", 2, 2, 0,
100		ARG_MAGIC|ARG_DN|RBAC_ADMIN_DN,
101		rbac_cf_gen,
102		"(OLcfgCtAt:7.5 NAME 'olcRBACAdminDn' "
103			"DESC 'default admin DN for RBAC repository ' "
104			"SYNTAX OMsDirectoryString "
105			"SINGLE-VALUE )",
106		NULL, NULL
107	},
108	{ "rbac-pwd", "adminPwd", 2, 2, 0,
109		ARG_MAGIC|RBAC_ADMIN_PWD,
110		rbac_cf_gen,
111		"(OLcfgCtAt:7.6 NAME 'olcRBACAdminPwd' "
112			"DESC 'default admin pwd for RBAC repository ' "
113			"SYNTAX OMsDirectoryString "
114			"SINGLE-VALUE )",
115		NULL, NULL
116	},
117	{ "rbac-session-admin", "sessionAdminDN", 2, 2, 0,
118		ARG_MAGIC|ARG_DN|RBAC_SESSION_ADMIN_DN,
119		rbac_cf_gen,
120		"(OLcfgCtAt:7.7 NAME 'olcRBACSessionAdminDn' "
121			"DESC 'admin DN for RBAC session repository ' "
122			"SYNTAX OMsDirectoryString "
123			"SINGLE-VALUE )",
124		NULL, NULL
125	},
126	{ "rbac-session-admin-pwd", "sessionAdminPwd", 2, 2, 0,
127		ARG_MAGIC|RBAC_SESSION_ADMIN_PWD,
128		rbac_cf_gen,
129		"(OLcfgCtAt:7.8 NAME 'olcRBACSessionAdminPwd' "
130			"DESC 'admin pwd for RBAC session repository ' "
131			"SYNTAX OMsDirectoryString SINGLE-VALUE )",
132		NULL, NULL
133	},
134	{ "tenant", "tenant", 2, 2, 0,
135		ARG_MAGIC|ARG_DN|RBAC_TENANT,
136		rbac_cf_gen, "(OLcfgCtAt:7.9 NAME 'olcRBACTenant' "
137			"DESC 'RBAC tenant ' "
138			"SYNTAX OMsDirectoryString "
139			"SINGLE-VALUE )",
140		NULL, NULL
141	},
142	{ "rbac-default-audit-base-dn", "auditDN", 2, 2, 0,
143		ARG_MAGIC|ARG_DN|RBAC_DEFAULT_AUDIT_BASE_DN,
144		rbac_cf_gen,
145		"(OLcfgCtAt:7.10 NAME 'olcRBACDefaultAuditBaseDn' "
146			"DESC 'default base DN for RBAC audit records ' "
147			"SYNTAX OMsDirectoryString "
148			"SINGLE-VALUE )",
149		NULL, NULL
150	},
151	{ "rbac-default-tenant-id", "tenantId", 2, 2, 0,
152		ARG_MAGIC|RBAC_DEFAULT_TENANT_ID,
153		rbac_cf_gen,
154		"(OLcfgCtAt:7.11 NAME 'olcRBACDefaultTenantId' "
155			"DESC 'default tenant id' "
156			"SYNTAX OMsDirectoryString "
157			"SINGLE-VALUE )",
158		NULL, NULL
159	},
160
161	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
162};
163
164static ConfigOCs rbac_ocs[] = {
165	{ "( OLcfgCtOc:7.1 "
166			"NAME 'olcRBACConfig' "
167			"DESC 'RBAC configuration' "
168			"SUP olcOverlayConfig "
169			"MAY ( olcRBACDefaultUsersBaseDn $ olcRBACDefaultRolesBaseDn $ "
170			"olcRBACDefaultPermissionsBaseDn $ olcRBACDefaultSessionsBaseDn $ "
171			"olcRBACAdminDn $  olcRBACAdminPwd $ olcRBACSessionAdminDn $ "
172			"olcRBACSessionAdminPwd) )",
173		Cft_Overlay, rbaccfg },
174
175	{ NULL, 0, NULL }
176};
177
178static slap_verbmasks rbac_keys[] = {
179	{ BER_BVC("default_users_base_dn"), RBAC_DEFAULT_USERS_BASE_DN },
180	{ BER_BVC("default_roles_base_dn"), RBAC_DEFAULT_ROLES_BASE_DN },
181	{ BER_BVC("default_permissions_base_dn"),
182		RBAC_DEFAULT_PERMISSIONS_BASE_DN },
183	{ BER_BVC("tenant"), RBAC_TENANT },
184
185	{ BER_BVNULL, 0 }
186};
187
188static slap_verbmasks rbac_tenant_keys[] = {
189	{ BER_BVC("id"), RBAC_TENANT_ID },
190	{ BER_BVC("users_base_dn"), RBAC_USERS_BASE_DN },
191	{ BER_BVC("roles_base_dn"), RBAC_ROLES_BASE_DN },
192	{ BER_BVC("permissions_base_dn"), RBAC_PERMISSIONS_BASE_DN },
193
194	{ BER_BVNULL, 0 }
195};
196
197static void
198rbac_tenant_parse( char *tenent_info, tenant_info_t *tenants )
199{
200	return;
201}
202
203static int
204rbac_cf_gen( ConfigArgs *c )
205{
206	slap_overinst *on = (slap_overinst *)c->bi;
207	rbac_tenant_t *ri = &rbac_tenants;
208	int rc = 0;
209
210	if ( c->op == SLAP_CONFIG_EMIT ) {
211		switch ( c->type ) {
212			case RBAC_DEFAULT_USERS_BASE_DN:
213				value_add_one( &c->rvalue_vals, &ri->tenant_info.users_basedn );
214				break;
215			case RBAC_DEFAULT_ROLES_BASE_DN:
216				value_add_one( &c->rvalue_vals, &ri->tenant_info.roles_basedn );
217				break;
218			case RBAC_DEFAULT_PERMISSIONS_BASE_DN:
219				value_add_one(
220						&c->rvalue_vals, &ri->tenant_info.permissions_basedn );
221				break;
222			case RBAC_DEFAULT_SESSIONS_BASE_DN:
223				value_add_one(
224						&c->rvalue_vals, &ri->tenant_info.sessions_basedn );
225				break;
226			case RBAC_DEFAULT_AUDIT_BASE_DN:
227				value_add_one( &c->rvalue_vals, &ri->tenant_info.audit_basedn );
228				break;
229			case RBAC_ADMIN_DN:
230				value_add_one( &c->rvalue_vals, &ri->tenant_info.admin );
231				break;
232			case RBAC_ADMIN_PWD:
233				value_add_one( &c->rvalue_vals, &ri->tenant_info.pwd );
234				break;
235			case RBAC_SESSION_ADMIN_DN:
236				value_add_one(
237						&c->rvalue_vals, &ri->tenant_info.session_admin );
238				break;
239			case RBAC_DEFAULT_TENANT_ID:
240				value_add_one( &c->rvalue_vals, &ri->tenant_info.tid );
241				break;
242			default:
243				break;
244		}
245		return rc;
246	} else if ( c->op == LDAP_MOD_DELETE ) {
247		/* FIXME */
248		return 1;
249	}
250	switch ( c->type ) {
251		case RBAC_DEFAULT_USERS_BASE_DN: {
252			struct berval dn = BER_BVNULL;
253			ber_str2bv( c->argv[1], 0, 0, &dn );
254			rc = dnNormalize(
255					0, NULL, NULL, &dn, &ri->tenant_info.users_basedn, NULL );
256			break;
257		}
258		case RBAC_DEFAULT_ROLES_BASE_DN: {
259			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.roles_basedn );
260			break;
261		}
262		case RBAC_DEFAULT_PERMISSIONS_BASE_DN: {
263			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.permissions_basedn );
264			break;
265		}
266		case RBAC_DEFAULT_SESSIONS_BASE_DN: {
267			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.sessions_basedn );
268			break;
269		}
270		case RBAC_DEFAULT_AUDIT_BASE_DN: {
271			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.audit_basedn );
272			break;
273		}
274		case RBAC_ADMIN_DN: {
275			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.admin );
276			break;
277		}
278		case RBAC_ADMIN_PWD: {
279			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.pwd );
280			break;
281		}
282		case RBAC_SESSION_ADMIN_DN: {
283			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.session_admin );
284			break;
285		}
286		case RBAC_SESSION_ADMIN_PWD: {
287			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.session_admin_pwd );
288			break;
289		}
290		case RBAC_DEFAULT_TENANT_ID: {
291			ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.tid );
292			break;
293		}
294		case RBAC_TENANT: {
295			rbac_tenant_parse( c->argv[1], &ri->tenant_info );
296			break;
297		}
298		default:
299			break;
300	}
301
302	return rc;
303}
304
305/*
306 * rbac configuration
307 */
308
309tenant_info_t *
310rbac_tid2tenant( struct berval *tid )
311{
312	/* return the only tenant for now */
313	return &rbac_tenants.tenant_info;
314}
315
316//{ BER_BVC(LDAP_RBAC_EXOP_SESSION_ROLES), rbac_session_roles },
317
318static int
319slap_parse_rbac_session_roles(
320		struct berval *in,
321		rbac_req_t **reqpp,
322		const char **text,
323		void *ctx )
324{
325	int rc = LDAP_SUCCESS;
326	struct berval reqdata = BER_BVNULL;
327	rbac_req_t *reqp = NULL;
328	BerElementBuffer berbuf;
329	BerElement *ber = (BerElement *)&berbuf;
330	ber_tag_t tag;
331	ber_len_t len = -1;
332
333	*text = NULL;
334
335	if ( in == NULL || in->bv_len == 0 ) {
336		*text = "empty request data field in rbac_session_roles exop";
337		return LDAP_PROTOCOL_ERROR;
338	}
339
340	reqp = rbac_alloc_req( RBAC_REQ_SESSION_ROLES );
341
342	if ( !reqp ) {
343		*text = "unable to allocate memory for rbac_session_roles exop";
344		return LDAP_PROTOCOL_ERROR;
345	}
346
347	ber_dupbv_x( &reqdata, in, ctx );
348
349	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
350	ber_init2( ber, &reqdata, 0 );
351
352	tag = ber_scanf( ber, "{" /*}*/ );
353
354	if ( tag == LBER_ERROR ) {
355		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
356				"decoding error.\n" );
357		goto decoding_error;
358	}
359
360	tag = ber_peek_tag( ber, &len );
361	if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID_SESS ) {
362		struct berval uid;
363		tag = ber_scanf( ber, "m", &uid );
364		if ( tag == LBER_ERROR ) {
365			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
366					"user id parse failed.\n" );
367			goto decoding_error;
368		}
369		ber_dupbv_x( &reqp->uid, &uid, ctx );
370		tag = ber_peek_tag( ber, &len );
371	}
372
373	//tag = ber_peek_tag( ber, &len );
374	if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID_SESS ) {
375		struct berval sessid;
376		tag = ber_scanf( ber, "m", &sessid );
377		if ( tag == LBER_ERROR ) {
378			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
379					"session id parse failed.\n" );
380			goto decoding_error;
381		}
382		ber_dupbv_x( &reqp->sessid, &sessid, ctx );
383		tag = ber_peek_tag( ber, &len );
384	}
385
386	if ( tag != LBER_DEFAULT || len != 0 ) {
387decoding_error:;
388
389		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
390				"decoding error, len=%ld\n",
391				(long)len );
392		rc = LDAP_PROTOCOL_ERROR;
393		*text = "data decoding error";
394	}
395
396	if ( rc == LDAP_SUCCESS ) {
397		*reqpp = reqp;
398	} else {
399		rbac_free_req( reqp );
400		*reqpp = NULL;
401	}
402
403	if ( !BER_BVISNULL( &reqdata ) ) {
404		ber_memfree_x( reqdata.bv_val, ctx );
405	}
406
407	return rc;
408}
409
410static int
411rbac_session_roles( Operation *op, SlapReply *rs )
412{
413	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
414	const struct berval rbac_op = BER_BVC("SessionRoles");
415	rbac_req_t *reqp = NULL;
416	rbac_session_t *sessp;
417	int rc;
418
419	rs->sr_err = slap_parse_rbac_session_roles(
420			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
421
422	assert( rs->sr_err == LDAP_SUCCESS );
423
424	/* get the session using the session id */
425	sessp = rbac_session_byid( op, reqp );
426	if ( !sessp ) {
427		Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
428				"session not found\n" );
429		rc = LDAP_UNWILLING_TO_PERFORM;
430		goto done;
431	}
432
433	/* checking whether the session is owned by the user */
434	if ( !rbac_is_session_owner( sessp, reqp ) ) {
435		Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
436				"session not owned by user\n" );
437		rc = LDAP_UNWILLING_TO_PERFORM;
438		goto done;
439	}
440
441	rc = rbac_int_delete_session( op, sessp );
442	if ( rc != LDAP_SUCCESS ) {
443		Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
444				"unable to delete session\n" );
445		rc = LDAP_UNWILLING_TO_PERFORM;
446		goto done;
447	}
448
449	/*
450	 * If we wanted to...
451	 * load these roles into a response with a sequence nested within a
452	 * sequence: (No, we're not actually doing this here.)
453	 *		0x30 LL		ber_printf( ber,  "{" );
454	 *			0x04 L1
455	 *				0x04 L2 a b c d
456	 *				0x04 L3 e f g h
457	 *				0x04 L4 i j k l
458	 * add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
459	 * close it      ber_printf( ber, "t{W}", LDAP_TAG_EXOP_RBAC_ROLES, roles );
460	 */
461
462	/*
463	 * Instead we are...
464	 * loading these roles into the response within a sequence:  (Yes, we are doing this here.)
465	 *		0x30 LL		ber_printf( ber,  "{" );
466	 *			0x04 L1 a b c d
467	 *			0x04 L2 e f g h
468	 *			0x04 L3 i j k l
469	 *	add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
470	 *	close it      ber_printf( ber, "tW", LDAP_TAG_EXOP_RBAC_ROLES, roles );
471	 */
472	BerElementBuffer berbuf;
473	BerElement *ber = (BerElement *)&berbuf;
474	ber_init_w_nullc( ber, LBER_USE_DER );
475	BerVarray roles = NULL;
476	if ( sessp->roles ) {
477		struct berval tmpbv;
478		// open the sequence:
479		ber_printf( ber, "{" /*}*/ );
480		//char *role;
481		int i = 0;
482		//BerVarray roles = NULL;
483		for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
484			tmpbv.bv_val = sessp->roles[i].bv_val;
485			tmpbv.bv_len = sessp->roles[i].bv_len;
486			// add role name:
487			ber_bvarray_add_x( &roles, &tmpbv, NULL );
488
489			//LBER_F( int )
490			//ber_bvecadd_x LDAP_P(( struct berval ***bvec,
491			//	struct berval *bv, void *ctx ));
492
493			// first attempt at sequence within a sequence...
494			// open another sequence:
495			/*
496			ber_printf( ber, "{" } );
497			// add role name (again):
498			ber_bvarray_add_x(&roles, &tmpbv, NULL);
499			// close the nested sequence:
500			ber_printf( ber, { "}" );
501*/
502			// end 2nd sequence
503		}
504		/*
505		 * This is how we add several octet strings at one time. An array of struct berval's is supplied.
506		 * The array is terminated by a struct berval with a NULL bv_val.
507		 * Note that a construct like '{W}' is required to get an actual SEQUENCE OF octet strings.
508		 * But here we are using 'tW' which allows passing a collection of octets w/out a nesting within a sequence.
509         */
510		ber_printf( ber, "tW",
511				LDAP_TAG_EXOP_RBAC_ROLES, roles);
512
513		// TODO: determine why free on roles array causes a seg fault:
514		//ber_bvarray_free_x(roles, NULL);
515
516		// close the sequence:
517		ber_printf( ber, /*{*/ "N}" );
518	}
519
520	if ( rc < 0 ) {
521		rs->sr_err = LDAP_OTHER;
522		rs->sr_text = "internal error";
523	} else {
524		(void)ber_flatten( ber, &rs->sr_rspdata );
525		rs->sr_err = LDAP_SUCCESS;
526	}
527	ber_free_buf( ber );
528	// END LOAD ROLES INTO RESPONSE
529
530done:;
531	rs->sr_err = rc;
532
533	// always put the OID in the response:
534	rs->sr_rspoid = ch_strdup( slap_EXOP_SESSION_ROLES.bv_val );
535
536	/* generate audit log */
537	rbac_audit(
538			op, SessionRoles, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
539	rbac_free_session( sessp );
540	rbac_free_req( reqp );
541	return rs->sr_err;
542}
543
544static int
545rbac_session_rolesx( Operation *op, SlapReply *rs )
546{
547	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
548	const struct berval rbac_op = BER_BVC("SessionRoles");
549	rbac_session_t *sessp = NULL;
550	rbac_req_t *reqp = NULL;
551	int rc;
552
553	rs->sr_err = slap_parse_rbac_session_roles(
554			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
555
556	assert( rs->sr_err == LDAP_SUCCESS );
557
558	/* get the session using the session id */
559	sessp = rbac_session_byid( op, reqp );
560	if ( !sessp ) {
561		Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
562				"session not found\n" );
563		rc = LDAP_UNWILLING_TO_PERFORM;
564		goto done;
565	}
566
567	/* checking whether the session is owned by the user */
568	if ( !rbac_is_session_owner( sessp, reqp ) ) {
569		Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
570				"session not owned by user\n" );
571		rc = LDAP_UNWILLING_TO_PERFORM;
572		goto done;
573	}
574
575	rc = rbac_int_delete_session( op, sessp );
576	if ( rc != LDAP_SUCCESS ) {
577		Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
578				"unable to delete session\n" );
579		rc = LDAP_UNWILLING_TO_PERFORM;
580		goto done;
581	}
582
583	/*
584	 * If we wanted to...
585	 * load these roles into a response with a sequence nested within a
586	 * sequence: (No, we're not actually doing this here.)
587	 *		0x30 LL		ber_printf( ber,  "{" );
588	 *			0x04 L1
589	 *				0x04 L2 a b c d
590	 *				0x04 L3 e f g h
591	 *				0x04 L4 i j k l
592	 * add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
593	 * close it      ber_printf( ber, "t{W}", LDAP_TAG_EXOP_RBAC_ROLES, roles );
594	 */
595
596	/*
597	 * Instead we are...
598	 * loading these roles into the response within a sequence:  (Yes, we are doing this here.)
599	 *		0x30 LL		ber_printf( ber,  "{" );
600	 *			0x04 L1 a b c d
601	 *			0x04 L2 e f g h
602	 *			0x04 L3 i j k l
603	 *	add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
604	 *	close it      ber_printf( ber, "tW", LDAP_TAG_EXOP_RBAC_ROLES, roles );
605	 */
606	BerElementBuffer berbuf;
607	BerElement *ber = (BerElement *)&berbuf;
608	ber_init_w_nullc( ber, LBER_USE_DER );
609	BerVarray roles = NULL;
610	if ( sessp->roles ) {
611		struct berval tmpbv;
612		// open the sequence:
613		ber_printf( ber, "{" /*}*/ );
614		//char *role;
615		int i = 0;
616		//BerVarray roles = NULL;
617		for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
618			tmpbv.bv_val = sessp->roles[i].bv_val;
619			tmpbv.bv_len = sessp->roles[i].bv_len;
620			// add role name:
621			ber_bvarray_add_x( &roles, &tmpbv, NULL );
622
623			// first attempt at sequence within a sequence...
624			// open another sequence:
625			/*
626			ber_printf( ber, "{" } );
627			// add role name (again):
628			ber_bvarray_add_x(&roles, &tmpbv, NULL);
629			// close the nested sequence:
630			ber_printf( ber, { "}" );
631*/
632			// end 2nd sequence
633		}
634		/*
635		 * This is how we add several octet strings at one time. An array of struct berval's is supplied.
636		 * The array is terminated by a struct berval with a NULL bv_val.
637		 * Note that a construct like '{W}' is required to get an actual SEQUENCE OF octet strings.
638		 * But here we are using 'tW' which allows passing a collection of octets w/out a nesting within a sequence.
639         */
640		ber_printf( ber, "tW",
641				LDAP_TAG_EXOP_RBAC_ROLES, roles);
642
643		// TODO: determine why free on roles array causes a seg fault:
644		//ber_bvarray_free_x(roles, NULL);
645
646		// close the sequence:
647		ber_printf( ber, /*{*/ "N}" );
648	}
649
650	if ( rc < 0 ) {
651		rs->sr_err = LDAP_OTHER;
652		rs->sr_text = "internal error";
653	} else {
654		(void)ber_flatten( ber, &rs->sr_rspdata );
655		rs->sr_err = LDAP_SUCCESS;
656	}
657	ber_free_buf( ber );
658	// END LOAD ROLES INTO RESPONSE
659
660done:;
661	rs->sr_err = rc;
662
663	// always put the OID in the response:
664	rs->sr_rspoid = ch_strdup( slap_EXOP_SESSION_ROLES.bv_val );
665
666	/* generate audit log */
667	rbac_audit(
668			op, SessionRoles, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
669	rbac_free_session( sessp );
670	rbac_free_req( reqp );
671	return rs->sr_err;
672}
673
674/*
675 * slap_parse_rbac_create_session
676 */
677static int
678slap_parse_rbac_create_session(
679		struct berval *in,
680		rbac_req_t **reqpp,
681		const char **text,
682		void *ctx )
683{
684	int rc = LDAP_SUCCESS;
685	struct berval reqdata = BER_BVNULL;
686	rbac_req_t *reqp = NULL;
687	BerElementBuffer berbuf;
688	BerElement *ber = (BerElement *)&berbuf;
689	ber_tag_t tag;
690	ber_len_t len = -1;
691
692	*text = NULL;
693
694	if ( in == NULL || in->bv_len == 0 ) {
695		*text = "empty request data field in rbac_create_session exop";
696		return LDAP_PROTOCOL_ERROR;
697	}
698
699	reqp = rbac_alloc_req( RBAC_REQ_CREATE_SESSION );
700
701	if ( !reqp ) {
702		*text = "unable to allocate memory for bac_create_session exop";
703		return LDAP_PROTOCOL_ERROR;
704	}
705
706	ber_dupbv_x( &reqdata, in, ctx );
707
708	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
709	ber_init2( ber, &reqdata, 0 );
710
711	tag = ber_scanf( ber, "{" /*}*/ );
712
713	if ( tag == LBER_ERROR ) {
714		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
715				"decoding error.\n" );
716		goto decoding_error;
717	}
718
719	// Order: 1. sessionId, 2. tenantId, 3. userId, 4. password and 5. roles
720	/* must-have */
721	tag = ber_peek_tag( ber, &len );
722
723	// 1. SESSIONID
724	if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID ) {
725		struct berval bv;
726		tag = ber_scanf( ber, "m", &bv );
727		if ( tag == LBER_ERROR ) {
728			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
729					"session id parse failed.\n" );
730			goto decoding_error;
731		}
732		ber_dupbv_x( &reqp->sessid, &bv, ctx );
733		tag = ber_peek_tag( ber, &len );
734	}
735
736	// 2. TENANT ID
737	if ( tag == LDAP_TAG_EXOP_RBAC_TENANT_ID ) {
738		struct berval bv;
739		tag = ber_scanf( ber, "m", &bv );
740		if ( tag == LBER_ERROR ) {
741			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
742					"tenant id parse failed.\n" );
743			goto decoding_error;
744		}
745		ber_dupbv_x( &reqp->tenantid, &bv, ctx );
746		tag = ber_peek_tag( ber, &len );
747	}
748
749	// 3. USERID
750	if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID ) {
751		struct berval bv;
752		tag = ber_scanf( ber, "m", &bv );
753		if ( tag == LBER_ERROR ) {
754			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
755					"user id parse failed.\n" );
756			goto decoding_error;
757		}
758		ber_dupbv_x( &reqp->uid, &bv, ctx );
759		tag = ber_peek_tag( ber, &len );
760	}
761
762	// 4. PASSWORD
763	if ( tag == LDAP_TAG_EXOP_RBAC_AUTHTOK ) {
764		struct berval bv;
765		tag = ber_scanf( ber, "m", &bv);
766		if ( tag == LBER_ERROR ) {
767			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
768					"authtok parse failed.\n" );
769			goto decoding_error;
770		}
771		ber_dupbv_x( &reqp->authtok, &bv, ctx );
772		tag = ber_peek_tag( ber, &len );
773	}
774
775	// 5. ROLES
776	if ( tag == LDAP_TAG_EXOP_RBAC_ACTIVE_ROLE ) {
777		tag = ber_scanf( ber, "W", &reqp->roles);
778		if ( tag == LBER_ERROR ) {
779			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
780					"role parse failed.\n" );
781			goto decoding_error;
782		}
783		tag = ber_peek_tag( ber, &len );
784	}
785
786	if ( tag != LBER_DEFAULT || len != 0 ) {
787decoding_error:;
788
789		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
790				"decoding error, len=%ld\n",
791				(long)len );
792		rc = LDAP_PROTOCOL_ERROR;
793		*text = "data decoding error";
794	}
795
796	if ( rc == LDAP_SUCCESS ) {
797		Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_create_session: "
798				"SUCCESS\n" );
799
800		*reqpp = reqp;
801	} else {
802		Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_create_session: "
803				"NO SUCCESS RC=%d\n", rc );
804
805		rbac_free_req( reqp );
806		*reqpp = NULL;
807	}
808
809	if ( !BER_BVISNULL( &reqdata ) ) {
810		ber_memfree_x( reqdata.bv_val, ctx );
811	}
812
813	return rc;
814}
815
816/*
817 * rbac_create_session:
818 *     1. authenticate user
819 *     2. evaluate pwd policy
820 *     3. create session
821 */
822static int
823rbac_create_session( Operation *op, SlapReply *rs )
824{
825	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
826	struct berval rbac_op = BER_BVC("CreateSession");
827	BerElementBuffer berbuf;
828	BerElement *ber = (BerElement *)&berbuf;
829	int rc = LDAP_SUCCESS;
830	rbac_session_t *sessp = NULL;
831	rbac_user_t *userp = NULL;
832	rbac_req_t *reqp = NULL;
833
834	rs->sr_err = slap_parse_rbac_create_session(
835			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
836
837	assert( rs->sr_err == LDAP_SUCCESS );
838
839	/* read user entry */
840	userp = rbac_read_user( op, reqp );
841	if ( !userp ) {
842		Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
843				"unable to read user entry\n" );
844		rs->sr_err = LDAP_NO_SUCH_OBJECT;
845		rs->sr_text = "rbac_create_session: unable to read user entry";
846		goto done;
847	}
848
849	if ( !BER_BVISNULL( &userp->password ) ) {
850		/* if request is with pwd, authenticate the user */
851		rc = rbac_authenticate_user( op, userp );
852		if ( rc != LDAP_SUCCESS ) {
853			Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
854					"rbac_authenticate_user failed!\n" );
855			rs->sr_err = LDAP_INVALID_CREDENTIALS;
856			rs->sr_text = "rbac_create_session: invalid credential";
857			goto done;
858		}
859		/*
860		rbac_user_t *ui = op->o_callback->sc_private;
861		int pVal = ui->authz;
862		printf("password reset val=%d", pVal );
863*/
864
865	} else {
866		/* no pwd is provided, check whether the requesting session */
867		/* id has the access privilege to create a session on behalf */
868		/* of the user */
869		rc = rbac_create_session_acl_check( &reqp->sessid, userp );
870		if ( rc != LDAP_SUCCESS ) {
871			Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
872					"rbac_authenticate_user failed!\n" );
873			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
874			rs->sr_text = "rbac_create_session: session permission denied";
875			goto done;
876		}
877	}
878
879	/* check user temporal constraint */
880	rc = rbac_user_temporal_constraint( userp );
881	if ( rc != LDAP_SUCCESS ) {
882		Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
883				"rbac_user_temporal_constraint() failed!\n" );
884		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
885		rs->sr_text = "rbac_create_session: temporal constraint violation";
886		goto done;
887	}
888
889	sessp = rbac_alloc_session();
890	if ( !sessp ) {
891		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
892		rs->sr_text = "rbac_create_session: unable to allocate session";
893		goto done;
894	}
895
896	rc = activate_session_roles( sessp, reqp, userp );
897	if ( rc != LDAP_SUCCESS ) {
898		Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
899				"failed to activate roles to session!\n" );
900		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
901		rs->sr_text =
902				"rbac_create_session: failed to activate roles into session";
903		goto done;
904	}
905
906	/* store uid and tenant id in session */
907	ber_dupbv( &sessp->userdn, &userp->dn );
908	ber_dupbv( &sessp->uid, &reqp->uid );
909	ber_dupbv( &sessp->tenantid, &reqp->tenantid );
910
911	/* register RBAC session */
912	rc = rbac_register_session( op, rs, sessp );
913	if ( rc != LDAP_SUCCESS ) {
914		goto done;
915	}
916
917	ber_init_w_nullc( ber, LBER_USE_DER );
918	rc = ber_printf( ber, "{tO}", LDAP_TAG_EXOP_RBAC_SESSION_ID,
919			&sessp->sessid );
920	if ( rc < 0 ) {
921		rs->sr_err = LDAP_OTHER;
922		rs->sr_text = "internal error";
923	} else {
924		(void)ber_flatten( ber, &rs->sr_rspdata );
925		rs->sr_rspoid = ch_strdup( slap_EXOP_CREATE_SESSION.bv_val );
926		rs->sr_err = LDAP_SUCCESS;
927	}
928
929	ber_free_buf( ber );
930
931done:;
932
933	// always put the OID in the response:
934	rs->sr_rspoid = ch_strdup( slap_EXOP_CREATE_SESSION.bv_val );
935	/* generate audit log */
936	rbac_audit(
937			op, CreateSession, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
938
939	rbac_free_req( reqp );
940	rbac_free_session( sessp );
941
942	//if (rs->sr_err != LDAP_SUCCESS) {
943	//send_ldap_result( op, rs );
944	//}
945
946	return rs->sr_err;
947}
948
949/*
950 * slap_parse_rbac_check_access
951 */
952static int
953slap_parse_rbac_check_access(
954		struct berval *in,
955		rbac_req_t **reqpp,
956		const char **text,
957		void *ctx )
958{
959	int rc = LDAP_SUCCESS;
960	struct berval reqdata = BER_BVNULL;
961	rbac_req_t *reqp = NULL;
962	BerElementBuffer berbuf;
963	BerElement *ber = (BerElement *)&berbuf;
964	ber_tag_t tag;
965	ber_len_t len;
966
967	*text = NULL;
968	reqp = rbac_alloc_req( RBAC_REQ_CHECK_ACCESS );
969
970	if ( !reqp ) {
971		*text = "unable to allocate memory for slap_parse_rbac_check_access";
972		return LDAP_PROTOCOL_ERROR;
973	}
974
975	if ( in == NULL || in->bv_len == 0 ) {
976		*text = "empty request data field in rbac_check_access exop";
977		return LDAP_PROTOCOL_ERROR;
978	}
979
980	ber_dupbv_x( &reqdata, in, ctx );
981
982	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
983	ber_init2( ber, &reqdata, 0 );
984
985	tag = ber_scanf( ber, "{" /*}*/ );
986
987	if ( tag == LBER_ERROR ) {
988		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
989				"decoding error.\n" );
990		goto decoding_error;
991	}
992
993	// sessionId is required:
994	tag = ber_peek_tag( ber, &len );
995	if ( tag != LDAP_TAG_EXOP_RBAC_SESSION_ID ) {
996		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
997				"decoding error.\n" );
998		goto decoding_error;
999	} else {
1000		struct berval bv;
1001		tag = ber_scanf( ber, "m", &bv );
1002		if ( tag == LBER_ERROR ) {
1003			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
1004					"session id parse failed.\n" );
1005			goto decoding_error;
1006		}
1007		ber_dupbv_x( &reqp->sessid, &bv, ctx );
1008		tag = ber_peek_tag( ber, &len );
1009	}
1010
1011	// operationName is required:
1012	if ( tag != LDAP_TAG_EXOP_RBAC_OPNAME ) {
1013		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
1014				"decoding error.\n" );
1015		goto decoding_error;
1016	} else {
1017		struct berval bv;
1018		tag = ber_scanf( ber, "m", &bv );
1019		if ( tag == LBER_ERROR ) {
1020			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
1021					"opname parse failed.\n" );
1022			goto decoding_error;
1023		}
1024		ber_dupbv_x( &reqp->opname, &bv, ctx );
1025		tag = ber_peek_tag( ber, &len );
1026	}
1027
1028	// objectName is required:
1029	if ( tag != LDAP_TAG_EXOP_RBAC_OBJNAME ) {
1030		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
1031				"decoding error.\n" );
1032		goto decoding_error;
1033	} else {
1034		struct berval bv;
1035		tag = ber_scanf( ber, "m", &bv );
1036		if ( tag == LBER_ERROR ) {
1037			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
1038					"objname parse failed.\n" );
1039			goto decoding_error;
1040		}
1041		ber_dupbv_x( &reqp->objname, &bv, ctx );
1042		tag = ber_peek_tag( ber, &len );
1043	}
1044
1045	// objectId is optional:
1046	if ( tag == LDAP_TAG_EXOP_RBAC_OBJID ) {
1047		struct berval bv;
1048		tag = ber_scanf( ber, "m", &bv );
1049		if ( tag == LBER_ERROR ) {
1050			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
1051					"objid parse failed.\n" );
1052			goto decoding_error;
1053		}
1054		ber_dupbv_x( &reqp->objid, &bv, ctx );
1055		tag = ber_peek_tag( ber, &len );
1056	}
1057
1058	if ( tag != LBER_DEFAULT || len != 0 ) {
1059decoding_error:;
1060
1061		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
1062				"decoding error, len=%ld\n",
1063				(long)len );
1064		rc = LDAP_PROTOCOL_ERROR;
1065		*text = "data decoding error";
1066	}
1067
1068	if ( rc == LDAP_SUCCESS ) {
1069		Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_check_access: "
1070				"SUCCESS\n" );
1071		*reqpp = reqp;
1072	} else {
1073		Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_check_access: "
1074				"FAIL\n" );
1075		rbac_free_req( reqp );
1076	}
1077
1078	if ( !BER_BVISNULL( &reqdata ) ) {
1079		ber_memfree_x( reqdata.bv_val, ctx );
1080	}
1081
1082	return rc;
1083}
1084
1085// checkAcess F  (ALL)
1086static int
1087rbac_check_access( Operation *op, SlapReply *rs )
1088{
1089	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1090	rbac_session_t *sessp = NULL;
1091	rbac_permission_t *permp = NULL;
1092	rbac_constraint_t *cp = NULL;
1093	rbac_req_t *reqp = NULL;
1094	const struct berval rbac_op = BER_BVC("CheckAccess");
1095	int rc = LDAP_SUCCESS;
1096	int found = 0;
1097
1098	rs->sr_err = slap_parse_rbac_check_access(
1099			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
1100
1101	assert( rs->sr_err == LDAP_SUCCESS );
1102
1103	BER_BVZERO( &op->o_req_dn );
1104	BER_BVZERO( &op->o_req_ndn );
1105
1106	/* get the session using the session id */
1107	sessp = rbac_session_byid( op, reqp );
1108	if ( !sessp ) {
1109		Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
1110				"session not found\n" );
1111		rc = LDAP_UNWILLING_TO_PERFORM;
1112		goto done;
1113	}
1114
1115	/* read the permission using objectName and OpName */
1116	permp = rbac_read_permission( op, reqp );
1117	if ( !permp ) {
1118		Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
1119				"permission not found\n" );
1120		rc = LDAP_UNWILLING_TO_PERFORM;
1121		goto done;
1122	}
1123
1124	// Convert the user-role constraint data from BerVarray to rbac_constraint_t format
1125	cp = rbac_user_role_constraints( sessp->role_constraints );
1126
1127	// Now do the actual rbac checkAccess:
1128	rc = rbac_check_session_permission( sessp, permp, cp );
1129
1130	if ( rc != LDAP_SUCCESS ) {
1131		Debug( LDAP_DEBUG_ANY, "rbac_check_user_permission: "
1132				"failed\n" );
1133		rc = LDAP_UNWILLING_TO_PERFORM;
1134		goto done;
1135	}
1136
1137done:
1138
1139	rs->sr_err = rc;
1140	// always put the OID in the response:
1141	rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
1142
1143	/* generate audit log */
1144	rbac_audit( op, CheckAccess, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
1145
1146	rbac_free_permission( permp );
1147	rbac_free_req( reqp );
1148	rbac_free_session( sessp );
1149	rbac_free_constraints( cp );
1150
1151	return rs->sr_err;
1152}
1153
1154// checkAcess A loop back
1155static int
1156rbac_check_accessA( Operation *op, SlapReply *rs )
1157{
1158	int rc = LDAP_SUCCESS;
1159
1160	//rs->sr_err = slap_parse_rbac_check_access(op->ore_reqdata,
1161	//	&reqp, &rs->sr_text, NULL);
1162
1163	// always put the OID in the response:
1164	rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
1165	rs->sr_err = rc;
1166
1167	return rc;
1168}
1169
1170// checkAcess B parse
1171static int
1172rbac_check_accessB( Operation *op, SlapReply *rs )
1173{
1174	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1175	rbac_req_t *reqp = NULL;
1176	const struct berval rbac_op = BER_BVC("CheckAccess");
1177	int rc = LDAP_SUCCESS;
1178
1179	Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
1180
1181	rs->sr_err = slap_parse_rbac_check_access(
1182			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
1183
1184	assert( rs->sr_err == LDAP_SUCCESS );
1185
1186	BER_BVZERO( &op->o_req_dn );
1187	BER_BVZERO( &op->o_req_ndn );
1188
1189	// always put the OID in the response:
1190	rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
1191	rs->sr_err = rc;
1192
1193	rbac_free_req( reqp );
1194
1195	return rc;
1196}
1197
1198// checkAcess C - parse request & read session record
1199static int
1200rbac_check_accessC( Operation *op, SlapReply *rs )
1201{
1202	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1203	rbac_session_t *sessp = NULL;
1204	rbac_req_t *reqp = NULL;
1205	const struct berval rbac_op = BER_BVC("CheckAccess");
1206	int rc = LDAP_SUCCESS;
1207
1208	Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
1209
1210	rs->sr_err = slap_parse_rbac_check_access(
1211			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
1212
1213	assert( rs->sr_err == LDAP_SUCCESS );
1214
1215	BER_BVZERO( &op->o_req_dn );
1216	BER_BVZERO( &op->o_req_ndn );
1217
1218	/* get the session using the session id */
1219	sessp = rbac_session_byid( op, reqp );
1220	if ( !sessp ) {
1221		Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
1222				"session not found\n" );
1223		rc = LDAP_UNWILLING_TO_PERFORM;
1224		goto done;
1225	}
1226
1227done:
1228
1229	// always put the OID in the response:
1230	rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
1231	rs->sr_err = rc;
1232
1233	rbac_free_req( reqp );
1234	rbac_free_session( sessp );
1235	return rc;
1236}
1237
1238// checkAcess D, parse, read perm
1239static int
1240rbac_check_accessD( Operation *op, SlapReply *rs )
1241{
1242	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1243	rbac_permission_t *permp = NULL;
1244	rbac_req_t *reqp = NULL;
1245	const struct berval rbac_op = BER_BVC("CheckAccess");
1246	int rc = LDAP_SUCCESS;
1247
1248	Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
1249
1250	rs->sr_err = slap_parse_rbac_check_access(
1251			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
1252
1253	assert( rs->sr_err == LDAP_SUCCESS );
1254
1255	BER_BVZERO( &op->o_req_dn );
1256	BER_BVZERO( &op->o_req_ndn );
1257
1258	/* get the session using the session id */
1259	/*
1260	sessp = rbac_session_byid(op, reqp);
1261	if ( !sessp ) {
1262		Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
1263				"session not found\n" );
1264		rc = LDAP_UNWILLING_TO_PERFORM;
1265		goto done;
1266	}
1267*/
1268
1269	/* read the permission using objectName and OpName */
1270	permp = rbac_read_permission( op, reqp );
1271	if ( !permp ) {
1272		Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
1273				"permission not found\n" );
1274		rc = LDAP_UNWILLING_TO_PERFORM;
1275		goto done;
1276	}
1277
1278done:
1279
1280	// always put the OID in the response:
1281	rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
1282	rs->sr_err = rc;
1283
1284	rbac_free_permission( permp );
1285	rbac_free_req( reqp );
1286
1287	return rc;
1288}
1289
1290// checkAcess E everything but the audit insert
1291static int
1292rbac_check_accessE( Operation *op, SlapReply *rs )
1293{
1294	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1295	rbac_session_t *sessp = NULL;
1296	rbac_permission_t *permp = NULL;
1297	rbac_constraint_t *cp = NULL;
1298	rbac_req_t *reqp = NULL;
1299	const struct berval rbac_op = BER_BVC("CheckAccess");
1300	int rc = LDAP_SUCCESS;
1301
1302	Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
1303
1304	rs->sr_err = slap_parse_rbac_check_access(
1305			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
1306
1307	assert( rs->sr_err == LDAP_SUCCESS );
1308
1309	BER_BVZERO( &op->o_req_dn );
1310	BER_BVZERO( &op->o_req_ndn );
1311
1312	/* get the session using the session id */
1313	sessp = rbac_session_byid( op, reqp );
1314	if ( !sessp ) {
1315		Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
1316				"session not found\n" );
1317		rc = LDAP_UNWILLING_TO_PERFORM;
1318		goto done;
1319	}
1320
1321	/* read the permission using objectName and OpName */
1322	permp = rbac_read_permission( op, reqp );
1323	if ( !permp ) {
1324		Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
1325				"permission not found\n" );
1326		rc = LDAP_UNWILLING_TO_PERFORM;
1327		goto done;
1328	}
1329
1330	// Convert the user-role constraint data from BerVarray to rbac_constraint_t format
1331	cp = rbac_user_role_constraints( sessp->role_constraints );
1332
1333	// Now do the actual rbac checkAccess:
1334	rc = rbac_check_session_permission( sessp, permp, cp );
1335
1336	if ( rc != LDAP_SUCCESS ) {
1337		Debug( LDAP_DEBUG_ANY, "rbac_check_user_permission: "
1338				"failed\n" );
1339		rc = LDAP_UNWILLING_TO_PERFORM;
1340		goto done;
1341	}
1342
1343done:
1344
1345	rs->sr_err = rc;
1346	// always put the OID in the response:
1347	rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
1348
1349	/* generate audit log */
1350	//rbac_audit(op, CheckAccess, sessp, reqp, rs->sr_err,
1351	//	(char *) rs->sr_text);
1352
1353	rbac_free_permission( permp );
1354	rbac_free_req( reqp );
1355	rbac_free_session( sessp );
1356	rbac_free_constraints( cp );
1357
1358	return rs->sr_err;
1359}
1360
1361/* check whether role exists and role assigned to the user */
1362static int
1363rbac_check_user_role(
1364		rbac_req_t *reqp,
1365		rbac_session_t *sessp,
1366		rbac_user_t *userp )
1367{
1368	int rc = 0;
1369	int i;
1370
1371	//assert(!BER_BVISEMPTY(&reqp->roles[0]));
1372	assert( !BER_BVISEMPTY( &reqp->role ) );
1373
1374	for ( i = 0; !BER_BVISNULL( &userp->roles[i] ); i++ ) {
1375		//if (!ber_bvstrcasecmp(&userp->roles[i], &reqp->roles[0])) {
1376		if ( !ber_bvstrcasecmp( &userp->roles[i], &reqp->role ) ) {
1377			rc = 1; /* found the match */
1378			goto done;
1379		}
1380	}
1381
1382done:;
1383
1384	return rc;
1385}
1386
1387/* check whether role exists and role assigned to the session */
1388static int
1389rbac_check_session_role( rbac_req_t *reqp, rbac_session_t *sessp )
1390{
1391	int rc = 0;
1392	int i;
1393
1394	for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
1395		//if (!ber_bvstrcasecmp(&sessp->roles[i], &reqp->roles[0])) {
1396		if ( !ber_bvstrcasecmp( &sessp->roles[i], &reqp->role ) ) {
1397			rc = 1; /* found the match */
1398			goto done;
1399		}
1400	}
1401
1402done:;
1403
1404	return rc;
1405}
1406
1407/* make sure user is the owner of the session */
1408static int
1409rbac_check_user_session( rbac_session_t *sessp, rbac_req_t *reqp )
1410{
1411	int rc = 0;
1412
1413	if ( BER_BVISNULL( &sessp->uid ) || BER_BVISNULL( &reqp->uid ) ||
1414			sessp->uid.bv_len != reqp->uid.bv_len ) {
1415		goto done;
1416	}
1417
1418	if ( !strncasecmp(
1419				sessp->uid.bv_val, reqp->uid.bv_val, reqp->uid.bv_len ) ) {
1420		rc = 1;
1421		goto done;
1422	}
1423
1424done:;
1425
1426	return rc;
1427}
1428
1429/*
1430 * slap_parse_rbac_active_role
1431 */
1432static int
1433slap_parse_rbac_active_role(
1434		struct berval *in,
1435		int add_or_drop_role,
1436		rbac_req_t **reqpp,
1437		const char **text,
1438		void *ctx )
1439{
1440	int rc = LDAP_SUCCESS;
1441	struct berval reqdata = BER_BVNULL;
1442	rbac_req_t *reqp = NULL;
1443	BerElementBuffer berbuf;
1444	BerElement *ber = (BerElement *)&berbuf;
1445	ber_tag_t tag;
1446	ber_len_t len = -1;
1447
1448	*text = NULL;
1449
1450	if ( in == NULL || in->bv_len == 0 ) {
1451		*text = "empty request data field in rbac_create_session exop";
1452		return LDAP_PROTOCOL_ERROR;
1453	}
1454
1455	reqp = rbac_alloc_req( add_or_drop_role );
1456
1457	if ( !reqp ) {
1458		*text = "unable to allocate memory for rbac_add_drop_active_role exop";
1459		return LDAP_PROTOCOL_ERROR;
1460	}
1461
1462	ber_dupbv_x( &reqdata, in, ctx );
1463
1464	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
1465	ber_init2( ber, &reqdata, 0 );
1466
1467	tag = ber_scanf( ber, "{" /*}*/ );
1468
1469	if ( tag == LBER_ERROR ) {
1470		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_active_role: "
1471				"decoding error.\n" );
1472		goto decoding_error;
1473	}
1474
1475	tag = ber_peek_tag( ber, &len );
1476	//if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID ) {
1477	if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID_SESS ) {
1478		struct berval bv;
1479		tag = ber_scanf( ber, "m", &bv );
1480		if ( tag == LBER_ERROR ) {
1481			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_active_role: "
1482					"user id parse failed.\n" );
1483			goto decoding_error;
1484		}
1485		ber_dupbv( &reqp->uid, &bv );
1486		tag = ber_peek_tag( ber, &len );
1487	}
1488
1489	if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID_SESS ) {
1490		struct berval bv;
1491		tag = ber_scanf( ber, "m", &bv );
1492		if ( tag == LBER_ERROR ) {
1493			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_active_role: "
1494					"session id parse failed.\n" );
1495			goto decoding_error;
1496		}
1497		ber_dupbv( &reqp->sessid, &bv );
1498		tag = ber_peek_tag( ber, &len );
1499	}
1500
1501	if ( tag == LDAP_TAG_EXOP_RBAC_ROLE_NM_SESS ) {
1502		struct berval bv;
1503		tag = ber_scanf( ber, "m", &bv );
1504		//tag = ber_scanf( ber, "W", &reqp->roles);
1505		//tag = ber_scanf( ber, "m", &reqp->roles);
1506		//tag = ber_scanf( ber, "m", &reqp->roles[0]);
1507		if ( tag == LBER_ERROR ) {
1508			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
1509					"role parse failed.\n" );
1510			goto decoding_error;
1511		}
1512		ber_dupbv( &reqp->role, &bv );
1513		//ber_dupbv(&reqp->roles[0], &bv);
1514		tag = ber_peek_tag( ber, &len );
1515	}
1516
1517	if ( tag != LBER_DEFAULT || len != 0 ) {
1518decoding_error:;
1519		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
1520				"decoding error, len=%ld\n",
1521				(long)len );
1522		rc = LDAP_PROTOCOL_ERROR;
1523		*text = "data decoding error";
1524	}
1525
1526	if ( rc == LDAP_SUCCESS ) {
1527		*reqpp = reqp;
1528	} else {
1529		rbac_free_req( reqp );
1530		*reqpp = NULL;
1531	}
1532
1533	if ( !BER_BVISNULL( &reqdata ) ) {
1534		ber_memfree_x( reqdata.bv_val, ctx );
1535	}
1536
1537	return rc;
1538}
1539
1540static int
1541rbac_add_active_role( Operation *op, SlapReply *rs )
1542{
1543	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1544	struct berval rbac_op = BER_BVC("AddActiveRole");
1545	rbac_req_t *reqp = NULL;
1546	rbac_user_t *userp = NULL;
1547	rbac_session_t *sessp;
1548	int rc = LDAP_SUCCESS;
1549
1550	rs->sr_err = slap_parse_rbac_active_role( op->ore_reqdata,
1551			RBAC_REQ_ADD_ACTIVE_ROLE, &reqp, &rs->sr_text, NULL );
1552
1553	assert( rs->sr_err == LDAP_SUCCESS );
1554
1555	/* get the session using the session id */
1556	sessp = rbac_session_byid( op, reqp );
1557	if ( !sessp ) {
1558		Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
1559				"session not found\n" );
1560		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1561		rs->sr_text = "rbac_add_active_role: session not found";
1562		goto done;
1563	}
1564
1565	/* read user entry */
1566	userp = rbac_read_user( op, reqp );
1567	if ( !userp ) {
1568		Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
1569				"unable to read user entry\n" );
1570		rs->sr_err = LDAP_NO_SUCH_OBJECT;
1571		rs->sr_text = "rbac_add_active_role: unable to read user entry";
1572		goto done;
1573	}
1574
1575	/* make sure role exists and role assigned to the user */
1576	if ( !rbac_check_user_role( reqp, sessp, userp ) ) {
1577		Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
1578				"role not assigned to the user\n" );
1579		rs->sr_err = LDAP_NO_SUCH_OBJECT;
1580		rs->sr_text = "rbac_add_active_role: role not assigned to the user";
1581		goto done;
1582	}
1583
1584	/* make sure user is the owner of the session */
1585	if ( !rbac_check_user_session( sessp, reqp ) ) {
1586		Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
1587				"user not owner of session\n" );
1588		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1589		rs->sr_text = "rbac_add_active_role: user not owner of the session";
1590		goto done;
1591	}
1592
1593	/* add the role to the session */
1594	rc = rbac_session_add_role( op, sessp, reqp );
1595	if ( rc != LDAP_SUCCESS ) {
1596		rs->sr_err = rc;
1597		if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
1598			rs->sr_text =
1599					"rbac_add_active_role: role already activated in session";
1600			Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
1601					"role already activated in session\n" );
1602		} else {
1603			rs->sr_text = "rbac_add_active_role: unable to add role to session";
1604			Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
1605					"unable to add role to session\n" );
1606		}
1607		goto done;
1608	}
1609
1610done:
1611
1612	// always put the OID in the response:
1613	rs->sr_rspoid = ch_strdup( slap_EXOP_ADD_ACTIVE_ROLE.bv_val );
1614
1615	/* generate audit log */
1616	rbac_audit(
1617			op, AddActiveRole, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
1618
1619	rbac_free_session( sessp );
1620	rbac_free_user( userp );
1621	rbac_free_req( reqp );
1622
1623	return rs->sr_err;
1624}
1625
1626static int
1627rbac_drop_active_role( Operation *op, SlapReply *rs )
1628{
1629	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1630	const struct berval rbac_op = BER_BVC("DropActiveRole");
1631	rbac_session_t *sessp;
1632	rbac_req_t *reqp = NULL;
1633	int rc = LDAP_SUCCESS;
1634
1635	rs->sr_err = slap_parse_rbac_active_role( op->ore_reqdata,
1636			RBAC_REQ_DROP_ACTIVE_ROLE, &reqp, &rs->sr_text, NULL );
1637
1638	assert( rs->sr_err == LDAP_SUCCESS );
1639
1640	/* get the session using the session id */
1641	sessp = rbac_session_byid( op, reqp );
1642	if ( !sessp ) {
1643		Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
1644				"session not found\n" );
1645		rc = LDAP_UNWILLING_TO_PERFORM;
1646		goto done;
1647	}
1648
1649	if ( BER_BVISNULL( &reqp->role ) || !sessp->roles ||
1650			BER_BVISNULL( &sessp->roles[0] ) ) {
1651		Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
1652				"unavailable role\n" );
1653		rc = LDAP_UNWILLING_TO_PERFORM;
1654		goto done;
1655	}
1656
1657	/* make sure role exists and role assigned to the user */
1658	if ( !rbac_check_session_role( reqp, sessp ) ) {
1659		Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
1660				"role not assigned to session\n" );
1661		rc = LDAP_UNWILLING_TO_PERFORM;
1662		goto done;
1663	}
1664
1665	/* make sure user is the owner of the session */
1666	if ( !rbac_check_user_session( sessp, reqp ) ) {
1667		Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
1668				"user not owner of session\n" );
1669		rc = LDAP_UNWILLING_TO_PERFORM;
1670		rs->sr_text = "rbac_drop_active_role: user not owner of the session";
1671		goto done;
1672	}
1673
1674	/* drop the role to the session */
1675	rc = rbac_session_drop_role( op, sessp, reqp );
1676	if ( rc != LDAP_SUCCESS ) {
1677		Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
1678				"unable to drop active role from session\n" );
1679		rc = LDAP_UNWILLING_TO_PERFORM;
1680		rs->sr_text = "rbac_drop_active_role: unable to drop role from session";
1681		goto done;
1682	}
1683
1684done:
1685	rs->sr_err = rc;
1686
1687	// always put the OID in the response:
1688	rs->sr_rspoid = ch_strdup( slap_EXOP_DROP_ACTIVE_ROLE.bv_val );
1689
1690	/* generate audit log */
1691	rbac_audit(
1692			op, DropActiveRole, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
1693
1694	rbac_free_session( sessp );
1695	rbac_free_req( reqp );
1696
1697	return rs->sr_err;
1698}
1699
1700/*
1701 * slap_parse_rbac_delete_session
1702 */
1703static int
1704slap_parse_rbac_delete_session(
1705		struct berval *in,
1706		rbac_req_t **reqpp,
1707		const char **text,
1708		void *ctx )
1709{
1710	int rc = LDAP_SUCCESS;
1711	struct berval reqdata = BER_BVNULL;
1712	rbac_req_t *reqp = NULL;
1713	BerElementBuffer berbuf;
1714	BerElement *ber = (BerElement *)&berbuf;
1715	ber_tag_t tag;
1716	ber_len_t len = -1;
1717
1718	*text = NULL;
1719
1720	if ( in == NULL || in->bv_len == 0 ) {
1721		*text = "empty request data field in rbac_delete_session exop";
1722		return LDAP_PROTOCOL_ERROR;
1723	}
1724
1725	reqp = rbac_alloc_req( RBAC_REQ_DELETE_SESSION );
1726
1727	if ( !reqp ) {
1728		*text = "unable to allocate memory for rbac_delete_session exop";
1729		return LDAP_PROTOCOL_ERROR;
1730	}
1731
1732	ber_dupbv_x( &reqdata, in, ctx );
1733
1734	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
1735	ber_init2( ber, &reqdata, 0 );
1736
1737	tag = ber_scanf( ber, "{" /*}*/ );
1738
1739	if ( tag == LBER_ERROR ) {
1740		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
1741				"decoding error.\n" );
1742		goto decoding_error;
1743	}
1744
1745	tag = ber_peek_tag( ber, &len );
1746	if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID_SESS ) {
1747		struct berval uid;
1748		tag = ber_scanf( ber, "m", &uid );
1749		if ( tag == LBER_ERROR ) {
1750			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
1751					"user id parse failed.\n" );
1752			goto decoding_error;
1753		}
1754		ber_dupbv_x( &reqp->uid, &uid, ctx );
1755		tag = ber_peek_tag( ber, &len );
1756	}
1757
1758	//tag = ber_peek_tag( ber, &len );
1759	if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID_SESS ) {
1760		struct berval sessid;
1761		tag = ber_scanf( ber, "m", &sessid );
1762		if ( tag == LBER_ERROR ) {
1763			Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
1764					"session id parse failed.\n" );
1765			goto decoding_error;
1766		}
1767		ber_dupbv_x( &reqp->sessid, &sessid, ctx );
1768		tag = ber_peek_tag( ber, &len );
1769	}
1770
1771	if ( tag != LBER_DEFAULT || len != 0 ) {
1772decoding_error:;
1773
1774		Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
1775				"decoding error, len=%ld\n",
1776				(long)len );
1777		rc = LDAP_PROTOCOL_ERROR;
1778		*text = "data decoding error";
1779	}
1780
1781	if ( rc == LDAP_SUCCESS ) {
1782		*reqpp = reqp;
1783	} else {
1784		rbac_free_req( reqp );
1785		*reqpp = NULL;
1786	}
1787
1788	if ( !BER_BVISNULL( &reqdata ) ) {
1789		ber_memfree_x( reqdata.bv_val, ctx );
1790	}
1791
1792	return rc;
1793}
1794
1795static int
1796rbac_delete_session( Operation *op, SlapReply *rs )
1797{
1798	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1799	const struct berval rbac_op = BER_BVC("DeleteSession");
1800	rbac_session_t *sessp = NULL;
1801	rbac_req_t *reqp = NULL;
1802	int rc;
1803
1804	rs->sr_err = slap_parse_rbac_delete_session(
1805			op->ore_reqdata, &reqp, &rs->sr_text, NULL );
1806
1807	assert( rs->sr_err == LDAP_SUCCESS );
1808
1809	/* get the session using the session id */
1810	sessp = rbac_session_byid( op, reqp );
1811	if ( !sessp ) {
1812		Debug( LDAP_DEBUG_ANY, "rbac_delete_session: "
1813				"session not found\n" );
1814		rc = LDAP_UNWILLING_TO_PERFORM;
1815		goto done;
1816	}
1817
1818	/* checking whether the session is owned by the user */
1819	if ( !rbac_is_session_owner( sessp, reqp ) ) {
1820		Debug( LDAP_DEBUG_ANY, "rbac_delete_session: "
1821				"session not owned by user\n" );
1822		rc = LDAP_UNWILLING_TO_PERFORM;
1823		goto done;
1824	}
1825
1826	rc = rbac_int_delete_session( op, sessp );
1827	if ( rc != LDAP_SUCCESS ) {
1828		Debug( LDAP_DEBUG_ANY, "rbac_int_delete_session: "
1829				"unable to delete session\n" );
1830		rc = LDAP_UNWILLING_TO_PERFORM;
1831		goto done;
1832	}
1833
1834done:;
1835
1836	rs->sr_err = rc;
1837
1838	// always put the OID in the response:
1839	rs->sr_rspoid = ch_strdup( slap_EXOP_DELETE_SESSION.bv_val );
1840
1841	/* generate audit log */
1842	rbac_audit(
1843			op, DeleteSession, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
1844
1845	rbac_free_session( sessp );
1846	rbac_free_req( reqp );
1847
1848	return rs->sr_err;
1849}
1850
1851/* returns the permissions associated with a session */
1852static int
1853rbac_session_permissions( Operation *op, SlapReply *rs, rbac_req_t *reqp )
1854{
1855	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1856	const struct berval rbac_op = BER_BVC("SessionPermissions");
1857	rbac_session_t *sessp;
1858
1859	sessp = rbac_session_byid( op, reqp );
1860	if ( !sessp ) {
1861		Debug( LDAP_DEBUG_ANY, "rbac_session_permissions: "
1862				"session id not found\n" );
1863		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1864		goto done;
1865	}
1866
1867	rs->sr_err = rbac_int_session_permissions( op, rs, reqp, sessp );
1868	if ( rs->sr_err != LDAP_SUCCESS ) {
1869		Debug( LDAP_DEBUG_ANY, "rbac_session_permissions: "
1870				"permissions not found\n" );
1871		goto done;
1872	}
1873
1874done:;
1875	return rs->sr_err;
1876}
1877
1878/* extract session permission info from op */
1879int
1880rbac_search_parse_session_permissions_req(
1881		Operation *op,
1882		rbac_req_t **reqpp,
1883		const char **text,
1884		void *ctx )
1885{
1886	int rc = LDAP_SUCCESS;
1887	struct berval *sessid = NULL;
1888	rbac_req_t *reqp = NULL;
1889	*text = NULL;
1890	struct berval rbac_session_id = BER_BVC("sessionID");
1891	struct berval rbac_session_permissions_attr =
1892			BER_BVC("sessionPermissions");
1893	AttributeDescription *ad = NULL;
1894	Filter *f;
1895
1896	/* check simple assertion (sessionID=<session id>) */
1897	f = op->ors_filter;
1898	ad = f->f_ava->aa_desc;
1899	if ( !ad || ber_bvstrcasecmp( &rbac_session_id, &ad->ad_cname ) ) {
1900		goto done;
1901	}
1902	sessid = &f->f_ava->aa_value;
1903
1904	if ( !rbac_is_valid_session_id( sessid ) ) {
1905		Debug( LDAP_DEBUG_ANY, "rbac_search_parse_session_permissions_req: "
1906				"invalid session id\n" );
1907		rc = LDAP_UNWILLING_TO_PERFORM;
1908		goto done;
1909	}
1910
1911	/* check requested attr */
1912
1913	if ( !op->oq_search.rs_attrs ||
1914			BER_BVISNULL( &op->oq_search.rs_attrs[0].an_name ) ||
1915			ber_bvstrcasecmp( &op->oq_search.rs_attrs[0].an_name,
1916					&rbac_session_permissions_attr ) ||
1917			!BER_BVISNULL( &op->oq_search.rs_attrs[1].an_name ) ) {
1918		Debug( LDAP_DEBUG_ANY, "rbac_search_parse_session_permissions_req: "
1919				"only sessionPermissions allowed\n" );
1920		rc = LDAP_UNWILLING_TO_PERFORM;
1921		goto done;
1922	}
1923
1924	reqp = rbac_alloc_req( RBAC_REQ_SESSION_PERMISSIONS );
1925	if ( !reqp ) {
1926		*text = "unable to allocate memory for rbac_session_permissions req";
1927		rc = LDAP_UNWILLING_TO_PERFORM;
1928		goto done;
1929	}
1930
1931	/* retrieve session id from search filter */
1932	ber_dupbv_x( &reqp->sessid, sessid, ctx );
1933
1934done:;
1935
1936	if ( rc == LDAP_SUCCESS ) {
1937		*reqpp = reqp;
1938	} else {
1939		rbac_free_req( reqp );
1940		*reqpp = NULL;
1941	}
1942
1943	return rc;
1944}
1945
1946static int
1947rbac_search( Operation *op, SlapReply *rs )
1948{
1949	Debug( LDAP_DEBUG_ANY, "rbac_search entry\n" );
1950
1951	return SLAP_CB_CONTINUE;
1952}
1953
1954/*
1955static int
1956rbac_search( Operation *op, SlapReply *rs )
1957{
1958	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1959	rbac_req_t *reqp = NULL;
1960	int rc = SLAP_CB_CONTINUE;
1961
1962	 only session_permissions is implemented for now
1963	rc = rbac_search_parse_session_permissions_req(
1964			op, &reqp, &rs->sr_text, NULL );
1965	if ( !reqp ) {
1966		Debug( LDAP_DEBUG_ANY, "rbac_search: "
1967				"invalid search for session permissions\n" );
1968		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1969		goto done;
1970	}
1971
1972	rc = rbac_session_permissions( op, rs, reqp );
1973	if ( rc != LDAP_SUCCESS ) {
1974		Debug( LDAP_DEBUG_ANY, "rbac_search: "
1975				"session permissions failed\n" );
1976		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1977		goto done;
1978	}
1979
1980	rs->sr_err = LDAP_SUCCESS;
1981
1982done:;
1983	send_ldap_result( op, rs );
1984
1985	return rc;
1986}
1987*/
1988
1989static struct exop {
1990	struct berval oid;
1991	BI_op_extended *extended;
1992} rbac_exop_table[] = {
1993	{ BER_BVC(LDAP_RBAC_EXOP_CREATE_SESSION), rbac_create_session },
1994	{ BER_BVC(LDAP_RBAC_EXOP_CHECK_ACCESS), rbac_check_access },
1995	{ BER_BVC(LDAP_RBAC_EXOP_ADD_ACTIVE_ROLE), rbac_add_active_role },
1996	{ BER_BVC(LDAP_RBAC_EXOP_DROP_ACTIVE_ROLE), rbac_drop_active_role },
1997	{ BER_BVC(LDAP_RBAC_EXOP_DELETE_SESSION), rbac_delete_session },
1998	{ BER_BVC(LDAP_RBAC_EXOP_SESSION_ROLES), rbac_session_roles },
1999
2000	{ BER_BVNULL, NULL }
2001};
2002
2003static int
2004rbac_add( Operation *op, SlapReply *rs )
2005{
2006	return SLAP_CB_CONTINUE;
2007}
2008
2009static int
2010rbac_bind( Operation *op, SlapReply *rs )
2011{
2012	return SLAP_CB_CONTINUE;
2013}
2014
2015static int
2016rbac_compare( Operation *op, SlapReply *rs )
2017{
2018	return SLAP_CB_CONTINUE;
2019}
2020
2021static int
2022rbac_delete( Operation *op, SlapReply *rs )
2023{
2024	return SLAP_CB_CONTINUE;
2025}
2026
2027static int
2028rbac_modify( Operation *op, SlapReply *rs )
2029{
2030	return SLAP_CB_CONTINUE;
2031}
2032
2033static int
2034rbac_extended( Operation *op, SlapReply *rs )
2035{
2036	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
2037	int rc = SLAP_CB_CONTINUE;
2038	int i;
2039
2040	for ( i = 0; rbac_exop_table[i].extended != NULL; i++ ) {
2041		if ( bvmatch( &rbac_exop_table[i].oid, &op->oq_extended.rs_reqoid ) ) {
2042			rc = rbac_exop_table[i].extended( op, rs );
2043			switch ( rc ) {
2044				case LDAP_SUCCESS:
2045					break;
2046				case SLAP_CB_CONTINUE:
2047				case SLAPD_ABANDON:
2048					return rc;
2049				default:
2050					send_ldap_result( op, rs );
2051					return rc;
2052			}
2053			break;
2054		}
2055	}
2056
2057	return rc;
2058}
2059
2060static int
2061rbac_db_init( BackendDB *be, ConfigReply *cr )
2062{
2063	slap_overinst *on = (slap_overinst *)be->bd_info;
2064
2065	return 0;
2066}
2067
2068static int
2069rbac_db_open( BackendDB *be, ConfigReply *cr )
2070{
2071	int rc = LDAP_SUCCESS;
2072
2073	rc = rbac_initialize_tenants( be, cr );
2074
2075	return rc;
2076}
2077
2078static int
2079rbac_db_close( BackendDB *be, ConfigReply *cr )
2080{
2081	return 0;
2082}
2083
2084int
2085rbac_initialize()
2086{
2087	int rc;
2088
2089	rc = load_extop2( (struct berval *)&slap_EXOP_CREATE_SESSION,
2090			SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_create_session, 0 );
2091	if ( rc != LDAP_SUCCESS ) {
2092		Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
2093				"unable to register rbac_create_session exop: %d\n",
2094				rc );
2095		return rc;
2096	}
2097
2098	rc = load_extop2( (struct berval *)&slap_EXOP_CHECK_ACCESS,
2099			SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_check_access, 0 );
2100	if ( rc != LDAP_SUCCESS ) {
2101		Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
2102				"unable to register rbac_check_access exop: %d\n",
2103				rc );
2104		return rc;
2105	}
2106
2107	rc = load_extop2( (struct berval *)&slap_EXOP_ADD_ACTIVE_ROLE,
2108			SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_add_active_role, 0 );
2109	if ( rc != LDAP_SUCCESS ) {
2110		Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
2111				"unable to register rbac_add_active_role exop: %d\n",
2112				rc );
2113		return rc;
2114	}
2115
2116	rc = load_extop2( (struct berval *)&slap_EXOP_DROP_ACTIVE_ROLE,
2117			SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_drop_active_role, 0 );
2118	if ( rc != LDAP_SUCCESS ) {
2119		Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
2120				"unable to register rbac_drop_active_role exop: %d\n",
2121				rc );
2122		return rc;
2123	}
2124
2125	rc = load_extop2( (struct berval *)&slap_EXOP_DELETE_SESSION,
2126			SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_delete_session, 0 );
2127	if ( rc != LDAP_SUCCESS ) {
2128		Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
2129				"unable to register rbac_delete_session exop: %d\n",
2130				rc );
2131		return rc;
2132	}
2133
2134	rc = load_extop2( (struct berval *)&slap_EXOP_SESSION_ROLES,
2135			SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_session_roles, 0 );
2136	if ( rc != LDAP_SUCCESS ) {
2137		Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
2138				"unable to register rbac_session_roles exop: %d\n",
2139				rc );
2140		return rc;
2141	}
2142
2143	rbac.on_bi.bi_type = "rbac";
2144	rbac.on_bi.bi_db_init = rbac_db_init;
2145	rbac.on_bi.bi_db_open = rbac_db_open;
2146	rbac.on_bi.bi_db_close = rbac_db_close;
2147
2148	rbac.on_bi.bi_op_add = rbac_add;
2149	rbac.on_bi.bi_op_bind = rbac_bind;
2150	rbac.on_bi.bi_op_compare = rbac_compare;
2151	rbac.on_bi.bi_op_delete = rbac_delete;
2152	rbac.on_bi.bi_op_modify = rbac_modify;
2153	rbac.on_bi.bi_op_search = rbac_search;
2154	rbac.on_bi.bi_extended = rbac_extended;
2155	rbac.on_bi.bi_cf_ocs = rbac_ocs;
2156
2157	/*	rbac.on_bi.bi_connection_destroy = rbac_connection_destroy; */
2158
2159	rc = config_register_schema( rbaccfg, rbac_ocs );
2160	if ( rc ) return rc;
2161
2162	rc = rbac_initialize_repository();
2163	if ( rc != LDAP_SUCCESS ) {
2164		return rc;
2165	}
2166
2167	return overlay_register( &rbac );
2168}
2169
2170int
2171init_module( int argc, char *argv[] )
2172{
2173	return rbac_initialize();
2174}
2175