Back to index

openldap  2.4.31
search.c
Go to the documentation of this file.
00001 /* search.c - DNS SRV backend search function */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2000-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2000-2003 Kurt D. Zeilenga.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was originally developed by Kurt D. Zeilenga for inclusion
00019  * in OpenLDAP Software.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #include <stdio.h>
00025 
00026 #include <ac/socket.h>
00027 #include <ac/string.h>
00028 #include <ac/time.h>
00029 
00030 #include "slap.h"
00031 #include "proto-dnssrv.h"
00032 
00033 int
00034 dnssrv_back_search(
00035     Operation *op,
00036     SlapReply *rs )
00037 {
00038        int i;
00039        int rc;
00040        char *domain = NULL;
00041        char *hostlist = NULL;
00042        char **hosts = NULL;
00043        char *refdn;
00044        struct berval nrefdn = BER_BVNULL;
00045        BerVarray urls = NULL;
00046        int manageDSAit;
00047 
00048        rs->sr_ref = NULL;
00049 
00050        if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
00051               /* FIXME: need some means to determine whether the database
00052                * is a glue instance; if we got here with empty DN, then
00053                * we passed this same test in dnssrv_back_referrals() */
00054               if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) {
00055                      rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
00056                      rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed";
00057 
00058               } else {
00059                      rs->sr_err = LDAP_SUCCESS;
00060               }
00061               goto done;
00062        }
00063 
00064        manageDSAit = get_manageDSAit( op );
00065        /*
00066         * FIXME: we may return a referral if manageDSAit is not set
00067         */
00068        if ( !manageDSAit ) {
00069               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
00070                             "manageDSAit must be set" );
00071               goto done;
00072        }
00073 
00074        if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) {
00075               rs->sr_err = LDAP_REFERRAL;
00076               rs->sr_ref = default_referral;
00077               send_ldap_result( op, rs );
00078               rs->sr_ref = NULL;
00079               goto done;
00080        }
00081 
00082        Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n",
00083               op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain, 0 );
00084 
00085        if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) {
00086               Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n",
00087                      rc, 0, 0 );
00088               send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
00089                      "no DNS SRV RR available for DN" );
00090               goto done;
00091        }
00092 
00093        hosts = ldap_str2charray( hostlist, " " );
00094 
00095        if( hosts == NULL ) {
00096               Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 );
00097               send_ldap_error( op, rs, LDAP_OTHER,
00098                      "problem processing DNS SRV records for DN" );
00099               goto done;
00100        }
00101 
00102        for( i=0; hosts[i] != NULL; i++) {
00103               struct berval url;
00104 
00105               url.bv_len = STRLENOF( "ldap://" ) + strlen(hosts[i]);
00106               url.bv_val = ch_malloc( url.bv_len + 1 );
00107 
00108               strcpy( url.bv_val, "ldap://" );
00109               strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] );
00110 
00111               if( ber_bvarray_add( &urls, &url ) < 0 ) {
00112                      free( url.bv_val );
00113                      send_ldap_error( op, rs, LDAP_OTHER,
00114                      "problem processing DNS SRV records for DN" );
00115                      goto done;
00116               }
00117        }
00118 
00119        Statslog( LDAP_DEBUG_STATS,
00120            "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n",
00121            op->o_log_prefix, op->o_protocol,
00122               op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val, 0 );
00123 
00124        Debug( LDAP_DEBUG_TRACE,
00125               "DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n",
00126               op->oq_search.rs_scope,
00127               op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
00128               urls[0].bv_val );
00129 
00130        rc = ldap_domain2dn(domain, &refdn);
00131 
00132        if( rc != LDAP_SUCCESS ) {
00133               send_ldap_error( op, rs, LDAP_OTHER,
00134                      "DNS SRV problem processing manageDSAit control" );
00135               goto done;
00136 
00137        } else {
00138               struct berval bv;
00139               bv.bv_val = refdn;
00140               bv.bv_len = strlen( refdn );
00141 
00142               rc = dnNormalize( 0, NULL, NULL, &bv, &nrefdn, op->o_tmpmemctx );
00143               if( rc != LDAP_SUCCESS ) {
00144                      send_ldap_error( op, rs, LDAP_OTHER,
00145                             "DNS SRV problem processing manageDSAit control" );
00146                      goto done;
00147               }
00148        }
00149 
00150        if( !dn_match( &nrefdn, &op->o_req_ndn ) ) {
00151               /* requested dn is subordinate */
00152 
00153               Debug( LDAP_DEBUG_TRACE,
00154                      "DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n",
00155                      op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
00156                      refdn == NULL ? "" : refdn,
00157                      NULL );
00158 
00159               rs->sr_matched = refdn;
00160               rs->sr_err = LDAP_NO_SUCH_OBJECT;
00161               send_ldap_result( op, rs );
00162               rs->sr_matched = NULL;
00163 
00164        } else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) {
00165               send_ldap_error( op, rs, LDAP_SUCCESS, NULL );
00166 
00167        } else {
00168               Entry e = { 0 };
00169               AttributeDescription *ad_objectClass
00170                      = slap_schema.si_ad_objectClass;
00171               AttributeDescription *ad_ref = slap_schema.si_ad_ref;
00172               e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val );
00173               e.e_name.bv_len = op->o_req_dn.bv_len;
00174               e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val );
00175               e.e_nname.bv_len = op->o_req_ndn.bv_len;
00176 
00177               e.e_attrs = NULL;
00178               e.e_private = NULL;
00179 
00180               attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname, NULL );
00181               attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname, NULL );
00182 
00183               if ( ad_dc ) {
00184                      char          *p;
00185                      struct berval bv;
00186 
00187                      bv.bv_val = domain;
00188 
00189                      p = strchr( bv.bv_val, '.' );
00190                                    
00191                      if ( p == bv.bv_val ) {
00192                             bv.bv_len = 1;
00193 
00194                      } else if ( p != NULL ) {
00195                             bv.bv_len = p - bv.bv_val;
00196 
00197                      } else {
00198                             bv.bv_len = strlen( bv.bv_val );
00199                      }
00200 
00201                      attr_merge_normalize_one( &e, ad_dc, &bv, NULL );
00202               }
00203 
00204               if ( ad_associatedDomain ) {
00205                      struct berval bv;
00206 
00207                      ber_str2bv( domain, 0, 0, &bv );
00208                      attr_merge_normalize_one( &e, ad_associatedDomain, &bv, NULL );
00209               }
00210 
00211               attr_merge_normalize_one( &e, ad_ref, urls, NULL );
00212 
00213               rc = test_filter( op, &e, op->oq_search.rs_filter ); 
00214 
00215               if( rc == LDAP_COMPARE_TRUE ) {
00216                      rs->sr_entry = &e;
00217                      rs->sr_attrs = op->oq_search.rs_attrs;
00218                      rs->sr_flags = REP_ENTRY_MODIFIABLE;
00219                      send_search_entry( op, rs );
00220                      rs->sr_entry = NULL;
00221                      rs->sr_attrs = NULL;
00222                      rs->sr_flags = 0;
00223               }
00224 
00225               entry_clean( &e );
00226 
00227               rs->sr_err = LDAP_SUCCESS;
00228               send_ldap_result( op, rs );
00229        }
00230 
00231        if ( refdn ) free( refdn );
00232        if ( nrefdn.bv_val ) free( nrefdn.bv_val );
00233 
00234 done:
00235        if( domain != NULL ) ch_free( domain );
00236        if( hostlist != NULL ) ch_free( hostlist );
00237        if( hosts != NULL ) ldap_charray_free( hosts );
00238        if( urls != NULL ) ber_bvarray_free( urls );
00239        return 0;
00240 }