]> git.sur5r.net Git - openldap/blob - servers/slapd/search.c
a1c34b76dac8192bd7c5487012fbfac9d7e7b3d8
[openldap] / servers / slapd / search.c
1 /*
2  * Copyright (c) 1995 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/string.h>
18 #include <ac/socket.h>
19
20 #include "slap.h"
21 #include "ldapconfig.h"
22
23 extern int      get_filter();
24 extern Backend  *select_backend();
25
26 extern char     *default_referral;
27
28 void
29 do_search( conn, op )
30     Connection  *conn;  /* where to send results                       */
31     Operation   *op;    /* info about the op to which we're responding */
32 {
33         int             i, err;
34         int             scope, deref, attrsonly;
35         int             sizelimit, timelimit;
36         char            *base, *fstr;
37         Filter          *filter;
38         char            **attrs;
39         Backend         *be;
40
41         Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
42
43         /*
44          * Parse the search request.  It looks like this:
45          *
46          *      SearchRequest := [APPLICATION 3] SEQUENCE {
47          *              baseObject      DistinguishedName,
48          *              scope           ENUMERATED {
49          *                      baseObject      (0),
50          *                      singleLevel     (1),
51          *                      wholeSubtree    (2)
52          *              },
53          *              derefAliases    ENUMERATED {
54          *                      neverDerefaliases       (0),
55          *                      derefInSearching        (1),
56          *                      derefFindingBaseObj     (2),
57          *                      alwaysDerefAliases      (3)
58          *              },
59          *              sizelimit       INTEGER (0 .. 65535),
60          *              timelimit       INTEGER (0 .. 65535),
61          *              attrsOnly       BOOLEAN,
62          *              filter          Filter,
63          *              attributes      SEQUENCE OF AttributeType
64          *      }
65          */
66
67         /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
68         if ( ber_scanf( op->o_ber, "{aiiiib", &base, &scope, &deref, &sizelimit,
69             &timelimit, &attrsonly ) == LBER_ERROR ) {
70                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
71                 return;
72         }
73         if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
74             && scope != LDAP_SCOPE_SUBTREE ) {
75                 free( base );
76                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
77                     "Unknown search scope" );
78                 return;
79         }
80         (void) dn_normalize( base );
81
82         Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base, scope, deref );
83         Debug( LDAP_DEBUG_ARGS, "    %d %d %d\n", sizelimit, timelimit,
84             attrsonly);
85
86         /* filter - returns a "normalized" version */
87         filter = NULL;
88         fstr = NULL;
89         if ( (err = get_filter( conn, op->o_ber, &filter, &fstr )) != 0 ) {
90                 if ( fstr != NULL ) {
91                         free( fstr );
92                 }
93                 free( base );
94                 send_ldap_result( conn, op, err, NULL, "Bad search filter" );
95                 return;
96         }
97         Debug( LDAP_DEBUG_ARGS, "    filter: %s\n", fstr, 0, 0 );
98
99         /* attributes */
100         attrs = NULL;
101         if ( ber_scanf( op->o_ber, "{v}}", &attrs ) == LBER_ERROR ) {
102                 free( base );
103                 free( fstr );
104                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
105                 return;
106         }
107         Debug( LDAP_DEBUG_ARGS, "    attrs:", 0, 0, 0 );
108         if ( attrs != NULL ) {
109                 for ( i = 0; attrs[i] != NULL; i++ ) {
110                         attr_normalize( attrs[i] );
111                         Debug( LDAP_DEBUG_ARGS, " %s", attrs[i], 0, 0 );
112                 }
113         }
114         Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
115
116         Statslog( LDAP_DEBUG_STATS,
117             "conn=%d op=%d SRCH base=\"%s\" scope=%d filter=\"%s\"\n",
118             conn->c_connid, op->o_opid, base, scope, fstr );
119
120 #if defined( SLAPD_MONITOR_DN ) || defined( SLAPD_CONFIG_DN ) || defined( SLAPD_SCHEMA_DN )
121         if ( scope == LDAP_SCOPE_BASE ) {
122 #if defined( SLAPD_MONITOR_DN )
123                 if ( strcasecmp( base, SLAPD_MONITOR_DN ) == 0 ) {
124                         free( base );
125                         free( fstr );
126                         monitor_info( conn, op );
127                         return;
128                 }
129 #endif
130 #if defined( SLAPD_CONFIG_DN )
131                 if ( strcasecmp( base, SLAPD_CONFIG_DN ) == 0 ) {
132                         free( base );
133                         free( fstr );
134                         config_info( conn, op );
135                         return;
136                 }
137 #endif
138 #if defined( SLAPD_SCHEMA_DN )
139                 if ( strcasecmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
140                         free( base );
141                         free( fstr );
142                         schema_info( conn, op );
143                         return;
144                 }
145 #endif
146         }
147 #endif /* monitor or config or schema dn */
148
149         /*
150          * We could be serving multiple database backends.  Select the
151          * appropriate one, or send a referral to our "referral server"
152          * if we don't hold it.
153          */
154         if ( (be = select_backend( base )) == NULL ) {
155                 send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
156                     default_referral );
157
158                 free( base );
159                 free( fstr );
160                 filter_free( filter );
161                 if ( attrs != NULL ) {
162                         charray_free( attrs );
163                 }
164                 return;
165         }
166
167         /* actually do the search and send the result(s) */
168         if ( be->be_search != NULL ) {
169                 (*be->be_search)( be, conn, op, base, scope, deref, sizelimit,
170                     timelimit, filter, fstr, attrs, attrsonly );
171         } else {
172                 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
173                     "Function not implemented" );
174         }
175
176         free( base );
177         free( fstr );
178         filter_free( filter );
179         if ( attrs != NULL ) {
180                 charray_free( attrs );
181         }
182 }