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;
13
14use FreeDSx\Sasl\Exception\SaslBufferException;
15use FreeDSx\Sasl\Exception\SaslException;
16
17/**
18 * Helper functions to decode a SASL buffer when a security layer is installed. These can be used when receiving data
19 * over the wire with a SASL security layer to determine whether or not the buffer is complete, and then unwrap the data.
20 *
21 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
22 */
23class SaslBuffer
24{
25    /**
26     * Wraps the buffer by pre-pending the data length.
27     */
28    public static function wrap(string $data): string
29    {
30        return pack('N1', strlen($data)) . $data;
31    }
32
33    /**
34     * Unwrap the buffer by removing pre-pended length and verifying we have enough data. Only the data is returned.
35     *
36     * @throws SaslBufferException
37     * @throws SaslException
38     */
39    public static function unwrap(string $data): string
40    {
41        $length = strlen($data);
42        if ($length < 4) {
43            throw new SaslBufferException('Not enough data to unwrap the SASL buffer.');
44        }
45        $dataLength = $length - 4;
46        $bufferLength = hexdec(bin2hex(substr($data, 0, 4)));
47        if (!is_int($bufferLength)) {
48            throw new SaslException('The buffer length exceeds the maximum allowed.');
49        }
50        if ($dataLength < $bufferLength) {
51            throw new SaslBufferException('The SASL buffer is incomplete.');
52        }
53
54        return substr($data, 4, $bufferLength);
55    }
56}
57