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