]> git.sur5r.net Git - openldap/commitdiff
Added support for connecting to LDAP servers located using DNS
authorLuke Howard <lukeh@openldap.org>
Mon, 3 Jan 2000 02:33:22 +0000 (02:33 +0000)
committerLuke Howard <lukeh@openldap.org>
Mon, 3 Jan 2000 02:33:22 +0000 (02:33 +0000)
SRV records. Added lock around resolver library which is shared
by the DNS SRV code and the getdxbyname() code.

include/ldap.h
include/ldap_pvt.h
libraries/libldap/Makefile.in
libraries/libldap/dnssrv.c [new file with mode: 0644]
libraries/libldap/getdxbyname.c
libraries/libldap/ldap-int.h
libraries/libldap/util-int.c
libraries/libldap_r/Makefile.in

index d2f1a145e37f7cf5f77f0b23ecbc3cbc4d5da77a..322785c25da9b8ebca7b8af6c4c646d2f21d4df1 100644 (file)
@@ -554,7 +554,14 @@ LIBLDAP_F( void )
 ldap_controls_free LDAP_P((
        LDAPControl **ctrls ));
 
-  
+/*
+ * in dnssrv.c:
+ */
+LIBLDAP_F( int )
+ldap_dnssrv_init LDAP_P((
+       LDAP **ldp,
+       LDAP_CONST char *domain ));
+
 /*
  * in extended.c:
  */
index d1b48c1c2e654ac0decb823536800e00ccf20a81..a6674d702768310895ca99ee8e506b3aed852ce4 100644 (file)
 
 LDAP_BEGIN_DECL
 
+LIBLDAP_F ( int )
+ldap_pvt_domain2dn LDAP_P((
+       LDAP_CONST char *domain,
+       char **dn ));
+
 struct hostent;        /* avoid pulling in <netdb.h> */
 
 LIBLDAP_F( char * )
index 43bd9e71615257ad4e1134d1f121f7b22245b632..eb92ea5d18f38b530cb969af1b19d71d2dae8900 100644 (file)
@@ -17,7 +17,7 @@ SRCS  = bind.c open.c result.c error.c compare.c search.c \
        getdn.c getentry.c getattr.c getvalues.c addentry.c \
        request.c getdxbyname.c os-ip.c url.c charset.c \
        init.c options.c print.c string.c util-int.c schema.c \
-       charray.c digest.c tls.c dn.c os-local.c
+       charray.c digest.c tls.c dn.c os-local.c dnssrv.c
 OBJS   = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        controls.lo messages.lo references.lo extended.lo \
        modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
@@ -26,7 +26,7 @@ OBJS  = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
        request.lo getdxbyname.lo os-ip.lo url.lo charset.lo \
        init.lo options.lo print.lo string.lo util-int.lo schema.lo \
