TKEY   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 246
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 93%

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 4
dl 0
loc 246
ccs 93
cts 100
cp 0.93
rs 10
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getAlgorithm() 0 4 1
A setAlgorithm() 0 7 2
A getInception() 0 4 1
A setInception() 0 4 1
A getExpiration() 0 4 1
A setExpiration() 0 4 1
A getMode() 0 4 1
A setMode() 0 7 2
A getError() 0 4 1
A setError() 0 7 2
A getKeyData() 0 4 1
A setKeyData() 0 4 1
A getOtherData() 0 4 1
A setOtherData() 0 4 1
A toText() 0 12 1
A toWire() 0 16 1
A fromText() 0 19 3
A fromWire() 0 34 5
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 1
    public function toText(): string
185
    {
186 1
        return sprintf('%s %d %d %d %d %s %s',
187 1
            $this->algorithm,
188 1
            $this->inception->format('U'),
189 1
            $this->expiration->format('U'),
190 1
            $this->mode,
191 1
            $this->error,
192 1
            base64_encode($this->keyData),
193 1
            base64_encode($this->otherData)
194
        );
195
    }
196
197 1
    public function toWire(): string
198
    {
199 1
        $wire = Message::encodeName($this->algorithm);
200 1
        $wire .= pack('NNnnn',
201 1
            $this->inception->format('U'),
202 1
            $this->expiration->format('U'),
203 1
            $this->mode,
204 1
            $this->error,
205 1
            strlen($this->keyData)
206
        );
207 1
        $wire .= $this->keyData;
208 1
        $wire .= pack('n', strlen($this->otherData));
209 1
        $wire .= $this->otherData;
210
211 1
        return $wire;
212
    }
213
214 1
    public function fromText(string $text): void
215
    {
216 1
        $rdata = explode(Tokens::SPACE, $text);
217 1
        $this->setAlgorithm((string) array_shift($rdata));
218 1
        if (false === $inception = \DateTime::createFromFormat('U', (string) array_shift($rdata))) {
219
            throw new \UnexpectedValueException('Unable to parse inception date of TKEY Rdata.');
220
        }
221 1
        $this->setInception($inception);
222
223 1
        if (false === $expiration = \DateTime::createFromFormat('U', (string) array_shift($rdata))) {
224
            throw new \UnexpectedValueException('Unable to parse expiration date of TKEY Rdata.');
225
        }
226 1
        $this->setExpiration($expiration);
227
228 1
        $this->setMode((int) array_shift($rdata));
229 1
        $this->setError((int) array_shift($rdata));
230 1
        $this->setKeyData((string) base64_decode((string) array_shift($rdata)));
231 1
        $this->setOtherData((string) base64_decode((string) array_shift($rdata)));
232 1
    }
233
234 1
    public function fromWire(string $rdata, int &$offset = 0, ?int $rdLength = null): void
235
    {
236 1
        $algorithm = Message::decodeName($rdata, $offset);
237 1
        if (false === $integers = unpack('N<inception>/N<expiration>/n<mode>/n<error>/n<keySize>', $rdata, $offset)) {
238 1
            throw new DecodeException(static::TYPE, $rdata);
239 1
        }
240 1
        $offset += 14;
241 1
        $keySize = (int) $integers['<keySize>'];
242 1
        $keyData = substr($rdata, $offset, $keySize);
243 1
        $offset = (int) $offset + $keySize;
244 1
        if (false === $otherDataSize = unpack('n', $rdata, $offset)) {
245 1
            throw new DecodeException(static::TYPE, $rdata);
246
        }
247 1
        $offset += 2;
248
        $otherData = substr($rdata, $offset, $otherDataSize[1]);
249 1
        $offset += $otherDataSize[1];
250
251
        $this->setAlgorithm($algorithm);
252 1
253
        if (false === $inception = \DateTime::createFromFormat('U', (string) $integers['<inception>'])) {
254 1
            throw new \UnexpectedValueException('Unable to parse inception date of TKEY Rdata.');
255
        }
256
        $this->setInception($inception);
257 1
258
        if (false === $expiration = \DateTime::createFromFormat('U', (string) $integers['<expiration>'])) {
259 1
            throw new \UnexpectedValueException('Unable to parse expiration date of TKEY Rdata.');
260 1
        }
261 1
        $this->setExpiration($expiration);
262 1
263 1
        $this->setMode((int) $integers['<mode>']);
264
        $this->setError((int) $integers['<error>']);
265
        $this->setKeyData($keyData);
266
        $this->setOtherData($otherData);
267
    }
268
}
269