Home | History | Annotate | Line # | Download | only in rbac
      1 /*	$NetBSD: rbac.c,v 1.3 2025/09/05 21:16:18 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-2024 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.3 2025/09/05 21:16:18 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 
     38 static slap_overinst rbac;
     39 
     40 static struct berval slap_EXOP_CREATE_SESSION =
     41 		BER_BVC(LDAP_RBAC_EXOP_CREATE_SESSION);
     42 static struct berval slap_EXOP_CHECK_ACCESS =
     43 		BER_BVC(LDAP_RBAC_EXOP_CHECK_ACCESS);
     44 static struct berval slap_EXOP_ADD_ACTIVE_ROLE =
     45 		BER_BVC(LDAP_RBAC_EXOP_ADD_ACTIVE_ROLE);
     46 static struct berval slap_EXOP_DROP_ACTIVE_ROLE =
     47 		BER_BVC(LDAP_RBAC_EXOP_DROP_ACTIVE_ROLE);
     48 static struct berval slap_EXOP_DELETE_SESSION =
     49 		BER_BVC(LDAP_RBAC_EXOP_DELETE_SESSION);
     50 static struct berval slap_EXOP_SESSION_ROLES =
     51 		BER_BVC(LDAP_RBAC_EXOP_SESSION_ROLES);
     52 
     53 rbac_tenant_t rbac_tenants = {
     54 	{
     55 		.schema = &slap_rbac_jts_schema,
     56 	},
     57 	NULL
     58 };
     59 
     60 static ConfigDriver rbac_cf_gen;
     61 
     62 static 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 
    164 static 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 
    178 static 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 
    188 static 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 
    197 static void
    198 rbac_tenant_parse( char *tenent_info, tenant_info_t *tenants )
    199 {
    200 	return;
    201 }
    202 
    203 static int
    204 rbac_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 
    309 tenant_info_t *
    310 rbac_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 
    318 static int
    319 slap_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 ) {
    387 decoding_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 
    410 static int
    411 rbac_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 
    530 done:;
    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 
    544 static int
    545 rbac_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 
    660 done:;
    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  */
    677 static int
    678 slap_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 ) {
    787 decoding_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  */
    822 static int
    823 rbac_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 
    931 done:;
    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  */
    952 static int
    953 slap_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 ) {
   1059 decoding_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 // checkAccess F  (ALL)
   1086 static int
   1087 rbac_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 
   1137 done:
   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 // checkAccess A loop back
   1155 static int
   1156 rbac_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 // checkAccess B parse
   1171 static int
   1172 rbac_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 // checkAccess C - parse request & read session record
   1199 static int
   1200 rbac_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 
   1227 done:
   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 // checkAccess D, parse, read perm
   1239 static int
   1240 rbac_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 
   1278 done:
   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 // checkAccess E everything but the audit insert
   1291 static int
   1292 rbac_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 
   1343 done:
   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 */
   1362 static int
   1363 rbac_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 
   1382 done:;
   1383 
   1384 	return rc;
   1385 }
   1386 
   1387 /* check whether role exists and role assigned to the session */
   1388 static int
   1389 rbac_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 
   1402 done:;
   1403 
   1404 	return rc;
   1405 }
   1406 
   1407 /* make sure user is the owner of the session */
   1408 static int
   1409 rbac_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 
   1424 done:;
   1425 
   1426 	return rc;
   1427 }
   1428 
   1429 /*
   1430  * slap_parse_rbac_active_role
   1431  */
   1432 static int
   1433 slap_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 ) {
   1518 decoding_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 
   1540 static int
   1541 rbac_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 
   1610 done:
   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 
   1626 static int
   1627 rbac_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 
   1684 done:
   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  */
   1703 static int
   1704 slap_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 ) {
   1772 decoding_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 
   1795 static int
   1796 rbac_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 
   1834 done:;
   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 */
   1852 static int
   1853 rbac_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 
   1874 done:;
   1875 	return rs->sr_err;
   1876 }
   1877 
   1878 /* extract session permission info from op */
   1879 int
   1880 rbac_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 
   1934 done:;
   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 
   1946 static int
   1947 rbac_search( Operation *op, SlapReply *rs )
   1948 {
   1949 	Debug( LDAP_DEBUG_ANY, "rbac_search entry\n" );
   1950 
   1951 	return SLAP_CB_CONTINUE;
   1952 }
   1953 
   1954 /*
   1955 static int
   1956 rbac_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 
   1982 done:;
   1983 	send_ldap_result( op, rs );
   1984 
   1985 	return rc;
   1986 }
   1987 */
   1988 
   1989 static 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 
   2003 static int
   2004 rbac_add( Operation *op, SlapReply *rs )
   2005 {
   2006 	return SLAP_CB_CONTINUE;
   2007 }
   2008 
   2009 static int
   2010 rbac_bind( Operation *op, SlapReply *rs )
   2011 {
   2012 	return SLAP_CB_CONTINUE;
   2013 }
   2014 
   2015 static int
   2016 rbac_compare( Operation *op, SlapReply *rs )
   2017 {
   2018 	return SLAP_CB_CONTINUE;
   2019 }
   2020 
   2021 static int
   2022 rbac_delete( Operation *op, SlapReply *rs )
   2023 {
   2024 	return SLAP_CB_CONTINUE;
   2025 }
   2026 
   2027 static int
   2028 rbac_modify( Operation *op, SlapReply *rs )
   2029 {
   2030 	return SLAP_CB_CONTINUE;
   2031 }
   2032 
   2033 static int
   2034 rbac_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 
   2060 static int
   2061 rbac_db_init( BackendDB *be, ConfigReply *cr )
   2062 {
   2063 	slap_overinst *on = (slap_overinst *)be->bd_info;
   2064 
   2065 	return 0;
   2066 }
   2067 
   2068 static int
   2069 rbac_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 
   2078 static int
   2079 rbac_db_close( BackendDB *be, ConfigReply *cr )
   2080 {
   2081 	return 0;
   2082 }
   2083 
   2084 int
   2085 rbac_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 
   2170 int
   2171 init_module( int argc, char *argv[] )
   2172 {
   2173 	return rbac_initialize();
   2174 }
   2175