anonymous//src/Auth/Source/LdapMulti.php$0   A
last analyzed

Complexity

Total Complexity 1

Size/Duplication

Total Lines 12
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 1
c 0
b 0
f 0
dl 0
loc 12
rs 10
1
<?php
2
3
/**
4
 * LDAP authentication source.
5
 *
6
 * See the ldap-entry in config-templates/authsources.php for information about
7
 * configuration of this authentication source.
8
 *
9
 * This class is based on www/auth/login.php.
10
 *
11
 * @package simplesamlphp/simplesamlphp-module-ldap
12
 */
13
14
declare(strict_types=1);
15
16
namespace SimpleSAML\Module\ldap\Auth\Source;
17
18
use SimpleSAML\Assert\Assert;
19
use SimpleSAML\Auth;
20
use SimpleSAML\Configuration;
21
use SimpleSAML\Error;
22
use SimpleSAML\Module\core\Auth\UserPassOrgBase;
23
24
use function array_change_key_case;
25
use function array_key_exists;
26
use function strtolower;
27
use function var_export;
28
29
class LdapMulti extends UserPassOrgBase
30
{
31
    /**
32
     * An LDAP configuration object.
33
     */
34
    private Configuration $ldapConfig;
35
36
    /**
37
     * An array with mappings for organization => authsource.
38
     *
39
     * @var array<mixed>
40
     */
41
    private array $mapping;
42
43
    /**
44
     * An array with descriptions for organizations.
45
     *
46
     * @var array<mixed>
47
     */
48
    private array $orgs;
49
50
    /**
51
     * An array of organization IDs to LDAP configuration objects.
52
     *
53
     * @var array<mixed>
54
     */
55
    private array $ldapOrgs;
56
57
    /**
58
     * Whether we should include the organization as part of the username.
59
     */
60
    private bool $includeOrgInUsername;
61
62
63
    /**
64
     * Constructor for this authentication source.
65
     *
66
     * @param array<mixed> $info  Information about this authentication source.
67
     * @param array<mixed> $config  Configuration.
68
     */
69
    public function __construct(array $info, array $config)
70
    {
71
        // Call the parent constructor first, as required by the interface
72
        parent::__construct($info, $config);
73
74
        $this->ldapConfig = Configuration::loadFromArray(
75
            $config,
76
            'authsources[' . var_export($this->authId, true) . ']',
77
        );
78
79
        $usernameOrgMethod = $this->ldapConfig->getValueValidate(
80
            'username_organization_method',
81
            ['none', 'allow', 'force'],
82
        );
83
        $this->setUsernameOrgMethod($usernameOrgMethod);
84
85
        $this->includeOrgInUsername = $this->ldapConfig->getOptionalBoolean(
86
            'include_organization_in_username',
87
            false,
88
        );
89
90
        $this->mapping = array_change_key_case($this->ldapConfig->getArray('mapping'));
91
        Assert::notEmpty($this->mapping);
92
93
        $organizations = array_keys($this->mapping);
94
        $authsources = Configuration::getConfig('authsources.php');
95
96
        foreach ($organizations as $organization) {
97
            Assert::keyExists($this->mapping[$organization], 'authsource');
98
            $authsource = $this->mapping[$organization]['authsource'];
99
            Assert::notNull(Auth\Source::getById($authsource, Ldap::class));
100
101
            if (array_key_exists('description', $this->mapping[$organization])) {
102
                $this->orgs[$organization] = $this->mapping[$organization]['description'];
103
            } else {
104
                $this->orgs[$organization] = $organization;
105
            }
106
107
            $this->ldapOrgs[$organization] = Configuration::loadFromArray(
108
                $authsources->getValue($authsource),
109
                'authsources[' . var_export($this->authId, true) . '][' . var_export($organization, true) . ']',
110
            );
111
        }
112
    }
113
114
115
    /**
116
     * Attempt to log in using SASL and the given username and password.
117
     *
118
     * @param string $username  The username the user wrote.
119
     * @param string $password  The password the user wrote.
120
     * @param string $organization  The organization the user chose.
121
     * @param array<mixed> $sasl_args SASL options
122
     * @return array<mixed> Associative array with the users attributes.
123
     */
124
    protected function loginSasl(
125
        string $username,
126
        #[\SensitiveParameter]string $password,
127
        string $organization,
128
        array $sasl_args = [],
129
    ): array {
130
        $organization = strtolower($organization);
131
        if ($this->includeOrgInUsername) {
132
            $username = $username . '@' . $organization;
133
        }
134
135
        $authsource = $this->mapping[$organization]['authsource'];
136
137
        if (!array_key_exists($organization, $this->ldapOrgs)) {
138
            // The organization is unknown to us.
139
            throw new Error\Error('WRONGUSERPASS');
140
        }
141
142
        $sourceConfig = $this->ldapOrgs[$organization];
143
144
        $ldap = new class (['AuthId' => $authsource], $sourceConfig->toArray()) extends Ldap
145
        {
146
            /**
147
             * @param array<mixed> $sasl_args
148
             * @return array<mixed>
149
             */
150
            public function loginOverload(
151
                string $username,
152
                #[\SensitiveParameter]string $password,
153
                array $sasl_args,
154
            ): array {
155
                return $this->loginSasl($username, $password, $sasl_args);
156
            }
157
        };
158
159
        return $ldap->loginOverload($username, $password, $sasl_args);
160
    }
161
162
163
    /**
164
     * Attempt to log in using the given username and password.
165
     *
166
     * @param string $username  The username the user wrote.
167
     * @param string $password  The password the user wrote.
168
     * @param string $organization  The organization the user chose.
169
     * @return array<mixed> Associative array with the users attributes.
170
     */
171
    protected function login(string $username, #[\SensitiveParameter]string $password, string $organization): array
172
    {
173
        return $this->loginSasl($username, $password, $organization);
174
    }
175
176
177
    /**
178
     * Retrieve list of organizations.
179
     *
180
     * @return array<mixed> Associative array with the organizations.
181
     */
182
    protected function getOrganizations(): array
183
    {
184
        return $this->orgs;
185
    }
186
}
187