-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathLDAPConnect.php
More file actions
175 lines (153 loc) · 4.78 KB
/
LDAPConnect.php
File metadata and controls
175 lines (153 loc) · 4.78 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<?php
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 Cooperativa EITA <eita.org.br>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\LdapWriteSupport;
use LDAP\Connection;
use OC\ServerNotAvailableException;
use OCA\LdapWriteSupport\AppInfo\Application;
use OCA\User_LDAP\Configuration;
use OCA\User_LDAP\Helper;
use Psr\Log\LoggerInterface;
class LDAPConnect {
/** @var Configuration */
private $ldapConfig;
/** @var bool|null */
private $passwdSupport;
public function __construct(
Helper $ldapBackendHelper,
private LoggerInterface $logger,
) {
$this->passwdSupport = null;
$ldapConfigPrefixes = $ldapBackendHelper->getServerConfigurationPrefixes(true);
$prefix = array_shift($ldapConfigPrefixes);
$this->ldapConfig = new Configuration($prefix);
}
/**
* @return resource|Connection
* @throws ServerNotAvailableException
*/
public function connect() {
$ldapHost = $this->ldapConfig->ldapHost;
$ldapPort = $this->ldapConfig->ldapPort;
// shamelessly copied from OCA\User_LDAP\LDAP::connect()
$pos = strpos($ldapHost, '://');
if ($pos === false) {
$ldapHost = 'ldap://' . $ldapHost;
$pos = 4;
}
if (!str_contains(substr($ldapHost, $pos + 1), ':') && !empty($ldapPort)) {
$ldapHost .= ':' . $ldapPort;
}
// Connecting to LDAP - TODO: connect directly via LDAP plugin
$cr = ldap_connect($ldapHost);
if (!is_resource($cr) && !is_object($cr)) {
$this->logger->error('Unable to connect to LDAP host {ldapHost}:{ldapPort}',
[
'app' => Application::APP_ID,
'ldapHost' => $ldapHost,
'ldapPort' => $ldapPort,
]);
throw new ServerNotAvailableException('LDAP server not available');
}
ldap_set_option($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
$this->logger->debug('Connected to LDAP host {ldapHost}:{ldapPort}',
[
'app' => Application::APP_ID,
'ldapHost' => $ldapHost,
'ldapPort' => $ldapPort,
]);
return $cr;
}
/**
* @return false|resource|Connection
* @throws ServerNotAvailableException
*/
public function bind() {
$ds = $this->connect();
$dn = $this->ldapConfig->ldapAgentName;
$secret = $this->ldapConfig->ldapAgentPassword;
if (!ldap_bind($ds, $dn, $secret)) {
$this->logger->error('Unable to bind to LDAP server',
['app' => Application::APP_ID]
);
return false;
} else {
$this->logger->debug('Bound to LDAP server using credentials for {dn}', [
'app' => Application::APP_ID,
'dn' => $dn,
]);
return $ds;
}
}
/**
* @return false|resource|Connection
* @throws ServerNotAvailableException
*/
public function getLDAPConnection() {
return $this->bind();
}
public function getLDAPBaseUsers(): array {
$bases = $this->ldapConfig->ldapBaseUsers;
if (empty($bases)) {
$bases = $this->ldapConfig->ldapBase;
}
return $bases;
}
public function getLDAPBaseGroups(): array {
$bases = $this->ldapConfig->ldapBaseGroups;
if (empty($bases)) {
$bases = $this->ldapConfig->ldapBase;
}
return $bases;
}
public function getDisplayNameAttribute(): string {
return $this->ldapConfig->ldapUserDisplayName;
}
public function getGroupMemberAssocAttribute(): string {
return strtolower($this->ldapConfig->ldapGroupMemberAssocAttr);
}
public function groupsEnabled(): bool {
$filter = trim((string)$this->ldapConfig->ldapGroupFilter);
$gAssoc = trim((string)$this->ldapConfig->ldapGroupMemberAssocAttr);
return $filter !== '' && $gAssoc !== '';
}
public function hasPasswordPolicy(): bool {
$ppDN = $this->ldapConfig->ldapDefaultPPolicyDN;
return !empty($ppDN);
}
/**
* checks whether the LDAP server supports the passwd exop
*
* @param Connection $connection LDAP connection to check
* @return boolean either the user can or cannot
*/
public function hasPasswdExopSupport($connection): bool {
// TODO: We should cache this by ldap prefix, but currently we have no access to it.
if (is_null($this->passwdSupport)) {
$ret = ldap_read($connection, '', '(objectclass=*)', ['supportedExtension']);
if ($ret === false) {
$this->passwdSupport = false;
$this->logger->debug(
'Could not check passwd_exop support of LDAP host, host does not provide the supportedExtension entry.',
[ 'app' => Application::APP_ID ]
);
return false;
}
$ret = ldap_first_entry($connection, $ret);
if ($ret === false) {
$this->passwdSupport = false;
$this->logger->error(
'Could not check passwd_exop support of LDAP host, host returned malformed data for the supported ldap extension entry.',
[ 'app' => Application::APP_ID ]
);
return false;
}
$values = ldap_get_values($connection, $ret, 'supportedExtension');
$this->passwdSupport = ($values !== false) && in_array(LDAP_EXOP_MODIFY_PASSWD, $values);
}
return $this->passwdSupport;
}
}