From: Matt Benjamin Date: Mon, 1 Aug 2016 21:36:17 +0000 (-0400) Subject: rgw: add reinit/rebind logic (ldap) X-Git-Tag: ses5-milestone5~235^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9b8fccf68789ba5c5986766c544b23aeada0e87e;p=ceph.git rgw: add reinit/rebind logic (ldap) 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 --- diff --git a/src/rgw/rgw_ldap.cc b/src/rgw/rgw_ldap.cc index 6cca3b8af193..b8f7d3edfdcd 100644 --- a/src/rgw/rgw_ldap.cc +++ b/src/rgw/rgw_ldap.cc @@ -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(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) */ diff --git a/src/rgw/rgw_ldap.h b/src/rgw/rgw_ldap.h index b29e33adc8ad..a427ec46745e 100644 --- a/src/rgw/rgw_ldap.h +++ b/src/rgw/rgw_ldap.h @@ -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 #include #include +#include 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; + 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(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 */