]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/search.c
fix for select_backend suggested G. Gombas (ITS 1090)
[openldap] / servers / slapd / back-ldap / search.c
1 /* search.c - ldap backend search function */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7 /* This is an altered version */
8 /*
9  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
10  * 
11  * Permission is granted to anyone to use this software for any purpose
12  * on any computer system, and to alter it and redistribute it, subject
13  * to the following restrictions:
14  * 
15  * 1. The author is not responsible for the consequences of use of this
16  *    software, no matter how awful, even if they arise from flaws in it.
17  * 
18  * 2. The origin of this software must not be misrepresented, either by
19  *    explicit claim or by omission.  Since few users ever read sources,
20  *    credits should appear in the documentation.
21  * 
22  * 3. Altered versions must be plainly marked as such, and must not be
23  *    misrepresented as being the original software.  Since few users
24  *    ever read sources, credits should appear in the documentation.
25  * 
26  * 4. This notice may not be removed or altered.
27  *
28  *
29  *
30  * Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
31  * 
32  * This software is being modified by Pierangelo Masarati.
33  * The previously reported conditions apply to the modified code as well.
34  * Changes in the original code are highlighted where required.
35  * Credits for the original code go to the author, Howard Chu.
36  */
37
38 #include "portable.h"
39
40 #include <stdio.h>
41
42 #include <ac/socket.h>
43 #include <ac/string.h>
44 #include <ac/time.h>
45
46 #include "slap.h"
47 #include "back-ldap.h"
48
49 static void ldap_send_entry( Backend *be, Operation *op, struct ldapconn *lc,
50                              LDAPMessage *e, char **attrs, int attrsonly );
51
52 int
53 ldap_back_search(
54     Backend     *be,
55     Connection  *conn,
56     Operation   *op,
57     const char  *base,
58     const char  *nbase,
59     int         scope,
60     int         deref,
61     int         size,
62     int         time,
63     Filter      *filter,
64     const char  *filterstr,
65     char        **attrs,
66     int         attrsonly
67 )
68 {
69         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
70         struct ldapconn *lc;
71         struct timeval  tv;
72         LDAPMessage             *res, *e;
73         int     count, rc, msgid, sres = LDAP_SUCCESS; 
74         char *match = NULL, *err = NULL;
75         char *mbase, *mapped_filter, **mapped_attrs;
76
77         lc = ldap_back_getconn(li, conn, op);
78         if ( !lc ) {
79                 return( -1 );
80         }
81
82         if (deref != -1)
83                 ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&deref);
84         if (time != -1)
85                 ldap_set_option( lc->ld, LDAP_OPT_TIMELIMIT, (void *)&time);
86         if (size != -1)
87                 ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&size);
88         
89         if ( !ldap_back_dobind( lc, op ) ) {
90                 return( -1 );
91         }
92
93         mbase = ldap_back_dn_massage( li, ch_strdup( base ), 0 );
94         if ( mbase == NULL ) {
95                 return -1;
96         }
97
98         mapped_filter = ldap_back_map_filter(li, (char *)filterstr, 0);
99         if ( mapped_filter == NULL ) {
100                 mapped_filter = (char *)filterstr;
101         }
102
103         mapped_attrs = ldap_back_map_attrs(li, attrs, 0);
104         if ( mapped_attrs == NULL ) {
105                 mapped_attrs = attrs;
106         }
107
108         if ((msgid = ldap_search(lc->ld, mbase, scope, mapped_filter, mapped_attrs,
109                 attrsonly)) == -1)
110         {
111 fail:
112                 if (match)
113                         free(match);
114                 if (err)
115                         free(err);
116                 if (mapped_attrs != attrs)
117                         charray_free(mapped_attrs);
118                 if (mapped_filter != filterstr)
119                         free(mapped_filter);
120                 free(mbase);
121                 return( ldap_back_op_result(lc, op) );
122         }
123
124         /* We pull apart the ber result, stuff it into a slapd entry, and
125          * let send_search_entry stuff it back into ber format. Slow & ugly,
126          * but this is necessary for version matching, and for ACL processing.
127          */
128         
129         for (   count=0, rc=0;
130                         rc != -1;
131                         rc = ldap_result(lc->ld, LDAP_RES_ANY, 0, &tv, &res))
132         {
133                 int ab;
134
135                 /* check for abandon */
136                 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
137                 ab = op->o_abandon;
138                 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
139
140                 if (ab) {
141                         ldap_abandon(lc->ld, msgid);
142                         goto finish;
143                 }
144                 if (rc == 0) {
145                         tv.tv_sec = 0;
146                         tv.tv_usec = 100000;
147                         ldap_pvt_thread_yield();
148                 } else if (rc == LDAP_RES_SEARCH_ENTRY) {
149                         e = ldap_first_entry(lc->ld,res);
150                         ldap_send_entry(be, op, lc, e, attrs, attrsonly);
151                         count++;
152                         ldap_msgfree(res);
153                 } else {
154                         sres = ldap_result2error(lc->ld, res, 1);
155                         sres = ldap_back_map_result(sres);
156                         ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &err);
157                         ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
158                         rc = 0;
159                         break;
160                 }
161         }
162
163         if (rc == -1)
164                 goto fail;
165
166         send_search_result( conn, op, sres,
167                 match, err, NULL, NULL, count );
168
169 finish:
170         if (match)
171                 free(match);
172         if (err)
173                 free(err);
174         if (mapped_attrs != attrs)
175                 charray_free(mapped_attrs);
176         if (mapped_filter != filterstr)
177                 free(mapped_filter);
178         free(mbase);
179         return( 0 );
180 }
181
182 static void
183 ldap_send_entry(
184         Backend *be,
185         Operation *op,
186         struct ldapconn *lc,
187         LDAPMessage *e,
188         char **attrs,
189         int attrsonly
190 )
191 {
192         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
193         char *a, *mapped;
194         Entry ent;
195         BerElement *ber = NULL;
196         Attribute *attr, **attrp;
197         struct berval *dummy = NULL;
198         struct berval *bv;
199         const char *text;
200
201         ent.e_dn = ldap_back_dn_restore( li, ldap_get_dn(lc->ld, e), 0 );
202         ent.e_ndn = ch_strdup( ent.e_dn );
203         (void) dn_normalize( ent.e_ndn );
204         ent.e_id = 0;
205         ent.e_attrs = 0;
206         ent.e_private = 0;
207         attrp = &ent.e_attrs;
208
209         for (   a = ldap_first_attribute(lc->ld, e, &ber);
210                         a != NULL;
211                         a = ldap_next_attribute(lc->ld, e, ber))
212         {
213                 mapped = ldap_back_map(&li->at_map, a, 1);
214                 if (mapped == NULL)
215                         continue;
216                 attr = (Attribute *)ch_malloc( sizeof(Attribute) );
217                 if (attr == NULL)
218                         continue;
219                 attr->a_next = 0;
220                 attr->a_desc = NULL;
221                 if (slap_str2ad(mapped, &attr->a_desc, &text) != LDAP_SUCCESS) {
222                         ch_free(attr);
223                         continue;
224                 }
225                 attr->a_vals = ldap_get_values_len(lc->ld, e, a);
226                 if (!attr->a_vals) {
227                         attr->a_vals = &dummy;
228                 } else if ( strcasecmp( mapped, "objectclass" ) == 0 ) {
229                         int i, last;
230                         for ( last = 0; attr->a_vals[last]; last++ ) ;
231                         for ( i = 0; bv = attr->a_vals[i]; i++ ) {
232                                 mapped = ldap_back_map(&li->oc_map, bv->bv_val, 1);
233                                 if (mapped == NULL) {
234                                         ber_bvfree(attr->a_vals[i]);
235                                         attr->a_vals[i] = NULL;
236                                         if (--last < 0)
237                                                 break;
238                                         attr->a_vals[i] = attr->a_vals[last];
239                                         attr->a_vals[last] = NULL;
240                                         i--;
241                                 } else if ( mapped != bv->bv_val ) {
242                                         ch_free(bv->bv_val);
243                                         bv->bv_val = ch_strdup( mapped );
244                                         bv->bv_len = strlen( mapped );
245                                 }
246                         }
247                 }
248                 *attrp = attr;
249                 attrp = &attr->a_next;
250         }
251         send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, NULL );
252         while (ent.e_attrs) {
253                 attr = ent.e_attrs;
254                 ent.e_attrs = attr->a_next;
255                 ad_free(attr->a_desc, 1);
256                 if (attr->a_vals != &dummy)
257                         ber_bvecfree(attr->a_vals);
258                 free(attr);
259         }
260         if (ber)
261                 ber_free(ber,0);
262         
263         if ( ent.e_dn )
264                 free( ent.e_dn );
265         if ( ent.e_ndn )
266                 free( ent.e_ndn );
267 }