1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#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) */
|