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\Encoder; 13*0b3fd2d3SAndreas Gohr 14*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Exception\SaslEncodingException; 15*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\Message; 16*0b3fd2d3SAndreas Gohruse FreeDSx\Sasl\SaslContext; 17*0b3fd2d3SAndreas Gohr 18*0b3fd2d3SAndreas Gohr/** 19*0b3fd2d3SAndreas Gohr * Responsible for encoding / decoding PLAIN messages. 20*0b3fd2d3SAndreas Gohr * 21*0b3fd2d3SAndreas Gohr * @author Chad Sikorra <Chad.Sikorra@gmail.com> 22*0b3fd2d3SAndreas Gohr */ 23*0b3fd2d3SAndreas Gohrclass PlainEncoder implements EncoderInterface 24*0b3fd2d3SAndreas Gohr{ 25*0b3fd2d3SAndreas Gohr /** 26*0b3fd2d3SAndreas Gohr * {@inheritDoc} 27*0b3fd2d3SAndreas Gohr */ 28*0b3fd2d3SAndreas Gohr public function encode(Message $message, SaslContext $context): string 29*0b3fd2d3SAndreas Gohr { 30*0b3fd2d3SAndreas Gohr if (!$message->has('authzid')) { 31*0b3fd2d3SAndreas Gohr throw new SaslEncodingException('The PLAIN message must contain a authzid.'); 32*0b3fd2d3SAndreas Gohr } 33*0b3fd2d3SAndreas Gohr if (!$message->has('authcid')) { 34*0b3fd2d3SAndreas Gohr throw new SaslEncodingException('The PLAIN message must contain a authzid.'); 35*0b3fd2d3SAndreas Gohr } 36*0b3fd2d3SAndreas Gohr if (!$message->has('password')) { 37*0b3fd2d3SAndreas Gohr throw new SaslEncodingException('The PLAIN message must contain a password.'); 38*0b3fd2d3SAndreas Gohr } 39*0b3fd2d3SAndreas Gohr $authzid = $this->validate($message->get('authzid')); 40*0b3fd2d3SAndreas Gohr $authcid = $this->validate($message->get('authcid')); 41*0b3fd2d3SAndreas Gohr $password = $this->validate($message->get('password')); 42*0b3fd2d3SAndreas Gohr 43*0b3fd2d3SAndreas Gohr return $authzid . "\x00" . $authcid . "\x00" . $password; 44*0b3fd2d3SAndreas Gohr } 45*0b3fd2d3SAndreas Gohr 46*0b3fd2d3SAndreas Gohr /** 47*0b3fd2d3SAndreas Gohr * {@inheritDoc} 48*0b3fd2d3SAndreas Gohr */ 49*0b3fd2d3SAndreas Gohr public function decode(string $data, SaslContext $context): Message 50*0b3fd2d3SAndreas Gohr { 51*0b3fd2d3SAndreas Gohr if (preg_match('/^([^\x0]+)\x00([^\x0]+)\x00([^\x0]+)$/', $data, $matches) === 0) { 52*0b3fd2d3SAndreas Gohr throw new SaslEncodingException('The PLAIN message data is malformed.'); 53*0b3fd2d3SAndreas Gohr } 54*0b3fd2d3SAndreas Gohr 55*0b3fd2d3SAndreas Gohr return new Message([ 56*0b3fd2d3SAndreas Gohr 'authzid' => $matches[1], 57*0b3fd2d3SAndreas Gohr 'authcid' => $matches[2], 58*0b3fd2d3SAndreas Gohr 'password' => $matches[3], 59*0b3fd2d3SAndreas Gohr ]); 60*0b3fd2d3SAndreas Gohr } 61*0b3fd2d3SAndreas Gohr 62*0b3fd2d3SAndreas Gohr protected function validate(string $data): string 63*0b3fd2d3SAndreas Gohr { 64*0b3fd2d3SAndreas Gohr if (strpos($data,"\x00") !== false) { 65*0b3fd2d3SAndreas Gohr throw new SaslEncodingException('PLAIN mechanism data cannot contain a null character.'); 66*0b3fd2d3SAndreas Gohr } 67*0b3fd2d3SAndreas Gohr 68*0b3fd2d3SAndreas Gohr return $data; 69*0b3fd2d3SAndreas Gohr } 70*0b3fd2d3SAndreas Gohr} 71