Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / openldap / dist / contrib / slapd-modules / acl / posixgroup.c
blobc88e28bd14fff96213b38081b694d36ea1cdc2a4
1 /* $OpenLDAP: pkg/ldap/contrib/slapd-modules/acl/posixgroup.c,v 1.3.2.4 2008/02/11 23:26:38 kurt Exp $ */
2 /*
3 * Copyright 1998-2008 The OpenLDAP Foundation.
4 * All rights reserved.
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.
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>.
15 #include <portable.h>
17 #include <ac/string.h>
18 #include <slap.h>
19 #include <lutil.h>
21 /* Need dynacl... */
23 #ifdef SLAP_DYNACL
25 typedef struct pg_t {
26 slap_style_t pg_style;
27 struct berval pg_pat;
28 } pg_t;
30 static ObjectClass *pg_posixGroup;
31 static AttributeDescription *pg_memberUid;
32 static ObjectClass *pg_posixAccount;
33 static AttributeDescription *pg_uidNumber;
35 static int pg_dynacl_destroy( void *priv );
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 )
46 pg_t *pg;
47 int rc;
48 const char *text = NULL;
49 struct berval pat;
51 ber_str2bv( pattern, 0, 0, &pat );
53 pg = ch_calloc( 1, sizeof( pg_t ) );
55 pg->pg_style = style;
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;
66 break;
68 case ACL_STYLE_EXPAND:
69 ber_dupbv( &pg->pg_pat, &pat );
70 break;
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;
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;
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;
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;
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;
119 *privp = (void *)pg;
120 return 0;
122 cleanup:
123 (void)pg_dynacl_destroy( (void *)pg );
125 return 1;
128 static int
129 pg_dynacl_unparse(
130 void *priv,
131 struct berval *bv )
133 pg_t *pg = (pg_t *)priv;
134 char *ptr;
136 bv->bv_len = STRLENOF( " dynacl/posixGroup.expand=" ) + pg->pg_pat.bv_len;
137 bv->bv_val = ch_malloc( bv->bv_len + 1 );
139 ptr = lutil_strcopy( bv->bv_val, " dynacl/posixGroup" );
141 switch ( pg->pg_style ) {
142 case ACL_STYLE_BASE:
143 ptr = lutil_strcopy( ptr, ".exact=" );
144 break;
146 case ACL_STYLE_EXPAND:
147 ptr = lutil_strcopy( ptr, ".expand=" );
148 break;
150 default:
151 assert( 0 );
154 ptr = lutil_strncopy( ptr, pg->pg_pat.bv_val, pg->pg_pat.bv_len );
155 ptr[ 0 ] = '\0';
157 bv->bv_len = ptr - bv->bv_val;
159 return 0;
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 )
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;
183 ACL_INVALIDATE( *deny );
185 /* get user */
186 if ( target && dn_match( &target->e_nname, &op->o_ndn ) ) {
187 user = target;
188 rc = LDAP_SUCCESS;
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;
196 rc = be_entry_get_rw( op, &op->o_ndn, pg_posixAccount, pg_uidNumber, 0, &user );
199 if ( rc != LDAP_SUCCESS || user == NULL ) {
200 op->o_bd = be;
201 return 0;
204 /* get target */
205 if ( pg->pg_style == ACL_STYLE_EXPAND ) {
206 char buf[ 1024 ];
207 struct berval bv;
209 bv.bv_len = sizeof( buf ) - 1;
210 bv.bv_val = buf;
212 if ( acl_string_expand( &bv, &pg->pg_pat,
213 target->e_nname.bv_val,
214 nmatch, matches ) )
216 goto cleanup;
219 if ( dnNormalize( 0, NULL, NULL, &bv, &group_ndn,
220 op->o_tmpmemctx ) != LDAP_SUCCESS )
222 /* did not expand to a valid dn */
223 goto cleanup;
226 } else {
227 group_ndn = pg->pg_pat;
230 if ( target && dn_match( &target->e_nname, &group_ndn ) ) {
231 group = target;
232 rc = LDAP_SUCCESS;
234 } else {
235 group_be = op->o_bd = select_backend( &group_ndn, 0, 0 );
236 if ( op->o_bd == NULL ) {
237 goto cleanup;
239 rc = be_entry_get_rw( op, &group_ndn, pg_posixGroup, pg_memberUid, 0, &group );
242 if ( group_ndn.bv_val != pg->pg_pat.bv_val ) {
243 op->o_tmpfree( group_ndn.bv_val, op->o_tmpmemctx );
246 if ( rc == LDAP_SUCCESS && group != NULL ) {
247 Attribute *a_uid,
248 *a_member;
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;
254 } else {
255 a_member = attr_find( group->e_attrs, pg_memberUid );
256 if ( !a_member ) {
257 rc = LDAP_NO_SUCH_ATTRIBUTE;
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 );
268 } else {
269 rc = LDAP_NO_SUCH_OBJECT;
273 if ( rc == LDAP_SUCCESS ) {
274 ACL_LVL_ASSIGN_WRITE( *grant );
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;
284 if ( user != NULL && user != target ) {
285 op->o_bd = user_be;
286 be_entry_release_r( op, user );
287 op->o_bd = be;
290 return 0;
293 static int
294 pg_dynacl_destroy(
295 void *priv )
297 pg_t *pg = (pg_t *)priv;
299 if ( pg != NULL ) {
300 if ( !BER_BVISNULL( &pg->pg_pat ) ) {
301 ber_memfree( pg->pg_pat.bv_val );
303 ch_free( pg );
306 return 0;
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
318 init_module( int argc, char *argv[] )
320 return slap_dynacl_register( &pg_dynacl );
323 #endif /* SLAP_DYNACL */