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