+++ /dev/null
-LDAP auxprop plugin for SASL-enabled servers.
-Copyright (C) 2002,2003 by Howard Chu, hyc@symas.com
-
-This software is licensed under the terms of the OpenLDAP license.
-
-The file ldapdb.c was written for Cyrus SASL 2.1.3 and OpenLDAP 2.1.3.
-Due to various bugs in the Cyrus source you should use Cyrus SASL 2.1.15
-or newer. You need at least Cyrus SASL 2.1.16 to use the auxprop-store
-functionality.
-
-The version of ldapdb bundled with OpenLDAP 2.1.22 and older will work
-with all OpenLDAP releases 2.1.3 and up. The ldapdb in OpenLDAP 2.1.23
-uses a different LDAP request and requires the server to be 2.1.23 or newer.
-
-It can be compiled by copying into the Cyrus SASL source tree, in the
-plugins subdirectory. No configuration or build script is provided.
-
-To compile, type "make ldapdb.lo". To link, you'll have to copy the
-link rule for one of the other plugins. Below is a sample on my Linux
-system:
-
- /bin/sh ../libtool --mode=link gcc -Wall -W -g -O2 -L/usr/local/lib -Wl,-rpath,/usr/local/lib -module -export-dynamic -rpath /usr/lib/sasl2 -o libldapdb.la -version-info 2:4:0 ldapdb.lo -lldap -llber -lssl -lcrypto
-
-Once installed, you need to add some config items to the SASL server's
-config file in /usr/lib/sasl2. For example:
-
-ldapdb_uri: ldap://ldap.example.com
-ldapdb_id: root
-ldapdb_pw: secret
-ldapdb_mech: DIGEST-MD5
-
-This config assumes an LDAP server on the same machine as the server
-that is using SASL. The LDAP server must be configured to map the SASL
-authcId "root" into a DN that has proxy authorization privileges to
-every account that is allowed to login to this server. (See the OpenLDAP
-Admin Guide section 10 for details.)
-
-Unlike other LDAP-enabled plugins for other services that are common
-on the web, this plugin does not require you to configure DN search
-patterns to map usernames to LDAP DNs. This plugin requires SASL name
-mapping to be configured on the target slapd. This approach keeps the
-LDAP-specific configuration details in one place, the slapd.conf, and
-makes the configuration of remote services much simpler.
-
-An additional keyword "ldapdb_rc" may be specified in the config file.
-The filename specified here will be put into the server's LDAPRC
-environment variable, and libldap-specific config options may be set
-in that ldaprc file. The main purpose behind this option is to allow
-a client TLS certificate to be configured, so that SASL/EXTERNAL may
-be used between the SASL server and the LDAP server. This is the most
-optimal way to use this plugin when the servers are on separate machines.
-
-Note: this plugin is not for use with slapd itself. When OpenLDAP is
-built with SASL support, slapd uses its own internal auxprop module.
-By default, without configuring anything else, slapd will fail to load
-the ldapdb module when it's present. This is as it should be. If you
-don't like the "auxpropfunc: error -7" message that is sent to syslog
-by slapd, you can stop it by creating /usr/lib/sasl2/slapd.conf with:
-
- auxprop_plugin: slapd
-
-which will force the SASL library to ignore all other auxprop modules.
-
-This plugin has been in use for over a year at many sites with good
-results. If you have questions or problems, please send feedback via
-the openldap-software mailing list.
-
- -- Howard Chu
-
-Update... With OpenLDAP 2.1.13 you can use SASL/EXTERNAL on ldapi://.
-This is fast and secure, and needs no username or password to be stored.
-The SASL config file is just
-
-ldapdb_uri: ldapi://
-ldapdb_mech: EXTERNAL
-
-The slapd.conf will need to map these usernames to LDAP DNs:
-
-sasl-regexp uidNumber=(.*)\\+gidNumber=(.*),cn=peercred,cn=external,cn=auth
- ldap:///dc=example,dc=com??sub?(&(uidNumber=$1)(gidNumber=$2))
-
-sasl-regexp uid=(.*),cn=external,cn=auth
- ldap:///dc=example,dc=com??sub?(uid=$1)
-
-Update... With OpenLDAP 2.1.23 you can use the ldapdb_starttls keyword
-to use the StartTLS extended operation on an LDAP session. This item
-may be set to either "try" or "demand", e.g.:
-
-ldapdb_uri: ldap://ldap.example.com
-ldapdb_starttls: try
-
-When set to "try" any failure in StartTLS is ignored. When set to "demand"
-then any failure aborts the connection.
+++ /dev/null
-/* $OpenLDAP$ */
-/* SASL LDAP auxprop implementation
- * Copyright (C) 2002,2003 Howard Chu, All rights reserved. <hyc@symas.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-
-#include "sasl.h"
-#include "saslutil.h"
-#include "saslplug.h"
-
-#ifndef SASL_VERSION_FULL
-#define SASL_VERSION_FULL ((SASL_VERSION_MAJOR << 16) |\
- (SASL_VERSION_MINOR << 8) |SASL_VERSION_STEP)
-#endif
-
-#include "plugin_common.h"
-
-#include <ldap.h>
-
-static char ldapdb[] = "ldapdb";
-
-typedef struct ldapctx {
- const char *uri; /* URI of LDAP server */
- struct berval id; /* SASL authcid to bind as */
- struct berval pw; /* password for bind */
- struct berval mech; /* SASL mech */
- int use_tls; /* Issue StartTLS request? */
-} ldapctx;
-
-static int ldapdb_interact(LDAP *ld, unsigned flags __attribute__((unused)),
- void *def, void *inter)
-{
- sasl_interact_t *in = inter;
- ldapctx *ctx = def;
- struct berval p;
-
- for (;in->id != SASL_CB_LIST_END;in++)
- {
- p.bv_val = NULL;
- switch(in->id)
- {
- case SASL_CB_GETREALM:
- ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &p.bv_val);
- if (p.bv_val) p.bv_len = strlen(p.bv_val);
- break;
- case SASL_CB_AUTHNAME:
- p = ctx->id;
- break;
- case SASL_CB_PASS:
- p = ctx->pw;
- break;
- }
- if (p.bv_val)
- {
- in->result = p.bv_val;
- in->len = p.bv_len;
- }
- }
- return LDAP_SUCCESS;
-}
-
-typedef struct connparm {
- LDAP *ld;
- LDAPControl c;
- LDAPControl *ctrl[2];
- struct berval *dn;
-} connparm;
-
-static int ldapdb_connect(ldapctx *ctx, sasl_server_params_t *sparams,
- const char *user, unsigned ulen, connparm *cp)
-{
- int i;
- char *authzid;
-
- if((i=ldap_initialize(&cp->ld, ctx->uri))) {
- return i;
- }
-
- authzid = sparams->utils->malloc(ulen + sizeof("u:"));
- if (!authzid) {
- return LDAP_NO_MEMORY;
- }
- strcpy(authzid, "u:");
- strcpy(authzid+2, user);
- cp->c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
- cp->c.ldctl_value.bv_val = authzid;
- cp->c.ldctl_value.bv_len = ulen + 2;
- cp->c.ldctl_iscritical = 1;
-
- i = LDAP_VERSION3;
- ldap_set_option(cp->ld, LDAP_OPT_PROTOCOL_VERSION, &i);
-
- /* If TLS is set and it fails, continue or bail out as requested */
- if (ctx->use_tls && (i=ldap_start_tls_s(cp->ld, NULL, NULL)) != LDAP_SUCCESS
- && ctx->use_tls > 1) {
- sparams->utils->free(authzid);
- return i;
- }
-
- i = ldap_sasl_interactive_bind_s(cp->ld, NULL, ctx->mech.bv_val, NULL,
- NULL, LDAP_SASL_QUIET, ldapdb_interact, ctx);
- if (i != LDAP_SUCCESS) {
- sparams->utils->free(authzid);
- return i;
- }
-
- cp->ctrl[0] = &cp->c;
- cp->ctrl[1] = NULL;
- i = ldap_whoami_s(cp->ld, &cp->dn, cp->ctrl, NULL);
- if (i == LDAP_SUCCESS && cp->dn) {
- if (!cp->dn->bv_val || strncmp(cp->dn->bv_val, "dn:", 3)) {
- ber_bvfree(cp->dn);
- cp->dn = NULL;
- i = LDAP_INVALID_SYNTAX;
- } else {
- cp->c.ldctl_value = *(cp->dn);
- }
- }
- sparams->utils->free(authzid);
- return i;
-}
-
-static void ldapdb_auxprop_lookup(void *glob_context,
- sasl_server_params_t *sparams,
- unsigned flags,
- const char *user,
- unsigned ulen)
-{
- ldapctx *ctx = glob_context;
- connparm cp;
- int ret, i, n, *aindx;
- const struct propval *pr;
- struct berval **bvals;
- LDAPMessage *msg, *res;
- char **attrs = NULL;
-
- if(!ctx || !sparams || !user) return;
-
- pr = sparams->utils->prop_get(sparams->propctx);
- if(!pr) return;
-
- /* count how many attrs to fetch */
- for(i = 0, n = 0; pr[i].name; i++) {
- if(pr[i].name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID))
- continue;
- if(pr[i].values && !(flags & SASL_AUXPROP_OVERRIDE))
- continue;
- n++;
- }
- /* nothing to do, bail out */
- if (!n) return;
-
- /* alloc an array of attr names for search, and index to the props */
- attrs = sparams->utils->malloc((n+1)*sizeof(char *)*2);
- if (!attrs) return;
-
- aindx = (int *)(attrs + n + 1);
-
- /* copy attr list */
- for (i=0, n=0; pr[i].name; i++) {
- if(pr[i].name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID))
- continue;
- if(pr[i].values && !(flags & SASL_AUXPROP_OVERRIDE))
- continue;
- attrs[n] = (char *)pr[i].name;
- if (pr[i].name[0] == '*') attrs[n]++;
- aindx[n] = i;
- n++;
- }
- attrs[n] = NULL;
-
- if(ldapdb_connect(ctx, sparams, user, ulen, &cp)) {
- goto done;
- }
-
- ret = ldap_search_ext_s(cp.ld, cp.dn->bv_val+3, LDAP_SCOPE_BASE,
- "(objectclass=*)", attrs, 0, cp.ctrl, NULL, NULL, 1, &res);
- ber_bvfree(cp.dn);
-
- if (ret != LDAP_SUCCESS) goto done;
-
- for(msg=ldap_first_message(cp.ld, res); msg; msg=ldap_next_message(cp.ld, msg))
- {
- if (ldap_msgtype(msg) != LDAP_RES_SEARCH_ENTRY) continue;
- for (i=0; i<n; i++)
- {
- bvals = ldap_get_values_len(cp.ld, msg, attrs[i]);
- if (!bvals) continue;
- if (pr[aindx[i]].values)
- sparams->utils->prop_erase(sparams->propctx, pr[aindx[i]].name);
- sparams->utils->prop_set(sparams->propctx, pr[aindx[i]].name,
- bvals[0]->bv_val, bvals[0]->bv_len);
- ber_bvecfree(bvals);
- }
- }
- ldap_msgfree(res);
-
- done:
- if(attrs) sparams->utils->free(attrs);
- if(cp.ld) ldap_unbind(cp.ld);
-}
-
-#if SASL_VERSION_FULL >= 0x020110
-static int ldapdb_auxprop_store(void *glob_context,
- sasl_server_params_t *sparams,
- struct propctx *prctx,
- const char *user,
- unsigned ulen)
-{
- ldapctx *ctx = glob_context;
- connparm cp;
- const struct propval *pr;
- int i, n;
- LDAPMod **mods;
-
- /* just checking if we are enabled */
- if (!prctx) return SASL_OK;
-
- if (!sparams || !user) return SASL_BADPARAM;
-
- pr = sparams->utils->prop_get(prctx);
- if (!pr) return SASL_BADPARAM;
-
- for (n=0; pr[n].name; n++);
- if (!n) return SASL_BADPARAM;
-
- mods = sparams->utils->malloc((n+1) * sizeof(LDAPMod*) + n * sizeof(LDAPMod));
- if (!mods) return SASL_NOMEM;
-
- if((i=ldapdb_connect(ctx, sparams, user, ulen, &cp)) == 0) {
-
- for (i=0; i<n; i++) {
- mods[i] = (LDAPMod *)((char *)(mods+n+1) + i * sizeof(LDAPMod));
- mods[i]->mod_op = LDAP_MOD_REPLACE;
- mods[i]->mod_type = (char *)pr[i].name;
- mods[i]->mod_values = (char **)pr[i].values;
- }
- mods[i] = NULL;
-
- i = ldap_modify_ext_s(cp.ld, cp.dn->bv_val+3, mods, cp.ctrl, NULL);
- ber_bvfree(cp.dn);
- }
-
- sparams->utils->free(mods);
-
- if (i) {
- sparams->utils->seterror(sparams->utils->conn, 0,
- ldap_err2string(i));
- if (i == LDAP_NO_MEMORY) i = SASL_NOMEM;
- else i = SASL_FAIL;
- }
- if (cp.ld) ldap_unbind(cp.ld);
- return i;
-}
-#endif /* SASL_VERSION_FULL >= 2.1.16 */
-
-static void ldapdb_auxprop_free(void *glob_ctx, const sasl_utils_t *utils)
-{
- utils->free(glob_ctx);
-}
-
-static sasl_auxprop_plug_t ldapdb_auxprop_plugin = {
- 0, /* Features */
- 0, /* spare */
- NULL, /* glob_context */
- ldapdb_auxprop_free, /* auxprop_free */
- ldapdb_auxprop_lookup, /* auxprop_lookup */
- ldapdb, /* name */
-#if SASL_VERSION_FULL >=0x020110
- ldapdb_auxprop_store /* spare if <2.1.16*/
-#else
- NULL
-#endif
-};
-
-static int ldapdb_auxprop_plug_init(const sasl_utils_t *utils,
- int max_version,
- int *out_version,
- sasl_auxprop_plug_t **plug,
- const char *plugname __attribute__((unused)))
-{
- ldapctx tmp, *p;
- const char *s;
- unsigned len;
-
- if(!out_version || !plug) return SASL_BADPARAM;
-
- if(max_version < SASL_AUXPROP_PLUG_VERSION) return SASL_BADVERS;
-
- memset(&tmp, 0, sizeof(tmp));
-
- utils->getopt(utils->getopt_context, ldapdb, "ldapdb_uri", &tmp.uri, NULL);
- if(!tmp.uri) return SASL_BADPARAM;
-
- utils->getopt(utils->getopt_context, ldapdb, "ldapdb_id",
- (const char **)&tmp.id.bv_val, &len);
- tmp.id.bv_len = len;
- utils->getopt(utils->getopt_context, ldapdb, "ldapdb_pw",
- (const char **)&tmp.pw.bv_val, &len);
- tmp.pw.bv_len = len;
- utils->getopt(utils->getopt_context, ldapdb, "ldapdb_mech",
- (const char **)&tmp.mech.bv_val, &len);
- tmp.mech.bv_len = len;
- utils->getopt(utils->getopt_context, ldapdb, "ldapdb_starttls", &s, NULL);
- if (s)
- {
- if (!strcasecmp(s, "demand")) tmp.use_tls = 2;
- else if (!strcasecmp(s, "try")) tmp.use_tls = 1;
- }
- utils->getopt(utils->getopt_context, ldapdb, "ldapdb_rc", &s, &len);
- if (s)
- {
- char *str = utils->malloc(sizeof("LDAPRC=")+len);
- if (!str) return SASL_NOMEM;
- strcpy( str, "LDAPRC=" );
- strcpy( str + sizeof("LDAPRC=")-1, s );
- if (putenv(str))
- {
- utils->free(str);
- return SASL_NOMEM;
- }
- }
-
- p = utils->malloc(sizeof(ldapctx));
- if (!p) return SASL_NOMEM;
- *p = tmp;
- ldapdb_auxprop_plugin.glob_context = p;
-
- *out_version = SASL_AUXPROP_PLUG_VERSION;
-
- *plug = &ldapdb_auxprop_plugin;
-
- return SASL_OK;
-}
-
-SASL_AUXPROP_PLUG_INIT( ldapdb )
-