xref: /plugin/pureldap/vendor/freedsx/sasl/src/FreeDSx/Sasl/Sasl.php (revision 0b3fd2d31e4d1997548a8fbc53fa771027c4a47f)
1*0b3fd2d3SAndreas Gohr<?php
2*0b3fd2d3SAndreas Gohr
3*0b3fd2d3SAndreas Gohr/**
4*0b3fd2d3SAndreas Gohr * This file is part of the FreeDSx SASL package.
5*0b3fd2d3SAndreas Gohr *
6*0b3fd2d3SAndreas Gohr * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
7*0b3fd2d3SAndreas Gohr *
8*0b3fd2d3SAndreas Gohr * For the full copyright and license information, please view the LICENSE
9*0b3fd2d3SAndreas Gohr * file that was distributed with this source code.
10*0b3fd2d3SAndreas Gohr */
11*0b3fd2d3SAndreas Gohr
12*0b3fd2d3SAndreas Gohrnamespace FreeDSx\Sasl;
13*0b3fd2d3SAndreas Gohr
14*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Exception\SaslException;
15*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Mechanism\AnonymousMechanism;
16*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Mechanism\CramMD5Mechanism;
17*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Mechanism\DigestMD5Mechanism;
18*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Mechanism\MechanismInterface;
19*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Mechanism\PlainMechanism;
20*0b3fd2d3SAndreas Gohr
21*0b3fd2d3SAndreas Gohr/**
22*0b3fd2d3SAndreas Gohr * The main SASL class.
23*0b3fd2d3SAndreas Gohr *
24*0b3fd2d3SAndreas Gohr * @author Chad Sikorra <Chad.Sikorra@gmail.com>
25*0b3fd2d3SAndreas Gohr */
26*0b3fd2d3SAndreas Gohrclass Sasl
27*0b3fd2d3SAndreas Gohr{
28*0b3fd2d3SAndreas Gohr    /**
29*0b3fd2d3SAndreas Gohr     * @var MechanismInterface[]
30*0b3fd2d3SAndreas Gohr     */
31*0b3fd2d3SAndreas Gohr    protected $mechanisms = [];
32*0b3fd2d3SAndreas Gohr
33*0b3fd2d3SAndreas Gohr    protected $options = [
34*0b3fd2d3SAndreas Gohr        'supported' => []
35*0b3fd2d3SAndreas Gohr    ];
36*0b3fd2d3SAndreas Gohr
37*0b3fd2d3SAndreas Gohr    public function __construct(array $options = [])
38*0b3fd2d3SAndreas Gohr    {
39*0b3fd2d3SAndreas Gohr        $this->options = $options + $this->options;
40*0b3fd2d3SAndreas Gohr        $this->initMechs();
41*0b3fd2d3SAndreas Gohr    }
42*0b3fd2d3SAndreas Gohr
43*0b3fd2d3SAndreas Gohr    /**
44*0b3fd2d3SAndreas Gohr     * Get a mechanism object by its name.
45*0b3fd2d3SAndreas Gohr     */
46*0b3fd2d3SAndreas Gohr    public function get(string $mechanism): MechanismInterface
47*0b3fd2d3SAndreas Gohr    {
48*0b3fd2d3SAndreas Gohr        $mech = $this->mechanisms[$mechanism] ?? null;
49*0b3fd2d3SAndreas Gohr
50*0b3fd2d3SAndreas Gohr        if ($mech === null) {
51*0b3fd2d3SAndreas Gohr            throw new SaslException('The mechanism "%s" is not supported.');
52*0b3fd2d3SAndreas Gohr        }
53*0b3fd2d3SAndreas Gohr
54*0b3fd2d3SAndreas Gohr        return $mech;
55*0b3fd2d3SAndreas Gohr    }
56*0b3fd2d3SAndreas Gohr
57*0b3fd2d3SAndreas Gohr    /**
58*0b3fd2d3SAndreas Gohr     * Whether or not the mechanism is supported.
59*0b3fd2d3SAndreas Gohr     */
60*0b3fd2d3SAndreas Gohr    public function supports(string $mechanism): bool
61*0b3fd2d3SAndreas Gohr    {
62*0b3fd2d3SAndreas Gohr        return isset($this->mechanisms()[$mechanism]);
63*0b3fd2d3SAndreas Gohr    }
64*0b3fd2d3SAndreas Gohr
65*0b3fd2d3SAndreas Gohr    /**
66*0b3fd2d3SAndreas Gohr     * Add a mechanism object.
67*0b3fd2d3SAndreas Gohr     *
68*0b3fd2d3SAndreas Gohr     * @return Sasl
69*0b3fd2d3SAndreas Gohr     */
70*0b3fd2d3SAndreas Gohr    public function add(MechanismInterface $mechanism): self
71*0b3fd2d3SAndreas Gohr    {
72*0b3fd2d3SAndreas Gohr        $this->mechanisms[$mechanism->getName()] = $mechanism;
73*0b3fd2d3SAndreas Gohr
74*0b3fd2d3SAndreas Gohr        return $this;
75*0b3fd2d3SAndreas Gohr    }
76*0b3fd2d3SAndreas Gohr
77*0b3fd2d3SAndreas Gohr    /**
78*0b3fd2d3SAndreas Gohr     * Remove a mechanism by its name.
79*0b3fd2d3SAndreas Gohr     *
80*0b3fd2d3SAndreas Gohr     * @return Sasl
81*0b3fd2d3SAndreas Gohr     */
82*0b3fd2d3SAndreas Gohr    public function remove(string $mechanism): self
83*0b3fd2d3SAndreas Gohr    {
84*0b3fd2d3SAndreas Gohr        if (isset($this->mechanisms[$mechanism])) {
85*0b3fd2d3SAndreas Gohr            unset($this->mechanisms[$mechanism]);
86*0b3fd2d3SAndreas Gohr        }
87*0b3fd2d3SAndreas Gohr
88*0b3fd2d3SAndreas Gohr        return $this;
89*0b3fd2d3SAndreas Gohr    }
90*0b3fd2d3SAndreas Gohr
91*0b3fd2d3SAndreas Gohr    /**
92*0b3fd2d3SAndreas Gohr     * Given an array of mechanism names, and optional options, select the best supported mechanism available.
93*0b3fd2d3SAndreas Gohr     *
94*0b3fd2d3SAndreas Gohr     * @param string[] $choices array of mechanisms by their name
95*0b3fd2d3SAndreas Gohr     * @param array $options array of options (ie. ['use_integrity' => true])
96*0b3fd2d3SAndreas Gohr     * @return MechanismInterface the mechanism selected.
97*0b3fd2d3SAndreas Gohr     * @throws SaslException if no supported mechanism could be found.
98*0b3fd2d3SAndreas Gohr     */
99*0b3fd2d3SAndreas Gohr    public function select(array $choices = [], array $options = []): MechanismInterface
100*0b3fd2d3SAndreas Gohr    {
101*0b3fd2d3SAndreas Gohr        $selector = new MechanismSelector($this->mechanisms());
102*0b3fd2d3SAndreas Gohr
103*0b3fd2d3SAndreas Gohr        return $selector->select($choices, $options);
104*0b3fd2d3SAndreas Gohr    }
105*0b3fd2d3SAndreas Gohr
106*0b3fd2d3SAndreas Gohr    /**
107*0b3fd2d3SAndreas Gohr     * @return MechanismInterface[]
108*0b3fd2d3SAndreas Gohr     */
109*0b3fd2d3SAndreas Gohr    public function mechanisms(): array
110*0b3fd2d3SAndreas Gohr    {
111*0b3fd2d3SAndreas Gohr        return $this->mechanisms;
112*0b3fd2d3SAndreas Gohr    }
113*0b3fd2d3SAndreas Gohr
114*0b3fd2d3SAndreas Gohr    protected function initMechs(): void
115*0b3fd2d3SAndreas Gohr    {
116*0b3fd2d3SAndreas Gohr        $this->mechanisms = [
117*0b3fd2d3SAndreas Gohr            DigestMD5Mechanism::NAME => new DigestMD5Mechanism(),
118*0b3fd2d3SAndreas Gohr            CramMD5Mechanism::NAME => new CramMD5Mechanism(),
119*0b3fd2d3SAndreas Gohr            PlainMechanism::NAME => new PlainMechanism(),
120*0b3fd2d3SAndreas Gohr            AnonymousMechanism::NAME => new AnonymousMechanism(),
121*0b3fd2d3SAndreas Gohr        ];
122*0b3fd2d3SAndreas Gohr
123*0b3fd2d3SAndreas Gohr        if (is_array($this->options['supported']) && !empty($this->options['supported'])) {
124*0b3fd2d3SAndreas Gohr            foreach (array_keys($this->mechanisms) as $mechName) {
125*0b3fd2d3SAndreas Gohr                if (!in_array($mechName, $this->options['supported'], true)) {
126*0b3fd2d3SAndreas Gohr                    unset($this->mechanisms[$mechName]);
127*0b3fd2d3SAndreas Gohr                }
128*0b3fd2d3SAndreas Gohr            }
129*0b3fd2d3SAndreas Gohr        }
130*0b3fd2d3SAndreas Gohr    }
131*0b3fd2d3SAndreas Gohr}
132