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