]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/group.c
Sync with HEAD
[openldap] / servers / slapd / back-meta / group.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2003 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This work was initially developed by the Howard Chu for inclusion
17  * in OpenLDAP Software and subsequently enhanced by Pierangelo
18  * Masarati.
19  */
20 /* This is an altered version */
21 /*
22  * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
23  *
24  * This work has been developed to fulfill the requirements
25  * of SysNet s.n.c. <http:www.sys-net.it> and it has been donated
26  * to the OpenLDAP Foundation in the hope that it may be useful
27  * to the Open Source community, but WITHOUT ANY WARRANTY.
28  *
29  * Permission is granted to anyone to use this software for any purpose
30  * on any computer system, and to alter it and redistribute it, subject
31  * to the following restrictions:
32  *
33  * 1. The author and SysNet s.n.c. are not responsible for the consequences
34  *    of use of this software, no matter how awful, even if they arise from 
35  *    flaws in it.
36  *
37  * 2. The origin of this software must not be misrepresented, either by
38  *    explicit claim or by omission.  Since few users ever read sources,
39  *    credits should appear in the documentation.
40  *
41  * 3. Altered versions must be plainly marked as such, and must not be
42  *    misrepresented as being the original software.  Since few users
43  *    ever read sources, credits should appear in the documentation.
44  *    SysNet s.n.c. cannot be responsible for the consequences of the
45  *    alterations.
46  *
47  * 4. This notice may not be removed or altered.
48  *
49  *
50  * This software is based on the backend back-ldap, implemented
51  * by Howard Chu <hyc@highlandsun.com>, and modified by Mark Valence
52  * <kurash@sassafras.com>, Pierangelo Masarati <ando@sys-net.it> and other
53  * contributors. The contribution of the original software to the present
54  * implementation is acknowledged in this copyright statement.
55  *
56  * A special acknowledgement goes to Howard for the overall architecture
57  * (and for borrowing large pieces of code), and to Mark, who implemented
58  * from scratch the attribute/objectclass mapping.
59  *
60  * The original copyright statement follows.
61  *
62  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
63  *
64  * Permission is granted to anyone to use this software for any purpose
65  * on any computer system, and to alter it and redistribute it, subject
66  * to the following restrictions:
67  *
68  * 1. The author is not responsible for the consequences of use of this
69  *    software, no matter how awful, even if they arise from flaws in it.
70  *
71  * 2. The origin of this software must not be misrepresented, either by
72  *    explicit claim or by omission.  Since few users ever read sources,
73  *    credits should appear in the documentation.
74  *
75  * 3. Altered versions must be plainly marked as such, and must not be
76  *    misrepresented as being the original software.  Since few users
77  *    ever read sources, credits should appear in the
78  *    documentation.
79  *
80  * 4. This notice may not be removed or altered.
81  *
82  */
83
84 #include "portable.h"
85
86 #include <stdio.h>
87
88 #include <ac/socket.h>
89 #include <ac/string.h>
90
91 #include "slap.h"
92 #include "../back-ldap/back-ldap.h"
93 #include "back-meta.h"
94 #include "lutil.h"
95
96 /* return 0 IFF op_dn is a value in group_at (member) attribute
97  * of entry with gr_dn AND that entry has an objectClass
98  * value of group_oc (groupOfNames)
99  */
100 int
101 meta_back_group(
102                 Backend                 *be,
103                 Connection              *conn,
104                 Operation               *op,
105                 Entry                   *target,
106                 struct berval           *gr_ndn,
107                 struct berval           *op_ndn,
108                 ObjectClass             *group_oc,
109                 AttributeDescription    *group_at
110 )
111 {
112         struct metainfo *li = ( struct metainfo * )be->be_private;    
113         int rc = 1, candidate;
114         Attribute   *attr;
115         AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
116         LDAPMessage     *result;
117         char *gattr[ 2 ];
118         char *filter = NULL, *ptr;
119         LDAP *ld = NULL;
120         struct berval mop_ndn = { 0, NULL }, mgr_ndn = { 0, NULL };
121
122         struct berval group_oc_name = { 0, NULL };
123         struct berval group_at_name = group_at->ad_cname;
124
125         if ( group_oc->soc_names && group_oc->soc_names[ 0 ] ) {
126                 group_oc_name.bv_val = group_oc->soc_names[ 0 ];
127         } else {
128                 group_oc_name.bv_val = group_oc->soc_oid;
129         }
130
131         if ( group_oc_name.bv_val ) {
132                 group_oc_name.bv_len = strlen( group_oc_name.bv_val );
133         }
134
135         if ( target != NULL && dn_match( &target->e_nname, gr_ndn ) ) {
136                 /* we already have a copy of the entry */
137                 /* attribute and objectclass mapping has already been done */
138
139                 /*
140                  * first we need to check if the objectClass attribute
141                  * has been retrieved; otherwise we need to repeat the search
142                  */
143                 attr = attr_find( target->e_attrs, ad_objectClass );
144                 if ( attr != NULL ) {
145
146                         /*
147                          * Now we can check for the group objectClass value
148                          */
149                         if ( !is_entry_objectclass( target, group_oc, 0 ) ) {
150                                 return 1;
151                         }
152
153                         /*
154                          * This part has been reworked: the group attr compare
155                          * fails only if the attribute is PRESENT but the value
156                          * is NOT PRESENT; if the attribute is NOT PRESENT, the
157                          * search must be repeated as well.
158                          * This may happen if a search for an entry has already
159                          * been performed (target is not null) but the group
160                          * attribute has not been required
161                          */
162                         attr = attr_find( target->e_attrs, group_at );
163                         if ( attr != NULL ) {
164                                 rc = value_find_ex( group_at,
165                                         SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
166                                         attr->a_vals, op_ndn );
167                                 if ( rc != LDAP_SUCCESS ) {
168                                         return 1;
169                                 }
170                                 return 0;
171                         } /* else: repeat the search */
172                 } /* else: repeat the search */
173         } /* else: do the search */
174
175         candidate = meta_back_select_unique_candidate( li, gr_ndn );
176         if ( candidate == -1 ) {
177                 goto cleanup;
178         }
179
180         /*
181          * Rewrite the op ndn if needed
182          */
183         switch ( rewrite_session( li->targets[ candidate ]->rwinfo, "bindDn",
184                                 op_ndn->bv_val, conn, &mop_ndn.bv_val ) ) {
185         case REWRITE_REGEXEC_OK:
186                 if ( mop_ndn.bv_val != NULL && mop_ndn.bv_val[ 0 ] != '\0' ) {
187                         mop_ndn.bv_len = strlen( mop_ndn.bv_val );
188                 } else {
189                         mop_ndn = *op_ndn;
190                 }
191 #ifdef NEW_LOGGING
192                 LDAP_LOG( BACK_META, DETAIL1,
193                         "[rw] bindDn (op ndn in group): \"%s\" -> \"%s\"\n",
194                         op_ndn->bv_val, mop_ndn.bv_val, 0 );
195 #else /* !NEW_LOGGING */
196                 Debug( LDAP_DEBUG_ARGS,
197                                 "rw> bindDn (op ndn in group):"
198                                 " \"%s\" -> \"%s\"\n%s",
199                                 op_ndn->bv_val, mop_ndn.bv_val, "" );
200 #endif /* !NEW_LOGGING */
201                 break;
202                 
203         case REWRITE_REGEXEC_UNWILLING:
204                 /* continues to next case */
205                 
206         case REWRITE_REGEXEC_ERR:
207                 return 1;
208         }
209
210         /*
211          * Rewrite the gr ndn if needed
212          */
213         switch ( rewrite_session( li->targets[ candidate ]->rwinfo,
214                                 "searchBase",
215                                 gr_ndn->bv_val, conn, &mgr_ndn.bv_val ) ) {
216         case REWRITE_REGEXEC_OK:
217                 if ( mgr_ndn.bv_val != NULL && mgr_ndn.bv_val[ 0 ] != '\0' ) {
218                         mgr_ndn.bv_len = strlen( mgr_ndn.bv_val );
219                 } else {
220                         mgr_ndn = *gr_ndn;
221                 }
222 #ifdef NEW_LOGGING
223                 LDAP_LOG( BACK_META, DETAIL1,
224                         "[rw] searchBase (gr ndn in group): \"%s\" -> \"%s\"\n",
225                         gr_ndn->bv_val, mgr_ndn.bv_val, 0 );
226 #else /* !NEW_LOGGING */
227                 Debug( LDAP_DEBUG_ARGS,
228                                 "rw> searchBase (gr ndn in group):"
229                                 " \"%s\" -> \"%s\"\n%s",
230                                 gr_ndn->bv_val, mgr_ndn.bv_val, "" );
231 #endif /* !NEW_LOGGING */
232                 break;
233                 
234         case REWRITE_REGEXEC_UNWILLING:
235                 /* continues to next case */
236                 
237         case REWRITE_REGEXEC_ERR:
238                 goto cleanup;
239         }
240         
241         ldap_back_map( &li->targets[ candidate ]->oc_map,
242                         &group_oc_name, &group_oc_name, BACKLDAP_MAP );
243         if ( group_oc_name.bv_val == NULL || group_oc_name.bv_val[0] == '\0' ) {
244                 goto cleanup;
245         }
246         ldap_back_map( &li->targets[ candidate ]->at_map,
247                         &group_at_name, &group_at_name, BACKLDAP_MAP );
248         if ( group_at_name.bv_val == NULL || group_at_name.bv_val[0] == '\0' ) {
249                 goto cleanup;
250         }
251
252         filter = ch_malloc( sizeof( "(&(objectclass=)(=))" )
253                         + group_oc_name.bv_len
254                         + group_at_name.bv_len
255                         + mop_ndn.bv_len + 1 );
256         if ( filter == NULL ) {
257                 goto cleanup;
258         }
259
260         rc = ldap_initialize( &ld, li->targets[ candidate ]->uri );
261         if ( rc != LDAP_SUCCESS ) {
262                 goto cleanup;
263         }
264
265         rc = ldap_bind_s( ld, li->targets[ candidate ]->binddn.bv_val,
266                         li->targets[ candidate ]->bindpw.bv_val, 
267                         LDAP_AUTH_SIMPLE );
268         if ( rc != LDAP_SUCCESS ) {
269                 goto cleanup;
270         }
271
272         ptr = lutil_strcopy( filter, "(&(objectclass=" );
273         ptr = lutil_strcopy( ptr , group_oc_name.bv_val );
274         ptr = lutil_strcopy( ptr , ")(" );
275         ptr = lutil_strcopy( ptr , group_at_name.bv_val );
276         ptr = lutil_strcopy( ptr , "=" );
277         ptr = lutil_strcopy( ptr , mop_ndn.bv_val );
278         strcpy( ptr , "))" );
279
280         gattr[ 0 ] = "objectclass";
281         gattr[ 1 ] = NULL;
282         rc = 1;
283         if ( ldap_search_ext_s( ld, mgr_ndn.bv_val, LDAP_SCOPE_BASE, filter,
284                                 gattr, 0, NULL, NULL, LDAP_NO_LIMIT,
285                                 LDAP_NO_LIMIT, &result ) == LDAP_SUCCESS ) {
286                 if ( ldap_first_entry( ld, result ) != NULL ) {
287                         rc = 0;
288                 }
289                 ldap_msgfree( result );
290         }
291
292 cleanup:;
293         if ( ld != NULL ) {
294                 ldap_unbind( ld );
295         }
296         if ( filter != NULL ) {
297                 ch_free( filter );
298         }
299         if ( mop_ndn.bv_val != op_ndn->bv_val ) {
300                 free( mop_ndn.bv_val );
301         }
302         if ( mgr_ndn.bv_val != gr_ndn->bv_val ) {
303                 free( mgr_ndn.bv_val );
304         }
305
306         return rc;
307 }
308