Issues (1507)

Security Analysis    not enabled

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.

PHPDaemon/Servers/IRCBouncer/Connection.php (13 issues)

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
namespace PHPDaemon\Servers\IRCBouncer;
3
4
use PHPDaemon\Core\Daemon;
5
use PHPDaemon\Core\Timer;
6
use PHPDaemon\Utils\IRC;
7
8
/**
9
 * @package    NetworkServers
10
 * @subpackage IRCBouncer
11
 * @author     Vasily Zorin <[email protected]>
12
 */
13
class Connection extends \PHPDaemon\Network\Connection
14
{
15
16
    /**
17
     * @var string
18
     */
19
    public $EOL = "\r\n";
20
21
    /**
22
     * @var object
23
     */
24
    public $attachedServer;
25
26
    /**
27
     * @var string
28
     */
29
    public $usermask;
30
31
    /**
32
     * @var integer
33
     */
34
    public $latency;
35
36
    /**
37
     * @var integer
38
     */
39
    public $lastPingTS;
40
41
    /**
42
     * @var integer
43
     */
44
    public $timeout = 180;
45
46
    /**
47
     * @var boolean
48
     */
49
    public $protologging = false;
50
51
    /**
52
     * Called when the connection is handshaked (at low-level), and peer is ready to recv. data
53
     * @return void
54
     */
55
    public function onReady()
56
    {
57
        $conn = $this;
58
        $this->keepaliveTimer = setTimeout(function ($timer) use ($conn) {
0 ignored issues
show
The property keepaliveTimer does not seem to exist. Did you mean keepalive?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
The parameter $timer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
59
            $conn->ping();
60
        }, 10e6);
61
    }
62
63
    /**
64
     * @TODO DESCR
65
     */
66
    public function onFinish()
67
    {
68
        if ($this->attachedServer) {
69
            $this->attachedServer->attachedClients->detach($this);
70
        }
71
        Timer::remove($this->keepaliveTimer);
0 ignored issues
show
The property keepaliveTimer does not seem to exist. Did you mean keepalive?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
72
        parent::onFinish();
73
    }
74
75
    /**
76
     * @TODO DESCR
77
     */
78
    public function ping()
79
    {
80
        $this->lastPingTS = microtime(true);
0 ignored issues
show
Documentation Bug introduced by
The property $lastPingTS was declared of type integer, but microtime(true) is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
81
        $this->writeln('PING :' . $this->usermask);
82
        Timer::setTimeout($this->keepaliveTimer);
0 ignored issues
show
The property keepaliveTimer does not seem to exist. Did you mean keepalive?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
83
    }
84
85
    /**
86
     * @TODO DESCR
87
     * @param  string $from From
88
     * @param  string $cmd Command
89
     * @param  mixed ...$args Arguments
90
     */
91
    public function command($from, $cmd)
92
    {
93
        if ($from === null) {
94
            $from = $this->pool->config->servername->value;
95
        }
96
        $cmd = IRC::getCodeByCommand($cmd);
97
        $line = ':' . $from . ' ' . $cmd;
98 View Code Duplication
        for ($i = 2, $s = func_num_args(); $i < $s; ++$i) {
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...
99
            $arg = func_get_arg($i);
100
            if (($i + 1 === $s) && (mb_orig_strpos($arg, "\x20") !== false)) {
101
                $line .= ' :';
102
            } else {
103
                $line .= ' ';
104
            }
105
            $line .= $arg;
106
        }
107
        $this->writeln($line);
108
        if ($this->pool->protologging && $cmd !== 'PONG') {
109
            Daemon::log('=>=>=>=> ' . json_encode($line));
110
        }
111
    }
112
113
    /**
114
     * @TODO
115
     * @param  string $from From
116
     * @param  string $cmd Command
117
     * @param  array $args Arguments
118
     */
119
    public function commandArr($from, $cmd, $args)
120
    {
121
        if ($from === null) {
122
            $from = $this->pool->config->servername->value;
123
        }
124
        if (is_string($args)) {
125
            Daemon::log(get_class($this) . '->commandArr: args is string');
126
            return;
127
        }
128
        $cmd = IRC::getCodeByCommand($cmd);
129
        $line = ':' . $from . ' ' . $cmd;
130 View Code Duplication
        for ($i = 0, $s = sizeof($args); $i < $s; ++$i) {
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...
131
            if (($i + 1 === $s) && (mb_orig_strpos($args[$i], "\x20") !== false)) {
132
                $line .= ' :';
133
            } else {
134
                $line .= ' ';
135
            }
136
            $line .= $args[$i];
137
        }
138
        $this->writeln($line);
139
        if ($this->pool->protologging && $cmd !== 'PONG') {
140
            Daemon::log('=>=>=>=> ' . json_encode($line));
141
        }
142
    }
143
144
    /**
145
     * @TODO DESCR
146
     */
147
    public function detach()
148
    {
149
        if ($this->attachedServer) {
150
            $this->attachedServer->attachedClients->detach($this);
151
            $this->attachedServer = null;
152
        }
153
    }
154
155
    /**
156
     * @TODO DESCR
157
     */
158
    public function attachTo()
159
    {
160
        if ($this->pool->conn) {
161
            $this->attachedServer = $this->pool->conn;
162
            $this->attachedServer->attachedClients->attach($this);
163
        } else {
164
            return;
165
        }
166
        $this->msgFromBNC('Attached to ' . $this->attachedServer->url);
167
        $this->usermask = $this->attachedServer->nick . '!' . $this->attachedServer->user . '@' . $this->pool->config->servername->value;
168
        $this->command(null, 'RPL_WELCOME', $this->attachedServer->nick,
169
            'Welcome to phpDaemon bouncer -- ' . $this->pool->config->servername->value);
170
        foreach ($this->attachedServer->channels as $chan) {
171
            $this->exportChannel($chan);
172
        }
173
    }
174
175
    /**
176
     * @TODO DESCR
177
     * @param object $chan
178
     */
179
    public function exportChannel($chan)
180
    {
181
        $this->command($this->usermask, 'JOIN', $chan->name);
182
        $this->command($this->usermask, 'RPL_TOPIC', $chan->irc->nick, $chan->name, $chan->topic);
183
        $names = $chan->exportNicksArray();
184
        $packet = '';
185
        $maxlen = 510 - 7 - mb_orig_strlen($this->pool->config->servername->value) - $chan->irc->nick - 1;
186
        for ($i = 0, $s = sizeof($names); $i < $s; ++$i) {
187
            $packet .= ($packet !== '' ? ' ' : '') . $names[$i];
188
            if (!isset($names[$i + 1]) || (mb_orig_strlen($packet) + mb_orig_strlen($names[$i + 1]) + 1 > $maxlen)) {
189
                $this->command(null, 'RPL_NAMREPLY', $chan->irc->nick, $chan->type, $chan->name, $packet);
190
                $packet = '';
191
            }
192
        }
193
        $this->command(null, 'RPL_ENDOFNAMES', $chan->irc->nick, $chan->name, 'End of /NAMES list');
194
    }
195
196
    /**
197
     * @TODO DESCR
198
     * @param string $cmd Command
199
     * @param array $args Arguments
200
     */
201
    public function onCommand($cmd, $args)
202
    {
203
        if ($cmd === 'USER') {
204
            //list ($nick) = $args;
205
            $this->attachTo();
206
            return;
207
        } elseif ($cmd === 'QUIT') {
208
            $this->finish();
209
            return;
210
        } elseif ($cmd === 'PING') {
211
            $this->writeln(isset($args[0]) ? 'PONG :' . $args[0] : 'PONG');
212
            return;
213 View Code Duplication
        } elseif ($cmd === 'PONG') {
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...
214
            if ($this->lastPingTS) {
215
                $this->latency = microtime(true) - $this->lastPingTS;
0 ignored issues
show
Documentation Bug introduced by
The property $latency was declared of type integer, but microtime(true) - $this->lastPingTS is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
216
                $this->lastPingTS = null;
217
                $this->event('lantency');
218
            }
219
            return;
220
        } elseif ($cmd === 'NICK') {
221
            return;
222
        } elseif ($cmd === 'PRIVMSG') {
223
            list($target, $msg) = $args;
224
            if ($target === '$') {
225
                if (preg_match('~^\s*(NICK\s+\S+|DETACH|ATTACH|BYE)\s*$~i', $msg, $m)) {
226
                    $clientCmd = strtoupper($m[1]);
227
                    if ($clientCmd === 'NICK') {
228
                    } elseif ($clientCmd === 'DETACH') {
229
                        $this->detach();
230
                        $this->msgFromBNC('Detached.');
231
                    } elseif ($clientCmd === 'ATTACH') {
232
                        $this->attachTo();
233
                    } elseif ($clientCmd === 'BYE') {
234
                        $this->detach();
235
                        $this->msgFromBNC('Bye-bye.');
236
                        $this->finish();
237
                    }
238
                } else {
239
                    $this->msgFromBNC('Unknown command: ' . $msg);
240
                }
241
                return;
242
            }
243
            $this->pool->messages->insert([
244
                'from' => $this->usermask,
245
                'to' => $target,
246
                'body' => $msg,
247
                'ts' => microtime(true),
248
                'dir' => 'o',
249
            ]);
250
        }
251
        if ($this->attachedServer) {
252
            $this->attachedServer->commandArr($cmd, $args);
253
        }
254
        if ($this->protologging) {
255
            Daemon::$process->log('<=<=<=< ' . $cmd . ': ' . json_encode($args));
256
        }
257
    }
258
259
    /**
260
     * @TODO DESCR
261
     * @param string $msg
262
     */
263
    public function msgFromBNC($msg)
264
    {
265
        if ($this->usermask === null) {
266
            return;
267
        }
268
        $this->command('$!@' . $this->pool->config->servername->value, 'PRIVMSG', $this->usermask, $msg);
269
    }
270
271
    /**
272
     * Called when new data received
273
     * @return void
274
     */
275
    public function onRead()
276
    {
277
        Timer::setTimeout($this->keepaliveTimer);
0 ignored issues
show
The property keepaliveTimer does not seem to exist. Did you mean keepalive?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
278
        while (($line = $this->readline()) !== null) {
279
            if ($line === '') {
280
                continue;
281
            }
282
            if (mb_orig_strlen($line) > 512) {
283
                Daemon::$process->log('IRCBouncerConnection error: buffer overflow.');
284
                $this->finish();
285
                return;
286
            }
287
            $line = mb_orig_substr($line, 0, -mb_orig_strlen($this->EOL));
288
            $p = mb_orig_strpos($line, ':', 1);
289
            $max = $p ? substr_count($line, "\x20", 0, $p) + 1 : 18;
290
            $e = explode("\x20", $line, $max);
291
            $i = 0;
292
            $cmd = $e[$i++];
293
            $args = [];
294
295 View Code Duplication
            for ($s = min(sizeof($e), 14); $i < $s; ++$i) {
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...
296
                if ($e[$i][0] === ':') {
297
                    $args[] = mb_orig_substr($e[$i], 1);
298
                    break;
299
                }
300
                $args[] = $e[$i];
301
            }
302
303 View Code Duplication
            if (ctype_digit($cmd)) {
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...
304
                $code = (int)$cmd;
305
                $cmd = isset(IRC::$codes[$code]) ? IRC::$codes[$code] : 'UNKNOWN-' . $code;
306
            }
307
            $this->onCommand($cmd, $args);
308
        }
309
        if (mb_orig_strlen($this->buf) > 512) {
0 ignored issues
show
The property buf does not exist on object<PHPDaemon\Servers\IRCBouncer\Connection>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
310
            Daemon::$process->log('IRCClientConnection error: buffer overflow.');
311
            $this->finish();
312
        }
313
    }
314
}
315