/* * Copyright (C) 1997-2003 Luke Howard. This file is part of the nss_ldap library. Contributed by Luke Howard, , 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 #include #include #include #include #include #include #include #include #include #ifdef HAVE_LBER_H #include #endif #ifdef HAVE_LDAP_H #include #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; }