diff options
Diffstat (limited to 'src/rgw/rgw_ldap.cc')
-rw-r--r-- | src/rgw/rgw_ldap.cc | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/rgw/rgw_ldap.cc b/src/rgw/rgw_ldap.cc new file mode 100644 index 000000000..27b2c24af --- /dev/null +++ b/src/rgw/rgw_ldap.cc @@ -0,0 +1,128 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +#include "rgw_ldap.h" + +#include "common/ceph_crypto.h" +#include "common/ceph_context.h" +#include "common/common_init.h" +#include "common/dout.h" +#include "common/safe_io.h" +#include <boost/algorithm/string.hpp> + +#include "include/ceph_assert.h" + +#define dout_subsys ceph_subsys_rgw + +std::string parse_rgw_ldap_bindpw(CephContext* ctx) +{ + string ldap_bindpw; + string ldap_secret = ctx->_conf->rgw_ldap_secret; + + if (ldap_secret.empty()) { + ldout(ctx, 10) + << __func__ << " LDAP auth no rgw_ldap_secret file found in conf" + << dendl; + } else { + // FIPS zeroization audit 20191116: this memset is not intended to + // wipe out a secret after use. + char bindpw[1024]; + memset(bindpw, 0, 1024); + int pwlen = safe_read_file("" /* base */, ldap_secret.c_str(), + bindpw, 1023); + if (pwlen > 0) { + ldap_bindpw = bindpw; + boost::algorithm::trim(ldap_bindpw); + if (ldap_bindpw.back() == '\n') + ldap_bindpw.pop_back(); + } + ::ceph::crypto::zeroize_for_security(bindpw, sizeof(bindpw)); + } + + return 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 */ + if (searchfilter.empty()) { + /* no search filter provided in config, we construct our own */ + filter = "("; + filter += dnattr; + filter += "="; + filter += uid; + filter += ")"; + } else { + if (searchfilter.find("@USERNAME@") != std::string::npos) { + /* we need to substitute the @USERNAME@ placeholder */ + filter = searchfilter; + filter.replace(searchfilter.find("@USERNAME@"), std::string("@USERNAME@").length(), uid); + } else { + /* no placeholder for username, so we need to append our own username filter to the custom searchfilter */ + filter = "(&("; + filter += searchfilter; + filter += ")("; + filter += dnattr; + filter += "="; + filter += uid; + filter += "))"; + } + } + } + ldout(g_ceph_context, 12) + << __func__ << " search filter: " << filter + << dendl; + 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 + << "ldap err=" << ret + << 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) */ |