Re: LDAP Auth: Require user to be in specified LDAP-group

2012-12-12 Thread 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-12 16:52:30.43587 +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,40 @@ static int _ldapfull_check_password(auth
 {
 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, char *username, char *realm) {
@@ -856,6 +924,8 @@ DLLEXPORT int ar_init(authreg_t ar)
 
 

two ldap modules (Re: LDAP Auth: Require user to be in specified LDAP-group)

2012-12-12 Thread Justin T Pryzby
I compared the two ldap modules here:
http://www.mail-archive.com/jabberd2@lists.xiaoka.com/msg01381.html
(Was it really three years ago??)

Is there any reason to maintain both?  What does full mean in
ldapfull?

Justin

On Wed, Dec 12, 2012 at 05:07:34PM +0100, Guido Winkelmann wrote:
 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.
 
   Guido

 diff -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.in2012-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.c2012-02-19 
 14:23:09.0 +0100
 +++ jabberd-2.2.17/storage/authreg_ldapfull.c 2012-12-12 16:52:30.43587 
 +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,40 @@ static int _ldapfull_check_password(auth
  {
  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  ) {
  

Unable to connect to server, probably database related

2012-12-12 Thread Dylan
Okay, so I'm trying to set up a jabber server on my laptop. I'm running
on Fedora 17 x86_64 and installed it from the provided binaries with yum
install jabberd. I've been following the rpm quick start guide
https://github.com/jabberd2/jabberd2/wiki/InstallGuide-QuickStartGuideRPM.I
was able to get a database set up and the server starts fine, but I
think it's having some problems actually using the database. When it's
set to the default sqlite database it sort of works - the server is up,
anyway, though I can't seem to register any accounts on it (I'm using
pidgin and get a 500: Internal Server Error). This I don't care about
- I don't plan on using sqlite anyway, just not sure if it's related.
When using MySQL, the service appears to start fine (I start it with
service jabberd start) but I'm not able to connect to the server at all.
I have double and triple checked that I can log in to the jabberd2
database with the jabberd2 user and the secret_pass password (I'm just
trying to get it running with the defaults right now) and that those are
the credentials listed in the sm.xml and c2s.xml files. Oh, and I'm
running it on my laptop just using the localhost.localdomain domain to
rule out any firewall issues. I have no idea what's wrong. Any
suggestions? Attached are my c2s.xml and sm.xml configuration files, the
only two I've changed.




!-- Session manager configuration --
sm
  !-- Our ID on the network (default: sm) --
  idsm/id

  !-- The process ID file. Comment this out if you don't need to know
   the process ID from outside the process (eg for control scripts) --
  pidfile/var/lib/jabberd/pid/sm.pid/pidfile

  !-- Router connection configuration --
  router
!-- IP/port the router is waiting for connections on --
ip127.0.0.1/ip!-- default: 127.0.0.1 --
port5347/port !-- default: 5347 --

!-- Username/password to authenticate as --
userjabberd/user  !-- default: jabberd --
pass3498e9b05da27cfc60f8bdf6d66726db1f3f6c68/pass   !-- default: secret --

!-- File containing an SSL certificate and private key to use when
 setting up an encrypted channel with the router. From
 SSL_CTX_use_certificate_chain_file(3): The certificates must be
 in PEM format and must be sorted starting with the subject's
 certificate (actual client or server certificate), followed
 by intermediate CA certificates if applicable, and ending
 at the highest level (root) CA (the latter one being optional).
 If this is commented out, or the file can't be read, no attempt
 will be made to establish an encrypted channel with the router. --
!--
pemfile/etc/jabberd/server.pem/pemfile
--

!-- Router connection retry --
retry
  !-- If the connection to the router can't be established at
   startup, we should try again this many times before exiting.
   Use -1 to retry indefinitely. [default: 3] --
  init3/init

  !-- If we lost the connection to the router during normal
   operation (ie we've successfully connected to the router in
   the past), we should try to reconnect this many times before
   exiting. Use -1 to retry indefinitely. [default: 3] --
  lost3/lost

  !-- Sleep for this many seconds before trying attempting a
   reconnect. [default: 2] --
  sleep2/sleep
/retry
  /router

  !-- Log configuration - type is syslog, file or stdout --
  log type='syslog'
!-- If logging to syslog, this is the log ident --
identjabberd/sm/ident

!-- If logging to syslog, this is the log facility
 (local0 - local7)[default: local3] --
facilitylocal3/facility

!-- If logging to file, this is the filename of the logfile --
!--
file/var/lib/jabberd/log/sm.log/file
--
  /log

  !-- Local network configuration --
  local
!-- Who we identify ourselves as.
 Users will have this as the domain part of their JID.
 If you want your server to be accessible from other
 Jabber servers, this IDs must be FQDN resolvable by DNSes.
 If not set, the SM id is used. --
idlocalhost.localdomain/id
!--
idvhost1.localdomain/id
idvhost2.localdomain/id
--

  /local

  !-- Storage database configuration --
  storage
!-- Dynamic storage modules path --
path/usr/lib64/jabberd/path

!-- By default, we use the SQLite driver for all storage --
drivermysql/driver

!-- Its also possible to explicitly list alternate drivers for
 specific data types. --

!-- Store vcards in a ldapvcard database instead --
!--
driver type='vcard'ldapvcard/driver
--

!-- Read mapping for group id - group name from ldap.
 Used by mod_published_roster.
 See ldapvcard section for options.
 When resolving group id to group name, it searches for
 groupsobjectclass objects at groupsdn