X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fdnssrv.c;h=16b15447cac2bfefc717104998aa5b065cb6fb87;hb=7164c4c66215da39f03e353a9c72eba408abddbf;hp=3b87e3c9ccf7950eaefcb4f5cdc2f46f5565acaa;hpb=a466a643189d7a659da1d8331c53a9d54a021ab8;p=openldap
diff --git a/libraries/libldap/dnssrv.c b/libraries/libldap/dnssrv.c
index 3b87e3c9cc..16b15447ca 100644
--- a/libraries/libldap/dnssrv.c
+++ b/libraries/libldap/dnssrv.c
@@ -1,12 +1,21 @@
/* $OpenLDAP$ */
-/*
- * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software .
+ *
+ * Copyright 1998-2011 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * .
*/
/*
- * locate using DNS SRV records. Location code based on
- * MIT Kerberos KDC location code.
+ * locate LDAP servers using DNS SRV records.
+ * Location code based on MIT Kerberos KDC location code.
*/
#include "portable.h"
@@ -28,93 +37,209 @@
#include
#endif
-/* Sometimes this is not defined. */
-#ifndef T_SRV
-#define T_SRV 33
-#endif /* T_SRV */
-
-int ldap_pvt_domain2dn(LDAP_CONST char *domain_in, char **dnp)
+int ldap_dn2domain(
+ LDAP_CONST char *dn_in,
+ char **domainp)
{
- char *domain, *s, *tok_r, *dn;
- size_t loc;
+ int i, j;
+ char *ndomain;
+ LDAPDN dn = NULL;
+ LDAPRDN rdn = NULL;
+ LDAPAVA *ava = NULL;
+ struct berval domain = BER_BVNULL;
+ static const struct berval DC = BER_BVC("DC");
+ static const struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25");
- if (domain_in == NULL || dnp == NULL) {
- return LDAP_NO_MEMORY;
- }
- domain = LDAP_STRDUP(domain_in);
- if (domain == NULL) {
- return LDAP_NO_MEMORY;
- }
- dn = NULL;
- loc = 0;
-
- for (s = ldap_pvt_strtok(domain, ".", &tok_r);
- s != NULL;
- s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
- size_t len = strlen(s);
-
- dn = (char *) LDAP_REALLOC(dn, loc + len + 4);
- if (dn == NULL) {
- LDAP_FREE(domain);
- return LDAP_NO_MEMORY;
+ assert( dn_in != NULL );
+ assert( domainp != NULL );
+
+ *domainp = NULL;
+
+ if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) {
+ return -2;
}
- if (loc > 0) {
- /* not first time. */
- strcpy(dn + loc, ",");
- loc++;
+
+ if( dn ) for( i=0; dn[i] != NULL; i++ ) {
+ rdn = dn[i];
+
+ for( j=0; rdn[j] != NULL; j++ ) {
+ ava = rdn[j];
+
+ if( rdn[j+1] == NULL &&
+ (ava->la_flags & LDAP_AVA_STRING) &&
+ ava->la_value.bv_len &&
+ ( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0
+ || ber_bvcmp( &ava->la_attr, &DCOID ) == 0 ) )
+ {
+ if( domain.bv_len == 0 ) {
+ ndomain = LDAP_REALLOC( domain.bv_val,
+ ava->la_value.bv_len + 1);
+
+ if( ndomain == NULL ) {
+ goto return_error;
+ }
+
+ domain.bv_val = ndomain;
+
+ AC_MEMCPY( domain.bv_val, ava->la_value.bv_val,
+ ava->la_value.bv_len );
+
+ domain.bv_len = ava->la_value.bv_len;
+ domain.bv_val[domain.bv_len] = '\0';
+
+ } else {
+ ndomain = LDAP_REALLOC( domain.bv_val,
+ ava->la_value.bv_len + sizeof(".") + domain.bv_len );
+
+ if( ndomain == NULL ) {
+ goto return_error;
+ }
+
+ domain.bv_val = ndomain;
+ domain.bv_val[domain.bv_len++] = '.';
+ AC_MEMCPY( &domain.bv_val[domain.bv_len],
+ ava->la_value.bv_val, ava->la_value.bv_len );
+ domain.bv_len += ava->la_value.bv_len;
+ domain.bv_val[domain.bv_len] = '\0';
+ }
+ } else {
+ domain.bv_len = 0;
+ }
+ }
}
- strcpy(dn + loc, "dc=");
- loc += 3;
- strcpy(dn + loc, s);
- loc += len;
- }
- LDAP_FREE(domain);
+ if( domain.bv_len == 0 && domain.bv_val != NULL ) {
+ LDAP_FREE( domain.bv_val );
+ domain.bv_val = NULL;
+ }
- *dnp = dn;
+ ldap_dnfree( dn );
+ *domainp = domain.bv_val;
+ return 0;
- return LDAP_SUCCESS;
+return_error:
+ ldap_dnfree( dn );
+ LDAP_FREE( domain.bv_val );
+ return -1;
+}
+
+int ldap_domain2dn(
+ LDAP_CONST char *domain_in,
+ char **dnp)
+{
+ char *domain, *s, *tok_r, *dn, *dntmp;
+ size_t loc;
+
+ assert( domain_in != NULL );
+ assert( dnp != NULL );
+
+ domain = LDAP_STRDUP(domain_in);
+ if (domain == NULL) {
+ return LDAP_NO_MEMORY;
+ }
+ dn = NULL;
+ loc = 0;
+
+ for (s = ldap_pvt_strtok(domain, ".", &tok_r);
+ s != NULL;
+ s = ldap_pvt_strtok(NULL, ".", &tok_r))
+ {
+ size_t len = strlen(s);
+
+ dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
+ if (dntmp == NULL) {
+ if (dn != NULL)
+ LDAP_FREE(dn);
+ LDAP_FREE(domain);
+ return LDAP_NO_MEMORY;
+ }
+
+ dn = dntmp;
+
+ if (loc > 0) {
+ /* not first time. */
+ strcpy(dn + loc, ",");
+ loc++;
+ }
+ strcpy(dn + loc, "dc=");
+ loc += sizeof("dc=")-1;
+
+ strcpy(dn + loc, s);
+ loc += len;
+ }
+
+ LDAP_FREE(domain);
+ *dnp = dn;
+ return LDAP_SUCCESS;
}
/*
- * Lookup LDAP servers for domain (using the DNS
- * SRV record _ldap._tcp.domain), set the default
- * base using an algorithmic mapping of the domain,
- * and return a session.
+ * Lookup and return LDAP servers for domain (using the DNS
+ * SRV record _ldap._tcp.domain).
*/
-int ldap_dnssrv_init(LDAP ** ldp, LDAP_CONST char *domain)
+int ldap_domain2hostlist(
+ LDAP_CONST char *domain,
+ char **list )
{
-#ifdef HAVE_RES_SEARCH
+#ifdef HAVE_RES_QUERY
+#define DNSBUFSIZ (64*1024)
char *request;
- char *dn;
char *hostlist = NULL;
- LDAP *ld = NULL;
int rc, len, cur = 0;
- unsigned char reply[1024];
+ unsigned char reply[DNSBUFSIZ];
+
+ assert( domain != NULL );
+ assert( list != NULL );
+
+ if( *domain == '\0' ) {
+ return LDAP_PARAM_ERROR;
+ }
request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
if (request == NULL) {
- rc = LDAP_NO_MEMORY;
- goto out;
+ return LDAP_NO_MEMORY;
}
sprintf(request, "_ldap._tcp.%s", domain);
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
-#endif
+ LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex);
+
+ rc = LDAP_UNAVAILABLE;
+#ifdef NS_HFIXEDSZ
+ /* Bind 8/9 interface */
+ len = res_query(request, ns_c_in, ns_t_srv, reply, sizeof(reply));
+# ifndef T_SRV
+# define T_SRV ns_t_srv
+# endif
+#else
+ /* Bind 4 interface */
+# ifndef T_SRV
+# define T_SRV 33
+# endif
- len = res_search(request, C_IN, T_SRV, reply, sizeof(reply));
+ len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
+#endif
if (len >= 0) {
unsigned char *p;
- char host[1024];
+ char host[DNSBUFSIZ];
int status;
u_short port;
- int priority, weight;
+ /* int priority, weight; */
/* Parse out query */
p = reply;
+
+#ifdef NS_HFIXEDSZ
+ /* Bind 8/9 interface */
+ p += NS_HFIXEDSZ;
+#elif defined(HFIXEDSZ)
+ /* Bind 4 interface w/ HFIXEDSZ */
+ p += HFIXEDSZ;
+#else
+ /* Bind 4 interface w/o HFIXEDSZ */
p += sizeof(HEADER);
+#endif
+
status = dn_expand(reply, reply + len, p, host, sizeof(host));
if (status < 0) {
goto out;
@@ -143,12 +268,17 @@ int ldap_dnssrv_init(LDAP ** ldp, LDAP_CONST char *domain)
if (status < 0) {
goto out;
}
- priority = (p[0] << 8) | p[1];
- weight = (p[2] << 8) | p[3];
+ /* ignore priority and weight for now */
+ /* priority = (p[0] << 8) | p[1]; */
+ /* weight = (p[2] << 8) | p[3]; */
port = (p[4] << 8) | p[5];
- buflen = strlen(host) + /* :XXXXX\0 */ 7;
- hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
+ if ( port == 0 || host[ 0 ] == '\0' ) {
+ goto add_size;
+ }
+
+ buflen = strlen(host) + STRLENOF(":65355 ");
+ hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen + 1);
if (hostlist == NULL) {
rc = LDAP_NO_MEMORY;
goto out;
@@ -157,8 +287,9 @@ int ldap_dnssrv_init(LDAP ** ldp, LDAP_CONST char *domain)
/* not first time around */
hostlist[cur++] = ' ';
}
- cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
+ cur += sprintf(&hostlist[cur], "%s:%hu", host, port);
}
+add_size:;
p += size;
}
}
@@ -167,43 +298,21 @@ int ldap_dnssrv_init(LDAP ** ldp, LDAP_CONST char *domain)
rc = LDAP_UNAVAILABLE;
goto out;
}
- rc = ldap_create(&ld);
- if (rc != LDAP_SUCCESS) {
- goto out;
- }
- rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, hostlist);
- if (rc != LDAP_SUCCESS) {
- goto out;
- }
- rc = ldap_pvt_domain2dn(domain, &dn);
- if (rc != LDAP_SUCCESS) {
- goto out;
- }
- if (ld->ld_options.ldo_defbase != NULL) {
- LDAP_FREE(ld->ld_options.ldo_defbase);
- }
- ld->ld_options.ldo_defbase = dn;
-
- *ldp = ld;
rc = LDAP_SUCCESS;
+ *list = hostlist;
out:
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
-#endif
+ LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex);
if (request != NULL) {
LDAP_FREE(request);
}
- if (hostlist != NULL) {
+ if (rc != LDAP_SUCCESS && hostlist != NULL) {
LDAP_FREE(hostlist);
}
- if (rc != LDAP_SUCCESS && ld != NULL) {
- ldap_ld_free(ld, 1, NULL, NULL);
- }
return rc;
#else
return LDAP_NOT_SUPPORTED;
-#endif /* HAVE_RES_SEARCH */
+#endif /* HAVE_RES_QUERY */
}