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