1<?php 2 3/** 4 * This file is part of the FreeDSx SASL package. 5 * 6 * (c) Chad Sikorra <Chad.Sikorra@gmail.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace FreeDSx\Sasl\Challenge; 13 14use FreeDSx\Sasl\Encoder\PlainEncoder; 15use FreeDSx\Sasl\Exception\SaslException; 16use FreeDSx\Sasl\Message; 17use FreeDSx\Sasl\SaslContext; 18 19/** 20 * The PLAIN challenge / response class. 21 * 22 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 23 */ 24class PlainChallenge implements ChallengeInterface 25{ 26 /** 27 * @var PlainEncoder 28 */ 29 protected $encoder; 30 31 /** 32 * @var SaslContext 33 */ 34 protected $context; 35 36 public function __construct(bool $isServerMode = false) 37 { 38 $this->encoder = new PlainEncoder(); 39 $this->context = new SaslContext(); 40 $this->context->setIsServerMode($isServerMode); 41 } 42 43 /** 44 * {@inheritDoc} 45 */ 46 public function challenge(?string $received = null, array $options = []): SaslContext 47 { 48 $received = $received === null ? null : $this->encoder->decode($received, $this->context); 49 50 if ($this->context->isServerMode()) { 51 return $this->serverProcess($received, $options); 52 } else { 53 return $this->clientProcess($options); 54 } 55 } 56 57 protected function serverProcess(?Message $message, array $options): SaslContext 58 { 59 if ($message === null) { 60 return $this->context; 61 } 62 if (!(isset($options['validate']) && is_callable($options['validate']))) { 63 throw new SaslException('You must pass a callable validate option to the plain mechanism in server mode.'); 64 } 65 $authzId = $message->get('authzid'); 66 $authcId = $message->get('authcid'); 67 $password = $message->get('password'); 68 69 $this->context->setIsComplete(true); 70 $this->context->setIsAuthenticated((bool) $options['validate']($authzId, $authcId, $password)); 71 72 return $this->context; 73 } 74 75 protected function clientProcess(array $options): SaslContext 76 { 77 if (!isset($options['username'])) { 78 throw new SaslException('You must supply a username for the PLAIN mechanism.'); 79 } 80 if (!isset($options['password'])) { 81 throw new SaslException('You must supply a password for the PLAIN mechanism.'); 82 } 83 $message = new Message([ 84 'authzid' => $options['username'], 85 'authcid' => $options['username'], 86 'password' => $options['password'], 87 ]); 88 $this->context->setResponse($this->encoder->encode($message, $this->context)); 89 $this->context->setIsComplete(true); 90 91 return $this->context; 92 } 93} 94