diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/smap.texi | 103 | ||||
-rw-r--r-- | modules/ldap/ldap.c | 136 |
3 files changed, 188 insertions, 55 deletions
@@ -1,4 +1,4 @@ -Smap NEWS -- history of user-visible changes. 2011-03-09 +Smap NEWS -- history of user-visible changes. 2014-08-24 Copyright (C) 2006-2010, 2014 Sergey Poznyakoff See the end of file for copying conditions. @@ -7,6 +7,8 @@ Please send Smap bug reports to <gray+smap@gnu.org.ua> Version 1.1.90, Git +* new module: ldap + Version 1.1, 2010-07-03 diff --git a/doc/smap.texi b/doc/smap.texi index 08af20b..4bc5325 100644 --- a/doc/smap.texi +++ b/doc/smap.texi @@ -113,6 +113,7 @@ Modules Shipped with Smap * guile:: * mysql:: * postgres:: +* ldap:: * sed:: Mailutils @@ -1661,6 +1662,7 @@ in detail in the following sections. * guile:: * mysql:: * postgres:: +* ldap:: * sed:: @end menu @@ -2380,7 +2382,7 @@ attempts to use a globally defined connection. a set of @dfn{smap reply templates} to use. When dispatched a sockmap query, the database expands the SQL query template using the actual values of @samp{$@{map@}} (the map name) and -@samp{$@{key@}} (the key value) and sends the expanded query to the | +@samp{$@{key@}} (the key value) and sends the expanded query to the MySQL server. If the server responds with a non-empty set of tuples, the @dfn{positive reply template} is expanded and the result is used as a response. Otherwise, if the query produced an empty set, the @@ -2709,6 +2711,105 @@ query. The @var{template} may refer to the variables described in Default value is @samp{NOTFOUND}. @end table +@node ldap +@section ldap +@cindex ldap module +@cindex @acronym{LDAP} + The @command{ldap} module provides interface to the Lightweight +Directory Access Protocol. The configuration is similar to that +of SQL modules: + + The @acronym{LDAP} parameters may be configured either globally, when +loading the module, or locally, when defining a smap database. If a +database definition lacks some configuration statements, it looks them +up in a global definition. + + Each database has a @dfn{filter template} and up to three @dfn{smap +reply templates}. When dispatched a sockmap query, the database +expands the filter template using the actual values of @samp{$@{map@}} +(the map name) and @samp{$@{key@}} (the key value) and uses the +obtained filter to query the @acronym{LDAP} server. If the server +responds with a non-empty set of tuples, the @dfn{positive reply +template} is expanded and the result is used as a response. +Otherwise, if the query produced an empty set, the smap database uses +the @dfn{negative reply template} to create the response. + +@menu +* LDAP Configuration:: +* LDAP Filter and SMAP Replies:: +@end menu + +@node LDAP Configuration +@subsection LDAP Configuration + +@flindex /etc/ldap.conf +The @acronym{LDAP} configuration is read from the file +@file{/etc/ldap.conf} and from module and database command line. The +settings from the command line override those from +@file{/etc/ldap.conf}. Alternative configuration file can be +specified using the @option{config-file} option. + +@table @option +@kwindex config-file +@item config-file=@var{file} + Read configuration from file @var{file} instead of @file{/etc/ldap.conf}. + +@kwindex tls-cacert +@kwindex tls_cacert +@item tls-cacert=@var{file} +@itemx tls_cacert=@var{file} + Read TLS Certificate Authority from @var{file}. + +@kwindex uri +@item uri=@var{string} + Specifies the URI of LDAP server to connect to. Multiple URIs are +allowed. Each URI is @samp{@var{scheme}://[@var{name}[:@var{port}]]}. +The @var{scheme} part is one of: @samp{ldap}, meaning LDAP over TCP +(default port 389), @samp{ldaps}, meaning LDAP over SSL (TLS) (default +port 636), or @samp{ldapi}, meaning LDAP over UNIX socket. For +@samp{ldap} and @samp{ldaps}, @var{name} is the host name or IP +address of the remote server. Optional @var{port} specifies the TCP +port to use instead of the default one. For @samp{ldapi}, @var{name} +is the pathname of the UNIX socket and @var{port} is not used. Note, +that directory separators must be URL-encoded (using @samp{%2F} +instead of @samp{/}). + +@kwindex base +@item base=@var{string} + Sets the default base DN for ldap operations. The base must be +specified as a Distinguished Name in LDAP format. + +@kwindex binddn +@item binddn=@var{dn} + The DN to bind as. + +@kwindex bindpw +@item bindpw=@var{password} + Password for @code{binddn}. + +@kwindex bindpwfile +@item bindpwfile=@var{file} + Read password from @var{file}. This is a safer alternative to +@option{bindpw}. +@end table + +@node LDAP Filter and SMAP Replies +@subsection LDAP Filter and SMAP Replies + +@table @option +@kwindex filter +@item filter=@var{pattern} + +@kwindex positive-reply +@item positive-reply=@var{reply} + +@kwindex negative-reply +@item negative-reply=@var{reply} + +@kwindex onerror-reply +@item onerror-reply=@var{reply} +@end table + @node sed @section Sed @cindex sed module diff --git a/modules/ldap/ldap.c b/modules/ldap/ldap.c index bb382eb..7935236 100644 --- a/modules/ldap/ldap.c +++ b/modules/ldap/ldap.c @@ -72,7 +72,8 @@ struct ldap_db { LDAP *ldap; }; -static struct ldap_conf def_conf; +static struct ldap_conf dfl_conf; +static char dfl_config_file[] = "/etc/ldap.conf"; static char dfl_positive_reply[] = "OK"; static char dfl_negative_reply[] = "NOTFOUND"; static char dfl_onerror_reply[] = "NOTFOUND"; @@ -253,49 +254,86 @@ readconf(struct smap_option const *opt, const char *val, char **errmsg) *errmsg = "parse error"; return rc; } - + +#define MKOPT_DEFAULT 0 +#define MKOPT_REUSE 0x01 +#define MKOPT_RESET 0x02 static int -mod_ldap_init(int argc, char **argv) +make_options(struct ldap_conf *conf, int flags, + struct smap_option **ret_options) { - struct smap_option init_option[] = { + static struct smap_option init_option[] = { { SMAP_OPTSTR(config-file), smap_opt_null, - &init_option, 0, readconf }, - { SMAP_OPTSTR(ssl-ca), smap_opt_string, - &def_conf.cacert }, - { SMAP_OPTSTR(tls-ca), smap_opt_string, - &def_conf.cacert }, + (void*)offsetof(struct ldap_conf, config_file) }, + { SMAP_OPTSTR(tls_cacert), smap_opt_string, + (void*)offsetof(struct ldap_conf, cacert) }, + { SMAP_OPTSTR(tls-cacert), smap_opt_string, + (void*)offsetof(struct ldap_conf, cacert) }, { SMAP_OPTSTR(uri), smap_opt_string, - &def_conf.uri }, + (void*)offsetof(struct ldap_conf, uri) }, { SMAP_OPTSTR(base), smap_opt_string, - &def_conf.base }, + (void*)offsetof(struct ldap_conf, base) }, { SMAP_OPTSTR(filter), smap_opt_string, - &def_conf.filter }, + (void*)offsetof(struct ldap_conf, filter) }, { SMAP_OPTSTR(binddn), smap_opt_string, - &def_conf.binddn }, + (void*)offsetof(struct ldap_conf, binddn) }, { SMAP_OPTSTR(bindpw), smap_opt_string, - &def_conf.bindpw }, + (void*)offsetof(struct ldap_conf, bindpw) }, { SMAP_OPTSTR(bindpwfile), smap_opt_string, - &def_conf.bindpwfile }, + (void*)offsetof(struct ldap_conf, bindpwfile) }, { SMAP_OPTSTR(positive-reply), smap_opt_string, - &def_conf.positive_reply }, + (void*)offsetof(struct ldap_conf, positive_reply) }, { SMAP_OPTSTR(negative-reply), smap_opt_string, - &def_conf.negative_reply }, + (void*)offsetof(struct ldap_conf, negative_reply) }, { SMAP_OPTSTR(onerror-reply), smap_opt_string, - &def_conf.onerror_reply }, + (void*)offsetof(struct ldap_conf, onerror_reply) }, { NULL } }; + int i; + struct smap_option *opt; + + if (flags & MKOPT_REUSE) + opt = *ret_options; + else { + opt = malloc(sizeof(init_option)); + if (!opt) + return 1; + *ret_options = opt; + } + memcpy(opt, init_option, sizeof(init_option)); + + if (flags & MKOPT_RESET) + opt->type = smap_opt_string; + for (i = 0; opt[i].name; i++) { + opt[i].data = (char*)conf + (size_t) opt[i].data; + if ((flags & MKOPT_RESET) && i) + opt[i].type = smap_opt_null; + } + + return 0; +} + +static int +mod_ldap_init(int argc, char **argv) +{ + struct smap_option *opt; + int rc; dbgid = smap_debug_alloc("ldap"); - if (smap_parseopt(init_option, argc, argv, 0, NULL)) + if (make_options(&dfl_conf, MKOPT_DEFAULT, &opt)) { + smap_error("not enough memory"); return 1; + } - return 0; + rc = smap_parseopt(opt, argc, argv, 0, NULL); + free(opt); + return rc; } static char * @@ -681,46 +719,38 @@ mod_ldap_init_db(const char *dbid, int argc, char **argv) struct ldap_db *db; struct ldap_conf conf; size_t i, j; + struct smap_option *opt; - struct smap_option init_option[] = { - { SMAP_OPTSTR(config-file), smap_opt_null, - &init_option, 0, readconf }, - { SMAP_OPTSTR(ssl-ca), smap_opt_string, - &conf.cacert }, - { SMAP_OPTSTR(tls-ca), smap_opt_string, - &conf.cacert }, - { SMAP_OPTSTR(uri), smap_opt_string, - &conf.uri }, - { SMAP_OPTSTR(base), smap_opt_string, - &conf.base }, - - { SMAP_OPTSTR(filter), smap_opt_string, - &conf.filter }, - - { SMAP_OPTSTR(binddn), smap_opt_string, - &conf.binddn }, - - { SMAP_OPTSTR(bindpw), smap_opt_string, - &conf.bindpw }, - { SMAP_OPTSTR(bindpwfile), smap_opt_string, - &conf.bindpwfile }, - - { SMAP_OPTSTR(positive-reply), smap_opt_string, - &conf.positive_reply }, - { SMAP_OPTSTR(negative-reply), smap_opt_string, - &conf.negative_reply }, - { SMAP_OPTSTR(onerror-reply), smap_opt_string, - &conf.onerror_reply }, - { NULL } - }; + if (!ldap_conf_cpy(&conf, &dfl_conf)) + return NULL; - if (!ldap_conf_cpy(&conf, &def_conf)) + if (make_options(&conf, MKOPT_RESET, &opt)) { + smap_error("not enough memory"); + ldap_conf_free(&conf); + return NULL; + } + + if (smap_parseopt(opt, argc, argv, 0, NULL)) { + ldap_conf_free(&conf); return NULL; + } + + make_options(&conf, MKOPT_REUSE, &opt); + + if (!conf.config_file && access(dfl_config_file, R_OK) == 0) + conf.config_file = strdup(dfl_config_file); + + if (conf.config_file && parse_ldap_conf(conf.config_file, opt)) { + free(opt); + ldap_conf_free(&conf); + } - if (smap_parseopt(init_option, argc, argv, 0, NULL)) { + if (smap_parseopt(opt, argc, argv, 0, NULL)) { + free(opt); ldap_conf_free(&conf); return NULL; } + free(opt); if (!conf.filter) { smap_error("%s: filter must be defined", dbid); |