diff -uNr cyrus-sasl-2.1.25.orig/saslauthd/lak.c cyrus-sasl-2.1.25/saslauthd/lak.c --- cyrus-sasl-2.1.25.orig/saslauthd/lak.c 2009-12-04 04:07:03.000000000 +0900 +++ cyrus-sasl-2.1.25/saslauthd/lak.c 2012-11-04 00:58:23.843750000 +0900 @@ -91,6 +91,7 @@ static int lak_auth_custom(LAK *, const char *, const char *, const char *, const char *); static int lak_auth_bind(LAK *, const char *, const char *, const char *, const char *); static int lak_auth_fastbind(LAK *, const char *, const char *, const char *, const char *); +static int lak_auth_saslbind(LAK *, const char *, const char *, const char *, const char *); static int lak_group_member(LAK *, const char *, const char *, const char *, const char *); static char *lak_result_get(const LAK_RESULT *, const char *); static int lak_result_add(const char *, const char *, LAK_RESULT **); @@ -110,6 +111,7 @@ { LAK_AUTH_METHOD_BIND, lak_auth_bind }, { LAK_AUTH_METHOD_CUSTOM, lak_auth_custom }, { LAK_AUTH_METHOD_FASTBIND, lak_auth_fastbind }, + { LAK_AUTH_METHOD_SASLBIND, lak_auth_saslbind }, { -1, NULL } }; @@ -235,6 +237,8 @@ conf->auth_method = LAK_AUTH_METHOD_CUSTOM; } else if (!strcasecmp(p, "fastbind")) { conf->auth_method = LAK_AUTH_METHOD_FASTBIND; + } else if (!strcasecmp(p, "saslbind")) { + conf->auth_method = LAK_AUTH_METHOD_SASLBIND; } } else if (!strcasecmp(key, "ldap_timeout")) { conf->timeout.tv_sec = lak_config_int(p); @@ -278,6 +282,9 @@ !strcasecmp(key, "ldap_sasl_authz_id")) strlcpy(conf->authz_id, p, LAK_BUF_LEN); + else if (!strcasecmp(key, "ldap_sasl_username_attr")) + strlcpy(conf->sasl_username_attr, p, LAK_BUF_LEN); + else if (!strcasecmp(key, "ldap_realm") || !strcasecmp(key, "ldap_sasl_realm")) strlcpy(conf->realm, p, LAK_BUF_LEN); @@ -323,6 +330,10 @@ conf->auth_method == LAK_AUTH_METHOD_BIND) conf->auth_method = LAK_AUTH_METHOD_FASTBIND; + if (!conf->use_sasl && + conf->auth_method == LAK_AUTH_METHOD_SASLBIND) + conf->auth_method = LAK_AUTH_METHOD_BIND; + if ( ISSET(conf->group_filter) && ISSET(conf->search_base) && EMPTY(conf->group_search_base) ) @@ -389,6 +400,7 @@ conf->restart = 1; conf->start_tls = 0; conf->use_sasl = 0; + strlcpy(conf->sasl_username_attr, "cn", LAK_BUF_LEN); strlcpy(conf->path, configfile, LAK_PATH_LEN); @@ -1509,6 +1521,50 @@ return rc; } + +static int lak_auth_saslbind( + LAK *lak, + const char *user, + const char *service, + const char *realm, + const char *password) +{ + LAK_USER *lu = NULL; + LAK_RESULT *lres; + int rc; + const char *attrs[] = { lak->conf->sasl_username_attr, NULL}; + + rc = lak_retrieve(lak, user, service, realm, attrs, &lres); + if (rc != LAK_OK) + return rc; + + syslog(LOG_INFO|LOG_AUTH, "Mapped user: %s -> %s", user, lres->value); + rc = lak_user( + NULL, + lres->value, + NULL, + lak->conf->mech, + lak->conf->realm, + password, + &lu); + if (rc != LAK_OK) + goto done; + + rc = lak_bind(lak, lu); + + if ( rc == LAK_OK && + (ISSET(lak->conf->group_dn) || + ISSET(lak->conf->group_filter)) ) + rc = lak_group_member(lak, user, service, realm, NULL); + +done:; + if (lu) + lak_user_free(lu); + if (lres != NULL) + lak_result_free(lres); + + return rc; +} int lak_authenticate( LAK *lak, diff -uNr cyrus-sasl-2.1.25.orig/saslauthd/lak.h cyrus-sasl-2.1.25/saslauthd/lak.h --- cyrus-sasl-2.1.25.orig/saslauthd/lak.h 2004-02-25 06:56:31.000000000 +0900 +++ cyrus-sasl-2.1.25/saslauthd/lak.h 2012-10-31 21:43:37.078125000 +0900 @@ -58,6 +58,7 @@ #define LAK_AUTH_METHOD_BIND 0 #define LAK_AUTH_METHOD_CUSTOM 1 #define LAK_AUTH_METHOD_FASTBIND 2 +#define LAK_AUTH_METHOD_SASLBIND 3 #define LAK_GROUP_MATCH_METHOD_ATTR 0 #define LAK_GROUP_MATCH_METHOD_FILTER 1 @@ -84,6 +85,7 @@ char search_base[LAK_DN_LEN]; char filter[LAK_DN_LEN]; char password_attr[LAK_BUF_LEN]; + char sasl_username_attr[LAK_BUF_LEN]; char group_dn[LAK_DN_LEN]; char group_attr[LAK_BUF_LEN]; char group_filter[LAK_DN_LEN]; diff -uNr cyrus-sasl-2.1.25.orig/saslauthd/LDAP_SASLAUTHD cyrus-sasl-2.1.25/saslauthd/LDAP_SASLAUTHD --- cyrus-sasl-2.1.25.orig/saslauthd/LDAP_SASLAUTHD 2004-02-25 06:56:31.000000000 +0900 +++ cyrus-sasl-2.1.25/saslauthd/LDAP_SASLAUTHD 2012-11-04 22:27:01.535024200 +0900 @@ -82,7 +82,7 @@ within the first set of <>. There may be a second set of <> which provide available values. -ldap_auth_method: +ldap_auth_method: Specify an authentication method. The bind method uses the LDAP bind facility to verify the password. The @@ -101,6 +101,18 @@ 1. Expanding the ldap_filter expression gives the user's fully-qualified DN 2. There is no cost to staying bound as a named user + The saslbind method works as following: + 1. binds using SASL with ldap_id (or ldap_bind_dn) and ldap_password. + 2. searches for the user using ldap_search_base and ldap_filter + as the bind method do, and retrieves the username from the attribute + specified with ldap_sasl_username_attr. + 3. binds using SASL with the retrieved username and the passed password. + Generally, this method has a performance disadvantage. It is prefered to + configure your ldap server to map SASL user ID to DN as you want (for example, + by adding a new realm and sasl-regexp). + The saslbind method is not available when ldap_use_sasl is turned off. In that + case the bind method is used. + ldap_bind_dn: Specify DN (distinguished name) to bind to the LDAP directory. Do not specify this parameter for the anonymous bind. @@ -236,6 +248,10 @@ Use SASL bind rather than simple bind when connecting to the ldap server. +ldap_sasl_username_attr: + Specify what attribute to use for SASL authentication. + For example, use sAMAccountName with Active Directory. + ldap_version: <3> <2|3> Specify the LDAP protocol version. If ldap_start_tls and/or ldap_use_sasl are enabled, ldap_version will be automatiacally set to