-       charray.lo digest.lo tls.lo dn.lo os-local.lo
+       charray.lo digest.lo tls.lo dn.lo os-local.lo dnssrv.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
diff --git a/libraries/libldap/dnssrv.c b/libraries/libldap/dnssrv.c
new file mode 100644 (file)
index 0000000..3b87e3c
--- /dev/null
@@ -0,0 +1,209 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+/*
+ * locate using DNS SRV records. Location code based on
+ * MIT Kerberos KDC location code.
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/param.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#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)
+{
+    char *domain, *s, *tok_r, *dn;
+    size_t loc;
+
+    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;
+       }
+       if (loc > 0) {
+           /* not first time. */
+           strcpy(dn + loc, ",");
+           loc++;
+       }
+       strcpy(dn + loc, "dc=");
+       loc += 3;
+
+       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.
+ */
+int ldap_dnssrv_init(LDAP ** ldp, LDAP_CONST char *domain)
+{
+#ifdef HAVE_RES_SEARCH
+    char *request;
+    char *dn;
+    char *hostlist = NULL;
+    LDAP *ld = NULL;
+    int rc, len, cur = 0;
+    unsigned char reply[1024];
+
+    request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
+    if (request == NULL) {
+       rc = LDAP_NO_MEMORY;
+       goto out;
+    }
+    sprintf(request, "_ldap._tcp.%s", domain);
+
+#ifdef LDAP_R_COMPILE
+    ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
+#endif
+
+    len = res_search(request, C_IN, T_SRV, reply, sizeof(reply));
+    if (len >= 0) {
+       unsigned char *p;
+       char host[1024];
+       int status;
+       u_short port;
+       int priority, weight;
+
+       /* Parse out query */
+       p = reply;
+       p += sizeof(HEADER);
+       status = dn_expand(reply, reply + len, p, host, sizeof(host));
+       if (status < 0) {
+           goto out;
+       }
+       p += status;
+       p += 4;
+
+       while (p < reply + len) {
+           int type, class, ttl, size;
+           status = dn_expand(reply, reply + len, p, host, sizeof(host));
+           if (status < 0) {
+               goto out;
+           }
+           p += status;
+           type = (p[0] << 8) | p[1];
+           p += 2;
+           class = (p[0] << 8) | p[1];
+           p += 2;
+           ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+           p += 4;
+           size = (p[0] << 8) | p[1];
+           p += 2;
+           if (type == T_SRV) {
+               int buflen;
+               status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
+               if (status < 0) {
+                   goto out;
+               }
+               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 (hostlist == NULL) {
+                   rc = LDAP_NO_MEMORY;
+                   goto out;
+               }
+               if (cur > 0) {
+                   /* not first time around */
+                   hostlist[cur++] = ' ';
+               }
+               cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
+           }
+           p += size;
+       }
+    }
+    if (hostlist == NULL) {
+       /* No LDAP servers found in DNS. */
+       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;
+
+  out:
+#ifdef LDAP_R_COMPILE
+    ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
+#endif
+
+    if (request != NULL) {
+       LDAP_FREE(request);
+    }
+    if (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 */
+}
index 602721a05ed11124989aefae3565904aeac102c6..841c3115410254d7859447b53df36bea627aee04 100644 (file)
@@ -44,6 +44,10 @@ ldap_getdxbyname( const char *domain )
 
     memset( buf, 0, sizeof( buf ));
 
+#ifdef LDAP_R_COMPILE
+    ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
+#endif
+
     if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0
                || ( dxs = decode_answer( buf, rc )) == NULL ) {
        /*
@@ -60,6 +64,10 @@ ldap_getdxbyname( const char *domain )
        }
     }
 
+#ifdef LDAP_R_COMPILE
+    ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
+#endif
+
     return( dxs );
 }
 
index 06914666c642672eac41b1a694f0f5168a403743..475c2ceb0935cf48c9d47fda89f470c2c9ffc1c3 100644 (file)
@@ -277,6 +277,11 @@ struct ldap {
 };
 #define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION )
 
+#if defined(HAVE_RES_SEARCH) && defined(LDAP_R_COMPILE)
+#include <ldap_pvt_thread.h>
+extern ldap_pvt_thread_mutex_t ldap_int_resolv_mutex;
+#endif /* HAVE_RES_SEARCH && LDAP_R_COMPILE */
+
 /*
  * in init.c
  */
index a3128e6e17b14c284e5f0c5de311ff788afa1495..158f23472f27eaa5748f3117e1a651a957140e6a 100644 (file)
@@ -64,6 +64,9 @@
 # ifndef HAVE_GETHOSTBYADDR_R
        static ldap_pvt_thread_mutex_t ldap_int_gethostbyaddr_mutex;
 # endif
+# ifdef HAVE_RES_SEARCH
+       ldap_pvt_thread_mutex_t ldap_int_resolv_mutex;
+# endif
 #endif /* LDAP_R_COMPILE */
 
 char *ldap_pvt_ctime( const time_t *tp, char *buf )
@@ -274,6 +277,10 @@ void ldap_int_utils_init( void )
        ldap_pvt_thread_mutex_init( &ldap_int_gethostbyaddr_mutex );
 #endif
 
+#ifdef HAVE_RES_SEARCH
+       ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex );
+#endif
+
        /* call other module init functions here... */
 #endif
 }
index 3454faefeeb62d79060e02296136fdfdb2825b31..43cf54d086c68b1549e0423313333ff22250494f 100644 (file)
@@ -16,7 +16,7 @@ XXSRCS        = apitest.c test.c tmpltest.c extended.c \
        getdn.c getentry.c getattr.c getvalues.c addentry.c \
        request.c getdxbyname.c os-ip.c url.c charset.c \
        init.c options.c print.c string.c util-int.c schema.c \
-       charray.c digest.c tls.c dn.c os-local.c
+       charray.c digest.c tls.c dn.c os-local.c dnssrv.c
 SRCS   = thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
        thr_pth.c thr_sleep.c thr_stub.c rdwr.c
 OBJS   = extended.lo \
@@ -29,7 +29,7 @@ OBJS  = extended.lo \
        init.lo options.lo print.lo string.lo util-int.lo schema.lo \
        thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \
        thr_pth.lo thr_sleep.lo thr_stub.lo rdwr.lo \
-       charray.lo digest.lo tls.lo dn.lo os-local.lo
+       charray.lo digest.lo tls.lo dn.lo os-local.lo dnssrv.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries