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