Issues (166)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

lib/Message.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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;
15
16
use Badcow\DNS\Rdata\DecodeException;
17
use Badcow\DNS\Rdata\UnsupportedTypeException;
18
19
class Message
20
{
21
    /**
22
     * ID.
23
     *
24
     * @var int
25
     */
26
    private $id;
27
28
    /**
29
     * QR.
30
     *
31
     * @var bool
32
     */
33
    private $isResponse;
34
35
    /**
36
     * OPCODE.
37
     *
38
     * @var int
39
     */
40
    private $opcode;
41
42
    /**
43
     * AA.
44
     *
45
     * @var bool
46
     */
47
    private $isAuthoritative;
48
49
    /**
50
     * TC.
51
     *
52
     * @var bool
53
     */
54
    private $isTruncated;
55
56
    /**
57
     * RD.
58
     *
59
     * @var bool
60
     */
61
    private $isRecursionDesired;
62
63
    /**
64
     * RA.
65
     *
66
     * @var bool
67
     */
68
    private $isRecursionAvailable;
69
70
    /**
71
     * Bit 9 of the header flags.
72
     *
73
     * @var int
74
     */
75
    private $bit9 = 0;
76
77
    /**
78
     * AD.
79
     *
80
     * {@link https://tools.ietf.org/html/rfc4035#section-3.2.3}
81
     *
82
     * @var bool
83
     */
84
    private $isAuthenticData;
85
86
    /**
87
     * CD.
88
     *
89
     * {@link https://tools.ietf.org/html/rfc4035#section-3.2.2}
90
     *
91
     * @var bool
92
     */
93
    private $isCheckingDisabled;
94
95
    /**
96
     * RCODE.
97
     *
98
     * @var int
99
     */
100
    private $rcode;
101
102
    /**
103
     * @var Question[]
104
     */
105
    private $questions = [];
106
107
    /**
108
     * @var ResourceRecord[]
109
     */
110
    private $answers = [];
111
112
    /**
113
     * @var ResourceRecord[]
114
     */
115
    private $authoritatives = [];
116
117
    /**
118
     * @var ResourceRecord[]
119
     */
120
    private $additionals = [];
121
122
    /**
123
     * Encode a domain name as a sequence of labels.
124 43
     */
125
    public static function encodeName(string $name): string
126 43
    {
127 3
        if ('.' === $name) {
128
            return chr(0);
129
        }
130 40
131 40
        $name = rtrim($name, '.').'.';
132
        $res = '';
133 40
134 40
        foreach (explode('.', $name) as $label) {
135
            $res .= chr(strlen($label)).$label;
136
        }
137 40
138
        return $res;
139
    }
140 30
141
    public static function decodeName(string $string, int &$offset = 0): string
142 30
    {
143 30
        $len = ord($string[$offset]);
144
        ++$offset;
145 30
146 30
        $isCompressed = (bool) (0b11000000 & $len);
147
        $_offset = 0;
148 30
149 7
        if ($isCompressed) {
150 7
            $_offset = $offset + 1;
151 7
            $offset = (0b00111111 & $len) * 256 + ord($string[$offset]);
152 7
            $len = ord($string[$offset]);
153
            ++$offset;
154
        }
155 30
156 3
        if (0 === $len) {
157
            return '.';
158
        }
159 27
160 27
        $name = '';
161 27
        while (0 !== $len) {
162 27
            $name .= substr($string, $offset, $len).'.';
163 27
            $offset += $len;
164 27
            $len = ord($string[$offset]);
165 7
            if ($len & 0b11000000) {
166 7
                $name .= self::decodeName($string, $offset);
167
                break;
168
            }
169 27
170
            ++$offset;
171
        }
172 27
173 7
        if ($isCompressed) {
174
            $offset = $_offset;
175
        }
176 27
177
        return $name;
178
    }
179 2
180
    public function getId(): int
181 2
    {
182
        return $this->id;
183
    }
184 8
185
    public function setId(int $id): void
186 8
    {
187 8
        $this->id = $id;
188
    }
189 2
190
    public function isResponse(): bool
191 2
    {
192
        return $this->isResponse;
193
    }
194 8
195
    public function setResponse(bool $isResponse): void
196 8
    {
197 8
        $this->isResponse = $isResponse;
198
    }
199 1
200
    public function isQuery(): bool
201 1
    {
202
        return !$this->isResponse;
203
    }
204 1
205
    public function setQuery(bool $query): void
206 1
    {
207 1
        $this->setResponse(!$query);
208
    }
209 2
210
    public function getOpcode(): int
211 2
    {
212
        return $this->opcode;
213
    }
214 7
215
    public function setOpcode(int $opcode): void
216 7
    {
217 7
        $this->opcode = $opcode;
218
    }
219 2
220
    public function isAuthoritative(): bool
221 2
    {
222
        return $this->isAuthoritative;
223
    }
224 7
225
    public function setAuthoritative(bool $isAuthoritative): void
226 7
    {
227 7
        $this->isAuthoritative = $isAuthoritative;
228
    }
229 2
230
    public function isTruncated(): bool
231 2
    {
232
        return $this->isTruncated;
233
    }
234 7
235
    public function setTruncated(bool $isTruncated): void
236 7
    {
237 7
        $this->isTruncated = $isTruncated;
238
    }
239 2
240
    public function isRecursionDesired(): bool
241 2
    {
242
        return $this->isRecursionDesired;
243
    }
244 7
245
    public function setRecursionDesired(bool $isRecursionDesired): void
246 7
    {
247 7
        $this->isRecursionDesired = $isRecursionDesired;
248
    }
249 2
250
    public function isRecursionAvailable(): bool
251 2
    {
252
        return $this->isRecursionAvailable;
253
    }
254 7
255
    public function setRecursionAvailable(bool $isRecursionAvailable): void
256 7
    {
257 7
        $this->isRecursionAvailable = $isRecursionAvailable;
258
    }
259 2
260
    public function getBit9(): int
261 2
    {
262
        return $this->bit9;
263
    }
264 7
265
    public function setBit9(int $bit9): void
266 7
    {
267 7
        $this->bit9 = $bit9;
268
    }
269 2
270
    public function isAuthenticData(): bool
271 2
    {
272
        return $this->isAuthenticData;
273
    }
274 7
275
    public function setAuthenticData(bool $isAuthenticData): void
276 7
    {
277 7
        $this->isAuthenticData = $isAuthenticData;
278
    }
279 2
280
    public function isCheckingDisabled(): bool
281 2
    {
282
        return $this->isCheckingDisabled;
283
    }
284 7
285
    public function setCheckingDisabled(bool $isCheckingDisabled): void
286 7
    {
287 7
        $this->isCheckingDisabled = $isCheckingDisabled;
288
    }
289 2
290
    public function getRcode(): int
291 2
    {
292
        return $this->rcode;
293
    }
294 7
295
    public function setRcode(int $rcode): void
296 7
    {
297 7
        $this->rcode = $rcode;
298
    }
299
300
    /**
301
     * @return Question[]
302 3
     */
303
    public function getQuestions(): array
304 3
    {
305
        return $this->questions;
306
    }
307 8
308
    public function addQuestion(Question $question): void
309 8
    {
310 8
        $this->questions[] = $question;
311
    }
312
313
    /**
314
     * @param Question[] $questions
315 1
     */
316
    public function setQuestions(array $questions): void
317 1
    {
318 1
        $this->questions = [];
319 1
        foreach ($questions as $question) {
320
            $this->addQuestion($question);
321 1
        }
322
    }
323
324
    /**
325
     * @return ResourceRecord[]
326 3
     */
327
    public function getAnswers(): array
328 3
    {
329
        return $this->answers;
330
    }
331 7
332
    public function addAnswer(ResourceRecord $answer): void
333 7
    {
334 7
        $this->answers[] = $answer;
335
    }
336
337
    /**
338
     * @param ResourceRecord[] $answers
339 7
     */
340
    public function setAnswers(array $answers): void
341 7
    {
342 7
        $this->answers = [];
343 7
        foreach ($answers as $answer) {
344
            $this->addAnswer($answer);
345 7
        }
346
    }
347
348
    /**
349
     * @return ResourceRecord[]
350 2
     */
351
    public function getAuthoritatives(): array
352 2
    {
353
        return $this->authoritatives;
354
    }
355 5
356
    public function addAuthoritative(ResourceRecord $authoritative): void
357 5
    {
358 5
        $this->authoritatives[] = $authoritative;
359
    }
360
361
    /**
362
     * @param ResourceRecord[] $authoritatives
363 7
     */
364
    public function setAuthoritatives(array $authoritatives): void
365 7
    {
366 7
        $this->authoritatives = [];
367 5
        foreach ($authoritatives as $authoritative) {
368
            $this->addAuthoritative($authoritative);
369 7
        }
370
    }
371
372
    /**
373
     * @return ResourceRecord[]
374 3
     */
375
    public function getAdditionals(): array
376 3
    {
377
        return $this->additionals;
378
    }
379 7
380
    public function addAdditional(ResourceRecord $additional): void
381 7
    {
382 7
        $this->additionals[] = $additional;
383
    }
384
385
    /**
386
     * @param ResourceRecord[] $additionals
387 7
     */
388
    public function setAdditionals(array $additionals): void
389 7
    {
390 7
        $this->additionals = [];
391 7
        foreach ($additionals as $additional) {
392
            $this->addAdditional($additional);
393 7
        }
394
    }
395 6
396
    public function countQuestions(): int
397 6
    {
398
        return count($this->questions);
399
    }
400 6
401
    public function countAnswers(): int
402 6
    {
403
        return count($this->answers);
404
    }
405 6
406
    public function countAuthoritatives(): int
407 6
    {
408
        return count($this->authoritatives);
409
    }
410 6
411
    public function countAdditionals(): int
412 6
    {
413
        return count($this->additionals);
414
    }
415
416
    /**
417
     * @throws UnsetValueException
418 3
     */
419
    public function toWire(): string
420
    {
421 3
        $flags = 0x0 |
422 3
        ($this->isResponse & 0x1) << 15 |
423 3
        ($this->opcode & 0xf) << 11 |
424 3
        ($this->isAuthoritative & 0x1) << 10 |
425 3
        ($this->isTruncated & 0x1) << 9 |
426 3
        ($this->isRecursionDesired & 0x1) << 8 |
427 3
        ($this->isRecursionAvailable & 0x1) << 7 |
428 3
        ($this->bit9 & 0x1) << 6 |
429 3
        ($this->isAuthenticData & 0x1) << 5 |
430 3
        ($this->isCheckingDisabled & 0x1) << 4 |
431
        ($this->rcode & 0xf);
432 3
433 3
        $encoded = pack(
434 3
            'nnnnnn',
435
            $this->id,
436 3
            $flags,
437 3
            $this->countQuestions(),
438 3
            $this->countAnswers(),
439 3
            $this->countAuthoritatives(),
440
            $this->countAdditionals()
441
        );
442 3
443
        foreach (array_merge($this->questions, $this->answers, $this->authoritatives, $this->additionals) as $resource) {
444 3
            /* @var ResourceRecord|Question $resource */
445
            $encoded .= $resource->toWire();
446
        }
447 3
448
        return $encoded;
449
    }
450
451
    /**
452
     * @throws UnsupportedTypeException
453 7
     */
454
    public static function fromWire(string $encoded): Message
455 7
    {
456 7
        $message = new self();
457 7
        $offset = 0;
458 7 View Code Duplication
        if (false === $header = unpack('nid/nflags/nqdcount/nancount/nnscount/narcount', $encoded, $offset)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
459 7
            throw new \UnexpectedValueException(sprintf('Malformed header encountered. "%s"', DecodeException::binaryToHex($encoded)));
460
        }
461 7
        $offset += 12;
462 7
        $flags = $header['flags'];
463 7
464 7
        $message->setId($header['id']);
465 7
        $message->setResponse((bool) ($flags >> 15 & 0x1));
466 7
        $message->setOpcode($flags >> 11 & 0xf);
467 7
        $message->setAuthoritative((bool) ($flags >> 10 & 0x1));
468 7
        $message->setTruncated((bool) ($flags >> 9 & 0x1));
469 7
        $message->setRecursionDesired((bool) ($flags >> 8 & 0x1));
470 7
        $message->setRecursionAvailable((bool) ($flags >> 7 & 0x1));
471 7
        $message->setBit9($flags >> 6 & 0x1);
472
        $message->setAuthenticData((bool) ($flags >> 5 & 0x1));
473 7
        $message->setCheckingDisabled((bool) ($flags >> 4 & 0x1));
474 7
        $message->setRcode($flags & 0xf);
475
476
        for ($i = 0; $i < $header['qdcount']; ++$i) {
477 7
            $message->addQuestion(Question::fromWire($encoded, $offset));
478 7
        }
479 7
480
        $rrs = [];
481
        while ($offset < strlen($encoded)) {
482 7
            $rrs[] = ResourceRecord::fromWire($encoded, $offset);
483 7
        }
484 7
485
        $message->setAnswers(array_splice($rrs, 0, $header['ancount']));
486 7
        $message->setAuthoritatives(array_splice($rrs, 0, $header['nscount']));
487
        $message->setAdditionals(array_splice($rrs, 0, $header['arcount']));
488
489
        return $message;
490
    }
491
}
492