Completed
Push — master ( fe5fd9...28190b )
by Sam
07:00 queued 04:19
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 1
    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 1
    public function getAlgorithm(): string
100
    {
101 1
        return $this->algorithm;
102
    }
103
104 4
    public function setAlgorithm(string $algorithm): void
105
    {
106 4
        if (!Validator::fullyQualifiedDomainName($algorithm)) {
107
            throw new \InvalidArgumentException('Algorithm must be a fully qualified domain name.');
108
        }
109 4
        $this->algorithm = $algorithm;
110 4
    }
111
112 1
    public function getInception(): \DateTime
113
    {
114 1
        return $this->inception;
115
    }
116
117 4
    public function setInception(\DateTime $inception): void
118
    {
119 4
        $this->inception = $inception;
120 4
    }
121
122 1
    public function getExpiration(): \DateTime
123
    {
124 1
        return $this->expiration;
125
    }
126
127 4
    public function setExpiration(\DateTime $expiration): void
128
    {
129 4
        $this->expiration = $expiration;
130 4
    }
131
132 1
    public function getMode(): int
133
    {
134 1
        return $this->mode;
135
    }
136
137 4
    public function setMode(int $mode): void
138
    {
139 4
        if (!Validator::isUnsignedInteger($mode, 16)) {
140
            throw new \InvalidArgumentException('Mode must be 16-bit integer.');
141
        }
142 4
        $this->mode = $mode;
143 4
    }
144
145 1
    public function getError(): int
146
    {
147 1
        return $this->error;
148
    }
149
150 4
    public function setError(int $error): void
151
    {
152 4
        if (!Validator::isUnsignedInteger($error, 16)) {
153
            throw new \InvalidArgumentException('Error must be 16-bit integer.');
154
        }
155 4
        $this->error = $error;
156 4
    }
157
158 1
    public function getKeyData(): string
159
    {
160 1
        return $this->keyData;
161
    }
162
163
    /**
164
     * @param string $keyData binary stream
165
     */
166 4
    public function setKeyData(string $keyData): void
167
    {
168 4
        $this->keyData = $keyData;
169 4
    }
170
171 1
    public function getOtherData(): string
172
    {
173 1
        return $this->otherData;
174
    }
175
176
    /**
177
     * @param string $otherData binary stream
178
     */
179 4
    public function setOtherData(string $otherData): void
180
    {
181 4
        $this->otherData = $otherData;
182 4
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187 1
    public function toText(): string
188
    {
189 1
        return sprintf('%s %d %d %d %d %s %s',
190 1
            $this->algorithm,
191 1
            $this->inception->format('U'),
192 1
            $this->expiration->format('U'),
193 1
            $this->mode,
194 1
            $this->error,
195 1
            base64_encode($this->keyData),
196 1
            base64_encode($this->otherData)
197
        );
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203 1
    public function toWire(): string
204
    {
205 1
        $wire = Message::encodeName($this->algorithm);
206 1
        $wire .= pack('NNnnn',
207 1
            $this->inception->format('U'),
208 1
            $this->expiration->format('U'),
209 1
            $this->mode,
210 1
            $this->error,
211 1
            strlen($this->keyData)
212
        );
213 1
        $wire .= $this->keyData;
214 1
        $wire .= pack('n', strlen($this->otherData));
215 1
        $wire .= $this->otherData;
216
217 1
        return $wire;
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223 1
    public function fromText(string $text): void
224
    {
225 1
        $rdata = explode(Tokens::SPACE, $text);
226 1
        $this->setAlgorithm((string) array_shift($rdata));
227 1
        if (false === $inception = \DateTime::createFromFormat('U', (string) array_shift($rdata))) {
228
            throw new \UnexpectedValueException('Unable to parse inception date of TKEY Rdata.');
229
        }
230 1
        $this->setInception($inception);
231
232 1
        if (false === $expiration = \DateTime::createFromFormat('U', (string) array_shift($rdata))) {
233
            throw new \UnexpectedValueException('Unable to parse expiration date of TKEY Rdata.');
234
        }
235 1
        $this->setExpiration($expiration);
236
237 1
        $this->setMode((int) array_shift($rdata));
238 1
        $this->setError((int) array_shift($rdata));
239 1
        $this->setKeyData((string) base64_decode((string) array_shift($rdata)));
240 1
        $this->setOtherData((string) base64_decode((string) array_shift($rdata)));
241 1
    }
242
243
    /**
244
     * {@inheritdoc}
245
     */
246 1
    public function fromWire(string $rdata, int &$offset = 0, ?int $rdLength = null): void
247
    {
248 1
        $algorithm = Message::decodeName($rdata, $offset);
249 1
        $integers = unpack('N<inception>/N<expiration>/n<mode>/n<error>/n<keySize>', $rdata, $offset);
250 1
        $offset += 14;
251 1
        $keySize = (int) $integers['<keySize>'];
252 1
        $keyData = substr($rdata, $offset, $keySize);
253 1
        $offset = (int) $offset + $keySize;
254 1
        $otherDataSize = unpack('n', $rdata, $offset)[1];
255 1
        $offset += 2;
256 1
        $otherData = substr($rdata, $offset, $otherDataSize);
257 1
        $offset += $otherDataSize;
258
259 1
        $this->setAlgorithm($algorithm);
260
261 1
        if (false === $inception = \DateTime::createFromFormat('U', (string) $integers['<inception>'])) {
262
            throw new \UnexpectedValueException('Unable to parse inception date of TKEY Rdata.');
263
        }
264 1
        $this->setInception($inception);
265
266 1
        if (false === $expiration = \DateTime::createFromFormat('U', (string) $integers['<expiration>'])) {
267
            throw new \UnexpectedValueException('Unable to parse expiration date of TKEY Rdata.');
268
        }
269 1
        $this->setExpiration($expiration);
270
271 1
        $this->setMode((int) $integers['<mode>']);
272 1
        $this->setError((int) $integers['<error>']);
273 1
        $this->setKeyData($keyData);
274 1
        $this->setOtherData($otherData);
275 1
    }
276
}
277