]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_ldap.cc
import quincy 17.2.0
[ceph.git] / ceph / src / rgw / rgw_ldap.cc
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae
FG
3
4#include "rgw_ldap.h"
5
92f5a8d4 6#include "common/ceph_crypto.h"
7c673cae
FG
7#include "common/ceph_context.h"
8#include "common/common_init.h"
9#include "common/dout.h"
10#include "common/safe_io.h"
11#include <boost/algorithm/string.hpp>
12
11fdf7f2 13#include "include/ceph_assert.h"
7c673cae
FG
14
15#define dout_subsys ceph_subsys_rgw
16
20effc67
TL
17using namespace std;
18
7c673cae
FG
19std::string parse_rgw_ldap_bindpw(CephContext* ctx)
20{
21 string ldap_bindpw;
22 string ldap_secret = ctx->_conf->rgw_ldap_secret;
23
24 if (ldap_secret.empty()) {
25 ldout(ctx, 10)
26 << __func__ << " LDAP auth no rgw_ldap_secret file found in conf"
27 << dendl;
28 } else {
92f5a8d4
TL
29 // FIPS zeroization audit 20191116: this memset is not intended to
30 // wipe out a secret after use.
7c673cae
FG
31 char bindpw[1024];
32 memset(bindpw, 0, 1024);
33 int pwlen = safe_read_file("" /* base */, ldap_secret.c_str(),
34 bindpw, 1023);
92f5a8d4
TL
35 if (pwlen > 0) {
36 ldap_bindpw = bindpw;
37 boost::algorithm::trim(ldap_bindpw);
38 if (ldap_bindpw.back() == '\n')
39 ldap_bindpw.pop_back();
40 }
41 ::ceph::crypto::zeroize_for_security(bindpw, sizeof(bindpw));
7c673cae
FG
42 }
43
44 return ldap_bindpw;
45}
46
47#if defined(HAVE_OPENLDAP)
48namespace rgw {
49
11fdf7f2 50 int LDAPHelper::auth(const std::string &uid, const std::string &pwd) {
7c673cae
FG
51 int ret;
52 std::string filter;
53 if (msad) {
54 filter = "(&(objectClass=user)(sAMAccountName=";
55 filter += uid;
56 filter += "))";
57 } else {
58 /* openldap */
59 if (searchfilter.empty()) {
60 /* no search filter provided in config, we construct our own */
61 filter = "(";
62 filter += dnattr;
63 filter += "=";
64 filter += uid;
65 filter += ")";
66 } else {
67 if (searchfilter.find("@USERNAME@") != std::string::npos) {
68 /* we need to substitute the @USERNAME@ placeholder */
69 filter = searchfilter;
70 filter.replace(searchfilter.find("@USERNAME@"), std::string("@USERNAME@").length(), uid);
71 } else {
72 /* no placeholder for username, so we need to append our own username filter to the custom searchfilter */
73 filter = "(&(";
74 filter += searchfilter;
75 filter += ")(";
76 filter += dnattr;
77 filter += "=";
78 filter += uid;
79 filter += "))";
80 }
81 }
82 }
83 ldout(g_ceph_context, 12)
84 << __func__ << " search filter: " << filter
85 << dendl;
86 char *attrs[] = { const_cast<char*>(dnattr.c_str()), nullptr };
87 LDAPMessage *answer = nullptr, *entry = nullptr;
88 bool once = true;
89
90 lock_guard guard(mtx);
91
92 retry_bind:
93 ret = ldap_search_s(ldap, searchdn.c_str(), LDAP_SCOPE_SUBTREE,
94 filter.c_str(), attrs, 0, &answer);
95 if (ret == LDAP_SUCCESS) {
96 entry = ldap_first_entry(ldap, answer);
97 if (entry) {
98 char *dn = ldap_get_dn(ldap, entry);
99 ret = simple_bind(dn, pwd);
100 if (ret != LDAP_SUCCESS) {
101 ldout(g_ceph_context, 10)
102 << __func__ << " simple_bind failed uid=" << uid
103 << "ldap err=" << ret
104 << dendl;
105 }
106 ldap_memfree(dn);
107 } else {
108 ldout(g_ceph_context, 12)
109 << __func__ << " ldap_search_s no user matching uid=" << uid
110 << dendl;
111 ret = LDAP_NO_SUCH_ATTRIBUTE; // fixup result
112 }
113 ldap_msgfree(answer);
114 } else {
115 ldout(g_ceph_context, 5)
116 << __func__ << " ldap_search_s error uid=" << uid
117 << " ldap err=" << ret
118 << dendl;
119 /* search should never fail--try to rebind */
120 if (once) {
121 rebind();
122 once = false;
123 goto retry_bind;
124 }
125 }
126 return (ret == LDAP_SUCCESS) ? ret : -EACCES;
127 } /* LDAPHelper::auth */
128}
129
130#endif /* defined(HAVE_OPENLDAP) */