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