TSIG   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 222
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 92%

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 5
dl 0
loc 222
ccs 92
cts 100
cp 0.92
rs 10
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getAlgorithmName() 0 4 1
A setAlgorithmName() 0 8 2
A getTimeSigned() 0 4 1
A setTimeSigned() 0 4 1
A getFudge() 0 4 1
A setFudge() 0 7 2
A getMac() 0 4 1
A setMac() 0 4 1
A getOriginalId() 0 4 1
A setOriginalId() 0 7 2
A getError() 0 4 1
A setError() 0 7 2
A getOtherData() 0 4 1
A setOtherData() 0 4 1
A toText() 0 12 1
A toWire() 0 15 1
A fromText() 0 23 4
A fromWire() 0 31 4
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Badcow DNS Library.
7
 *
8
 * (c) Samuel Williams <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Badcow\DNS\Rdata;
15
16
use Badcow\DNS\Message;
17
use Badcow\DNS\Parser\ParseException;
18
use Badcow\DNS\Parser\Tokens;
19
use Badcow\DNS\Rcode;
20
use Badcow\DNS\Validator;
21
22
/**
23
 * {@link https://tools.ietf.org/html/rfc2845}.
24
 */
25
class TSIG implements RdataInterface
26
{
27 1
    use RdataTrait;
28
29
    const TYPE = 'TSIG';
30
    const TYPE_CODE = 250;
31
32
    /**
33
     * Name of the algorithm in domain name syntax.
34
     *
35
     * @var string
36
     */
37
    private $algorithmName;
38
39
    /**
40
     * @var \DateTime
41
     */
42
    private $timeSigned;
43
44
    /**
45
     * Seconds of error permitted in time signed.
46
     *
47
     * @var int
48
     */
49
    private $fudge;
50
51
    /**
52
     * Message authentication code.
53
     *
54
     * @var string
55
     */
56
    private $mac;
57
58
    /**
59
     * @var int
60
     */
61
    private $originalId;
62
63
    /**
64
     * @var int
65
     */
66
    private $error = Rcode::NOERROR;
67
68
    /**
69
     * @var string
70
     */
71
    private $otherData;
72
73 2
    public function getAlgorithmName(): string
74
    {
75 2
        return $this->algorithmName;
76
    }
77
78 4
    public function setAlgorithmName(string $algorithmName): void
79
    {
80 4
        if (!Validator::fullyQualifiedDomainName($algorithmName)) {
81
            throw new \InvalidArgumentException('Algorithm name must be in the form of a fully qualified domain name.');
82
        }
83
84 4
        $this->algorithmName = $algorithmName;
85 4
    }
86
87 2
    public function getTimeSigned(): \DateTime
88
    {
89 2
        return $this->timeSigned;
90
    }
91
92 4
    public function setTimeSigned(\DateTime $timeSigned): void
93
    {
94 4
        $this->timeSigned = $timeSigned;
95 4
    }
96
97 2
    public function getFudge(): int
98
    {
99 2
        return $this->fudge;
100
    }
101
102 4
    public function setFudge(int $fudge): void
103
    {
104 4
        if (!Validator::isUnsignedInteger($fudge, 16)) {
105
            throw new \InvalidArgumentException(sprintf('Fudge must be an unsigned 16-bit integer, "%d" given.', $fudge));
106
        }
107 4
        $this->fudge = $fudge;
108 4
    }
109
110 2
    public function getMac(): string
111
    {
112 2
        return $this->mac;
113
    }
114
115 4
    public function setMac(string $mac): void
116
    {
117 4
        $this->mac = $mac;
118 4
    }
119
120 2
    public function getOriginalId(): int
121
    {
122 2
        return $this->originalId;
123
    }
124
125 4
    public function setOriginalId(int $originalId): void
126
    {
127 4
        if (!Validator::isUnsignedInteger($originalId, 16)) {
128
            throw new \InvalidArgumentException(sprintf('Original ID must be an unsigned 16-bit integer, "%d" given.', $originalId));
129
        }
130 4
        $this->originalId = $originalId;
131 4
    }
132
133 2
    public function getError(): int
134
    {
135 2
        return $this->error;
136
    }
137
138 4
    public function setError(int $error): void
139
    {
140 4
        if (!Validator::isUnsignedInteger($error, 16)) {
141
            throw new \InvalidArgumentException(sprintf('Error must be an unsigned 16-bit integer, "%d" given.', $error));
142
        }
143 4
        $this->error = $error;
144 4
    }
145
146 2
    public function getOtherData(): string
147
    {
148 2
        return $this->otherData;
149
    }
150
151 4
    public function setOtherData(string $otherData): void
152
    {
153 4
        $this->otherData = $otherData;
154 4
    }
155
156 1
    public function toText(): string
157
    {
158 1
        return sprintf('%s %d %d %s %d %d %s',
159 1
            $this->algorithmName,
160 1
            $this->timeSigned->format('U'),
161 1
            $this->fudge,
162 1
            base64_encode($this->mac),
163 1
            $this->originalId,
164 1
            $this->error,
165 1
            base64_encode($this->otherData)
166
        );
167
    }
168
169 1
    public function toWire(): string
170
    {
171 1
        $timeSigned = (int) $this->timeSigned->format('U');
172 1
        $hex1 = (0xffff00000000 & $timeSigned) >> 32;
173 1
        $hex2 = (0x0000ffff0000 & $timeSigned) >> 16;
174 1
        $hex3 = 0x00000000ffff & $timeSigned;
175
176 1
        $wire = Message::encodeName($this->algorithmName);
177 1
        $wire .= pack('nnnnn', $hex1, $hex2, $hex3, $this->fudge, strlen($this->mac));
178 1
        $wire .= $this->mac;
179 1
        $wire .= pack('nnn', $this->originalId, $this->error, strlen($this->otherData));
180 1
        $wire .= $this->otherData;
181
182 1
        return $wire;
183
    }
184
185
    /**
186
     * @throws ParseException
187
     */
188 1
    public function fromText(string $text): void
189
    {
190 1
        $rdata = explode(Tokens::SPACE, $text);
191 1
        $this->setAlgorithmName((string) array_shift($rdata));
192 1
        if (false === $timeSigned = \DateTime::createFromFormat('U', (string) array_shift($rdata))) {
193
            throw new ParseException('Unable to decode TSIG time signed.');
194
        }
195 1
        $this->setTimeSigned($timeSigned);
196 1
        $this->setFudge((int) array_shift($rdata));
197
198 1
        if (false === $mac = base64_decode((string) array_shift($rdata), true)) {
199
            throw new ParseException('Unable to decode TSIG MAC. Malformed base64 string.');
200
        }
201 1
        $this->setMac($mac);
202
203 1
        $this->setOriginalId((int) array_shift($rdata));
204 1
        $this->setError((int) array_shift($rdata));
205
206 1
        if (false === $otherData = base64_decode((string) array_shift($rdata), true)) {
207
            throw new ParseException('Unable to decode TSIG other data. Malformed base64 string.');
208
        }
209 1
        $this->setOtherData($otherData);
210 1
    }
211
212
    /**
213
     * @throws DecodeException
214
     */
215 1
    public function fromWire(string $rdata, int &$offset = 0, ?int $rdLength = null): void
216
    {
217 1
        $this->setAlgorithmName(Message::decodeName($rdata, $offset));
218
219 1
        if (false === $args = unpack('n<hex1>/n<hex2>/n<hex3>/n<fudge>/n<macLen>', $rdata, $offset)) {
220 1
            throw new DecodeException(static::TYPE, $rdata);
221
        }
222 1
        $offset += 10;
223 1
224
        $timeSigned = ($args['<hex1>'] << 32) + ($args['<hex2>'] << 16) + $args['<hex3>'];
225
        if (false === $objTimeSigned = \DateTime::createFromFormat('U', (string) $timeSigned)) {
226
            throw new DecodeException(static::TYPE, $rdata);
227 1
        }
228 1
229 1
        $macLen = (int) $args['<macLen>'];
230 1
        $this->setFudge($args['<fudge>']);
231 1
        $this->setTimeSigned($objTimeSigned);
232
        $this->setMac(substr($rdata, $offset, $macLen));
233 1
        $offset += $macLen;
234 1
235 1
        if (false === $args = unpack('n<id>/n<error>/n<otherLen>', $rdata, (int) $offset)) {
236
            throw new DecodeException(static::TYPE, $rdata);
237 1
        }
238 1
        $offset += 6;
239 1
        $otherLen = (int) $args['<otherLen>'];
240 1
241 1
        $this->setOriginalId($args['<id>']);
242
        $this->setError($args['<error>']);
243
        $this->setOtherData(substr($rdata, (int) $offset, $otherLen));
244
        $offset += $otherLen;
245
    }
246
}
247