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