Added support for connecting to LDAP servers located using DNS

SRV records. Added lock around resolver library which is shared
by the DNS SRV code and the getdxbyname() code.
This commit is contained in:
Luke Howard 2000-01-03 02:33:22 +00:00
parent 57b62dc7d4
commit a466a64318
8 changed files with 246 additions and 5 deletions

View file

@ -554,7 +554,14 @@ LIBLDAP_F( void )
ldap_controls_free LDAP_P(( ldap_controls_free LDAP_P((
LDAPControl **ctrls )); LDAPControl **ctrls ));
/*
* in dnssrv.c:
*/
LIBLDAP_F( int )
ldap_dnssrv_init LDAP_P((
LDAP **ldp,
LDAP_CONST char *domain ));
/* /*
* in extended.c: * in extended.c:
*/ */

View file

@ -21,6 +21,11 @@
LDAP_BEGIN_DECL LDAP_BEGIN_DECL
LIBLDAP_F ( int )
ldap_pvt_domain2dn LDAP_P((
LDAP_CONST char *domain,
char **dn ));
struct hostent; /* avoid pulling in <netdb.h> */ struct hostent; /* avoid pulling in <netdb.h> */
LIBLDAP_F( char * ) LIBLDAP_F( char * )

View 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 \ getdn.c getentry.c getattr.c getvalues.c addentry.c \
request.c getdxbyname.c os-ip.c url.c charset.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 \ 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 \ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
controls.lo messages.lo references.lo extended.lo \ controls.lo messages.lo references.lo extended.lo \
modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.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 \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
request.lo getdxbyname.lo os-ip.lo url.lo charset.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 \ 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_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries LDAP_LIBDIR= ../../libraries

209
libraries/libldap/dnssrv.c Normal file
View file

@ -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 */
}

View file

@ -44,6 +44,10 @@ ldap_getdxbyname( const char *domain )
memset( buf, 0, sizeof( buf )); 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 if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0
|| ( dxs = decode_answer( buf, rc )) == NULL ) { || ( 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 ); return( dxs );
} }

View file

@ -277,6 +277,11 @@ struct ldap {
}; };
#define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION ) #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 * in init.c
*/ */

View file

@ -64,6 +64,9 @@
# ifndef HAVE_GETHOSTBYADDR_R # ifndef HAVE_GETHOSTBYADDR_R
static ldap_pvt_thread_mutex_t ldap_int_gethostbyaddr_mutex; static ldap_pvt_thread_mutex_t ldap_int_gethostbyaddr_mutex;
# endif # endif
# ifdef HAVE_RES_SEARCH
ldap_pvt_thread_mutex_t ldap_int_resolv_mutex;
# endif
#endif /* LDAP_R_COMPILE */ #endif /* LDAP_R_COMPILE */
char *ldap_pvt_ctime( const time_t *tp, char *buf ) 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 ); ldap_pvt_thread_mutex_init( &ldap_int_gethostbyaddr_mutex );
#endif #endif
#ifdef HAVE_RES_SEARCH
ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex );
#endif
/* call other module init functions here... */ /* call other module init functions here... */
#endif #endif
} }

View file

@ -16,7 +16,7 @@ XXSRCS = apitest.c test.c tmpltest.c extended.c \
getdn.c getentry.c getattr.c getvalues.c addentry.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \
request.c getdxbyname.c os-ip.c url.c charset.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 \ 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 \ 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 thr_pth.c thr_sleep.c thr_stub.c rdwr.c
OBJS = extended.lo \ OBJS = extended.lo \
@ -29,7 +29,7 @@ OBJS = extended.lo \
init.lo options.lo print.lo string.lo util-int.lo schema.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_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 \ 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_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries LDAP_LIBDIR= ../../libraries