]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/search.c
Fix memory leak in new schema code.
[openldap] / servers / slapd / back-ldap / search.c
1 /* search.c - ldap backend search function */
2 /* $OpenLDAP$ */
3
4 /*
5  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
6  * 
7  * Permission is granted to anyone to use this software for any purpose
8  * on any computer system, and to alter it and redistribute it, subject
9  * to the following restrictions:
10  * 
11  * 1. The author is not responsible for the consequences of use of this
12  *    software, no matter how awful, even if they arise from flaws in it.
13  * 
14  * 2. The origin of this software must not be misrepresented, either by
15  *    explicit claim or by omission.  Since few users ever read sources,
16  *    credits should appear in the documentation.
17  * 
18  * 3. Altered versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.  Since few users
20  *    ever read sources, credits should appear in the documentation.
21  * 
22  * 4. This notice may not be removed or altered.
23  */
24
25 #include "portable.h"
26
27 #include <stdio.h>
28
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/time.h>
32
33 #include "slap.h"
34 #include "back-ldap.h"
35
36 static void ldap_send_entry( Backend *be, Operation *op, struct ldapconn *lc,
37                              LDAPMessage *e, char **attrs, int attrsonly );
38
39 int
40 ldap_back_search(
41     Backend     *be,
42     Connection  *conn,
43     Operation   *op,
44     const char  *base,
45     const char  *nbase,
46     int         scope,
47     int         deref,
48     int         size,
49     int         time,
50     Filter      *filter,
51     const char  *filterstr,
52     char        **attrs,
53     int         attrsonly
54 )
55 {
56         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
57         struct ldapconn *lc;
58         struct timeval  tv;
59         LDAPMessage             *res, *e;
60         int                     i, rc, msgid, sres = LDAP_SUCCESS; 
61         char *match = NULL, *err = NULL;
62
63         lc = ldap_back_getconn(li, conn, op);
64         if (!lc)
65                 return( -1 );
66
67         if (deref != -1)
68                 ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&deref);
69         if (time != -1)
70                 ldap_set_option( lc->ld, LDAP_OPT_TIMELIMIT, (void *)&time);
71         if (size != -1)
72                 ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&size);
73         if (!lc->bound) {
74                 ldap_back_dobind(lc, op);
75                 if (!lc->bound)
76                         return( -1 );
77         }
78
79         if ((msgid = ldap_search(lc->ld, base, scope, filterstr, attrs,
80                 attrsonly)) == -1)
81 fail:           return( ldap_back_op_result(lc, op) );
82
83         /* We pull apart the ber result, stuff it into a slapd entry, and
84          * let send_search_entry stuff it back into ber format. Slow & ugly,
85          * but this is necessary for version matching, and for ACL processing.
86          */
87         
88         for (i=0, rc=0; rc != -1;
89                 rc = ldap_result(lc->ld, LDAP_RES_ANY, 0, &tv, &res)) {
90                 int ab;
91
92                 /* check for abandon */
93                 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
94                 ab = op->o_abandon;
95                 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
96
97                 if (ab) {
98                         ldap_abandon(lc->ld, msgid);
99                 } else if (rc == 0) {
100                         tv.tv_sec = 0;
101                         tv.tv_usec = 100000;
102                         ldap_pvt_thread_yield();
103                         continue;
104                 } else if (rc == LDAP_RES_SEARCH_ENTRY) {
105                         e = ldap_first_entry(lc->ld,res);
106                         ldap_send_entry(be, op, lc, e, attrs, attrsonly);
107                         i++;
108                         ldap_msgfree(res);
109                 } else {
110                         sres = ldap_result2error(lc->ld, res, 1);
111                         ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &err);
112                         ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
113                         rc = 0;
114                 }
115                 if (ab)
116                         return (0);
117                 else if (rc == 0)
118                         break;
119         }
120
121         if (rc == -1)
122                 goto fail;
123
124         send_search_result( conn, op, sres,
125                 match, err, NULL, NULL, i );
126         if (match)
127                 free(match);
128         if (err)
129                 free(err);
130         return( 0 );
131 }
132
133 static void
134 ldap_send_entry(
135         Backend *be,
136         Operation *op,
137         struct ldapconn *lc,
138         LDAPMessage *e,
139         char **attrs,
140         int attrsonly
141 )
142 {
143         char *a;
144         Entry ent;
145         BerElement *ber = NULL;
146         Attribute *attr, **attrp;
147         struct berval *dummy = NULL;
148 #ifdef SLAPD_SCHEMA_NOT_COMPAT
149         char *text;
150 #endif
151
152         ent.e_dn = ldap_get_dn(lc->ld, e);
153         ent.e_ndn = ch_strdup( ent.e_dn);
154         (void) dn_normalize( ent.e_ndn );
155         ent.e_id = 0;
156         ent.e_attrs = 0;
157         ent.e_private = 0;
158         attrp = &ent.e_attrs;
159
160         for (   a = ldap_first_attribute(lc->ld, e, &ber);
161                         a != NULL;
162                         a = ldap_next_attribute(lc->ld, e, ber))
163         {
164                 attr = (Attribute *)ch_malloc( sizeof(Attribute) );
165                 if (attr == NULL)
166                         continue;
167                 attr->a_next = 0;
168 #ifdef SLAPD_SCHEMA_NOT_COMPAT
169                 slap_str2ad(a, &attr->a_desc, &text);
170 #else
171                 attr->a_type = ch_strdup(a);
172                 attr->a_syntax = attr_syntax(a);
173 #endif
174                 attr->a_vals = ldap_get_values_len(lc->ld, e, a);
175                 if (!attr->a_vals)
176                         attr->a_vals = &dummy;
177                 *attrp = attr;
178                 attrp = &attr->a_next;
179         }
180         send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, NULL );
181         for (;ent.e_attrs;) {
182                 attr=ent.e_attrs;
183                 ent.e_attrs = attr->a_next;
184 #ifdef SLAPD_SCHEMA_NOT_COMPAT
185                 ad_free(attr->a_desc, 1);
186 #else
187                 free(attr->a_type);
188 #endif
189                 if (attr->a_vals != &dummy)
190                         ber_bvecfree(attr->a_vals);
191                 free(attr);
192         }
193         if (ber)
194                 ber_free(ber,0);
195 }