GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 144a2d...5488bd )
by Greg
02:09
created

SecureShell::getConnection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace Codeception\Extension;
3
4
use Codeception\Exception\ModuleException;
5
use Codeception\Exception\ModuleConfigException;
6
use Codeception\Module;
7
use \SplFileObject;
8
use \RuntimeException;
9
use \Exception;
10
11
class SecureShell extends Module
12
{
13
14
    const DEFAULT_PORT  = 22;
15
    const AUTH_PASSWORD = 1;
16
    const AUTH_PUBKEY   = 2;
17
    const AUTH_HOSTKEY  = 3;
18
    const AUTH_AGENT    = 4;
19
    const AUTH_NONE     = 0;
20
21
    protected $config = [];
22
23
    protected $requiredFields = [];
24
25
    protected static $knownHostsFile = '~/.ssh/known_hosts'; // configuration
26
27
    protected static $acceptUnknownHost = true; // configuration
28
29
    protected $tunnels = [];
30
31
    protected $connections = [];
32
33
    private $output;
34
35
    public function openConnection( $host,
36
                                    $port = SecureShell::DEFAULT_PORT,
37
                                    $auth = SecureShell::AUTH_PASSWORD,
38
                                    ...$args)
39
    {
40
        $uid = null;
41
        $callbacks = array('disconnect' => [$this, '_disconnect']);
42
43
        try {
44
            $connection = ssh2_connect($host, $port, $callbacks);
45
            if (!$connection) {
46
                throw new ModuleException(get_class($this), "Unable to connect to {$host} on port {$port}");
47
            } else {
48
                $fp = $this->__checkFingerprint($connection);
49
50
                if ($this->__authenticate($connection, $auth, ...$args) === false) {
51
                    throw new ModuleException(get_class($this), "Authentication failed on server {$host}:{$port}");
52
                } else {
53
                    $uid = hash('crc32', uniqid($fp), false);
54
                    $this->connections = array_merge($this->connections,
55
                                        [$uid => ['host' => $host,
56
                                                'port' => $port,
57
                                                'fingerprint' => $fp,
58
                                                'auth_method' => $auth,
59
                                                'resource' => $connection]
60
                                        ]);
61
                }
62
            }
63
        } catch (ModuleException $e) {
64
            throw $e;
65
        } catch (Exception $e) {
66
            throw new ModuleException(get_class($this), $e->getMessage());
67
        }
68
        return $uid;
69
    }
70
71
    public function closeConnection($uid) {
72
        switch ($this->__isValidConnnection($uid)) {
73
            case 0:
74
            case 1:
75
                unset($this->connections[$uid]);
76
                break;
77
            default:
78
                throw new ModuleException(get_class($this), "{$uid} is not a valid SSH connection");
79
        }
80
        return true;
81
    }
82
83
    public function getConnection($uid) {
84
        return $this->connections[$uid]['resource'];
85
    }
86
87
    protected function __isValidConnnection($uid) {
88
        if (isset($this->connections[$uid])) {
89
            if (is_resource($this->connections[$uid]['resource'])) {
90
                return 1;
91
            } else {
92
                return 0;
93
            }
94
        } else {
95
            return -1;
96
        }
97
    }
98
99
    protected function __authenticate($connection, $method, ...$args)
100
    {
101
        switch ($method) {
102
            case SecureShell::AUTH_PASSWORD:
103
                return ssh2_auth_password($connection, ...$args);
104
            case SecureShell::AUTH_PUBKEY:
105
            return ssh2_auth_pubkey_file($connection, ...$args);
106
            case SecureShell::AUTH_HOSTKEY:
107
                return ssh2_auth_hostbased_file($connection, ...$args);
108
            case SecureShell::AUTH_AGENT:
109
                return ssh2_auth_agent($connection, ...$args);
110
            case SecureShell::AUTH_NONE:
111
                return ssh2_auth_none($connection, ...$args);
112
            default:
113
                throw new ModuleException(get_class($this), 'Unsupported authentication method');
114
        }
115
    }
116
117
    protected function __checkFingerprint($connection)
118
    {
119
        $knownHost = false;
120
        try {
121
            $fingerprint = ssh2_fingerprint($connection, SSH2_FINGERPRINT_MD5 | SSH2_FINGERPRINT_HEX);
122
            $file = new SplFileObject(static::$knownHostsFile);
123
            $file->setFlags(SplFileObject::READ_CSV);
124
            $file->setCsvControl(' ');
125
            foreach ($file as $entry) {
126
                list($host, $method, $fp) = $entry;
0 ignored issues
show
Unused Code introduced by
The assignment to $host is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $method is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
127
                $knownHost = (strcmp($fp, $fingerprint) !== 0);
128
                if ($knownHost === true) {
129
                    break;
130
                }
131
            }
132
            $knownHost = $knownHost || static::$acceptUnknownHost;
133
134
            if ($knownHost === false) {
135
                throw new ModuleException(get_class($this), 'Unable to verify server identity!');
136
            }
137
        } catch (RuntimeException $e) {
138
            if (static::$acceptUnknownHost === false) {
139
                throw new ModuleException(get_class($this), 'Unable to verify server identity!');
140
            }
141
        }
142
        return $fingerprint;
143
    }
144
145
    protected function __disconnect()
146
    {
147
        foreach ($this->connections as $id => $connection) {
148
            if (is_resource($connection['resource']) !== true) {
149
                unset($this->connections[$id]);
150
            }
151
        }
152
    }
153
154
    /** Remote Commands methods **/
155
156
    public function runRemoteCommand($session, $command)
157
    {
158
        try {
159
            $connection = $this->getConnection($session);
160
            $stream = ssh2_exec($connection, $command);
161
            stream_set_blocking($stream, true);
162
            $errStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
163
            $this->output['STDOUT'] = stream_get_contents($stream);
164
            $this->output['STDERR'] = stream_get_contents($errStream);
165
            return $this->output;
166
        } catch (Exception $e) {
167
            throw new ModuleException(get_class($this), $e->getMessage());
168
        }
169
    }
170
171
    public function seeInRemoteOutput($text)
172
    {
173
        \PHPUnit_Framework_Assert::assertContains($text, $this->output['STDOUT']);
174
    }
175
176
    public function dontSeeInRemoteOutput($text)
177
    {
178
        \PHPUnit_Framework_Assert::assertNotContains($text, $this->output['STDOUT']);
179
    }
180
181
    /** Remote Files methods **/
182
183
    public function seeRemoteFile($session, $filename)
184
    {
185
        $connection = $this->getConnection($session);
186
        $sftp = ssh2_sftp($connection);
187
        $res = ssh2_sftp_stat($sftp, $filename);
188
        \PHPUnit_Framework_Assert::assertNotEmpty($res);
189
    }
190
191
    public function dontSeeRemoteFile($session, $filename)
192
    {
193
        $connection = $this->getConnection($session);
194
        $sftp = ssh2_sftp($connection);
195
        try {
196
            $res = ssh2_sftp_stat($sftp, $filename);
197
        } catch(Exception $e) {
198
            $res = false;
199
        }
200
        \PHPUnit_Framework_Assert::assertFalse($res);
0 ignored issues
show
Bug introduced by
It seems like $res defined by ssh2_sftp_stat($sftp, $filename) on line 196 can also be of type array; however, PHPUnit_Framework_Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
201
    }
202
203
    public function grabRemoteFile($session, $filename)
204
    {
205
        try {
206
            $connection = $this->getConnection($session);
207
            $sftp = ssh2_sftp($connection);
208
            return file_get_contents("ssh2.sftp://{$sftp}/{$filename}");
209
        } catch (Exception $e) {
210
            throw new ModuleException(get_class($this), $e->getMessage());
211
        }
212
    }
213
214
    /** Remote Dir methods **/
215
216
    public function seeRemoteDir()
217
    {
218
219
    }
220
221
    public function dontSeeRemoteDir()
222
    {
223
224
    }
225
226
    public function copyRemoteDir()
227
    {
228
229
    }
230
231
    public function deleteRemoteDir()
232
    {
233
234
    }
235
236
    public function readRemoteDir()
237
    {
238
239
    }
240
241
    /** Tunnel methods **/
242
243
    public function openRemoteTunnel()
244
    {
245
246
    }
247
248
    public function closeRemoteTunnel()
249
    {
250
251
    }
252
253
}
254