The same patch for git master.
>From 559475a60dbe5a793f2632f5abb723ec19bedc07 Mon Sep 17 00:00:00 2001
From: Guido Winkelmann <[email protected]>
Date: Thu, 13 Dec 2012 00:57:10 +0100
Subject: [PATCH] ldapfull: Check for ldap group membership on login
Administrators can now supply a <group_dn> configuration directive. If
it is given, only users who are members of this group will be allowed to login
---
etc/c2s.xml.dist.in | 9 +++++
storage/authreg_ldapfull.c | 82 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 85 insertions(+), 6 deletions(-)
diff --git a/etc/c2s.xml.dist.in b/etc/c2s.xml.dist.in
index eb402d5..6626b43 100644
--- a/etc/c2s.xml.dist.in
+++ b/etc/c2s.xml.dist.in
@@ -563,6 +563,15 @@
<!--
<validattr>valid</validattr>
-->
+
+ <!-- Group that users must be members of
+ If this is set, only user that are members of the specified LDAP
+ group can log in. The group must be specified with its full
+ distinguished name -->
+ <!--
+ <group_dn>cn=jabberdusers,ou=servicegroups,dc=example,dc=com</group_dn>
+ -->
+
<fulluid/>
<!-- If pwscheme is not defined, then passwords are stored in clear
text and digest authentication may be done.
diff --git a/storage/authreg_ldapfull.c b/storage/authreg_ldapfull.c
index b651dce..5149b29 100644
--- a/storage/authreg_ldapfull.c
+++ b/storage/authreg_ldapfull.c
@@ -68,6 +68,7 @@ typedef struct moddata_st
const char *objectclass;
const char *uidattr;
const char *validattr;
+ const char *group_dn;
const char *pwattr;
const char *pwscheme;
@@ -585,7 +586,51 @@ retry:
return dn;
}
-/** do we have this user? */
+/** Is this user part of the given LDAP group? */
+static int _ldapfull_user_in_group(moddata_t data, const char *user_dn, const char *group_dn)
+{
+ LDAPMessage *result, *entry;
+ int tried = 0;
+ char filter[1024];
+
+ log_debug(ZONE, "checking whether user with dn %s is in group %s", user_dn, group_dn);
+
+ memset(filter, 0, 1024);
+ snprintf(filter, 1024, "(member=%s)", user_dn); // TODO Check if snprintf result was truncated
+
+ retry:
+ if(ldap_search_s(data->ld, group_dn, LDAP_SCOPE_BASE, filter, NULL, 0, &result))
+ {
+ if( tried++ < LDAPFULL_SEARCH_MAX_RETRIES ) {
+ log_debug(ZONE, "ldap: group search fail, will retry; %s: %s", filter, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
+ _ldapfull_unbind(data);
+ if( _ldapfull_connect_bind(data) == 0 ) {
+ goto retry;
+ } else {
+ return 0;
+ }
+ }
+ log_write(data->ar->c2s->log, LOG_ERR, "ldap: group search %s failed: %s", filter, ldap_err2string(_ldapfull_get_lderrno(data->ld)));
+ _ldapfull_unbind(data);
+ return 0;
+ }
+
+ entry = ldap_first_entry(data->ld, result);
+ if(entry == NULL)
+ {
+ ldap_msgfree(result);
+
+ return 0;
+ }
+ else
+ {
+ ldap_msgfree(result);
+
+ return 1;
+ }
+}
+
+/** Get distinguished name for this user if we have it */
static int _ldapfull_find_user_dn(moddata_t data, const char *username, const char *realm, const char **dn)
{
*dn = NULL;
@@ -603,7 +648,12 @@ static int _ldapfull_user_exists(authreg_t ar, const char *username, const char
{
const char *dn;
if (_ldapfull_find_user_dn((moddata_t) ar->private, username, realm, &dn)) {
- ldap_memfree((void*)dn);
+ if(((moddata_t) ar->private)->group_dn != NULL
+ && !_ldapfull_user_in_group((moddata_t) ar->private, dn, ((moddata_t) ar->private)->group_dn)) {
+ ldap_memfree(dn);
+ return 0;
+ }
+ ldap_memfree(dn);
return 1;
}
return 0;
@@ -751,22 +801,40 @@ static int _ldapfull_check_password(authreg_t ar, const char *username, const ch
{
moddata_t data = (moddata_t) ar->private;
char buf[LDAPFULL_PASSBUF_MAX];
+ char *dn;
log_debug(ZONE, "checking password for %s", username);
if(password[0] == '\0')
return 1;
+ if(data->group_dn != NULL) {
+ if (!_ldapfull_find_user_dn(data, username, realm, &dn))
+ return 1;
+ }
/* The bind scheme doesn't need the password read first, so short circuit
the whole passhash scheme */
- if (!strcmp(data->pwscheme, "bind"))
- return _ldapfull_check_password_bind(ar, username, realm, password);
+ if (!strcmp(data->pwscheme, "bind")) {
+ if(_ldapfull_check_password_bind(ar, username, realm, password) == 0) {
+ if(data->group_dn != NULL && !_ldapfull_user_in_group(data, dn, data->group_dn))
+ return 1;
+ else
+ return 0;
+ }
+ }
if( _ldapfull_get_password(ar,username,realm,buf) != 0 ) {
return 1;
}
- return ! _ldapfull_check_passhash(data,buf,password);
+ if(_ldapfull_check_passhash(data,buf,password)){
+ if(data->group_dn != NULL && !_ldapfull_user_in_group(data, dn, data->group_dn))
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 1;
}
static int _ldapfull_create_user(authreg_t ar, const char *username, const char *realm) {
@@ -856,9 +924,11 @@ DLLEXPORT int ar_init(authreg_t ar)
data->uidattr = config_get_one(ar->c2s->config, "authreg.ldapfull.uidattr", 0);
if(data->uidattr == NULL)
data->uidattr = "uid";
-
+
data->validattr = config_get_one(ar->c2s->config, "authreg.ldapfull.validattr", 0);
+ data->group_dn = config_get_one(ar->c2s->config, "authreg.ldapfull.group_dn", 0);
+
data->pwattr = config_get_one(ar->c2s->config, "authreg.ldapfull.pwattr", 0);
if(data->pwattr == NULL)
data->pwattr = "jabberPassword";
--
1.7.8.6