search.c revision 1.1 1 1.1 lukem /* search.c - DNS SRV backend search function */
2 1.1 lukem /* $OpenLDAP: pkg/ldap/servers/slapd/back-dnssrv/search.c,v 1.44.2.4 2008/02/11 23:26:46 kurt Exp $ */
3 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 1.1 lukem *
5 1.1 lukem * Copyright 2000-2008 The OpenLDAP Foundation.
6 1.1 lukem * Portions Copyright 2000-2003 Kurt D. Zeilenga.
7 1.1 lukem * All rights reserved.
8 1.1 lukem *
9 1.1 lukem * Redistribution and use in source and binary forms, with or without
10 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
11 1.1 lukem * Public License.
12 1.1 lukem *
13 1.1 lukem * A copy of this license is available in the file LICENSE in the
14 1.1 lukem * top-level directory of the distribution or, alternatively, at
15 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
16 1.1 lukem */
17 1.1 lukem /* ACKNOWLEDGEMENTS:
18 1.1 lukem * This work was originally developed by Kurt D. Zeilenga for inclusion
19 1.1 lukem * in OpenLDAP Software.
20 1.1 lukem */
21 1.1 lukem
22 1.1 lukem #include "portable.h"
23 1.1 lukem
24 1.1 lukem #include <stdio.h>
25 1.1 lukem
26 1.1 lukem #include <ac/socket.h>
27 1.1 lukem #include <ac/string.h>
28 1.1 lukem #include <ac/time.h>
29 1.1 lukem
30 1.1 lukem #include "slap.h"
31 1.1 lukem #include "proto-dnssrv.h"
32 1.1 lukem
33 1.1 lukem int
34 1.1 lukem dnssrv_back_search(
35 1.1 lukem Operation *op,
36 1.1 lukem SlapReply *rs )
37 1.1 lukem {
38 1.1 lukem int i;
39 1.1 lukem int rc;
40 1.1 lukem char *domain = NULL;
41 1.1 lukem char *hostlist = NULL;
42 1.1 lukem char **hosts = NULL;
43 1.1 lukem char *refdn;
44 1.1 lukem struct berval nrefdn = BER_BVNULL;
45 1.1 lukem BerVarray urls = NULL;
46 1.1 lukem int manageDSAit;
47 1.1 lukem
48 1.1 lukem rs->sr_ref = NULL;
49 1.1 lukem
50 1.1 lukem if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
51 1.1 lukem /* FIXME: need some means to determine whether the database
52 1.1 lukem * is a glue instance; if we got here with empty DN, then
53 1.1 lukem * we passed this same test in dnssrv_back_referrals() */
54 1.1 lukem if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) {
55 1.1 lukem rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
56 1.1 lukem rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed";
57 1.1 lukem
58 1.1 lukem } else {
59 1.1 lukem rs->sr_err = LDAP_SUCCESS;
60 1.1 lukem }
61 1.1 lukem goto done;
62 1.1 lukem }
63 1.1 lukem
64 1.1 lukem manageDSAit = get_manageDSAit( op );
65 1.1 lukem /*
66 1.1 lukem * FIXME: we may return a referral if manageDSAit is not set
67 1.1 lukem */
68 1.1 lukem if ( !manageDSAit ) {
69 1.1 lukem send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
70 1.1 lukem "manageDSAit must be set" );
71 1.1 lukem goto done;
72 1.1 lukem }
73 1.1 lukem
74 1.1 lukem if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) {
75 1.1 lukem rs->sr_err = LDAP_REFERRAL;
76 1.1 lukem rs->sr_ref = default_referral;
77 1.1 lukem send_ldap_result( op, rs );
78 1.1 lukem rs->sr_ref = NULL;
79 1.1 lukem goto done;
80 1.1 lukem }
81 1.1 lukem
82 1.1 lukem Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n",
83 1.1 lukem op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain, 0 );
84 1.1 lukem
85 1.1 lukem if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) {
86 1.1 lukem Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n",
87 1.1 lukem rc, 0, 0 );
88 1.1 lukem send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
89 1.1 lukem "no DNS SRV RR available for DN" );
90 1.1 lukem goto done;
91 1.1 lukem }
92 1.1 lukem
93 1.1 lukem hosts = ldap_str2charray( hostlist, " " );
94 1.1 lukem
95 1.1 lukem if( hosts == NULL ) {
96 1.1 lukem Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 );
97 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER,
98 1.1 lukem "problem processing DNS SRV records for DN" );
99 1.1 lukem goto done;
100 1.1 lukem }
101 1.1 lukem
102 1.1 lukem for( i=0; hosts[i] != NULL; i++) {
103 1.1 lukem struct berval url;
104 1.1 lukem
105 1.1 lukem url.bv_len = STRLENOF( "ldap://" ) + strlen(hosts[i]);
106 1.1 lukem url.bv_val = ch_malloc( url.bv_len + 1 );
107 1.1 lukem
108 1.1 lukem strcpy( url.bv_val, "ldap://" );
109 1.1 lukem strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] );
110 1.1 lukem
111 1.1 lukem if( ber_bvarray_add( &urls, &url ) < 0 ) {
112 1.1 lukem free( url.bv_val );
113 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER,
114 1.1 lukem "problem processing DNS SRV records for DN" );
115 1.1 lukem goto done;
116 1.1 lukem }
117 1.1 lukem }
118 1.1 lukem
119 1.1 lukem Statslog( LDAP_DEBUG_STATS,
120 1.1 lukem "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n",
121 1.1 lukem op->o_log_prefix, op->o_protocol,
122 1.1 lukem op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val, 0 );
123 1.1 lukem
124 1.1 lukem Debug( LDAP_DEBUG_TRACE,
125 1.1 lukem "DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n",
126 1.1 lukem op->oq_search.rs_scope,
127 1.1 lukem op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
128 1.1 lukem urls[0].bv_val );
129 1.1 lukem
130 1.1 lukem rc = ldap_domain2dn(domain, &refdn);
131 1.1 lukem
132 1.1 lukem if( rc != LDAP_SUCCESS ) {
133 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER,
134 1.1 lukem "DNS SRV problem processing manageDSAit control" );
135 1.1 lukem goto done;
136 1.1 lukem
137 1.1 lukem } else {
138 1.1 lukem struct berval bv;
139 1.1 lukem bv.bv_val = refdn;
140 1.1 lukem bv.bv_len = strlen( refdn );
141 1.1 lukem
142 1.1 lukem rc = dnNormalize( 0, NULL, NULL, &bv, &nrefdn, op->o_tmpmemctx );
143 1.1 lukem if( rc != LDAP_SUCCESS ) {
144 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER,
145 1.1 lukem "DNS SRV problem processing manageDSAit control" );
146 1.1 lukem goto done;
147 1.1 lukem }
148 1.1 lukem }
149 1.1 lukem
150 1.1 lukem if( !dn_match( &nrefdn, &op->o_req_ndn ) ) {
151 1.1 lukem /* requested dn is subordinate */
152 1.1 lukem
153 1.1 lukem Debug( LDAP_DEBUG_TRACE,
154 1.1 lukem "DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n",
155 1.1 lukem op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
156 1.1 lukem refdn == NULL ? "" : refdn,
157 1.1 lukem NULL );
158 1.1 lukem
159 1.1 lukem rs->sr_matched = refdn;
160 1.1 lukem rs->sr_err = LDAP_NO_SUCH_OBJECT;
161 1.1 lukem send_ldap_result( op, rs );
162 1.1 lukem rs->sr_matched = NULL;
163 1.1 lukem
164 1.1 lukem } else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) {
165 1.1 lukem send_ldap_error( op, rs, LDAP_SUCCESS, NULL );
166 1.1 lukem
167 1.1 lukem } else {
168 1.1 lukem Entry e = { 0 };
169 1.1 lukem AttributeDescription *ad_objectClass
170 1.1 lukem = slap_schema.si_ad_objectClass;
171 1.1 lukem AttributeDescription *ad_ref = slap_schema.si_ad_ref;
172 1.1 lukem e.e_name.bv_val = strdup( op->o_req_dn.bv_val );
173 1.1 lukem e.e_name.bv_len = op->o_req_dn.bv_len;
174 1.1 lukem e.e_nname.bv_val = strdup( op->o_req_ndn.bv_val );
175 1.1 lukem e.e_nname.bv_len = op->o_req_ndn.bv_len;
176 1.1 lukem
177 1.1 lukem e.e_attrs = NULL;
178 1.1 lukem e.e_private = NULL;
179 1.1 lukem
180 1.1 lukem attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname, NULL );
181 1.1 lukem attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname, NULL );
182 1.1 lukem
183 1.1 lukem if ( ad_dc ) {
184 1.1 lukem char *p;
185 1.1 lukem struct berval bv;
186 1.1 lukem
187 1.1 lukem bv.bv_val = domain;
188 1.1 lukem
189 1.1 lukem p = strchr( bv.bv_val, '.' );
190 1.1 lukem
191 1.1 lukem if ( p == bv.bv_val ) {
192 1.1 lukem bv.bv_len = 1;
193 1.1 lukem
194 1.1 lukem } else if ( p != NULL ) {
195 1.1 lukem bv.bv_len = p - bv.bv_val;
196 1.1 lukem
197 1.1 lukem } else {
198 1.1 lukem bv.bv_len = strlen( bv.bv_val );
199 1.1 lukem }
200 1.1 lukem
201 1.1 lukem attr_merge_normalize_one( &e, ad_dc, &bv, NULL );
202 1.1 lukem }
203 1.1 lukem
204 1.1 lukem if ( ad_associatedDomain ) {
205 1.1 lukem struct berval bv;
206 1.1 lukem
207 1.1 lukem ber_str2bv( domain, 0, 0, &bv );
208 1.1 lukem attr_merge_normalize_one( &e, ad_associatedDomain, &bv, NULL );
209 1.1 lukem }
210 1.1 lukem
211 1.1 lukem attr_merge_normalize_one( &e, ad_ref, urls, NULL );
212 1.1 lukem
213 1.1 lukem rc = test_filter( op, &e, op->oq_search.rs_filter );
214 1.1 lukem
215 1.1 lukem if( rc == LDAP_COMPARE_TRUE ) {
216 1.1 lukem rs->sr_entry = &e;
217 1.1 lukem rs->sr_attrs = op->oq_search.rs_attrs;
218 1.1 lukem rs->sr_flags = REP_ENTRY_MODIFIABLE;
219 1.1 lukem send_search_entry( op, rs );
220 1.1 lukem rs->sr_entry = NULL;
221 1.1 lukem rs->sr_attrs = NULL;
222 1.1 lukem }
223 1.1 lukem
224 1.1 lukem entry_clean( &e );
225 1.1 lukem
226 1.1 lukem rs->sr_err = LDAP_SUCCESS;
227 1.1 lukem send_ldap_result( op, rs );
228 1.1 lukem }
229 1.1 lukem
230 1.1 lukem if ( refdn ) free( refdn );
231 1.1 lukem if ( nrefdn.bv_val ) free( nrefdn.bv_val );
232 1.1 lukem
233 1.1 lukem done:
234 1.1 lukem if( domain != NULL ) ch_free( domain );
235 1.1 lukem if( hostlist != NULL ) ch_free( hostlist );
236 1.1 lukem if( hosts != NULL ) ldap_charray_free( hosts );
237 1.1 lukem if( urls != NULL ) ber_bvarray_free( urls );
238 1.1 lukem return 0;
239 1.1 lukem }
240 1.1 lukem
241