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 ( d7e253...55763c )
by François
03:03
created

OpenVpn::writeProcess()   C

Complexity

Conditions 9
Paths 16

Size

Total Lines 80
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 80
rs 5.6205
c 0
b 0
f 0
cc 9
eloc 54
nc 16
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 *  Copyright (C) 2016 SURFnet.
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU Affero General Public License as
7
 *  published by the Free Software Foundation, either version 3 of the
8
 *  License, or (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU Affero General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU Affero General Public License
16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
namespace SURFnet\VPN\Server\Config;
19
20
use SURFnet\VPN\Server\InstanceConfig;
21
use SURFnet\VPN\Server\PoolConfig;
22
use SURFnet\VPN\Server\IP;
23
use RuntimeException;
24
25
class OpenVpn
26
{
27
    /** @var string */
28
    private $vpnConfigDir;
29
30
    public function __construct($vpnConfigDir)
31
    {
32
        $this->vpnConfigDir = $vpnConfigDir;
33
    }
34
35
    public function write($instanceId, InstanceConfig $instanceConfig)
36
    {
37
        $instanceNumber = $instanceConfig->instanceNumber();
38
        foreach ($instanceConfig->pools() as $poolNumber => $poolId) {
39
            $poolConfig = $instanceConfig->pool($poolId);
40
            $poolConfig->s('instanceId', $instanceId);
41
            $poolConfig->s('poolId', $poolId);
42
            $this->writePool($instanceNumber, $poolNumber, $poolConfig);
43
        }
44
    }
45
46
    private function writePool($instanceNumber, $poolNumber, PoolConfig $poolConfig)
47
    {
48
        $range = new IP($poolConfig->v('range'));
49
        $range6 = new IP($poolConfig->v('range6'));
50
        $processCount = $poolConfig->getProcessCount();
51
52
        $splitRange = $range->split($processCount);
53
        $splitRange6 = $range6->split($processCount);
54
55
        $poolConfig->s('managementIp', sprintf('127.42.%d.%d', 100 + $instanceNumber, 100 + $poolNumber));
56
57
        for ($i = 0; $i < $processCount; ++$i) {
58
            // protocol is udp unless it is the last process when there is
59
            // not just one process
60
            if (1 === $processCount || $i !== $processCount - 1) {
61
                $proto = 'udp';
62
                $port = 1194 + $i;
63
            } else {
64
                $proto = 'tcp';
65
                $port = 1194;
66
            }
67
68
            $poolConfig->s('range', $splitRange[$i]);
69
            $poolConfig->s('range6', $splitRange6[$i]);
70
            $poolConfig->s('dev', sprintf('tun-%d-%d-%d', $instanceNumber, $poolNumber, $i));
71
            $poolConfig->s('proto', $proto);
72
            $poolConfig->s('port', $port);
73
            $poolConfig->s('managementPort', 11940 + $i);
74
            $poolConfig->s(
75
                'configName',
76
                sprintf(
77
                    'server-%s-%s-%s-%d.conf',
78
                    $poolConfig->v('instanceId'),
79
                    $poolConfig->v('poolId'),
80
                    $poolConfig->v('proto'),
81
                    $poolConfig->v('port')
82
                )
83
            );
84
85
            $this->writeProcess($poolConfig);
86
        }
87
    }
88
89
    private function writeProcess(PoolConfig $poolConfig)
90
    {
91
        $tlsDir = sprintf('/etc/openvpn/tls/%s', $poolConfig->v('instanceId'));
92
93
        $rangeIp = new IP($poolConfig->v('range'));
94
        $range6Ip = new IP($poolConfig->v('range6'));
95
96
        // static options
97
        $serverConfig = [
98
            '# OpenVPN Server Configuration',
99
            'verb 3',
100
            'dev-type tun',
101
            'user openvpn',
102
            'group openvpn',
103
            'topology subnet',
104
            'persist-key',
105
            'persist-tun',
106
            'keepalive 10 60',
107
            'comp-lzo no',
108
            'remote-cert-tls client',
109
            'tls-version-min 1.2',
110
            'tls-cipher TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA',
111
            'auth SHA256',
112
            'cipher AES-256-CBC',
113
            'client-connect /usr/bin/vpn-server-api-client-connect',
114
            'client-disconnect /usr/bin/vpn-server-api-client-disconnect',
115
            'push "comp-lzo no"',
116
            'push "explicit-exit-notify 3"',
117
            sprintf('ca %s/ca.crt', $tlsDir),
118
            sprintf('cert %s/server.crt', $tlsDir),
119
            sprintf('key %s/server.key', $tlsDir),
120
            sprintf('dh %s/dh.pem', $tlsDir),
121
            sprintf('tls-auth %s/ta.key 0', $tlsDir),
122
            sprintf('server %s %s', $rangeIp->getNetwork(), $rangeIp->getNetmask()),
123
            sprintf('server-ipv6 %s', $range6Ip->getAddressPrefix()),
124
            sprintf('max-clients %d', $rangeIp->getNumberOfHosts() - 1),
125
            sprintf('script-security %d', $poolConfig->v('twoFactor', false) ? 3 : 2),
126
            sprintf('dev %s', $poolConfig->v('dev')),
127
            sprintf('port %d', $poolConfig->v('port')),
128
            sprintf('management %s %d', $poolConfig->v('managementIp'), $poolConfig->v('managementPort')),
129
            sprintf('setenv INSTANCE_ID %s', $poolConfig->v('instanceId')),
130
            sprintf('setenv POOL_ID %s', $poolConfig->v('poolId')),
131
            sprintf('proto %s', 'tcp' === $poolConfig->v('proto') ? 'tcp-server' : 'udp'),
132
            sprintf('local %s', 'tcp' === $poolConfig->v('proto') ? $poolConfig->v('managementIp') : $poolConfig->v('listen', '0.0.0.0')),
133
134
            // increase the renegotiation time to 8h from the default of 1h when
135
            // using 2FA, otherwise the user would be asked for the 2FA key every
136
            // hour
137
            sprintf('reneg-sec %d', $poolConfig->v('twoFactor', false) ? 28800 : 3600),
138
        ];
139
140
        if ($poolConfig->v('enableLog', false)) {
141
            $serverConfig[] = 'log /dev/null';
142
        }
143
144
        if ('tcp' === $poolConfig->v('proto')) {
145
            $serverConfig[] = 'tcp-nodelay';
146
        }
147
148
        if ($poolConfig->v('twoFactor', false)) {
149
            $serverConfig[] = 'auth-user-pass-verify /usr/bin/vpn-server-api-verify-otp via-env';
150
        }
151
152
        // Routes
153
        $serverConfig = array_merge($serverConfig, self::getRoutes($poolConfig));
154
155
        // DNS
156
        $serverConfig = array_merge($serverConfig, self::getDns($poolConfig));
157
158
        // Client-to-client
159
        $serverConfig = array_merge($serverConfig, self::getClientToClient($poolConfig));
160
161
        sort($serverConfig, SORT_STRING);
162
163
        $configFile = sprintf('%s/%s', $this->vpnConfigDir, $poolConfig->v('configName'));
164
165
        if (false === @file_put_contents($configFile, implode(PHP_EOL, $serverConfig))) {
166
            throw new RuntimeException(sprintf('unable to write configuration file "%s"', $configFile));
167
        }
168
    }
169
170
    private static function getRoutes(PoolConfig $poolConfig)
171
    {
172
        $routeConfig = [];
173
        if ($poolConfig->v('defaultGateway', false)) {
174
            $routeConfig[] = 'push "redirect-gateway def1 bypass-dhcp"';
175
176
            // for Windows clients we need this extra route to mark the TAP adapter as
177
            // trusted and as having "Internet" access to allow the user to set it to
178
            // "Home" or "Work" to allow accessing file shares and printers
179
            // NOTE: this will break OS X tunnelblick because on disconnect it will
180
            // remove all default routes, including the one set before the VPN
181
            // was brought up
182
            //$routeConfig[] = 'push "route 0.0.0.0 0.0.0.0"';
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
183
184
            // for iOS we need this OpenVPN 2.4 "ipv6" flag to redirect-gateway
185
            // See https://docs.openvpn.net/docs/openvpn-connect/openvpn-connect-ios-faq.html
186
            $routeConfig[] = 'push "redirect-gateway ipv6"';
187
188
            // we use 2000::/3 instead of ::/0 because it seems to break on native IPv6
189
            // networks where the ::/0 default route already exists
190
            $routeConfig[] = 'push "route-ipv6 2000::/3"';
191
        } else {
192
            // there may be some routes specified, push those, and not the default
193
            foreach ($poolConfig->v('routes', []) as $route) {
194
                $routeIp = new IP($route);
195
                if (6 === $routeIp->getFamily()) {
196
                    // IPv6
197
                    $routeConfig[] = sprintf('push "route-ipv6 %s"', $routeIp->getAddressPrefix());
198
                } else {
199
                    // IPv4
200
                    $routeConfig[] = sprintf('push "route %s %s"', $routeIp->getAddress(), $routeIp->getNetmask());
201
                }
202
            }
203
        }
204
205
        return $routeConfig;
206
    }
207
208
    private static function getDns(PoolConfig $poolConfig)
209
    {
210
        // only push DNS if we are the default route
211
        if (!$poolConfig->v('defaultGateway', false)) {
212
            return [];
213
        }
214
215
        $dnsEntries = [];
216
        foreach ($poolConfig->v('dns', []) as $dnsAddress) {
217
            $dnsEntries[] = sprintf('push "dhcp-option DNS %s"', $dnsAddress);
218
        }
219
220
        // prevent DNS leakage on Windows
221
        $dnsEntries[] = 'push "block-outside-dns"';
222
223
        return $dnsEntries;
224
    }
225
226
    private static function getClientToClient(PoolConfig $poolConfig)
227
    {
228
        if (!$poolConfig->v('clientToClient', false)) {
229
            return [];
230
        }
231
232
        $rangeIp = new IP($poolConfig->v('range'));
233
        $range6Ip = new IP($poolConfig->v('range6'));
234
235
        return [
236
            'client-to-client',
237
            sprintf('push "route %s %s"', $rangeIp->getAddress(), $rangeIp->getNetmask()),
238
            sprintf('push "route-ipv6 %s"', $range6Ip->getAddressPrefix()),
239
        ];
240
    }
241
}
242