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