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
rbac_read_permission_cb(Operation * op,SlapReply * rs)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
rbac_check_session_permission(rbac_session_t * sessp,rbac_permission_t * permp,rbac_constraint_t * role_constraints)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 *
rbac_read_permission(Operation * op,rbac_req_t * reqp)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
rbac_free_permission(rbac_permission_t * permp)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