]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/compare.c
Fixed minor compile errors
[openldap] / servers / slapd / back-meta / compare.c
1 /*
2  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  *
5  * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
6  *
7  * This work has been developed to fulfill the requirements
8  * of SysNet s.n.c. <http:www.sys-net.it> and it has been donated
9  * to the OpenLDAP Foundation in the hope that it may be useful
10  * to the Open Source community, but WITHOUT ANY WARRANTY.
11  *
12  * Permission is granted to anyone to use this software for any purpose
13  * on any computer system, and to alter it and redistribute it, subject
14  * to the following restrictions:
15  *
16  * 1. The author and SysNet s.n.c. are not responsible for the consequences
17  *    of use of this software, no matter how awful, even if they arise from 
18  *    flaws in it.
19  *
20  * 2. The origin of this software must not be misrepresented, either by
21  *    explicit claim or by omission.  Since few users ever read sources,
22  *    credits should appear in the documentation.
23  *
24  * 3. Altered versions must be plainly marked as such, and must not be
25  *    misrepresented as being the original software.  Since few users
26  *    ever read sources, credits should appear in the documentation.
27  *    SysNet s.n.c. cannot be responsible for the consequences of the
28  *    alterations.
29  * 
30  * 4. This notice may not be removed or altered.
31  *
32  *
33  * This software is based on the backend back-ldap, implemented
34  * by Howard Chu <hyc@highlandsun.com>, and modified by Mark Valence
35  * <kurash@sassafras.com>, Pierangelo Masarati <ando@sys-net.it> and other
36  * contributors. The contribution of the original software to the present
37  * implementation is acknowledged in this copyright statement.
38  *
39  * A special acknowledgement goes to Howard for the overall architecture
40  * (and for borrowing large pieces of code), and to Mark, who implemented
41  * from scratch the attribute/objectclass mapping.
42  *
43  * The original copyright statement follows.
44  *
45  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
46  *
47  * Permission is granted to anyone to use this software for any purpose
48  * on any computer system, and to alter it and redistribute it, subject
49  * to the following restrictions:
50  *
51  * 1. The author is not responsible for the consequences of use of this
52  *    software, no matter how awful, even if they arise from flaws in it.
53  *
54  * 2. The origin of this software must not be misrepresented, either by
55  *    explicit claim or by omission.  Since few users ever read sources,
56  *    credits should appear in the documentation.
57  *
58  * 3. Altered versions must be plainly marked as such, and must not be
59  *    misrepresented as being the original software.  Since few users
60  *    ever read sources, credits should appear in the
61  *    documentation.
62  *
63  * 4. This notice may not be removed or altered.
64  *
65  */
66
67 #include "portable.h"
68
69 #include <stdio.h>
70
71 #include <ac/string.h>
72 #include <ac/socket.h>
73
74 #include "slap.h"
75 #include "../back-ldap/back-ldap.h"
76 #include "back-meta.h"
77
78 int
79 meta_back_compare( Operation *op, SlapReply *rs )
80 {
81         struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
82         struct metaconn *lc;
83         struct metasingleconn *lsc;
84         char *match = NULL, *err = NULL;
85         struct berval mmatch = { 0, NULL };
86         int candidates = 0, last = 0, i, count = 0, rc;
87         int cres = LDAP_SUCCESS, rres = LDAP_SUCCESS;
88         int *msgid;
89         dncookie dc;
90
91         lc = meta_back_getconn( op, rs, META_OP_ALLOW_MULTIPLE,
92                         &op->o_req_ndn, NULL );
93         if ( !lc ) {
94                 send_ldap_result( op, rs );
95                 return -1;
96         }
97         
98         if ( !meta_back_dobind( lc, op ) ) {
99                 rs->sr_err = LDAP_OTHER;
100                 send_ldap_result( op, rs );
101                 return -1;
102         }
103
104         msgid = ch_calloc( sizeof( int ), li->ntargets );
105         if ( msgid == NULL ) {
106                 return -1;
107         }
108
109         /*
110          * start an asynchronous compare for each candidate target
111          */
112         dc.conn = op->o_conn;
113         dc.rs = rs;
114         dc.ctx = "compareDn";
115
116         for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
117                 struct berval mdn = { 0, NULL };
118                 struct berval mapped_attr = op->oq_compare.rs_ava->aa_desc->ad_cname;
119                 struct berval mapped_value = op->oq_compare.rs_ava->aa_value;
120
121                 if ( lsc->candidate != META_CANDIDATE ) {
122                         msgid[ i ] = -1;
123                         continue;
124                 }
125
126                 /*
127                  * Rewrite the compare dn, if needed
128                  */
129                 dc.rwmap = &li->targets[ i ]->rwmap;
130
131                 switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
132                 case LDAP_UNWILLING_TO_PERFORM:
133                         rc = 1;
134                         goto finish;
135
136                 default:
137                         break;
138                 }
139
140                 /*
141                  * if attr is objectClass, try to remap the value
142                  */
143                 if ( op->oq_compare.rs_ava->aa_desc == slap_schema.si_ad_objectClass ) {
144                         ldap_back_map( &li->targets[ i ]->rwmap.rwm_oc,
145                                         &op->oq_compare.rs_ava->aa_value,
146                                         &mapped_value, BACKLDAP_MAP );
147
148                         if ( mapped_value.bv_val == NULL || mapped_value.bv_val[0] == '\0' ) {
149                                 continue;
150                         }
151                 /*
152                  * else try to remap the attribute
153                  */
154                 } else {
155                         ldap_back_map( &li->targets[ i ]->rwmap.rwm_at,
156                                 &op->oq_compare.rs_ava->aa_desc->ad_cname,
157                                 &mapped_attr, BACKLDAP_MAP );
158                         if ( mapped_attr.bv_val == NULL || mapped_attr.bv_val[0] == '\0' ) {
159                                 continue;
160                         }
161                 }
162                 
163                 /*
164                  * the compare op is spawned across the targets and the first
165                  * that returns determines the result; a constraint on unicity
166                  * of the result ought to be enforced
167                  */
168                 msgid[ i ] = ldap_compare( lc->conns[ i ].ld, mdn.bv_val,
169                                 mapped_attr.bv_val, mapped_value.bv_val );
170                 if ( mdn.bv_val != op->o_req_dn.bv_val ) {
171                         free( mdn.bv_val );
172                         mdn.bv_val = NULL;
173                 }
174                 if ( mapped_attr.bv_val != op->oq_compare.rs_ava->aa_desc->ad_cname.bv_val ) {
175                         free( mapped_attr.bv_val );
176                 }
177                 if ( mapped_value.bv_val != op->oq_compare.rs_ava->aa_value.bv_val ) {
178                         free( mapped_value.bv_val );
179                 }
180
181                 if ( msgid[ i ] == -1 ) {
182                         continue;
183                 }
184
185                 ++candidates;
186         }
187
188         /*
189          * wait for replies
190          */
191         for ( rc = 0, count = 0; candidates > 0; ) {
192
193                 /*
194                  * FIXME: should we check for abandon?
195                  */
196                 for ( i = 0, lsc = lc->conns; !META_LAST(lsc); lsc++, i++ ) {
197                         int             lrc;
198                         LDAPMessage     *res = NULL;
199
200                         if ( msgid[ i ] == -1 ) {
201                                 continue;
202                         }
203
204                         lrc = ldap_result( lsc->ld, msgid[ i ],
205                                         0, NULL, &res );
206
207                         if ( lrc == 0 ) {
208                                 /*
209                                  * FIXME: should we yield?
210                                  */
211                                 if ( res ) {
212                                         ldap_msgfree( res );
213                                 }
214                                 continue;
215
216                         } else if ( lrc == LDAP_RES_COMPARE ) {
217                                 if ( count > 0 ) {
218                                         rres = LDAP_OTHER;
219                                         rc = -1;
220                                         goto finish;
221                                 }
222                                 
223                                 rs->sr_err = ldap_result2error( lsc->ld, res, 1 );
224                                 switch ( rs->sr_err ) {
225                                 case LDAP_COMPARE_TRUE:
226                                 case LDAP_COMPARE_FALSE:
227
228                                         /*
229                                          * true or flase, got it;
230                                          * sending to cache ...
231                                          */
232                                         if ( li->cache.ttl != META_DNCACHE_DISABLED ) {
233                                                 ( void )meta_dncache_update_entry( &li->cache, &op->o_req_ndn, i );
234                                         }
235
236                                         count++;
237                                         rc = 0;
238                                         break;
239
240                                 default:
241                                         rres = ldap_back_map_result( rs );
242
243                                         if ( err != NULL ) {
244                                                 free( err );
245                                         }
246                                         ldap_get_option( lsc->ld,
247                                                 LDAP_OPT_ERROR_STRING, &err );
248
249                                         if ( match != NULL ) {
250                                                 free( match );
251                                         }
252                                         ldap_get_option( lsc->ld,
253                                                 LDAP_OPT_MATCHED_DN, &match );
254                                         
255                                         last = i;
256                                         break;
257                                 }
258                                 msgid[ i ] = -1;
259                                 --candidates;
260
261                         } else {
262                                 msgid[ i ] = -1;
263                                 --candidates;
264                                 if ( res ) {
265                                         ldap_msgfree( res );
266                                 }
267                                 break;
268                         }
269                 }
270         }
271
272 finish:;
273
274         /*
275          * Rewrite the matched portion of the search base, if required
276          * 
277          * FIXME: only the last one gets caught!
278          */
279         if ( count == 1 ) {
280                 if ( match != NULL ) {
281                         free( match );
282                         match = NULL;
283                 }
284                 
285                 /*
286                  * the result of the compare is assigned to the res code
287                  * that will be returned
288                  */
289                 rres = cres;
290                 
291                 /*
292                  * At least one compare failed with matched portion,
293                  * and none was successful
294                  */
295         } else if ( match != NULL &&  match[0] != '\0' ) {
296                 struct berval matched;
297
298                 matched.bv_val = match;
299                 matched.bv_len = strlen( match );
300
301                 dc.ctx = "matchedDn";
302                 ldap_back_dn_massage( &dc, &matched, &mmatch );
303         }
304
305         rs->sr_err = rres;
306         rs->sr_matched = mmatch.bv_val;
307         send_ldap_result( op, rs );
308         rs->sr_matched = NULL;
309
310         if ( match != NULL ) {
311                 if ( mmatch.bv_val != match ) {
312                         free( mmatch.bv_val );
313                 }
314                 free( match );
315         }
316
317         if ( msgid ) {
318                 free( msgid );
319         }
320         
321         return rc;
322 }
323