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