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