]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add reinit/rebind logic (ldap) 10532/head
authorMatt Benjamin <mbenjamin@redhat.com>
Mon, 1 Aug 2016 21:36:17 +0000 (17:36 -0400)
committerMatt Benjamin <mbenjamin@redhat.com>
Mon, 1 Aug 2016 21:36:17 +0000 (17:36 -0400)
Gracefully handle stale LDAP connections by rebinding--verified
with MS AD.  Rebind is attempted once per request until rebound--
not worse than misconfiguring the environment.

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
src/rgw/rgw_ldap.cc
src/rgw/rgw_ldap.h

index 6cca3b8af1938639dc62f2c5d87cd23e343df3e5..b8f7d3edfdcda38e17f9a013b6181917c4b9efc8 100644 (file)
@@ -37,3 +37,66 @@ std::string parse_rgw_ldap_bindpw(CephContext* ctx)
 
   return std::move(ldap_bindpw);
 }
+
+#if defined(HAVE_OPENLDAP)
+namespace rgw {
+
+  int LDAPHelper::auth(const std::string uid, const std::string pwd) {
+    int ret;
+    std::string filter;
+    if (msad) {
+      filter = "(&(objectClass=user)(sAMAccountName=";
+      filter += uid;
+      filter += "))";
+    } else {
+      /* openldap */
+      filter = "(";
+      filter += dnattr;
+      filter += "=";
+      filter += uid;
+      filter += ")";
+    }
+    char *attrs[] = { const_cast<char*>(dnattr.c_str()), nullptr };
+    LDAPMessage *answer = nullptr, *entry = nullptr;
+    bool once = true;
+
+    lock_guard guard(mtx);
+
+  retry_bind:
+    ret = ldap_search_s(ldap, searchdn.c_str(), LDAP_SCOPE_SUBTREE,
+                       filter.c_str(), attrs, 0, &answer);
+    if (ret == LDAP_SUCCESS) {
+      entry = ldap_first_entry(ldap, answer);
+      if (entry) {
+       char *dn = ldap_get_dn(ldap, entry);
+       ret = simple_bind(dn, pwd);
+       if (ret != LDAP_SUCCESS) {
+         ldout(g_ceph_context, 10)
+           << __func__ << " simple_bind failed uid=" << uid
+           << dendl;
+       }
+       ldap_memfree(dn);
+      } else {
+       ldout(g_ceph_context, 12)
+         << __func__ << " ldap_search_s no user matching uid=" << uid
+         << dendl;
+       ret = LDAP_NO_SUCH_ATTRIBUTE; // fixup result
+      }
+      ldap_msgfree(answer);
+    } else {
+      ldout(g_ceph_context, 5)
+       << __func__ << " ldap_search_s error uid=" << uid
+       << " ldap err=" << ret
+       << dendl;
+      /* search should never fail--try to rebind */
+      if (once) {
+       rebind();
+       once = false;
+       goto retry_bind;
+      }
+    }
+    return (ret == LDAP_SUCCESS) ? ret : -EACCES;
+  } /* LDAPHelper::auth */
+}
+
+#endif /* defined(HAVE_OPENLDAP) */
index b29e33adc8adc56cb589073fc34d1f2c06def4ee..a427ec46745e16680d5f89db4f942d53b0dcbaf2 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef RGW_LDAP_H
 #define RGW_LDAP_H
 
+#include "acconfig.h"
+
 #if defined(HAVE_OPENLDAP)
 #define LDAP_DEPRECATED 1
 #include "ldap.h"
@@ -14,6 +16,7 @@
 #include <vector>
 #include <string>
 #include <iostream>
+#include <mutex>
 
 namespace rgw {
 
@@ -28,8 +31,11 @@ namespace rgw {
     std::string dnattr;
     LDAP *ldap;
     bool msad = false; /* TODO: possible future specialization */
+    std::mutex mtx;
 
   public:
+    using lock_guard = std::lock_guard<std::mutex>;
+
     LDAPHelper(std::string _uri, std::string _binddn, std::string _bindpw,
               std::string _searchdn, std::string _dnattr)
       : uri(std::move(_uri)), binddn(std::move(_binddn)),
@@ -58,52 +64,29 @@ namespace rgw {
       return (ret == LDAP_SUCCESS) ? ret : -EINVAL;
     }
 
+    int rebind() {
+      if (ldap) {
+       (void) ldap_unbind(ldap);
+       (void) init();
+       return bind();
+      }
+    }
+
     int simple_bind(const char *dn, const std::string& pwd) {
       LDAP* tldap;
       int ret = ldap_initialize(&tldap, uri.c_str());
       ret = ldap_simple_bind_s(tldap, dn, pwd.c_str());
       if (ret == LDAP_SUCCESS) {
-       ldap_unbind(tldap);
+       (void) ldap_unbind(tldap);
       }
       return ret; // OpenLDAP client error space
     }
 
-    int auth(const std::string uid, const std::string pwd) {
-      int ret;
-      std::string filter;
-      if (msad) {
-       filter = "(&(objectClass=user)(sAMAccountName=";
-       filter += uid;
-       filter += "))";
-      } else {
-       /* openldap */
-       filter = "(";
-       filter += dnattr;
-       filter += "=";
-       filter += uid;
-       filter += ")";
-      }
-      char *attrs[] = { const_cast<char*>(dnattr.c_str()), nullptr };
-      LDAPMessage *answer = nullptr, *entry = nullptr;
-      ret = ldap_search_s(ldap, searchdn.c_str(), LDAP_SCOPE_SUBTREE,
-                         filter.c_str(), attrs, 0, &answer);
-      if (ret == LDAP_SUCCESS) {
-       entry = ldap_first_entry(ldap, answer);
-       if (entry) {
-         char *dn = ldap_get_dn(ldap, entry);
-         ret = simple_bind(dn, pwd);
-         ldap_memfree(dn);
-       } else {
-         ret = LDAP_NO_SUCH_ATTRIBUTE; // fixup result
-       }
-       ldap_msgfree(answer);
-      }
-      return (ret == LDAP_SUCCESS) ? ret : -EACCES;
-    }
+    int auth(const std::string uid, const std::string pwd);
 
     ~LDAPHelper() {
       if (ldap)
-       ldap_unbind(ldap);
+       (void) ldap_unbind(ldap);
     }
 
   }; /* LDAPHelper */