/*
* Copyright (C) 1997-2003 Luke Howard. This file is part of the nss_ldap library. Contributed by Luke Howard, <lukeh@padl.com>, 1997. (The author maintains a non-exclusive licence to distribute this file under their own conditions.)
*
* The nss_ldap library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
*
* The nss_ldap library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License along with the nss_ldap library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Support DNS SRV records. I look up the SRV record for _ldap._tcp.gnu.org. and build the DN DC=gnu,DC=org. Thanks to Assar & co for resolve.[ch].
*/
/*static char rcsId[] =
"$Id: dnsconfig.c,v 1.1.1.1 2004/05/06 07:26:16 bushman Exp $";*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>
#include <netdb.h>
#include <syslog.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <string.h>
#ifdef HAVE_LBER_H
#include <lber.h>
#endif
#ifdef HAVE_LDAP_H
#include <ldap.h>
#endif
#ifndef HAVE_SNPRINTF
#include "snprintf.h"
#endif
#include "ldap-nss.h"
#include "globals.h"
#include "util.h"
#include "resolve.h"
#include "dnsconfig.h"
/* map gnu.org into DC=gnu,DC=org */
NSS_STATUS
_nss_ldap_getdnsdn(char *src_domain,
char **rval, char **buffer, size_t * buflen)
{
char *p;
int len = 0;
#ifdef HAVE_STRTOK_R
char *st = NULL;
#endif
char *bptr;
char *domain, *domain_copy;
/*
* we need to take a copy of domain, because strtok() modifies it in place. Bad.
*/
domain_copy = strdup(src_domain);
if (domain_copy == NULL) {
return NSS_TRYAGAIN;
}
domain = domain_copy;
bptr = *rval = *buffer;
**rval = '\0';
#ifndef HAVE_STRTOK_R
while ((p = strtok(domain, ".")))
#else
while ((p = strtok_r(domain, ".", &st)))
#endif
{
len = strlen(p);
if (*buflen < (size_t) (len + DC_ATTR_AVA_LEN + 1 /* D C = [,|\0] */ )) {
free(domain_copy);
return NSS_TRYAGAIN;
}
if (domain == NULL) {
strcpy(bptr, ",");
bptr++;
} else {
domain = NULL;
}
strcpy(bptr, DC_ATTR_AVA);
bptr += DC_ATTR_AVA_LEN;
strcpy(bptr, p);
bptr += len; /* don't include comma */
*buffer += len + DC_ATTR_AVA_LEN + 1;
*buflen -= len + DC_ATTR_AVA_LEN + 1;
}
if (bptr != NULL) {
(*rval)[bptr - *rval] = '\0';
}
free(domain_copy);
return NSS_SUCCESS;
}
NSS_STATUS
_nss_ldap_readconfigfromdns(ldap_config_t ** presult,
char *buffer, size_t buflen)
{
NSS_STATUS stat = NSS_SUCCESS;
struct dns_reply *r;
struct resource_record *rr;
char domain[MAXHOSTNAMELEN + 1];
ldap_config_t *result = NULL;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
return NSS_UNAVAIL;
}
snprintf(domain, sizeof(domain), "_ldap._tcp.%s.", _res.defdname);
r = dns_lookup(domain, "srv");
if (r == NULL) {
return NSS_NOTFOUND;
}
/* XXX sort by priority */
for (rr = r->head; rr != NULL; rr = rr->next) {
if (rr->type == T_SRV) {
int len;
ldap_config_t *last = result;
if (bytesleft(buffer, buflen, ldap_config_t *) <
sizeof(ldap_config_t)) {
dns_free_data(r);
return NSS_TRYAGAIN;
}
align(buffer, buflen, ldap_config_t *);
result = (ldap_config_t *) buffer;
buffer += sizeof(ldap_config_t);
buflen -= sizeof(ldap_config_t);
_nss_ldap_init_config(result);
if (last != NULL) {
last->ldc_next = result;
} else {
*presult = result;
}
len = strlen(rr->u.srv->target);
if (buflen < (size_t) (len + 1)) {
dns_free_data(r);
return NSS_TRYAGAIN;
}
/* Server Host */
memcpy(buffer, rr->u.srv->target, len + 1);
result->ldc_host = buffer;
buffer += len + 1;
buflen -= len + 1;
/* Port */
result->ldc_port = rr->u.srv->port;
#ifdef LDAPS_PORT
/* Hack: if the port is the registered SSL port, enable SSL. */
if (result->ldc_port == LDAPS_PORT) {
result->ldc_ssl_on = SSL_LDAPS;
}
#endif /* SSL */
/* DN */
stat = _nss_ldap_getdnsdn(_res.defdname,
&result->ldc_base, &buffer, &buflen);
if (stat != NSS_SUCCESS) {
dns_free_data(r);
return stat;
}
}
}
dns_free_data(r);
stat = NSS_SUCCESS;
return stat;
}
syntax highlighted by Code2HTML, v. 0.9.1