From 5cd554b923afc915d8acbde74f9f0c53e1d75799 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 2 Sep 2014 14:30:26 -0400
Subject: [PATCH]  Ticket 47850 - "nsslapd-allow-anonymous-access: rootdse"
 makes login as "admin" fail at the first time

Bug Description:  If anonymous bind access is restricted, console logins using
                  just the RDN fails.  This is becuase the console does anonymous
                  searches to find the real user.

Fix Description:  Added new config parameters to adm.conf to specfiy a bind DN and
                  password that is only used to search for users.

                  This "authentication" user should reside in o=netscaperoot, and have
                  access permissions to search the "config" database and the "users"
                  database.

https://fedorahosted.org/389/ticket/47850

Reviewed by: ?
---
 mod_admserv/mod_admserv.c | 45 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 3 deletions(-)

diff --git a/mod_admserv/mod_admserv.c b/mod_admserv/mod_admserv.c
index 420e36b..3fc19ff 100644
--- a/mod_admserv/mod_admserv.c
+++ b/mod_admserv/mod_admserv.c
@@ -1221,7 +1221,7 @@ static int update_admpwd(char *admroot, char *newuid, char *newpw);
 
 /* 
  * Miodrag (06-15-98)
- * The following metthod is called from the runtime command 
+ * The following method is called from the runtime command
  * "change_sie_password" after the sie password is changed
  * 
  * Return value: if successful, 1; otherwise, 0 is returned.
@@ -2731,6 +2731,7 @@ static int userauth(request_rec *r)
 static int
 authenticate_user(LdapServerData *data, char *baseDN, char *user, const char *pw, request_rec *r)
 {
+  AdmldapInfo    info;
   LDAP           *server;
   char           *userdn, *ldapURL;
   int             ldapError = LDAP_SUCCESS;
@@ -2751,7 +2752,39 @@ authenticate_user(LdapServerData *data, char *baseDN, char *user, const char *pw
    * is hopefully adequate to detect a DN...
    */
   if (!strchr(user, '=')) {
-      /* not a DN, so resolve the DN from the uid */
+      /*
+       * Not a DN, so resolve the DN from the uid.
+       */
+      const char *authdn = NULL;
+      const char *authpw = NULL;
+      int error = 0;
+
+      if (!(info = admldapBuildInfoOnly(configdir, &error))) {
+          ap_log_error(APLOG_MARK, APLOG_CRIT, 0 /* status */, NULL,
+                       "authenticate_user(): unable to create AdmldapInfo (error code = %d)",
+                       error);
+          return DECLINED;
+      }
+      authdn = admldapGetAuthDN(info);
+      authpw = admldapGetAuthPasswd(info);
+
+      if(authdn && authpw){
+          LDAPControl **ctrls = NULL;
+          /*
+           * An authentication bind DN and passwd was provided, perform the BIND so
+           * this DN lookup is not using an anonymous search (as anonymous access
+           * could be restricted on the DS side which would break the console).
+           */
+          ldapError = util_ldap_bind(server, authdn, authpw,
+                                 LDAP_SASL_SIMPLE, NULL, &ctrls, NULL, NULL);
+
+          if (ldapError) {
+              ap_log_error(APLOG_MARK, APLOG_ERR, 0 /* status */, NULL,
+                           "authenticate_user: Could not bind as [%s]: ldap error %d: %s",
+                           authdn, ldapError, ldap_err2string(ldapError));
+              return DECLINED;
+          }
+      }
 
       tries = 0;
       do {
@@ -2763,7 +2796,7 @@ authenticate_user(LdapServerData *data, char *baseDN, char *user, const char *pw
         closeLDAPConnection(server);
         if(!(server = openLDAPConnection(data))) {
           ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
-                        "unable to find user [%s] in server [%s:%d] under base DN [%s]",
+                        "authenticate_user: unable to find user [%s] in server [%s:%d] under base DN [%s]",
                         user, data->host, data->port, data->baseDN ? data->baseDN : baseDN);
           return DECLINED;
         }
@@ -2775,6 +2808,12 @@ authenticate_user(LdapServerData *data, char *baseDN, char *user, const char *pw
           if ((ldapError == LDAP_CONNECT_ERROR) || (ldapError == LDAP_SERVER_DOWN))
             return check_auth_users_cache(user, pw, r, 0); /* DS down. Use the cache, ignoring entry expiration. */
 
+          if(ldapError == LDAP_INAPPROPRIATE_AUTH){
+              ap_log_error(APLOG_MARK, APLOG_ERR, 0 /* status */, NULL,
+                           "authenticate_user: anonymous access is probably disabled, try setting "
+                           "\"authdn\" and \"authpw\" in adm.conf");
+          }
+
           return DECLINED; /* fall back to final check against admpw */
       }
   } else {
-- 
1.9.3

