From 9cc53f2a0819301c2de7ab93197eee11e8a365e7 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 27 Aug 2004 00:07:23 +0000 Subject: [PATCH] 1707. [contrib] sdb/ldap updated to version 1.0-beta. --- CHANGES | 2 + contrib/sdb/ldap/INSTALL.ldap | 66 ++++++++++----- contrib/sdb/ldap/README.ldap | 16 +++- contrib/sdb/ldap/ldapdb.c | 147 ++++++++++++++++++++++++++++++---- 4 files changed, 190 insertions(+), 41 deletions(-) diff --git a/CHANGES b/CHANGES index e26eccc9ce..6c7870f173 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +1707. [contrib] sdb/ldap updated to version 1.0-beta. + 1706. [placeholder] rt12328 1705. [placeholder] rt12327 diff --git a/contrib/sdb/ldap/INSTALL.ldap b/contrib/sdb/ldap/INSTALL.ldap index e3801ed258..9151129625 100644 --- a/contrib/sdb/ldap/INSTALL.ldap +++ b/contrib/sdb/ldap/INSTALL.ldap @@ -1,12 +1,12 @@ -This is the INSTALL file for 0.9. See +This is the INSTALL file for 1.0-beta. See http://www.venaas.no/ldap/bind-sdb/ for updates or other information. BUILDING You need the source for BIND 9.1.0 or newer (for zone transfers you will need at least 9.1.1rc3 due to a bug). Basically you need to follow -the instructions in doc/misc/sdb, if my instructions doesn't make sense, -please have a look at that as well. +the instructions in doc/misc/sdb, if my instructions don't make sense, +please have a look at those as well. Copy ldapdb.c to bin/named and ldapdb.h to bin/named/include in the source tree. @@ -22,11 +22,19 @@ Finally you need to edit bin/named/main.c. Below where it says it says "xxdb_init();" add the line "ldapdb_init();", and finally below where it says "xxdb_clear();", add "ldapdb_clear();". -Now you should hopefully be able to build it. If you get an error -message about ldap_memfree() not being defined, you're probably -using an LDAP library with the interface defined in RFC 1823. To -build, uncomment the #define RFC1823API line near the top of ldapdb.c. +Now you should hopefully be able to build as usual; first configure +and then make. If you get an error message about ldap_memfree() not +being defined, you're probably using an LDAP library with the +interface defined in RFC 1823. To build, uncomment the "#define +LDAPDB_RFC1823API" line near the top of ldapdb.c. +Also, if you're using an LDAPv2 only server, you need to change +the line "#define LDAPDB_LDAP_VERSION 3" in ldapdb.c. Simply +replace 3 with 2. Instead of editing the file, you may define +LDAPDB_LDAP_VERSION yourself. + +If you want to use TLS, you need to uncommed the #define LDAPDB_TLS" +line near the top of ldapdb.c. CONFIGURING @@ -34,26 +42,42 @@ Before you do any configuring of LDAP stuff, please try to configure and start bind as usual to see if things work. To do anything useful, you need to store a zone in some LDAP server. -From this release on, you must use a schema called dNSZone. Note that -it relies on some attribute definitions in the Cosine schema, so that -must be included as well. The Cosine schema probably comes with your -LDAP server. You can find dNSZone and further details on how to store -the data in your LDAP server at -http://www.venaas.no/ldap/bind-sdb/ +You must use a schema called dNSZone. Note that it relies on some +attribute definitions in the Cosine schema, so that must be included +as well. The Cosine schema probably comes with your LDAP server. You +can find dNSZone and further details on how to store the data in your +LDAP server at http://www.venaas.no/ldap/bind-sdb/ -For an example, have a look at my venaas.com zone. Try a subtree search -for objectClass=* at -ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no +To make BIND use a zone stored in LDAP, you will have to put something +like this in named.conf: -To use it with BIND, I've added the following to named.conf: zone "venaas.com" { type master; - database "ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 172800"; + database "ldap ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 172800"; }; When doing lookups BIND will do a sub-tree search below the base in the URL. The number 172800 is the TTL which will be used for all entries that -haven't got the dNSTTL attribute. It is also possible to add an filter to -the URL, say ldap://host/base???(o=internal) +haven't got the dNSTTL attribute. It is also possible to add a filter to +the URL, say "ldap://host/base???(o=internal)". -Stig Venaas 2002-04-17 +Version 1.0 also has support for simple LDAP bind, that is, binding to +LDAP using plain text authentication. The bind dn and password is coded +into the URL as extensions, according to RFC 2255. If you want simple +bind with say dn "cn=Manager,dc=venaas,dc=no" and password "secret", the +URL will be something like this: + +ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no????!bindname=cn=Manager%2cdc=venaas%2cdc=no,!x-bindpw=secret + +This URL may also include a filter part if you need it. Note that in +the bind dn, "," is hex-escaped as "%2c". This is necessary since "," +is the separator between the extension elements. The "!" in front of +"bindname" and "x-bindpw" can be omitted if you prefer. "x-bindpw" is +not standardized, but it's used by several other LDAP applications. See +RFC 2255 for details. + +Finally, if you enabled TLS when compiling, you can also use TLS if +you like. To do this you use the extension "x-tls", e.g. +ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no????!bindname=cn=Manager%2cdc=venaas%2cdc=no,!x-bindpw=secret,x-tls + +Stig Venaas 2004-08-15 diff --git a/contrib/sdb/ldap/README.ldap b/contrib/sdb/ldap/README.ldap index 10d6587255..b4ea18ab46 100644 --- a/contrib/sdb/ldap/README.ldap +++ b/contrib/sdb/ldap/README.ldap @@ -1,7 +1,15 @@ This is an attempt at an LDAP back-end for BIND 9 using the new simplified -database interface "sdb". This is the nineth release (0.9) and seems to -be pretty stable. Note that since version 0.4 a new schema is used. -It is not backwards compatible with versions before 0.4. +database interface "sdb". This is release 1.0-beta and should be pretty +stable. Note that since version 0.4 a new schema is used. It is not +backwards compatible with versions before 0.4. + +1.0-beta fixes a large memory leak. An extension x-tls for enabling TLS +has been added. + +1.0-alpha uses LDAPv3 by default and also supports LDAP simple bind. That +is, one can use plain text password for authentication. The bind dn and +password is coded into the URL using extensions bindname and x-bindpw +per RFC 2255. In 0.9 the code has been cleaned up a bit and should be slightly faster than previous versions. It also fixes an error with zone transfers (AXFR) @@ -37,4 +45,4 @@ contact me. See also http://www.venaas.no/ldap/bind-sdb/ for information. See INSTALL for how to build, install and use. -Stig Venaas 2001-12-29 +Stig Venaas 2004-08-15 diff --git a/contrib/sdb/ldap/ldapdb.c b/contrib/sdb/ldap/ldapdb.c index ca2866b9a6..ed124c07ea 100644 --- a/contrib/sdb/ldap/ldapdb.c +++ b/contrib/sdb/ldap/ldapdb.c @@ -1,18 +1,31 @@ /* - * ldapdb.c version 0.9 + * ldapdb.c version 1.0-beta * - * Copyright (C) 2002 Stig Venaas + * Copyright (C) 2002, 2004 Stig Venaas * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. + * + * Contributors: Jeremy C. McDermond */ +/* + * If you want to use TLS, uncomment the define below + */ +/* #define LDAPDB_TLS */ + /* * If you are using an old LDAP API uncomment the define below. Only do this * if you know what you're doing or get compilation errors on ldap_memfree(). + * This also forces LDAPv2. */ -/* #define RFC1823API */ +/* #define LDAPDB_RFC1823API */ + +/* Using LDAPv3 by default, change this if you want v2 */ +#ifndef LDAPDB_LDAP_VERSION +#define LDAPDB_LDAP_VERSION 3 +#endif #include @@ -55,6 +68,11 @@ struct ldapdb_data { char *filterone; int filteronelen; char *filtername; + char *bindname; + char *bindpw; +#ifdef LDAPDB_TLS + int tls; +#endif }; /* used by ldapdb_getconn */ @@ -160,7 +178,7 @@ ldapdb_getconn(struct ldapdb_data *data) conndata = malloc(sizeof(*conndata)); if (conndata == NULL) return (NULL); - (char *)conndata->index = data->hostport; + conndata->index = data->hostport; conndata->size = strlen(data->hostport); conndata->data = NULL; ldapdb_insert((struct ldapdb_entry **)&threaddata->data, @@ -173,12 +191,27 @@ ldapdb_getconn(struct ldapdb_data *data) static void ldapdb_bind(struct ldapdb_data *data, LDAP **ldp) { +#ifndef LDAPDB_RFC1823API + const int ver = LDAPDB_LDAP_VERSION; +#endif + if (*ldp != NULL) ldap_unbind(*ldp); *ldp = ldap_open(data->hostname, data->portno); if (*ldp == NULL) return; - if (ldap_simple_bind_s(*ldp, NULL, NULL) != LDAP_SUCCESS) { + +#ifndef LDAPDB_RFC1823API + ldap_set_option(*ldp, LDAP_OPT_PROTOCOL_VERSION, &ver); +#endif + +#ifdef LDAPDB_TLS + if (data->tls) { + ldap_start_tls_s(*ldp, NULL, NULL); + } +#endif + + if (ldap_simple_bind_s(*ldp, data->bindname, data->bindpw) != LDAP_SUCCESS) { ldap_unbind(*ldp); *ldp = NULL; } @@ -191,9 +224,9 @@ ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata) isc_result_t result = ISC_R_NOTFOUND; LDAP **ldp; LDAPMessage *res, *e; - char *fltr, *a, **vals, **names = NULL; + char *fltr, *a, **vals = NULL, **names = NULL; char type[64]; -#ifdef RFC1823API +#ifdef LDAPDB_RFC1823API void *ptr; #else BerElement *ptr; @@ -278,7 +311,7 @@ ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata) *s = toupper(*s); s = strstr(a, "RECORD"); if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) { -#ifndef RFC1823API +#ifndef LDAPDB_RFC1823API ldap_memfree(a); #endif continue; @@ -302,7 +335,7 @@ ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "LDAP sdb zone '%s': dns_sdb_put... failed for %s", zone, vals[i]); ldap_value_free(vals); -#ifndef RFC1823API +#ifndef LDAPDB_RFC1823API ldap_memfree(a); if (ptr != NULL) ber_free(ptr, 0); @@ -315,21 +348,23 @@ ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata) } ldap_value_free(vals); } -#ifndef RFC1823API +#ifndef LDAPDB_RFC1823API ldap_memfree(a); #endif } -#ifndef RFC1823API +#ifndef LDAPDB_RFC1823API if (ptr != NULL) ber_free(ptr, 0); #endif if (name == NULL) ldap_value_free(names); - /* cleanup this result */ + /* free this result */ ldap_msgfree(res); } + /* free final result */ + ldap_msgfree(res); return (result); } @@ -371,7 +406,56 @@ unhex(char *in) return in; } +/* returns 0 for ok, -1 for bad syntax, -2 for unknown critical extension */ +static int +parseextensions(char *extensions, struct ldapdb_data *data) +{ + char *s, *next, *name, *value; + int critical; + while (extensions != NULL) { + s = strchr(extensions, ','); + if (s != NULL) { + *s++ = '\0'; + next = s; + } else { + next = NULL; + } + + if (*extensions != '\0') { + s = strchr(extensions, '='); + if (s != NULL) { + *s++ = '\0'; + value = *s != '\0' ? s : NULL; + } else { + value = NULL; + } + name = extensions; + + critical = *name == '!'; + if (critical) { + name++; + } + if (*name == '\0') { + return -1; + } + + if (!strcasecmp(name, "bindname")) { + data->bindname = value; + } else if (!strcasecmp(name, "x-bindpw")) { + data->bindpw = value; +#ifdef LDAPDB_TLS + } else if (!strcasecmp(name, "x-tls")) { + data->tls = value == NULL || !strcasecmp(value, "true"); +#endif + } else if (critical) { + return -2; + } + } + extensions = next; + } + return 0; +} static void free_data(struct ldapdb_data *data) @@ -393,7 +477,7 @@ ldapdb_create(const char *zone, int argc, char **argv, void *driverdata, void **dbdata) { struct ldapdb_data *data; - char *s, *filter = NULL; + char *s, *filter = NULL, *extensions = NULL; int defaultttl; UNUSED(driverdata); @@ -439,6 +523,15 @@ ldapdb_create(const char *zone, int argc, char **argv, s = strchr(s, '?'); if (s != NULL) { *s++ = '\0'; + /* extensions */ + extensions = s; + s = strchr(s, '?'); + if (s != NULL) { + *s++ = '\0'; + } + if (*extensions == '\0') { + extensions = NULL; + } } if (*filter == '\0') { filter = NULL; @@ -449,15 +542,37 @@ ldapdb_create(const char *zone, int argc, char **argv, if (*data->base == '\0') { data->base = NULL; } + } - if ((data->base != NULL && unhex(data->base) == NULL) || (filter != NULL && unhex(filter) == NULL)) { + /* parse extensions */ + if (extensions != NULL) { + int err; + + err = parseextensions(extensions, data); + if (err < 0) { + /* err should be -1 or -2 */ free_data(data); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "LDAP sdb zone '%s': bad hex values", zone); + if (err == -1) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "LDAP sdb zone '%s': URL: extension syntax error", zone); + } else if (err == -2) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "LDAP sdb zone '%s': URL: unknown critical extension", zone); + } return (ISC_R_FAILURE); } } + if ((data->base != NULL && unhex(data->base) == NULL) || + (filter != NULL && unhex(filter) == NULL) || + (data->bindname != NULL && unhex(data->bindname) == NULL) || + (data->bindpw != NULL && unhex(data->bindpw) == NULL)) { + free_data(data); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "LDAP sdb zone '%s': URL: bad hex values", zone); + return (ISC_R_FAILURE); + } + /* compute filterall and filterone once and for all */ if (filter == NULL) { data->filteralllen = strlen(zone) + strlen("(zoneName=)") + 1;