]> git.sur5r.net Git - openldap/blob - contrib/slapd-modules/acl/posixgroup.c
Happy New Year (belated)
[openldap] / contrib / slapd-modules / acl / posixgroup.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2008 The OpenLDAP Foundation.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted only as authorized by the OpenLDAP
8  * Public License.
9  *
10  * A copy of this license is available in the file LICENSE in the
11  * top-level directory of the distribution or, alternatively, at
12  * <http://www.OpenLDAP.org/license.html>.
13  */
14
15 #include <portable.h>
16
17 #include <ac/string.h>
18 #include <slap.h>
19 #include <lutil.h>
20
21 /* Need dynacl... */
22
23 #ifdef SLAP_DYNACL
24
25 typedef struct pg_t {
26         slap_style_t            pg_style;
27         struct berval           pg_pat;
28 } pg_t;
29
30 static ObjectClass              *pg_posixGroup;
31 static AttributeDescription     *pg_memberUid;
32 static ObjectClass              *pg_posixAccount;
33 static AttributeDescription     *pg_uidNumber;
34
35 static int pg_dynacl_destroy( void *priv );
36
37 static int
38 pg_dynacl_parse(
39         const char      *fname,
40         int             lineno,
41         const char      *opts,
42         slap_style_t    style,
43         const char      *pattern,
44         void            **privp )
45 {
46         pg_t            *pg;
47         int             rc;
48         const char      *text = NULL;
49         struct berval   pat;
50
51         ber_str2bv( pattern, 0, 0, &pat );
52
53         pg = ch_calloc( 1, sizeof( pg_t ) );
54
55         pg->pg_style = style;
56
57         switch ( pg->pg_style ) {
58         case ACL_STYLE_BASE:
59                 rc = dnNormalize( 0, NULL, NULL, &pat, &pg->pg_pat, NULL );
60                 if ( rc != LDAP_SUCCESS ) {
61                         fprintf( stderr, "%s line %d: posixGroup ACL: "
62                                 "unable to normalize DN \"%s\".\n",
63                                 fname, lineno, pattern );
64                         goto cleanup;
65                 }
66                 break;
67
68         case ACL_STYLE_EXPAND:
69                 ber_dupbv( &pg->pg_pat, &pat );
70                 break;
71
72         default:
73                 fprintf( stderr, "%s line %d: posixGroup ACL: "
74                         "unsupported style \"%s\".\n",
75                         fname, lineno, style_strings[ pg->pg_style ] );
76                 goto cleanup;
77         }
78
79         /* TODO: use opts to allow the use of different
80          * group objects and member attributes */
81         if ( pg_posixGroup == NULL ) {
82                 pg_posixGroup = oc_find( "posixGroup" );
83                 if ( pg_posixGroup == NULL ) {
84                         fprintf( stderr, "%s line %d: posixGroup ACL: "
85                                 "unable to lookup \"posixGroup\" "
86                                 "objectClass.\n",
87                                 fname, lineno );
88                         goto cleanup;
89                 }
90
91                 pg_posixAccount = oc_find( "posixAccount" );
92                 if ( pg_posixGroup == NULL ) {
93                         fprintf( stderr, "%s line %d: posixGroup ACL: "
94                                 "unable to lookup \"posixAccount\" "
95                                 "objectClass.\n",
96                                 fname, lineno );
97                         goto cleanup;
98                 }
99
100                 rc = slap_str2ad( "memberUid", &pg_memberUid, &text );
101                 if ( rc != LDAP_SUCCESS ) {
102                         fprintf( stderr, "%s line %d: posixGroup ACL: "
103                                 "unable to lookup \"memberUid\" "
104                                 "attributeDescription (%d: %s).\n",
105                                 fname, lineno, rc, text );
106                         goto cleanup;
107                 }
108
109                 rc = slap_str2ad( "uidNumber", &pg_uidNumber, &text );
110                 if ( rc != LDAP_SUCCESS ) {
111                         fprintf( stderr, "%s line %d: posixGroup ACL: "
112                                 "unable to lookup \"uidNumber\" "
113                                 "attributeDescription (%d: %s).\n",
114                                 fname, lineno, rc, text );
115                         goto cleanup;
116                 }
117         }
118
119         *privp = (void *)pg;
120         return 0;
121
122 cleanup:
123         (void)pg_dynacl_destroy( (void *)pg );
124
125         return 1;
126 }
127
128 static int
129 pg_dynacl_unparse(
130         void            *priv,
131         struct berval   *bv )
132 {
133         pg_t            *pg = (pg_t *)priv;
134         char            *ptr;
135
136         bv->bv_len = STRLENOF( " dynacl/posixGroup.expand=" ) + pg->pg_pat.bv_len;
137         bv->bv_val = ch_malloc( bv->bv_len + 1 );
138
139         ptr = lutil_strcopy( bv->bv_val, " dynacl/posixGroup" );
140
141         switch ( pg->pg_style ) {
142         case ACL_STYLE_BASE:
143                 ptr = lutil_strcopy( ptr, ".exact=" );
144                 break;
145
146         case ACL_STYLE_EXPAND:
147                 ptr = lutil_strcopy( ptr, ".expand=" );
148                 break;
149
150         default:
151                 assert( 0 );
152         }
153
154         ptr = lutil_strncopy( ptr, pg->pg_pat.bv_val, pg->pg_pat.bv_len );
155         ptr[ 0 ] = '\0';
156
157         bv->bv_len = ptr - bv->bv_val;
158
159         return 0;
160 }
161
162 static int
163 pg_dynacl_mask(
164         void                    *priv,
165         struct slap_op          *op,
166         Entry                   *target,
167         AttributeDescription    *desc,
168         struct berval           *val,
169         int                     nmatch,
170         regmatch_t              *matches,
171         slap_access_t           *grant,
172         slap_access_t           *deny )
173 {
174         pg_t            *pg = (pg_t *)priv;
175         Entry           *group = NULL,
176                         *user = NULL;
177         int             rc;
178         Backend         *be = op->o_bd,
179                         *group_be = NULL,
180                         *user_be = NULL;
181         struct berval   group_ndn;
182
183         ACL_INVALIDATE( *deny );
184
185         /* get user */
186         if ( target && dn_match( &target->e_nname, &op->o_ndn ) ) {
187                 user = target;
188                 rc = LDAP_SUCCESS;
189
190         } else {
191                 user_be = op->o_bd = select_backend( &op->o_ndn, 0, 0 );
192                 if ( op->o_bd == NULL ) {
193                         op->o_bd = be;
194                         return 0;
195                 }
196                 rc = be_entry_get_rw( op, &op->o_ndn, pg_posixAccount, pg_uidNumber, 0, &user );
197         }
198
199         if ( rc != LDAP_SUCCESS || user == NULL ) {
200                 op->o_bd = be;
201                 return 0;
202         }
203
204         /* get target */
205         if ( pg->pg_style == ACL_STYLE_EXPAND ) {
206                 char            buf[ 1024 ];
207                 struct berval   bv;
208
209                 bv.bv_len = sizeof( buf ) - 1;
210                 bv.bv_val = buf;
211
212                 if ( acl_string_expand( &bv, &pg->pg_pat,
213                                 target->e_nname.bv_val,
214                                 nmatch, matches ) )
215                 {
216                         goto cleanup;
217                 }
218
219                 if ( dnNormalize( 0, NULL, NULL, &bv, &group_ndn,
220                                 op->o_tmpmemctx ) != LDAP_SUCCESS )
221                 {
222                         /* did not expand to a valid dn */
223                         goto cleanup;
224                 }
225                 
226         } else {
227                 group_ndn = pg->pg_pat;
228         }
229
230         if ( target && dn_match( &target->e_nname, &group_ndn ) ) {
231                 group = target;
232                 rc = LDAP_SUCCESS;
233
234         } else {
235                 group_be = op->o_bd = select_backend( &group_ndn, 0, 0 );
236                 if ( op->o_bd == NULL ) {
237                         goto cleanup;
238                 }
239                 rc = be_entry_get_rw( op, &group_ndn, pg_posixGroup, pg_memberUid, 0, &group );
240         }
241
242         if ( group_ndn.bv_val != pg->pg_pat.bv_val ) {
243                 op->o_tmpfree( group_ndn.bv_val, op->o_tmpmemctx );
244         }
245
246         if ( rc == LDAP_SUCCESS && group != NULL ) {
247                 Attribute       *a_uid,
248                                 *a_member;
249
250                 a_uid = attr_find( user->e_attrs, pg_uidNumber );
251                 if ( !a_uid || !BER_BVISNULL( &a_uid->a_nvals[ 1 ] ) ) {
252                         rc = LDAP_NO_SUCH_ATTRIBUTE;
253
254                 } else {
255                         a_member = attr_find( group->e_attrs, pg_memberUid );
256                         if ( !a_member ) {
257                                 rc = LDAP_NO_SUCH_ATTRIBUTE;
258
259                         } else {
260                                 rc = value_find_ex( pg_memberUid,
261                                         SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
262                                         SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
263                                         a_member->a_nvals, &a_uid->a_nvals[ 0 ],
264                                         op->o_tmpmemctx );
265                         }
266                 }
267
268         } else {
269                 rc = LDAP_NO_SUCH_OBJECT;
270         }
271
272
273         if ( rc == LDAP_SUCCESS ) {
274                 ACL_LVL_ASSIGN_WRITE( *grant );
275         }
276
277 cleanup:;
278         if ( group != NULL && group != target ) {
279                 op->o_bd = group_be;
280                 be_entry_release_r( op, group );
281                 op->o_bd = be;
282         }
283
284         if ( user != NULL && user != target ) {
285                 op->o_bd = user_be;
286                 be_entry_release_r( op, user );
287                 op->o_bd = be;
288         }
289
290         return 0;
291 }
292
293 static int
294 pg_dynacl_destroy(
295         void            *priv )
296 {
297         pg_t            *pg = (pg_t *)priv;
298
299         if ( pg != NULL ) {
300                 if ( !BER_BVISNULL( &pg->pg_pat ) ) {
301                         ber_memfree( pg->pg_pat.bv_val );
302                 }
303                 ch_free( pg );
304         }
305
306         return 0;
307 }
308
309 static struct slap_dynacl_t pg_dynacl = {
310         "posixGroup",
311         pg_dynacl_parse,
312         pg_dynacl_unparse,
313         pg_dynacl_mask,
314         pg_dynacl_destroy
315 };
316
317 int
318 init_module( int argc, char *argv[] )
319 {
320         return slap_dynacl_register( &pg_dynacl );
321 }
322
323 #endif /* SLAP_DYNACL */