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 36static slap_callback nullsc = { NULL, NULL, NULL, NULL }; 37 38extern rbac_ad_t rbac_session_permission_ads[]; 39extern rbac_ad_t rbac_session_ads[]; 40 41struct berval slapo_session_oc = BER_BVC("rbacSession"); 42 43typedef 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 51static int 52rbac_sess_fake_cb( Operation *op, SlapReply *rs ) 53{ 54 Debug( LDAP_DEBUG_ANY, "rbac_sess_fake_cb\n" ); 55 56 return 0; 57} 58 59static int 60rbac_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 103static int 104rbac_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 151static int 152rbac_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 */ 196int 197rbac_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 212done:; 213 return rc; 214} 215 216int 217rbac_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 268done:; 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 276int 277rbac_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 338done:; 339 if ( m ) { 340 slap_mods_free( m, 1 ); 341 } 342 343 return rc; 344} 345 346/* delete the session */ 347int 348rbac_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 378done:; 379 return rc; 380} 381 382rbac_session_t * 383rbac_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 413int 414rbac_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 507done:; 508 if ( e ) entry_free( e ); 509 return rc; 510} 511 512int 513rbac_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 615done:; 616 if ( e ) entry_free( e ); 617 618 return rc; 619} 620 621int 622rbac_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 */ 643rbac_req_t * 644rbac_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 654rbac_session_t * 655rbac_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 717done: 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 728rbac_session_t * 729rbac_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 788done: 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 799static char * 800rbac_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 822int 823rbac_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 903done:; 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 911void 912rbac_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 */ 957int 958activate_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 1002done:; 1003 return rc; 1004} 1005