-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathUserData.php
More file actions
145 lines (125 loc) · 4.02 KB
/
UserData.php
File metadata and controls
145 lines (125 loc) · 4.02 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
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\User_SAML;
use OCA\User_SAML\Exceptions\NoUserFoundException;
class UserData {
private $uid;
/** @var array */
private $attributes;
public function __construct(
private readonly UserResolver $userResolver,
private readonly SAMLSettings $samlSettings,
) {
}
public function setAttributes(array $attributes): void {
$this->attributes = $attributes;
$this->uid = null; // clear the state in case
}
public function getAttributes(): array {
$this->assertIsInitialized();
return $this->attributes;
}
public function hasUidMappingAttribute(): bool {
$this->assertIsInitialized();
$attribute = $this->getUidMappingAttribute();
return $attribute !== null && isset($this->attributes[$attribute]);
}
public function getOriginalUid(): string {
$this->assertIsInitialized();
return $this->extractSamlUserId();
}
public function getEffectiveUid(): string {
if ($this->uid !== null) {
return $this->uid;
}
$this->assertIsInitialized();
try {
$providedUid = $this->extractSamlUserId();
$uid = $this->testEncodedObjectGUID($providedUid);
$uid = $this->userResolver->findExistingUserId($uid, true, $providedUid !== $uid);
$this->uid = $uid;
} catch (NoUserFoundException) {
return '';
}
return $uid ?? '';
}
public function getGroups(): array {
$this->assertIsInitialized();
$mapping = $this->getProviderSettings()['saml-attribute-mapping-group_mapping'] ?? null;
if ($mapping === null || !isset($this->attributes[$mapping])) {
return [];
}
return is_array($this->attributes[$mapping])
? $this->attributes[$mapping]
: array_map(trim(...), explode(',', (string)$this->attributes[$mapping]));
}
protected function extractSamlUserId(): string {
$uidMapping = $this->getUidMappingAttribute();
if ($uidMapping !== null && isset($this->attributes[$uidMapping])) {
if (is_array($this->attributes[$uidMapping])) {
return trim((string)$this->attributes[$uidMapping][0]);
} else {
return trim((string)$this->attributes[$uidMapping]);
}
}
return '';
}
/**
* returns the plain text UUID if the provided $uid string is a
* base64-encoded binary string representing e.g. the objectGUID. Otherwise
*
*/
public function testEncodedObjectGUID(string $uid): string {
if (preg_match('/[^a-zA-Z0-9=+\/]/', $uid) !== 0) {
// certainly not encoded
return $uid;
}
$candidate = base64_decode($uid, true);
if ($candidate === false) {
return $uid;
}
$candidate = $this->convertObjectGUID2Str($candidate);
// the regex only matches the structure of the UUID, not its semantic
// (i.e. version or variant) simply to be future compatible
if (preg_match('/^[a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8}$/i', $candidate) === 1) {
$uid = $candidate;
}
return $uid;
}
/**
* @see \OCA\User_LDAP\Access::convertObjectGUID2Str
*/
protected function convertObjectGUID2Str(string $oguid): string {
$hex_guid = bin2hex($oguid);
$hex_guid_to_guid_str = '';
for ($k = 1; $k <= 4; ++$k) {
$hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
}
$hex_guid_to_guid_str .= '-';
for ($k = 1; $k <= 2; ++$k) {
$hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
}
$hex_guid_to_guid_str .= '-';
for ($k = 1; $k <= 2; ++$k) {
$hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
}
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
return strtoupper($hex_guid_to_guid_str);
}
protected function assertIsInitialized() {
if ($this->attributes === null) {
throw new \LogicException('UserData have to be initialized with setAttributes first');
}
}
protected function getProviderSettings(): array {
return $this->samlSettings->get($this->samlSettings->getProviderId());
}
protected function getUidMappingAttribute(): ?string {
return $this->getProviderSettings()['general-uid_mapping'] ?? null;
}
}