xref: /netbsd-src/external/bsd/openldap/dist/contrib/slapd-modules/rbac/rbac.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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 
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
rbac_tenant_parse(char * tenent_info,tenant_info_t * tenants)198 rbac_tenant_parse( char *tenent_info, tenant_info_t *tenants )
199 {
200 	return;
201 }
202 
203 static int
rbac_cf_gen(ConfigArgs * c)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 *
rbac_tid2tenant(struct berval * tid)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
slap_parse_rbac_session_roles(struct berval * in,rbac_req_t ** reqpp,const char ** text,void * ctx)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
rbac_session_roles(Operation * op,SlapReply * rs)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
rbac_session_rolesx(Operation * op,SlapReply * rs)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
slap_parse_rbac_create_session(struct berval * in,rbac_req_t ** reqpp,const char ** text,void * ctx)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
rbac_create_session(Operation * op,SlapReply * rs)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
slap_parse_rbac_check_access(struct berval * in,rbac_req_t ** reqpp,const char ** text,void * ctx)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 // checkAcess F  (ALL)
1086 static int
rbac_check_access(Operation * op,SlapReply * rs)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 // checkAcess A loop back
1155 static int
rbac_check_accessA(Operation * op,SlapReply * rs)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 // checkAcess B parse
1171 static int
rbac_check_accessB(Operation * op,SlapReply * rs)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 // checkAcess C - parse request & read session record
1199 static int
rbac_check_accessC(Operation * op,SlapReply * rs)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 // checkAcess D, parse, read perm
1239 static int
rbac_check_accessD(Operation * op,SlapReply * rs)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 // checkAcess E everything but the audit insert
1291 static int
rbac_check_accessE(Operation * op,SlapReply * rs)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
rbac_check_user_role(rbac_req_t * reqp,rbac_session_t * sessp,rbac_user_t * userp)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
rbac_check_session_role(rbac_req_t * reqp,rbac_session_t * sessp)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
rbac_check_user_session(rbac_session_t * sessp,rbac_req_t * reqp)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
slap_parse_rbac_active_role(struct berval * in,int add_or_drop_role,rbac_req_t ** reqpp,const char ** text,void * ctx)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
rbac_add_active_role(Operation * op,SlapReply * rs)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
rbac_drop_active_role(Operation * op,SlapReply * rs)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
slap_parse_rbac_delete_session(struct berval * in,rbac_req_t ** reqpp,const char ** text,void * ctx)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
rbac_delete_session(Operation * op,SlapReply * rs)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
rbac_session_permissions(Operation * op,SlapReply * rs,rbac_req_t * reqp)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
rbac_search_parse_session_permissions_req(Operation * op,rbac_req_t ** reqpp,const char ** text,void * ctx)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
rbac_search(Operation * op,SlapReply * rs)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
rbac_add(Operation * op,SlapReply * rs)2004 rbac_add( Operation *op, SlapReply *rs )
2005 {
2006 	return SLAP_CB_CONTINUE;
2007 }
2008 
2009 static int
rbac_bind(Operation * op,SlapReply * rs)2010 rbac_bind( Operation *op, SlapReply *rs )
2011 {
2012 	return SLAP_CB_CONTINUE;
2013 }
2014 
2015 static int
rbac_compare(Operation * op,SlapReply * rs)2016 rbac_compare( Operation *op, SlapReply *rs )
2017 {
2018 	return SLAP_CB_CONTINUE;
2019 }
2020 
2021 static int
rbac_delete(Operation * op,SlapReply * rs)2022 rbac_delete( Operation *op, SlapReply *rs )
2023 {
2024 	return SLAP_CB_CONTINUE;
2025 }
2026 
2027 static int
rbac_modify(Operation * op,SlapReply * rs)2028 rbac_modify( Operation *op, SlapReply *rs )
2029 {
2030 	return SLAP_CB_CONTINUE;
2031 }
2032 
2033 static int
rbac_extended(Operation * op,SlapReply * rs)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
rbac_db_init(BackendDB * be,ConfigReply * cr)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
rbac_db_open(BackendDB * be,ConfigReply * cr)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
rbac_db_close(BackendDB * be,ConfigReply * cr)2079 rbac_db_close( BackendDB *be, ConfigReply *cr )
2080 {
2081 	return 0;
2082 }
2083 
2084 int
rbac_initialize()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
init_module(int argc,char * argv[])2171 init_module( int argc, char *argv[] )
2172 {
2173 	return rbac_initialize();
2174 }
2175