xref: /netbsd-src/external/bsd/openldap/dist/contrib/slapd-modules/rbac/rbacsess.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: rbacsess.c,v 1.2 2021/08/14 16:14:53 christos Exp $	*/
2 
3 /* rbacsess.c - RBAC session */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  *
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: rbacsess.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 static slap_callback nullsc = { NULL, NULL, NULL, NULL };
37 
38 extern rbac_ad_t rbac_session_permission_ads[];
39 extern rbac_ad_t rbac_session_ads[];
40 
41 struct berval slapo_session_oc = BER_BVC("rbacSession");
42 
43 typedef struct session_perm_req {
44 	Operation *op;
45 	SlapReply *rs;
46 	struct berval *sessid;
47 	struct berval permdn;
48 	tenant_info_t *tenantp;
49 } session_perm_req_t;
50 
51 static int
rbac_sess_fake_cb(Operation * op,SlapReply * rs)52 rbac_sess_fake_cb( Operation *op, SlapReply *rs )
53 {
54 	Debug( LDAP_DEBUG_ANY, "rbac_sess_fake_cb\n" );
55 
56 	return 0;
57 }
58 
59 static int
rbac_send_session_permission(session_perm_req_t * sess_perm_reqp,rbac_permission_t * perm)60 rbac_send_session_permission(
61 		session_perm_req_t *sess_perm_reqp,
62 		rbac_permission_t *perm )
63 {
64 	int i, rc = LDAP_SUCCESS;
65 	Operation *op = sess_perm_reqp->op;
66 	SlapReply *rs = sess_perm_reqp->rs;
67 	struct berval *sessidp = sess_perm_reqp->sessid;
68 	struct berval *permdnp = &sess_perm_reqp->permdn;
69 
70 	Entry *e = entry_alloc();
71 	e->e_attrs = NULL;
72 	ber_dupbv( &e->e_name, permdnp );
73 	ber_dupbv( &e->e_nname, permdnp );
74 	e->e_private = NULL;
75 	attr_merge_one( e, slap_rbac_schema.ad_session_id, sessidp, NULL );
76 
77 	for ( i = 0; !BER_BVISNULL( &rbac_session_permission_ads[i].attr ); i++ ) {
78 		switch ( rbac_session_permission_ads[i].type ) {
79 			case RBAC_OP_NAME:
80 				attr_merge_one( e, *rbac_session_permission_ads[i].ad,
81 						&perm->opName[0], NULL );
82 				break;
83 			case RBAC_OBJ_NAME:
84 				attr_merge_one( e, *rbac_session_permission_ads[i].ad,
85 						&perm->objName[0], NULL );
86 				break;
87 			case RBAC_ROLE_NAME:
88 				attr_merge( e, *rbac_session_permission_ads[i].ad, perm->roles,
89 						NULL );
90 				break;
91 			default:
92 				break;
93 		}
94 	}
95 
96 	rs->sr_entry = e;
97 	rs->sr_flags = REP_ENTRY_MUSTRELEASE;
98 	rc = send_search_entry( op, rs );
99 
100 	return rc;
101 }
102 
103 static int
rbac_session_permissions_cb(Operation * op,SlapReply * rs)104 rbac_session_permissions_cb( Operation *op, SlapReply *rs )
105 {
106 	session_perm_req_t *sess_perm_reqp = op->o_callback->sc_private;
107 	tenant_info_t *tenantp = NULL;
108 	rbac_permission_t *permp = NULL;
109 	rbac_ad_t *session_permissions_ads;
110 	int i;
111 
112 	if ( rs->sr_type != REP_SEARCH ) return 0;
113 
114 	assert( sess_perm_reqp );
115 
116 	tenantp = sess_perm_reqp->tenantp;
117 	session_permissions_ads = tenantp->schema->session_permissions_ads;
118 
119 	permp = ch_calloc( 1, sizeof(rbac_permission_t) );
120 
121 	for ( i = 0; !BER_BVISNULL( &session_permissions_ads[i].attr ); i++ ) {
122 		Attribute *attr = NULL;
123 
124 		attr = attr_find(
125 				rs->sr_entry->e_attrs, *session_permissions_ads[i].ad );
126 		if ( attr != NULL ) {
127 			switch ( session_permissions_ads[i].type ) {
128 				case RBAC_USERS:
129 					ber_bvarray_dup_x( &permp->uids, attr->a_nvals, NULL );
130 					break;
131 				case RBAC_ROLES:
132 					ber_bvarray_dup_x( &permp->roles, attr->a_nvals, NULL );
133 					break;
134 				case RBAC_OBJ_NAME:
135 					ber_bvarray_dup_x( &permp->objName, attr->a_nvals, NULL );
136 					break;
137 				case RBAC_OP_NAME:
138 					ber_bvarray_dup_x( &permp->opName, attr->a_nvals, NULL );
139 					break;
140 			}
141 		}
142 	}
143 
144 	rbac_send_session_permission( sess_perm_reqp, permp );
145 	rbac_free_permission( permp );
146 	permp = NULL;
147 
148 	return SLAP_CB_CONTINUE;
149 }
150 
151 static int
rbac_read_session_cb(Operation * op,SlapReply * rs)152 rbac_read_session_cb( Operation *op, SlapReply *rs )
153 {
154 	rbac_session_t *sessp = op->o_callback->sc_private;
155 	int i;
156 
157 	if ( rs->sr_type != REP_SEARCH ) return 0;
158 
159 	ber_dupbv( &sessp->sessdn, &rs->sr_entry->e_name );
160 
161 	for ( i = 0; !BER_BVISNULL( &rbac_session_ads[i].attr ); i++ ) {
162 		Attribute *attr = NULL;
163 		attr = attr_find( rs->sr_entry->e_attrs, *rbac_session_ads[i].ad );
164 		if ( attr != NULL ) {
165 			switch ( rbac_session_ads[i].type ) {
166 				case RBAC_SESSION_ID:
167 					ber_dupbv( &sessp->sessid, &attr->a_vals[0] );
168 					break;
169 				case RBAC_USER_DN:
170 					ber_dupbv( &sessp->userdn, &attr->a_vals[0] );
171 					break;
172 				case RBAC_ROLES:
173 					ber_bvarray_dup_x( &sessp->roles, attr->a_nvals, NULL );
174 					break;
175 				case RBAC_ROLE_CONSTRAINTS:
176 					ber_bvarray_dup_x(
177 							&sessp->role_constraints, attr->a_nvals, NULL );
178 					break;
179 				case RBAC_UID:
180 					ber_dupbv( &sessp->uid, &attr->a_vals[0] );
181 					break;
182 				case RBAC_TENANT_ID:
183 					ber_dupbv( &sessp->tenantid, &attr->a_vals[0] );
184 					break;
185 				default:
186 					break;
187 			}
188 		}
189 	}
190 
191 	//return SLAP_CB_CONTINUE;
192 	return 0;
193 }
194 
195 /* check whether the session is owned by the user */
196 int
rbac_is_session_owner(rbac_session_t * sessp,rbac_req_t * reqp)197 rbac_is_session_owner( rbac_session_t *sessp, rbac_req_t *reqp )
198 {
199 	int rc = 0;
200 
201 	if ( BER_BVISEMPTY( &sessp->uid ) || BER_BVISEMPTY( &reqp->uid ) ) {
202 		Debug( LDAP_DEBUG_ANY, "session not owned by user\n" );
203 		rc = 0;
204 		goto done;
205 	}
206 
207 	if ( !ber_bvstrcasecmp( &sessp->uid, &reqp->uid ) ) {
208 		rc = 1;
209 		goto done;
210 	}
211 
212 done:;
213 	return rc;
214 }
215 
216 int
rbac_session_add_role(Operation * op,rbac_session_t * sessp,rbac_req_t * reqp)217 rbac_session_add_role( Operation *op, rbac_session_t *sessp, rbac_req_t *reqp )
218 {
219 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
220 	slap_callback cb = { 0 };
221 	SlapReply rs2 = { REP_RESULT };
222 	Operation op2 = *op;
223 	rbac_callback_info_t rbac_cb;
224 	tenant_info_t *tenantp = NULL;
225 	struct berval vals[2];
226 	Modifications mod;
227 	int rc = LDAP_SUCCESS;
228 
229 	tenantp = rbac_tid2tenant( &reqp->tenantid );
230 	if ( !tenantp ) {
231 		Debug( LDAP_DEBUG_ANY, "rbac_session_add_role: "
232 				"no tenant info with the req\n" );
233 		goto done;
234 	}
235 
236 	// convert the role name to lower case:
237 	rbac_to_lower( &reqp->role );
238 
239 	//ber_dupbv( &vals[0], &reqp->roles[0]);
240 	ber_dupbv( &vals[0], &reqp->role );
241 	BER_BVZERO( &vals[1] );
242 
243 	/* create mod list */
244 	mod.sml_op = LDAP_MOD_ADD;
245 	mod.sml_flags = 0;
246 	mod.sml_type = slap_rbac_schema.ad_session_roles->ad_cname;
247 	mod.sml_desc = slap_rbac_schema.ad_session_roles;
248 	mod.sml_numvals = 1;
249 	mod.sml_values = vals;
250 	mod.sml_nvalues = NULL;
251 	mod.sml_next = NULL;
252 
253 	cb.sc_private = &rbac_cb;
254 	cb.sc_response = rbac_sess_fake_cb;
255 	op2.o_callback = &cb;
256 
257 	op2.o_tag = LDAP_REQ_MODIFY;
258 	op2.orm_modlist = &mod;
259 	op2.o_req_dn = sessp->sessdn;
260 	op2.o_req_ndn = sessp->sessdn;
261 	op2.o_bd = select_backend( &op2.o_req_ndn, 0 );
262 	op2.o_dn = op2.o_bd->be_rootdn;
263 	op2.o_ndn = op2.o_bd->be_rootdn;
264 	op2.ors_limit = NULL;
265 	rc = op2.o_bd->be_modify( &op2, &rs2 );
266 	ch_free( vals[0].bv_val );
267 
268 done:;
269 	if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
270 		Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
271 				"role already activated in session\n" );
272 	}
273 	return rc;
274 }
275 
276 int
rbac_session_drop_role(Operation * op,rbac_session_t * sessp,rbac_req_t * reqp)277 rbac_session_drop_role( Operation *op, rbac_session_t *sessp, rbac_req_t *reqp )
278 {
279 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
280 	slap_callback cb = { 0 };
281 	SlapReply rs2 = { REP_RESULT };
282 	Operation op2 = *op;
283 	rbac_callback_info_t rbac_cb;
284 	tenant_info_t *tenantp = NULL;
285 	Modifications *m = NULL;
286 	int rc = LDAP_SUCCESS;
287 
288 	tenantp = rbac_tid2tenant( &reqp->tenantid );
289 	if ( !tenantp ) {
290 		Debug( LDAP_DEBUG_ANY, "rbac_session_drop_role: "
291 				"no tenant info with the req\n" );
292 		goto done;
293 	}
294 
295 	/* create mod list */
296 	m = ch_calloc( sizeof(Modifications), 1 );
297 	m->sml_op = LDAP_MOD_DELETE;
298 	m->sml_flags = 0;
299 	m->sml_type = slap_rbac_schema.ad_session_roles->ad_cname;
300 	m->sml_desc = slap_rbac_schema.ad_session_roles;
301 	m->sml_numvals = 1;
302 	m->sml_values = ch_calloc( sizeof(struct berval), 2 );
303 	m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 );
304 	//ber_dupbv( &m->sml_values[0], &reqp->roles[0]);
305 
306 	// convert the role name to lower case:
307 	rbac_to_lower( &reqp->role );
308 
309 	ber_dupbv( &m->sml_values[0], &reqp->role );
310 
311 	// todo: determine if this needs to be done:
312 	//BER_BVZERO(&m->sml_values[1]);
313 
314 	ber_dupbv( &m->sml_nvalues[0], &reqp->role );
315 	BER_BVZERO( &m->sml_nvalues[1] );
316 
317 	//ber_dupbv( &m->sml_nvalues[0], &reqp->roles[0]);
318 	//ber_dupbv( &m->sml_nvalues[0], &reqp->role);
319 	//BER_BVZERO(&m->sml_nvalues[1]);
320 
321 	m->sml_next = NULL;
322 
323 	cb.sc_private = &rbac_cb;
324 	cb.sc_response = rbac_sess_fake_cb;
325 	op2.o_callback = &cb;
326 
327 	op2.o_dn = tenantp->session_admin;
328 	op2.o_ndn = tenantp->session_admin;
329 	op2.o_tag = LDAP_REQ_MODIFY;
330 	op2.orm_modlist = m;
331 	op2.o_req_dn = sessp->sessdn;
332 	op2.o_req_ndn = sessp->sessdn;
333 	op2.o_bd = select_backend( &op2.o_req_ndn, 0 );
334 
335 	op2.ors_limit = NULL;
336 	rc = op2.o_bd->be_modify( &op2, &rs2 );
337 
338 done:;
339 	if ( m ) {
340 		slap_mods_free( m, 1 );
341 	}
342 
343 	return rc;
344 }
345 
346 /* delete the session */
347 int
rbac_int_delete_session(Operation * op,rbac_session_t * sessp)348 rbac_int_delete_session( Operation *op, rbac_session_t *sessp )
349 {
350 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
351 	slap_callback cb = { 0 };
352 	SlapReply rs2 = { REP_RESULT };
353 	Operation op2 = *op;
354 	rbac_callback_info_t rbac_cb;
355 	tenant_info_t *tenantp = NULL;
356 	int rc = LDAP_SUCCESS;
357 
358 	tenantp = rbac_tid2tenant( &sessp->tenantid );
359 	if ( !tenantp ) {
360 		Debug( LDAP_DEBUG_ANY, "rbac_session_drop_role: "
361 				"no tenant info with the req\n" );
362 		goto done;
363 	}
364 
365 	/* delete RBAC session */
366 	cb.sc_private = &rbac_cb;
367 	cb.sc_response = rbac_sess_fake_cb;
368 	op2.o_callback = &cb;
369 
370 	op2.o_dn = tenantp->session_admin;
371 	op2.o_ndn = tenantp->session_admin;
372 	op2.o_tag = LDAP_REQ_DELETE;
373 	op2.o_req_dn = sessp->sessdn;
374 	op2.o_req_ndn = sessp->sessdn;
375 	op2.o_bd = select_backend( &op2.o_req_ndn, 0 );
376 	rc = op2.o_bd->be_delete( &op2, &rs2 );
377 
378 done:;
379 	return rc;
380 }
381 
382 rbac_session_t *
rbac_alloc_session()383 rbac_alloc_session()
384 {
385 	rbac_session_t *sessp = NULL;
386 
387 	sessp = ch_malloc( sizeof(rbac_session_t) );
388 	sessp->sessid.bv_len =
389 			lutil_uuidstr( sessp->uuidbuf, sizeof(sessp->uuidbuf) );
390 	sessp->sessid.bv_val = sessp->uuidbuf;
391 
392 	sessp->user = NULL;
393 	BER_BVZERO( &sessp->tenantid );
394 	BER_BVZERO( &sessp->uid );
395 	BER_BVZERO( &sessp->userdn );
396 	BER_BVZERO( &sessp->sessdn );
397 	BER_BVZERO( &sessp->message );
398 
399 	sessp->last_access = 0;
400 	sessp->timeout = 0;
401 	sessp->warning_id = 0;
402 	sessp->error_id = 0;
403 	sessp->grace_logins = 0;
404 	sessp->expiration_secs = 0;
405 	sessp->is_authenticated = 0;
406 
407 	sessp->roles = NULL;
408 	sessp->role_constraints = NULL;
409 
410 	return sessp;
411 }
412 
413 int
rbac_register_session(Operation * op,SlapReply * rs,rbac_session_t * sessp)414 rbac_register_session( Operation *op, SlapReply *rs, rbac_session_t *sessp )
415 {
416 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
417 	struct berval rdn, nrdn;
418 	SlapReply rs2 = { REP_RESULT };
419 	OperationBuffer opbuf;
420 	Operation *op2;
421 	Connection conn = { 0 };
422 	Entry *e = NULL;
423 	int rc = LDAP_SUCCESS;
424 	char rdnbuf[
425 		STRLENOF(RBAC_SESSION_RDN_EQ) + LDAP_LUTIL_UUIDSTR_BUFSIZE + 1];
426 	tenant_info_t *tenantp = rbac_tid2tenant( &sessp->tenantid );
427 #ifdef USE_NEW_THREAD_CONTEXT
428 	void *thrctx = ldap_pvt_thread_pool_context();
429 #else
430 	void *thrctx = op->o_tmpmemctx;
431 #endif
432 
433 	if ( !sessp ) {
434 		rc = LDAP_UNWILLING_TO_PERFORM;
435 		goto done;
436 	}
437 
438 	/* dynamic objects */
439 	e = entry_alloc();
440 
441 	strcpy( rdnbuf, RBAC_SESSION_RDN_EQ );
442 	strncat( rdnbuf, sessp->sessid.bv_val, sessp->sessid.bv_len );
443 	rdn.bv_val = rdnbuf;
444 	rdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
445 	nrdn.bv_val = rdnbuf;
446 	nrdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
447 
448 	build_new_dn( &e->e_name, &tenantp->sessions_basedn, &rdn, NULL );
449 	build_new_dn( &e->e_nname, &tenantp->sessions_basedn, &nrdn, NULL );
450 
451 	attr_merge_one( e, slap_schema.si_ad_objectClass, &slapo_session_oc, NULL );
452 	attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
453 			&slapo_session_oc, NULL );
454 	attr_merge_one( e, slap_rbac_schema.ad_session_id, &sessp->sessid, NULL );
455 
456 	if ( !BER_BVISNULL( &sessp->uid ) ) {
457 		attr_merge_one( e, slap_schema.si_ad_uid, &sessp->uid, NULL );
458 	}
459 
460 	/* add tenant id */
461 	if ( !BER_BVISNULL( &sessp->tenantid ) ) {
462 		attr_merge_one(
463 				e, slap_rbac_schema.ad_tenant_id, &sessp->tenantid, NULL );
464 	}
465 
466 	/* add the userdn */
467 	if ( !BER_BVISNULL( &sessp->userdn ) ) {
468 		attr_merge_one(
469 				e, slap_rbac_schema.ad_session_user_dn, &sessp->userdn, NULL );
470 	}
471 
472 	if ( sessp->roles ) {
473 		attr_merge( e, slap_rbac_schema.ad_session_roles, sessp->roles, NULL );
474 	}
475 
476 	// TODO: ensure this is correct way to store constraints in session:
477 	if ( sessp->role_constraints ) {
478 		attr_merge( e, slap_rbac_schema.ad_session_role_constraints,
479 				sessp->role_constraints, NULL );
480 	}
481 	/* rendered dynmaicObject */
482 	attr_merge_one( e, slap_schema.si_ad_objectClass,
483 			&slap_schema.si_oc_dynamicObject->soc_cname, NULL );
484 
485 	/* store RBAC session */
486 	connection_fake_init2( &conn, &opbuf, thrctx, 0 );
487 	op2 = &opbuf.ob_op;
488 	//Operation op2 = *op;
489 	//op2.o_callback = &nullsc;
490 	//rbac_callback_info_t rbac_cb;
491 	//cb.sc_private      = &rbac_cb;
492 	//cb.sc_response     = rbac_sess_fake_cb;
493 	//op2.o_callback    = &cb;
494 	//op2.ors_limit     = NULL;
495 	op->o_callback = &nullsc;
496 	op2->o_dn = tenantp->session_admin;
497 	op2->o_ndn = tenantp->session_admin;
498 	op2->o_tag = LDAP_REQ_ADD;
499 	op2->o_protocol = LDAP_VERSION3;
500 	op2->o_req_dn = e->e_name;
501 	op2->o_req_ndn = e->e_nname;
502 	op2->ora_e = e;
503 	op2->o_bd = frontendDB;
504 
505 	rc = op2->o_bd->be_add( op2, &rs2 );
506 
507 done:;
508 	if ( e ) entry_free( e );
509 	return rc;
510 }
511 
512 int
rbac_register_session2(Operation * op,SlapReply * rs,rbac_session_t * sessp)513 rbac_register_session2( Operation *op, SlapReply *rs, rbac_session_t *sessp )
514 {
515 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
516 	struct berval rdn, nrdn;
517 	SlapReply rs2 = { REP_RESULT };
518 	Operation op2 = *op;
519 	rbac_callback_info_t rbac_cb;
520 	//OperationBuffer opbuf;
521 	//Connection conn = {0};
522 	Entry *e = NULL;
523 	int rc = LDAP_SUCCESS;
524 	char rdnbuf[STRLENOF(RBAC_SESSION_RDN_EQ) + LDAP_LUTIL_UUIDSTR_BUFSIZE +
525 			1];
526 	tenant_info_t *tenantp = rbac_tid2tenant( &sessp->tenantid );
527 	slap_callback cb = { 0 };
528 	//#ifdef USE_NEW_THREAD_CONTEXT
529 	//	void *thrctx = ldap_pvt_thread_pool_context();
530 	//#else
531 	//	void *thrctx = op->o_tmpmemctx;
532 	//#endif
533 
534 	if ( !sessp ) {
535 		rc = LDAP_UNWILLING_TO_PERFORM;
536 		goto done;
537 	}
538 
539 	/* dynamic objects */
540 	e = entry_alloc();
541 
542 	strcpy( rdnbuf, RBAC_SESSION_RDN_EQ );
543 	strncat( rdnbuf, sessp->sessid.bv_val, sessp->sessid.bv_len );
544 	rdn.bv_val = rdnbuf;
545 	rdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
546 	nrdn.bv_val = rdnbuf;
547 	nrdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
548 
549 	build_new_dn( &e->e_name, &tenantp->sessions_basedn, &rdn, NULL );
550 	build_new_dn( &e->e_nname, &tenantp->sessions_basedn, &nrdn, NULL );
551 
552 	attr_merge_one( e, slap_schema.si_ad_objectClass, &slapo_session_oc, NULL );
553 	attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
554 			&slapo_session_oc, NULL );
555 	attr_merge_one( e, slap_rbac_schema.ad_session_id, &sessp->sessid, NULL );
556 
557 	if ( !BER_BVISNULL( &sessp->uid ) ) {
558 		attr_merge_one( e, slap_schema.si_ad_uid, &sessp->uid, NULL );
559 	}
560 
561 	/* add tenant id */
562 	if ( !BER_BVISNULL( &sessp->tenantid ) ) {
563 		attr_merge_one(
564 				e, slap_rbac_schema.ad_tenant_id, &sessp->tenantid, NULL );
565 	}
566 
567 	/* add the userdn */
568 	if ( !BER_BVISNULL( &sessp->userdn ) ) {
569 		attr_merge_one(
570 				e, slap_rbac_schema.ad_session_user_dn, &sessp->userdn, NULL );
571 	}
572 
573 	if ( sessp->roles ) {
574 		attr_merge( e, slap_rbac_schema.ad_session_roles, sessp->roles, NULL );
575 	}
576 
577 	// TODO: ensure this is correct way to store constraints in session:
578 	if ( sessp->role_constraints ) {
579 		attr_merge( e, slap_rbac_schema.ad_session_role_constraints,
580 				sessp->role_constraints, NULL );
581 	}
582 	/* rendered dynmaicObject */
583 	attr_merge_one( e, slap_schema.si_ad_objectClass,
584 			&slap_schema.si_oc_dynamicObject->soc_cname, NULL );
585 
586 	/* store RBAC session */
587 	//connection_fake_init2( &conn, &opbuf, thrctx, 0 );
588 	//op2 = &opbuf.ob_op;
589 	//op2.o_ctrlflag = op->o_ctrlflag;
590 	// todo this ain't right"
591 	//op2.o_ctrlflag = 0;
592 	//OperationBuffer *opbuf;
593 	//memset( opbuf, 0, sizeof(OperationBuffer));
594 	//op2.o_hdr = &opbuf->ob_hdr;
595 	//op2.o_controls = opbuf->ob_controls;
596 
597 	// fails on modify.c:353 with segfault
598 
599 	//op2.o_callback = &nullsc;
600 	cb.sc_private = &rbac_cb;
601 	cb.sc_response = rbac_sess_fake_cb;
602 	op2.o_callback = &cb;
603 	op2.o_dn = tenantp->session_admin;
604 	op2.o_ndn = tenantp->session_admin;
605 	op2.o_tag = LDAP_REQ_ADD;
606 	op2.o_protocol = LDAP_VERSION3;
607 	op2.o_req_dn = e->e_name;
608 	op2.o_req_ndn = e->e_nname;
609 	op2.ora_e = e;
610 	op2.o_bd = frontendDB;
611 	//op2.ors_limit     = NULL;
612 
613 	rc = op2.o_bd->be_add( &op2, &rs2 );
614 
615 done:;
616 	if ( e ) entry_free( e );
617 
618 	return rc;
619 }
620 
621 int
rbac_is_valid_session_id(struct berval * sessid)622 rbac_is_valid_session_id( struct berval *sessid )
623 {
624 	/* TODO: simple test */
625 	if ( !sessid || sessid->bv_len != 36 ) {
626 		if ( !sessid ) {
627 			Debug( LDAP_DEBUG_ANY, "rbac_is_valid_session_id: "
628 					"null sessid\n" );
629 		} else {
630 			Debug( LDAP_DEBUG_ANY, "rbac_is_valid_session_id: "
631 					"len (%lu)\n",
632 					sessid->bv_len );
633 		}
634 		return 0;
635 	}
636 
637 	else {
638 		return 1;
639 	}
640 }
641 
642 /* create an rbac request with the session ID */
643 rbac_req_t *
rbac_is_search_session_permissions(Operation * op)644 rbac_is_search_session_permissions( Operation *op )
645 {
646 	rbac_req_t *reqp = NULL;
647 
648 	/* check whether the search for sessionPermissions and *
649 	 * with a valid sessionID */
650 
651 	return reqp;
652 }
653 
654 rbac_session_t *
rbac_session_byid_fake(Operation * op,rbac_req_t * reqp)655 rbac_session_byid_fake( Operation *op, rbac_req_t *reqp )
656 {
657 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
658 	rbac_session_t *sessp = NULL;
659 	int rc = LDAP_SUCCESS;
660 	char fbuf[RBAC_BUFLEN];
661 	struct berval filter = { sizeof(fbuf), fbuf };
662 	SlapReply rs2 = { REP_RESULT };
663 	Operation op2 = *op;
664 	rbac_callback_info_t rbac_cb;
665 	slap_callback cb = { 0 };
666 	tenant_info_t *tenantp = NULL;
667 
668 	if ( !rbac_is_valid_session_id( &reqp->sessid ) ) {
669 		Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
670 				"invalid session id (%s)\n",
671 				reqp->sessid.bv_val );
672 		rc = LDAP_UNWILLING_TO_PERFORM;
673 		goto done;
674 	}
675 
676 	sessp = rbac_alloc_session();
677 	if ( !sessp ) {
678 		Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
679 				"unable to allocate session memory\n" );
680 		rc = LDAP_UNWILLING_TO_PERFORM;
681 		goto done;
682 	}
683 
684 	tenantp = rbac_tid2tenant( &reqp->tenantid );
685 
686 	/* session id filter */
687 	memset( fbuf, 0, sizeof(fbuf) );
688 	strcpy( fbuf, RBAC_SESSION_RDN_EQ );
689 	strncpy( &fbuf[0] + sizeof(RBAC_SESSION_RDN_EQ) - 1, reqp->sessid.bv_val,
690 			reqp->sessid.bv_len );
691 	filter.bv_val = fbuf;
692 	filter.bv_len = strlen( fbuf );
693 
694 	//cb.sc_private     = sessp;
695 	//cb.sc_response    = rbac_read_session_cb;
696 	cb.sc_private = &rbac_cb;
697 	cb.sc_response = rbac_sess_fake_cb;
698 	op2.o_callback = &cb;
699 	op2.o_tag = LDAP_REQ_SEARCH;
700 	op2.o_dn = tenantp->session_admin;
701 	op2.o_ndn = tenantp->session_admin;
702 	op2.o_req_dn = tenantp->sessions_basedn;
703 	op2.o_req_ndn = tenantp->sessions_basedn;
704 	op2.ors_filterstr = filter;
705 	op2.ors_filter = str2filter_x( &op2, filter.bv_val );
706 	op2.ors_scope = LDAP_SCOPE_SUBTREE;
707 	op2.ors_attrs = slap_rbac_schema.session_attrs;
708 	op2.ors_tlimit = SLAP_NO_LIMIT;
709 	op2.ors_slimit = SLAP_NO_LIMIT;
710 	op2.o_bd = frontendDB;
711 	// hyc change to fix seg fault:
712 	op2.ors_limit = NULL;
713 
714 	rc = op2.o_bd->be_search( &op2, &rs2 );
715 	filter_free_x( &op2, op2.ors_filter, 1 );
716 
717 done:
718 	// TODO: find equivalent way of check nentries (broke with fake connection fix)
719 	//if ( rc != LDAP_SUCCESS || rs2.sr_nentries <= 0 ) {
720 	if ( rc != LDAP_SUCCESS ) {
721 		rbac_free_session( sessp );
722 		sessp = NULL;
723 	}
724 
725 	return sessp;
726 }
727 
728 rbac_session_t *
rbac_session_byid(Operation * op,rbac_req_t * reqp)729 rbac_session_byid( Operation *op, rbac_req_t *reqp )
730 {
731 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
732 	rbac_session_t *sessp = NULL;
733 	int rc = LDAP_SUCCESS;
734 	char fbuf[RBAC_BUFLEN];
735 	struct berval filter = { sizeof(fbuf), fbuf };
736 	SlapReply rs2 = { REP_RESULT };
737 	Operation op2 = *op;
738 	slap_callback cb = { 0 };
739 	tenant_info_t *tenantp = NULL;
740 
741 	if ( !rbac_is_valid_session_id( &reqp->sessid ) ) {
742 		Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
743 				"invalid session id (%s)\n",
744 				reqp->sessid.bv_val );
745 		rc = LDAP_UNWILLING_TO_PERFORM;
746 		goto done;
747 	}
748 
749 	sessp = rbac_alloc_session();
750 	if ( !sessp ) {
751 		Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
752 				"unable to allocate session memory\n" );
753 		rc = LDAP_UNWILLING_TO_PERFORM;
754 		goto done;
755 	}
756 
757 	tenantp = rbac_tid2tenant( &reqp->tenantid );
758 
759 	/* session id filter */
760 	memset( fbuf, 0, sizeof(fbuf) );
761 	strcpy( fbuf, RBAC_SESSION_RDN_EQ );
762 	strncpy( &fbuf[0] + sizeof(RBAC_SESSION_RDN_EQ) - 1, reqp->sessid.bv_val,
763 			reqp->sessid.bv_len );
764 	filter.bv_val = fbuf;
765 	filter.bv_len = strlen( fbuf );
766 
767 	cb.sc_private = sessp;
768 	cb.sc_response = rbac_read_session_cb;
769 	op2.o_callback = &cb;
770 	op2.o_tag = LDAP_REQ_SEARCH;
771 	op2.o_dn = tenantp->session_admin;
772 	op2.o_ndn = tenantp->session_admin;
773 	op2.o_req_dn = tenantp->sessions_basedn;
774 	op2.o_req_ndn = tenantp->sessions_basedn;
775 	op2.ors_filterstr = filter;
776 	op2.ors_filter = str2filter_x( &op2, filter.bv_val );
777 	op2.ors_scope = LDAP_SCOPE_SUBTREE;
778 	op2.ors_attrs = slap_rbac_schema.session_attrs;
779 	op2.ors_tlimit = SLAP_NO_LIMIT;
780 	op2.ors_slimit = SLAP_NO_LIMIT;
781 	op2.o_bd = frontendDB;
782 	// hyc change to fix seg fault:
783 	op2.ors_limit = NULL;
784 
785 	rc = op2.o_bd->be_search( &op2, &rs2 );
786 	filter_free_x( &op2, op2.ors_filter, 1 );
787 
788 done:
789 	// TODO: find equivalent way of check nentries (broke with fake connection fix)
790 	//if ( rc != LDAP_SUCCESS || rs2.sr_nentries <= 0 ) {
791 	if ( rc != LDAP_SUCCESS ) {
792 		rbac_free_session( sessp );
793 		sessp = NULL;
794 	}
795 
796 	return sessp;
797 }
798 
799 static char *
rbac_int_session_permissions_filterstr(Operation * op,rbac_session_t * sessp)800 rbac_int_session_permissions_filterstr( Operation *op, rbac_session_t *sessp )
801 {
802 	char filterbuf[RBAC_BUFLEN];
803 	int i;
804 
805 	memset( filterbuf, 0, sizeof(filterbuf) );
806 
807 	strcat( filterbuf, "(&(objectClass=ftOperation)(|" );
808 	strcat( filterbuf, "(ftUsers=" );
809 	strcat( filterbuf, sessp->uid.bv_val );
810 	strcat( filterbuf, ")" );
811 
812 	/* add ftRoles filters */
813 	for ( i = 0; !BER_BVISEMPTY( &sessp->roles[i] ); i++ ) {
814 		strcat( filterbuf, "(ftRoles=" );
815 		strncat( filterbuf, sessp->roles[i].bv_val, sessp->roles[i].bv_len );
816 		strcat( filterbuf, ")" );
817 	}
818 	strcat( filterbuf, "))" );
819 	return strdup( filterbuf );
820 }
821 
822 int
rbac_int_session_permissions(Operation * op,SlapReply * rs,rbac_req_t * reqp,rbac_session_t * sessp)823 rbac_int_session_permissions(
824 		Operation *op,
825 		SlapReply *rs,
826 		rbac_req_t *reqp,
827 		rbac_session_t *sessp )
828 {
829 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
830 	tenant_info_t *tenantp = NULL;
831 	int rc;
832 	struct berval filter;
833 	char *filterstr;
834 	struct berval permndn = BER_BVNULL;
835 	OperationBuffer opbuf;
836 	Connection conn = { 0 };
837 	SlapReply rs2 = { REP_RESULT };
838 	Operation *op2;
839 	slap_callback cb = { 0 };
840 	char permbuf[1024];
841 	session_perm_req_t sess_perm_req;
842 #ifdef USE_NEW_THREAD_CONTEXT
843 	void *thrctx = ldap_pvt_thread_pool_context();
844 #else
845 	void *thrctx = op->o_tmpmemctx;
846 #endif
847 
848 	tenantp = rbac_tid2tenant( &reqp->tenantid );
849 
850 	/* construct session permissions dn */
851 	memset( permbuf, 0, sizeof(permbuf) );
852 	strcat( permbuf, "rbacSessid=" );
853 	strncat( permbuf, sessp->sessid.bv_val, sessp->sessid.bv_len );
854 	strcat( permbuf, ",dc=rbac" );
855 	sess_perm_req.op = op;
856 	sess_perm_req.rs = rs;
857 	sess_perm_req.permdn.bv_val = permbuf;
858 	sess_perm_req.permdn.bv_len = strlen( permbuf );
859 	sess_perm_req.sessid = &reqp->sessid;
860 	sess_perm_req.tenantp = tenantp;
861 
862 	filterstr = rbac_int_session_permissions_filterstr( op, sessp );
863 	if ( !filterstr ) {
864 		Debug( LDAP_DEBUG_ANY, "unable to construct filter for session permissions\n" );
865 		rc = LDAP_UNWILLING_TO_PERFORM;
866 		goto done;
867 	}
868 	filter.bv_val = filterstr;
869 	filter.bv_len = strlen( filterstr );
870 
871 	rc = dnNormalize(
872 			0, NULL, NULL, &tenantp->permissions_basedn, &permndn, NULL );
873 	if ( rc != LDAP_SUCCESS ) {
874 		Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
875 				"unable to normalize permission DN\n" );
876 		rc = LDAP_UNWILLING_TO_PERFORM;
877 		goto done;
878 	}
879 
880 	connection_fake_init2( &conn, &opbuf, thrctx, 0 );
881 	op2 = &opbuf.ob_op;
882 	//Operation op2 = *op;
883 	cb.sc_private = &sess_perm_req;
884 	cb.sc_response = rbac_session_permissions_cb;
885 	op2->o_callback = &cb;
886 	op2->o_tag = LDAP_REQ_SEARCH;
887 	op2->o_dn = tenantp->admin;
888 	op2->o_ndn = tenantp->admin;
889 	op2->o_req_dn = tenantp->permissions_basedn;
890 	op2->o_req_ndn = permndn;
891 	op2->ors_filterstr = filter;
892 	op2->ors_filter = str2filter_x( op, filter.bv_val );
893 	op2->ors_scope = LDAP_SCOPE_SUB;
894 	op2->ors_attrs = tenantp->schema->session_perm_attrs;
895 	op2->ors_tlimit = SLAP_NO_LIMIT;
896 	op2->ors_slimit = SLAP_NO_LIMIT;
897 	op2->ors_attrsonly = 0;
898 	op2->o_bd = frontendDB;
899 	//op2.ors_limit     = NULL;
900 	rc = op2->o_bd->be_search( op2, &rs2 );
901 	filter_free_x( op, op2->ors_filter, 1 );
902 
903 done:;
904 	/* generate audit log */
905 	rbac_audit( op, SessionPermissions, sessp, reqp, rc, (char *)rs->sr_text );
906 
907 	rs->sr_err = rc;
908 	return rs->sr_err;
909 }
910 
911 void
rbac_free_session(rbac_session_t * sessp)912 rbac_free_session( rbac_session_t *sessp )
913 {
914 	if ( !sessp ) return;
915 
916 	if ( sessp->user ) {
917 		rbac_free_user( sessp->user );
918 	}
919 
920 	if ( !BER_BVISNULL( &sessp->uid ) ) {
921 		ber_memfree( sessp->uid.bv_val );
922 	}
923 
924 	if ( !BER_BVISNULL( &sessp->tenantid ) ) {
925 		ber_memfree( sessp->tenantid.bv_val );
926 	}
927 
928 	if ( !BER_BVISNULL( &sessp->userdn ) ) {
929 		ber_memfree( sessp->userdn.bv_val );
930 	}
931 
932 	if ( !BER_BVISNULL( &sessp->sessdn ) ) {
933 		ber_memfree( sessp->sessdn.bv_val );
934 	}
935 
936 	if ( !BER_BVISNULL( &sessp->message ) ) {
937 		ber_memfree( sessp->message.bv_val );
938 	}
939 
940 	if ( sessp->roles ) {
941 		ber_bvarray_free( sessp->roles );
942 	}
943 
944 	if ( sessp->role_constraints ) {
945 		ber_bvarray_free( sessp->role_constraints );
946 	}
947 
948 	ch_free( sessp );
949 
950 	return;
951 }
952 
953 /* roles included from request are activated into a session only when
954  * they exist and have been assigned to the user. If no roles included in request, all
955  * roles assigned to the user are activated into the rbac session.
956  */
957 int
activate_session_roles(rbac_session_t * sessp,rbac_req_t * reqp,rbac_user_t * userp)958 activate_session_roles(
959 		rbac_session_t *sessp,
960 		rbac_req_t *reqp,
961 		rbac_user_t *userp )
962 {
963 	int i, j, rc = LDAP_UNWILLING_TO_PERFORM;
964 	if ( !sessp || !reqp || !userp ) {
965 		goto done;
966 	}
967 
968 	/* no role requested, assign all roles from the user to the session. */
969 	if ( reqp->roles == NULL || BER_BVISNULL( &reqp->roles[0] ) ) {
970 		//if (!reqp->roles || BER_BVISNULL(&reqp->roles[0])) {
971 		/* no roles assigned to the user */
972 		if ( !userp->roles || BER_BVISNULL( &userp->roles[0] ) ) goto done;
973 		for ( i = 0; !BER_BVISNULL( &userp->roles[i] ); i++ ) {
974 			struct berval role;
975 			ber_dupbv_x( &role, &userp->roles[i], NULL );
976 			ber_bvarray_add( &sessp->roles, &role );
977 			rc = LDAP_SUCCESS;
978 		}
979 
980 		// TODO: smm 20141218 - make sure this is correct way to add constraints to user session.
981 		for ( i = 0; !BER_BVISNULL( &userp->role_constraints[i] ); i++ ) {
982 			struct berval roleconstraint;
983 			ber_dupbv_x( &roleconstraint, &userp->role_constraints[i], NULL );
984 			ber_bvarray_add( &sessp->role_constraints, &roleconstraint );
985 			rc = LDAP_SUCCESS;
986 		}
987 
988 	} else {
989 		for ( i = 0; !BER_BVISNULL( &reqp->roles[i] ); i++ ) {
990 			for ( j = 0; !BER_BVISNULL( &userp->roles[j] ); j++ ) {
991 				if ( !ber_bvstrcasecmp( &reqp->roles[i], &userp->roles[j] ) ) {
992 					/* requested role is assigned to the user */
993 					struct berval role;
994 					ber_dupbv_x( &role, &userp->roles[i], NULL );
995 					ber_bvarray_add( &sessp->roles, &role );
996 					rc = LDAP_SUCCESS;
997 				}
998 			}
999 		}
1000 	}
1001 
1002 done:;
1003 	return rc;
1004 }
1005