Passed
Push — master ( 1b54b9...ff455f )
by Sam
10:10 queued 11s
created

TKEY::fromWire()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 29
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 3.0067

Importance

Changes 0
Metric Value
cc 3
eloc 21
nc 3
nop 3
dl 0
loc 29
ccs 20
cts 22
cp 0.9091
crap 3.0067
rs 9.584
c 0
b 0
f 0
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\Tokens;
18
use Badcow\DNS\Validator;
19
20
/**
21
 * {@link https://tools.ietf.org/html/rfc2930}.
22
 */
23
class TKEY implements RdataInterface
24
{
25
    use RdataTrait;
26
27
    const TYPE = 'TKEY';
28
    const TYPE_CODE = 249;
29
30
    /**
31
     * The algorithm name is in the form of a domain name with the same
32
     * meaning as in [RFC 2845]{@link https://tools.ietf.org/html/rfc2845}.
33
     * The algorithm determines how the secret keying material agreed to
34
     * using the TKEY RR is actually used to derive the algorithm specific key.
35
     *
36
     * @var string
37
     */
38
    private $algorithm;
39
40
    /**
41
     * @var \DateTime
42
     */
43
    private $inception;
44
45
    /**
46
     * @var \DateTime
47
     */
48
    private $expiration;
49
50
    /**
51
     * The mode field specifies the general scheme for key agreement or the
52
     * purpose of the TKEY DNS message. 16-bit integer.
53
     *
54
     * The following values of the Mode octet are defined, available, or reserved:
55
     *
56
     *      Value    Description
57
     *      -----    -----------
58
     *      0        - reserved, see section 7
59
     *      1       server assignment
60
     *      2       Diffie-Hellman exchange
61
     *      3       GSS-API negotiation
62
     *      4       resolver assignment
63
     *      5       key deletion
64
     *      6-65534   - available, see section 7
65
     *      65535     - reserved, see section 7
66
     *
67
     * @var int
68
     */
69
    private $mode;
70
71
    /**
72
     * The error code field is an extended RCODE.  The following values are defined:.
73
     *
74
     *      Value   Description
75
     *      -----   -----------
76
     *      0       - no error
77
     *      1-15   a non-extended RCODE
78
     *      16     BADSIG   (TSIG)
79
     *      17     BADKEY   (TSIG)
80
     *      18     BADTIME  (TSIG)
81
     *      19     BADMODE
82
     *      20     BADNAME
83
     *      21     BADALG
84
     *
85
     * @var int
86
     */
87
    private $error = 0;
88
89
    /**
90
     * @var string
91
     */
92
    private $keyData;
93
94
    /**
95
     * @var string
96
     */
97
    private $otherData;
98
99
    /**
100
     * @return string
101
     */
102 1
    public function getAlgorithm(): string
103
    {
104 1
        return $this->algorithm;
105
    }
106
107
    /**
108
     * @param string $algorithm
109
     */
110 4
    public function setAlgorithm(string $algorithm): void
111
    {
112 4
        if (!Validator::fullyQualifiedDomainName($algorithm)) {
113
            throw new \InvalidArgumentException('Algorithm must be a fully qualified domain name.');
114
        }
115 4
        $this->algorithm = $algorithm;
116 4
    }
117
118
    /**
119
     * @return \DateTime
120
     */
121 1
    public function getInception(): \DateTime
122
    {
123 1
        return $this->inception;
124
    }
125
126
    /**
127
     * @param \DateTime $inception
128
     */
129 4
    public function setInception(\DateTime $inception): void
130
    {
131 4
        $this->inception = $inception;
132 4
    }
133
134
    /**
135
     * @return \DateTime
136
     */
137 1
    public function getExpiration(): \DateTime
138
    {
139 1
        return $this->expiration;
140
    }
141
142
    /**
143
     * @param \DateTime $expiration
144
     */
145 4
    public function setExpiration(\DateTime $expiration): void
146
    {
147 4
        $this->expiration = $expiration;
148 4
    }
149
150
    /**
151
     * @return int
152
     */
153 1
    public function getMode(): int
154
    {
155 1
        return $this->mode;
156
    }
157
158
    /**
159
     * @param int $mode
160
     */
161 4
    public function setMode(int $mode): void
162
    {
163 4
        if (!Validator::isUnsignedInteger($mode, 16)) {
164
            throw new \InvalidArgumentException('Mode must be 16-bit integer.');
165
        }
166 4
        $this->mode = $mode;
167 4
    }
168
169
    /**
170
     * @return int
171
     */
172 1
    public function getError(): int
173
    {
174 1
        return $this->error;
175
    }
176
177
    /**
178
     * @param int $error
179
     */
180 4
    public function setError(int $error): void
181
    {
182 4
        if (!Validator::isUnsignedInteger($error, 16)) {
183
            throw new \InvalidArgumentException('Error must be 16-bit integer.');
184
        }
185 4
        $this->error = $error;
186 4
    }
187
188
    /**
189
     * @return string
190
     */
191 1
    public function getKeyData(): string
192
    {
193 1
        return $this->keyData;
194
    }
195
196
    /**
197
     * @param string $keyData binary stream
198
     */
199 4
    public function setKeyData(string $keyData): void
200
    {
201 4
        $this->keyData = $keyData;
202 4
    }
203
204
    /**
205
     * @return string
206
     */
207 1
    public function getOtherData(): string
208
    {
209 1
        return $this->otherData;
210
    }
211
212
    /**
213
     * @param string $otherData binary stream
214
     */
215 4
    public function setOtherData(string $otherData): void
216
    {
217 4
        $this->otherData = $otherData;
218 4
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223 1
    public function toText(): string
224
    {
225 1
        return sprintf('%s %d %d %d %d %s %s',
226 1
            $this->algorithm,
227 1
            $this->inception->format('U'),
228 1
            $this->expiration->format('U'),
229 1
            $this->mode,
230 1
            $this->error,
231 1
            base64_encode($this->keyData),
232 1
            base64_encode($this->otherData)
233
        );
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239 1
    public function toWire(): string
240
    {
241 1
        $wire = Message::encodeName($this->algorithm);
242 1
        $wire .= pack('NNnnn',
243 1
            $this->inception->format('U'),
244 1
            $this->expiration->format('U'),
245 1
            $this->mode,
246 1
            $this->error,
247 1
            strlen($this->keyData)
248
        );
249 1
        $wire .= $this->keyData;
250 1
        $wire .= pack('n', strlen($this->otherData));
251 1
        $wire .= $this->otherData;
252
253 1
        return $wire;
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259 1
    public function fromText(string $text): void
260
    {
261 1
        $rdata = explode(Tokens::SPACE, $text);
262 1
        $this->setAlgorithm((string) array_shift($rdata));
263 1
        if (false === $inception = \DateTime::createFromFormat('U', (string) array_shift($rdata))) {
264
            throw new \UnexpectedValueException('Unable to parse inception date of TKEY Rdata.');
265
        }
266 1
        $this->setInception($inception);
267
268 1
        if (false === $expiration = \DateTime::createFromFormat('U', (string) array_shift($rdata))) {
269
            throw new \UnexpectedValueException('Unable to parse expiration date of TKEY Rdata.');
270
        }
271 1
        $this->setExpiration($expiration);
272
273 1
        $this->setMode((int) array_shift($rdata));
274 1
        $this->setError((int) array_shift($rdata));
275 1
        $this->setKeyData((string) base64_decode((string) array_shift($rdata)));
276 1
        $this->setOtherData((string) base64_decode((string) array_shift($rdata)));
277 1
    }
278
279
    /**
280
     * {@inheritdoc}
281
     */
282 1
    public function fromWire(string $rdata, int &$offset = 0, ?int $rdLength = null): void
283
    {
284 1
        $algorithm = Message::decodeName($rdata, $offset);
285 1
        $integers = unpack('N<inception>/N<expiration>/n<mode>/n<error>/n<keySize>', $rdata, $offset);
286 1
        $offset += 14;
287 1
        $keySize = (int) $integers['<keySize>'];
288 1
        $keyData = substr($rdata, $offset, $keySize);
289 1
        $offset = (int) $offset + $keySize;
290 1
        $otherDataSize = unpack('n', $rdata, $offset)[1];
291 1
        $offset += 2;
292 1
        $otherData = substr($rdata, $offset, $otherDataSize);
293 1
        $offset += $otherDataSize;
294
295 1
        $this->setAlgorithm($algorithm);
296
297 1
        if (false === $inception = \DateTime::createFromFormat('U', (string) $integers['<inception>'])) {
298
            throw new \UnexpectedValueException('Unable to parse inception date of TKEY Rdata.');
299
        }
300 1
        $this->setInception($inception);
301
302 1
        if (false === $expiration = \DateTime::createFromFormat('U', (string) $integers['<expiration>'])) {
303
            throw new \UnexpectedValueException('Unable to parse expiration date of TKEY Rdata.');
304
        }
305 1
        $this->setExpiration($expiration);
306
307 1
        $this->setMode((int) $integers['<mode>']);
308 1
        $this->setError((int) $integers['<error>']);
309 1
        $this->setKeyData($keyData);
310 1
        $this->setOtherData($otherData);
311 1
    }
312
}
313