Home | History | Annotate | Line # | Download | only in rbac
      1 /*	$NetBSD: rbacperm.c,v 1.2 2021/08/14 16:14:53 christos Exp $	*/
      2 
      3 /* rbacperm.c - RBAC permission */
      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: rbacperm.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 int
     37 rbac_read_permission_cb( Operation *op, SlapReply *rs )
     38 {
     39 	rbac_callback_info_t *cbp = op->o_callback->sc_private;
     40 	rbac_ad_t *permission_ads;
     41 	rbac_permission_t *permp;
     42 	int i;
     43 
     44 	if ( rs->sr_type != REP_SEARCH ) return 0;
     45 
     46 	assert( cbp );
     47 
     48 	permp = ch_calloc( 1, sizeof(rbac_permission_t) );
     49 	permission_ads = cbp->tenantp->schema->permission_ads;
     50 
     51 	ber_dupbv( &permp->dn, &rs->sr_entry->e_name );
     52 	for ( i = 0; !BER_BVISNULL( &permission_ads[i].attr ); i++ ) {
     53 		Attribute *attr = NULL;
     54 		attr = attr_find( rs->sr_entry->e_attrs, *permission_ads[i].ad );
     55 		if ( attr != NULL ) {
     56 			switch ( permission_ads[i].type ) {
     57 				case RBAC_USERS:
     58 					ber_bvarray_dup_x( &permp->uids, attr->a_nvals, NULL );
     59 					break;
     60 				case RBAC_ROLES:
     61 					ber_bvarray_dup_x( &permp->roles, attr->a_nvals, NULL );
     62 					break;
     63 				default:
     64 					break;
     65 			}
     66 		}
     67 	}
     68 
     69 	cbp->private = (void *)permp;
     70 
     71 	return 0;
     72 }
     73 
     74 /*
     75  * check whether roles assigned to a user allows access to roles in
     76  * a permission, subject to role constraints
     77  */
     78 int
     79 rbac_check_session_permission(
     80 		rbac_session_t *sessp,
     81 		rbac_permission_t *permp,
     82 		rbac_constraint_t *role_constraints )
     83 {
     84 	int rc = LDAP_INSUFFICIENT_ACCESS;
     85 	rbac_constraint_t *cp = NULL;
     86 	int i, j;
     87 
     88 	if ( !sessp->roles || !permp->roles ) goto done;
     89 
     90 	for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
     91 		for ( j = 0; !BER_BVISNULL( &permp->roles[j] ); j++ ) {
     92 			if ( ber_bvstrcasecmp( &sessp->roles[i], &permp->roles[j] ) == 0 ) {
     93 				/* role temporal constraint */
     94 				cp = rbac_role2constraint( &permp->roles[j], role_constraints );
     95 				if ( !cp || rbac_check_time_constraint( cp ) == LDAP_SUCCESS ) {
     96 					rc = LDAP_SUCCESS;
     97 					goto done;
     98 				}
     99 			}
    100 		}
    101 	}
    102 done:;
    103 	return rc;
    104 }
    105 
    106 rbac_permission_t *
    107 rbac_read_permission( Operation *op, rbac_req_t *reqp )
    108 {
    109 	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
    110 	rbac_callback_info_t rbac_cb;
    111 	int rc = LDAP_SUCCESS;
    112 	char fbuf[1024];
    113 	struct berval filter = { sizeof(fbuf), fbuf };
    114 	char permbuf[1024];
    115 	struct berval permdn = { sizeof(permbuf), permbuf };
    116 	struct berval permndn = BER_BVNULL;
    117 	char pcls[] = "(objectClass=ftOperation)";
    118 	SlapReply rs2 = { REP_RESULT };
    119 	slap_callback cb = { 0 };
    120 	tenant_info_t *tenantp = rbac_tid2tenant( &reqp->tenantid );
    121 
    122 #if 0 /* check valid object name and op name */
    123 	if ( !is_valid_opname( &reqp->opname ) ||
    124 			!is_valid_objname( &reqp->objname ) ) {
    125 		Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
    126 				"invalid opname (%s) or objname (%s)\n",
    127 				reqp->opname.bv_val, reqp->objname.bv_val );
    128 		rc = LDAP_UNWILLING_TO_PERFORM;
    129 		goto done;
    130 	}
    131 #endif
    132 
    133 	if ( !tenantp ) {
    134 		Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
    135 				"missing tenant information\n" );
    136 		rc = LDAP_UNWILLING_TO_PERFORM;
    137 		goto done;
    138 	}
    139 
    140 	if ( reqp->objid.bv_val != NULL ) {
    141 		permdn.bv_len = snprintf( permdn.bv_val, permdn.bv_len,
    142 				"ftObjId=%s+ftOpNm=%s,ftObjNm=%s,%s", reqp->objid.bv_val,
    143 				reqp->opname.bv_val, reqp->objname.bv_val,
    144 				tenantp->permissions_basedn.bv_val );
    145 	} else {
    146 		permdn.bv_len = snprintf( permdn.bv_val, permdn.bv_len,
    147 				"ftOpNm=%s,ftObjNm=%s,%s", reqp->opname.bv_val,
    148 				reqp->objname.bv_val, tenantp->permissions_basedn.bv_val );
    149 	}
    150 
    151 	rc = dnNormalize( 0, NULL, NULL, &permdn, &permndn, NULL );
    152 	if ( rc != LDAP_SUCCESS ) {
    153 		Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
    154 				"unable to normalize permission DN\n" );
    155 		rc = LDAP_UNWILLING_TO_PERFORM;
    156 		goto done;
    157 	}
    158 
    159 	filter.bv_val = pcls;
    160 	filter.bv_len = strlen( pcls );
    161 	rbac_cb.tenantp = tenantp;
    162 	rbac_cb.private = NULL;
    163 
    164 	Operation op2 = *op;
    165 	cb.sc_private = &rbac_cb;
    166 	cb.sc_response = rbac_read_permission_cb;
    167 	op2.o_callback = &cb;
    168 	op2.o_tag = LDAP_REQ_SEARCH;
    169 	op2.o_dn = tenantp->admin;
    170 	op2.o_ndn = tenantp->admin;
    171 	op2.o_req_dn = permdn;
    172 	op2.o_req_ndn = permndn;
    173 	op2.ors_filterstr = filter;
    174 	op2.ors_filter = str2filter_x( &op2, filter.bv_val );
    175 	op2.ors_scope = LDAP_SCOPE_BASE;
    176 	op2.ors_attrs = tenantp->schema->perm_attrs;
    177 	op2.ors_tlimit = SLAP_NO_LIMIT;
    178 	op2.ors_slimit = SLAP_NO_LIMIT;
    179 	op2.ors_attrsonly = 0;
    180 	op2.ors_limit = NULL;
    181 	op2.o_bd = frontendDB;
    182 	rc = op2.o_bd->be_search( &op2, &rs2 );
    183 	filter_free_x( &op2, op2.ors_filter, 1 );
    184 
    185 done:;
    186 	ch_free( permndn.bv_val );
    187 
    188 	if ( rc != LDAP_SUCCESS ) {
    189 		rbac_free_permission((rbac_permission_t *)rbac_cb.private);
    190 	}
    191 
    192 	return (rbac_permission_t *)rbac_cb.private;
    193 }
    194 
    195 void
    196 rbac_free_permission( rbac_permission_t *permp )
    197 {
    198 	if ( !permp ) return;
    199 
    200 	if ( !BER_BVISNULL( &permp->dn ) ) {
    201 		ber_memfree( permp->dn.bv_val );
    202 	}
    203 
    204 	if ( !BER_BVISNULL( &permp->internalId ) ) {
    205 		ber_memfree( permp->internalId.bv_val );
    206 	}
    207 
    208 	if ( permp->opName ) {
    209 		ber_bvarray_free( permp->opName );
    210 	}
    211 
    212 	if ( permp->objName ) {
    213 		ber_bvarray_free( permp->objName );
    214 	}
    215 
    216 	if ( !BER_BVISNULL( &permp->objectId ) ) {
    217 		ber_memfree( permp->objectId.bv_val );
    218 	}
    219 
    220 	if ( !BER_BVISNULL( &permp->abstractName ) ) {
    221 		ber_memfree( permp->abstractName.bv_val );
    222 	}
    223 
    224 	if ( !BER_BVISNULL( &permp->type ) ) {
    225 		ber_memfree( permp->type.bv_val );
    226 	}
    227 
    228 	if ( permp->roles ) {
    229 		ber_bvarray_free( permp->roles );
    230 	}
    231 
    232 	if ( permp->uids ) {
    233 		ber_bvarray_free( permp->uids );
    234 	}
    235 	ch_free( permp );
    236 
    237 	return;
    238 }
    239