]> git.sur5r.net Git - openldap/blob - servers/slapd/back-dnssrv/search.c
mix refresh and fix; may need further work
[openldap] / servers / slapd / back-dnssrv / search.c
1 /* search.c - DNS SRV backend search function */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 2000-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8
9 #include "portable.h"
10
11 #include <stdio.h>
12
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #include "slap.h"
18 #include "external.h"
19
20 int
21 dnssrv_back_search(
22     Operation   *op,
23     SlapReply   *rs )
24 {
25         int i;
26         int rc;
27         char *domain = NULL;
28         char *hostlist = NULL;
29         char **hosts = NULL;
30         char *refdn;
31         struct berval nrefdn = { 0, NULL };
32         BerVarray urls = NULL;
33         int manageDSAit;
34
35         rs->sr_ref = NULL;
36
37         manageDSAit = get_manageDSAit( op );
38         /*
39          * FIXME: we may return a referral if manageDSAit is not set
40          */
41         if ( ! manageDSAit ) {
42                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
43                                 "manageDSAit must be set" );
44                 goto done;
45         }
46
47         if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) {
48                 rs->sr_err = LDAP_REFERRAL;
49                 rs->sr_ref = default_referral;
50                 send_ldap_result( op, rs );
51                 rs->sr_ref = NULL;
52                 goto done;
53         }
54
55         Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n",
56                 op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain, 0 );
57
58         if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) {
59                 Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n",
60                         rc, 0, 0 );
61                 send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
62                         "no DNS SRV RR available for DN" );
63                 goto done;
64         }
65
66         hosts = ldap_str2charray( hostlist, " " );
67
68         if( hosts == NULL ) {
69                 Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 );
70                 send_ldap_error( op, rs, LDAP_OTHER,
71                         "problem processing DNS SRV records for DN" );
72                 goto done;
73         }
74
75         for( i=0; hosts[i] != NULL; i++) {
76                 struct berval url;
77
78                 url.bv_len = sizeof("ldap://")-1 + strlen(hosts[i]);
79                 url.bv_val = ch_malloc( url.bv_len + 1 );
80
81                 strcpy( url.bv_val, "ldap://" );
82                 strcpy( &url.bv_val[sizeof("ldap://")-1], hosts[i] );
83
84                 if( ber_bvarray_add( &urls, &url ) < 0 ) {
85                         free( url.bv_val );
86                         send_ldap_error( op, rs, LDAP_OTHER,
87                         "problem processing DNS SRV records for DN" );
88                         goto done;
89                 }
90         }
91
92         Statslog( LDAP_DEBUG_STATS,
93             "conn=%lu op=%lu DNSSRV p=%d dn=\"%s\" url=\"%s\"\n",
94             op->o_connid, op->o_opid, op->o_protocol,
95                 op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val );
96
97         Debug( LDAP_DEBUG_TRACE,
98                 "DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n",
99                 op->oq_search.rs_scope,
100                 op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
101                 urls[0].bv_val );
102
103         rc = ldap_domain2dn(domain, &refdn);
104
105         if( rc != LDAP_SUCCESS ) {
106                 send_ldap_error( op, rs, LDAP_OTHER,
107                         "DNS SRV problem processing manageDSAit control" );
108                 goto done;
109
110         } else {
111                 struct berval bv;
112                 bv.bv_val = refdn;
113                 bv.bv_len = strlen( refdn );
114
115                 rc = dnNormalize2( NULL, &bv, &nrefdn );
116                 if( rc != LDAP_SUCCESS ) {
117                         send_ldap_error( op, rs, LDAP_OTHER,
118                                 "DNS SRV problem processing manageDSAit control" );
119                         goto done;
120                 }
121         }
122
123         if( !dn_match( &nrefdn, &op->o_req_ndn ) ) {
124                 /* requested dn is subordinate */
125
126                 Debug( LDAP_DEBUG_TRACE,
127                         "DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n",
128                         op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
129                         refdn == NULL ? "" : refdn,
130                         NULL );
131
132                 rs->sr_matched = refdn;
133                 rs->sr_err = LDAP_NO_SUCH_OBJECT;
134                 send_ldap_result( op, rs );
135                 rs->sr_matched = NULL;
136
137         } else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) {
138                 send_ldap_error( op, rs, LDAP_SUCCESS, NULL );
139
140         } else {
141                 struct berval   vals[2];
142                 Entry *e = ch_calloc( 1, sizeof(Entry) );
143                 AttributeDescription *ad_objectClass
144                         = slap_schema.si_ad_objectClass;
145                 AttributeDescription *ad_ref = slap_schema.si_ad_ref;
146                 e->e_name.bv_val = strdup( op->o_req_dn.bv_val );
147                 e->e_name.bv_len = op->o_req_dn.bv_len;
148                 e->e_nname.bv_val = strdup( op->o_req_ndn.bv_val );
149                 e->e_nname.bv_len = op->o_req_ndn.bv_len;
150
151                 e->e_attrs = NULL;
152                 e->e_private = NULL;
153
154                 vals[1].bv_val = NULL;
155
156                 vals[0].bv_val = "top";
157                 vals[0].bv_len = sizeof("top")-1;
158                 attr_mergeit( e, ad_objectClass, vals );
159
160                 vals[0].bv_val = "referral";
161                 vals[0].bv_len = sizeof("referral")-1;
162                 attr_mergeit( e, ad_objectClass, vals );
163
164                 vals[0].bv_val = "extensibleObject";
165                 vals[0].bv_len = sizeof("extensibleObject")-1;
166                 attr_mergeit( e, ad_objectClass, vals );
167
168                 {
169                         AttributeDescription *ad = NULL;
170                         const char *text;
171
172                         rc = slap_str2ad( "dc", &ad, &text );
173
174                         if( rc == LDAP_SUCCESS ) {
175                                 char *p;
176                                 vals[0].bv_val = ch_strdup( domain );
177
178                                 p = strchr( vals[0].bv_val, '.' );
179                                         
180                                 if( p == vals[0].bv_val ) {
181                                         vals[0].bv_val[1] = '\0';
182                                 } else if ( p != NULL ) {
183                                         *p = '\0';
184                                 }
185
186                                 vals[0].bv_len = strlen(vals[0].bv_val);
187                                 attr_mergeit( e, ad, vals );
188                         }
189                 }
190
191                 {
192                         AttributeDescription *ad = NULL;
193                         const char *text;
194
195                         rc = slap_str2ad( "associatedDomain", &ad, &text );
196
197                         if( rc == LDAP_SUCCESS ) {
198                                 vals[0].bv_val = domain;
199                                 vals[0].bv_len = strlen(domain);
200                                 attr_mergeit( e, ad, vals );
201                         }
202                 }
203
204                 attr_mergeit( e, ad_ref, urls );
205
206                 rc = test_filter( op, e, op->oq_search.rs_filter ); 
207
208                 if( rc == LDAP_COMPARE_TRUE ) {
209                         rs->sr_entry = e;
210                         rs->sr_attrs = op->oq_search.rs_attrs;
211                         send_search_entry( op, rs );
212                         rs->sr_entry = NULL;
213                         rs->sr_attrs = NULL;
214                 }
215
216                 entry_free( e );
217
218                 rs->sr_err = LDAP_SUCCESS;
219                 send_ldap_result( op, rs );
220         }
221
222         if ( refdn ) free( refdn );
223         if ( nrefdn.bv_val ) free( nrefdn.bv_val );
224
225 done:
226         if( domain != NULL ) ch_free( domain );
227         if( hostlist != NULL ) ch_free( hostlist );
228         if( hosts != NULL ) ldap_charray_free( hosts );
229         if( urls != NULL ) ber_bvarray_free( urls );
230         return 0;
231 }
232