mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
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:
parent
57b62dc7d4
commit
a466a64318
8 changed files with 246 additions and 5 deletions
|
|
@ -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:
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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 * )
|
||||||
|
|
|
||||||
|
|
@ -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
209
libraries/libldap/dnssrv.c
Normal 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 */
|
||||||
|
}
|
||||||
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue