The first patch had a memory leak.
Am Mittwoch, 12. Dezember 2012, 17:07:34 schrieb Guido Winkelmann:
This patch appears to work. Note, I have only done superficial testing
(checked that I can log in as a user who is in the specified group and that
I can not log in as one that is not in this group). I have not tested this
against AD, only OpenLDAP.
This patch applies to 2.2.17, but not to git-master.
Guidodiff -rup jabberd-2.2.17-orig/etc/c2s.xml.dist.in jabberd-2.2.17/etc/c2s.xml.dist.in
--- jabberd-2.2.17-orig/etc/c2s.xml.dist.in 2012-05-22 22:27:51.0 +0200
+++ jabberd-2.2.17/etc/c2s.xml.dist.in 2012-12-12 16:39:54.490003311 +0100
@@ -546,6 +546,15 @@
!--
validattrvalid/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_dncn=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 -rup jabberd-2.2.17-orig/storage/authreg_ldapfull.c jabberd-2.2.17/storage/authreg_ldapfull.c
--- jabberd-2.2.17-orig/storage/authreg_ldapfull.c 2012-02-19 14:23:09.0 +0100
+++ jabberd-2.2.17/storage/authreg_ldapfull.c 2012-12-13 16:30:13.690004078 +0100
@@ -68,6 +68,7 @@ typedef struct moddata_st
char *objectclass;
char *uidattr;
char *validattr;
+char *group_dn;
char *pwattr;
char *pwscheme;
@@ -583,6 +584,50 @@ retry:
return dn;
}
+/** Is this user part of the given LDAP group? */
+static int _ldapfull_user_in_group(moddata_t data, char *user_dn, 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;
+}
+}
+
/** do we have this user? */
static int _ldapfull_find_user_dn(moddata_t data, char *username, char *realm, char **dn)
{
@@ -601,6 +646,11 @@ static int _ldapfull_user_exists(authreg
{
char *dn;
if (_ldapfull_find_user_dn((moddata_t) ar-private, username, realm, 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;
}
@@ -748,22 +798,54 @@ static int _ldapfull_check_password(auth
{
moddata_t data = (moddata_t) ar-private;
char buf[LDAPFULL_PASSBUF_MAX];
+char *dn = NULL;
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)) {
+ldap_memfree(dn);
+return 1;
+}
+else {
+ldap_memfree(dn);
+return 0;
+}
+}
+}
if( _ldapfull_get_password(ar,username,realm,buf) != 0 ) {
+if(dn != NULL)
+ldap_memfree(dn);
return 1;
}
-return ! _ldapfull_check_passhash(data,buf,password);
+if(_ldapfull_check_passhash(data,buf,password)){
+if(data-group_dn != NULL