Completed
Branch Version3 (22030a)
by Sam
01:45
created

TKEY::fromText()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3.0213

Importance

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