Completed
Push — master ( e54095...b55a89 )
by Mr
02:48
created

Config::getParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace OpenVPN;
4
5
use OpenVPN\Interfaces\ConfigInterface;
6
use OpenVPN\Interfaces\GeneratorInterface;
7
use RuntimeException;
8
use function in_array;
9
use function is_bool;
10
11
/**
12
 * Class Config
13
 *
14
 * @property string    $modeSet             OpenVPN major mode: p2p, server
15
 * @property string    $local               Local host name or IP address
16
 * @property string    $remote              Remote host name or IP address
17
 * @property bool|null $remoteRandom        When multiple --remote address/ports are specified, initially randomize the order of the list
18
 * @property string    $proto               Protocol for communicating with remote host: tcp, udp, tcp-client
19
 * @property integer   $connectRetry        For --proto tcp-client, take n as the number of seconds to wait between connection retries (default=5)
20
 * @property string    $httpProxy           Connect to remote host through an HTTP proxy
21
 * @property bool|null $httpProxyRetry      Retry indefinitely on HTTP proxy errors. If an HTTP proxy error occurs, simulate a SIGUSR1 reset.
22
 * @property integer   $httpProxyTimeout    Set proxy timeout to n seconds, default=5.
23
 * @property string    $httpProxyOption     Set extended HTTP proxy options
24
 * @property string    $socksProxy          Connect to remote host through a Socks5 proxy
25
 * @property bool|null $socksProxyRetry     Retry indefinitely on Socks proxy errors. If a Socks proxy error occurs, simulate a SIGUSR1 reset.
26
 * @property string    $resolvRetry         If hostname resolve fails for --remote, retry resolve for n seconds before failing
27
 * @property bool|null $float               Allow remote peer to change its IP address and/or port number, such as due to DHCP
28
 * @property string    $ipchange            Execute shell command, format: cmd ip_address port_number
29
 * @property integer   $port                TCP/UDP port number for both local and remote: 1194
30
 * @property integer   $lport               TCP/UDP port number for local
31
 * @property integer   $rport               TCP/UDP port number for remote
32
 * @property bool|null $nobind              Do not bind to local address and port
33
 * @property string    $dev                 TUN/TAP virtual network device: tunX, tapX, null
34
 * @property string    $devType             Which device type are we using? device-type should be tun or tap
35
 * @property bool|null $tunIpv6             Build a tun link capable of forwarding IPv6 traffic
36
 * @property string    $devNode             Explicitly set the device node rather than using /dev/net/tun, /dev/tun, /dev/tap, etc.
37
 * @property string    $ifconfig            Set TUN/TAP adapter IP address of the local VPN endpoint.
38
 * @property bool|null $ifconfigNoexec      Don’t actually execute ifconfig/netsh commands, instead pass –ifconfig parameters to scripts using environmental variables.
39
 * @property bool|null $ifconfigNowarn      Don’t output an options consistency check warning
40
 * @property string    $ifconfigPool        Set aside a pool of subnets to be dynamically allocated to connecting clients, similar to a DHCP server.
41
 * @property string    $ifconfigPoolPersist Persist/unpersist ifconfig-pool data to file, at secondsintervals (default=600),
42
 * @property string    $cipher              Encrypt packets with cipher algorithm alg. The default is BF-CBC,an abbreviation for Blowfish in Cipher Block Chaining mode.
43
 * @property bool|null $redirectGateway
44
 * @property integer   $keyDirection
45
 * @property string    $remoteCertTls
46
 * @property string    $auth                Authenticate packets with HMAC using message digest algorithm alg. (The default is SHA1).
47
 * @property bool|null $authUserPass
48
 * @property bool|null $authNocache
49
 * @property string    $authUserPassVerify  Path to login script
50
 * @property bool|null $duplicateCn         You may need this if everyone is using same certificate
51
 * @property bool|null $persistKey
52
 * @property bool|null $persistTun
53
 * @property bool|null $compLzo             Use fast LZO compression — may add up to 1 byte per packet for incompressible data.
54
 * @property bool|null $compNoadapt         When used in conjunction with –comp-lzo, this option will disable OpenVPN’s adaptive compression algorithm.
55
 * @property integer   $verb                Set output verbosity to n(default=1). Each level shows all info from the previous levels: 0,1,2 ... 11
56
 * @property string    $server              A helper directive designed to simplify the configuration of OpenVPN’s server mode.
57
 * @property string    $serverBridge        A helper directive similar to --server which is designed to simplify the configuration of OpenVPN’s server mode in ethernet bridging configurations.
58
 * @property string    $keepalive
59
 * @property integer   $renegSec
60
 * @property string    $user
61
 * @property string    $group
62
 * @property string    $mute
63
 * @property string    $status
64
 * @property string    $logAppend
65
 * @property string    $clientConfigDir
66
 * @property string    $scriptSecurity
67
 * @property string    $usernameAsCommonName
68
 * @property string    $verifyClientCert
69
 *
70
 * @package OpenVPN
71
 */
72
class Config implements ConfigInterface, GeneratorInterface
73
{
74
    /**
75
     * Array with all certificates
76
     *
77
     * @var array
78
     */
79
    private $certs = [];
80
81
    /**
82
     * List of all routes available on server
83
     *
84
     * @var array
85
     */
86
    private $routes = [];
87
88
    /**
89
     * List of lines which must be pushed to clients
90
     *
91
     * @var array
92
     */
93
    private $pushes = [];
94
95
    /**
96
     * All parameters added via addParam method
97
     *
98
     * @var array
99
     */
100
    private $parameters = [];
101
102
    /**
103
     * Config constructor.
104
     *
105
     * @param array $parameters List of default parameters
106
     */
107 6
    public function __construct(array $parameters = [])
108
    {
109 6
        $this->setParams($parameters);
110 6
    }
111
112
    /**
113
     * Alias for client line of config
114
     *
115
     * @return \OpenVPN\Interfaces\ConfigInterface
116
     */
117
    public function client(): ConfigInterface
118
    {
119
        return $this->set('client');
120
    }
121
122
    /**
123
     * Import content of all listed certificates
124
     *
125
     * @return void
126
     */
127
    public function loadCertificates(): void
128
    {
129
        foreach ($this->certs as &$cert) {
130
            $cert['content'] = rtrim(file_get_contents($cert['path']));
131
        }
132
    }
133
134
    /**
135
     * Alias to setCert
136
     *
137
     * @deprecated TODO: Delete in future releases
138
     */
139
    public function addCert(string $type, string $pathOrContent, bool $isContent = false): ConfigInterface
140
    {
141
        return $this->setCert($type, $pathOrContent, $isContent);
142
    }
143
144
    /**
145
     * Add new cert into the configuration
146
     *
147
     * @param string    $type      Type of certificate [ca, cert, key, dh, tls-auth]
148
     * @param string    $path      Absolute or relative path to certificate or content of this file
149
     * @param bool|null $isContent If true, then script will try to load file from dist by $path
150
     *
151
     * @return \OpenVPN\Interfaces\ConfigInterface
152
     * @throws \RuntimeException
153
     */
154 6
    public function setCert(string $type, string $path, bool $isContent = null): ConfigInterface
155
    {
156 6
        $type = mb_strtolower($type);
157 6
        Helpers::isCertAllowed($type);
158 6
        if (true === $isContent) {
159 1
            $this->certs[$type]['content'] = $path;
160
        } else {
161 6
            $this->certs[$type]['path'] = $path;
162
        }
163 6
        return $this;
164
    }
165
166
    /**
167
     * Return information about specified certificate
168
     *
169
     * @param string $type
170
     *
171
     * @return array
172
     * @throws \RuntimeException
173
     */
174
    public function getCert(string $type): array
175
    {
176
        $type = mb_strtolower($type);
177
        Helpers::isCertAllowed($type);
178
        return $this->certs[$type] ?? [];
179
    }
180
181
    /**
182
     * Alias to setPush
183
     *
184
     * @deprecated TODO: Delete in future releases
185
     */
186
    public function addPush(string $line): ConfigInterface
187
    {
188
        return $this->setPush($line);
189
    }
190
191
    /**
192
     * Append new push into the array
193
     *
194
     * @param string $line String with line which must be pushed
195
     *
196
     * @return \OpenVPN\Interfaces\ConfigInterface
197
     */
198 3
    public function setPush(string $line): ConfigInterface
199
    {
200 3
        $this->pushes[] = trim($line, '"');
201 3
        return $this;
202
    }
203
204
    /**
205
     * Remove route line from push array
206
     *
207
     * @param string $line String with line which must be pushed
208
     *
209
     * @return \OpenVPN\Interfaces\ConfigInterface
210
     */
211
    public function unsetPush(string $line): ConfigInterface
212
    {
213
        unset($this->pushes[$line]);
214
        return $this;
215
    }
216
217
    /**
218
     * Append new route into the array
219
     *
220
     * @param string $line String with route
221
     *
222
     * @return \OpenVPN\Interfaces\ConfigInterface
223
     */
224 3
    public function setRoute(string $line): ConfigInterface
225
    {
226 3
        $this->routes[] = trim($line, '"');
227 3
        return $this;
228
    }
229
230
    /**
231
     * Remove route line from routes array
232
     *
233
     * @param string $line String with route
234
     *
235
     * @return \OpenVPN\Interfaces\ConfigInterface
236
     */
237
    public function unsetRoute(string $line): ConfigInterface
238
    {
239
        unset($this->routes[$line]);
240
        return $this;
241
    }
242
243
    /**
244
     * Alias to set
245
     *
246
     * @deprecated TODO: Delete in future releases
247
     */
248
    public function add(string $name, $value = null): ConfigInterface
249
    {
250
        return $this->set($name, $value);
251
    }
252
253
    /**
254
     * Add some new parameter to the list of parameters
255
     *
256
     * @param string           $name  Name of parameter
257
     * @param string|bool|null $value Value of parameter
258
     *
259
     * @return \OpenVPN\Interfaces\ConfigInterface
260
     * @example $this->add('client')->add('remote', 'vpn.example.com');
261
     */
262 3
    public function set(string $name, $value = null): ConfigInterface
263
    {
264 3
        $name = mb_strtolower($name);
265
266
        // Check if key is certificate or push, or classic parameter
267 3
        if (in_array($name, self::ALLOWED_TYPES_OF_CERTS, true)) {
268 3
            return $this->setCert($name, $value);
0 ignored issues
show
Bug introduced by
It seems like $value defined by parameter $value on line 262 can also be of type boolean or null; however, OpenVPN\Config::setCert() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
269
        }
270
271
        // If is push then use add push method
272 3
        if ($name === 'push') {
273 3
            return $this->setPush($value);
0 ignored issues
show
Bug introduced by
It seems like $value defined by parameter $value on line 262 can also be of type boolean or null; however, OpenVPN\Config::setPush() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
274
        }
275
276
        // If is push then use add push method
277 3
        if ($name === 'route') {
278 3
            return $this->setRoute($value);
0 ignored issues
show
Bug introduced by
It seems like $value defined by parameter $value on line 262 can also be of type boolean or null; however, OpenVPN\Config::setRoute() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
279
        }
280
281
        // Check if provided value is boolean and if it's true, then set null (that mean parameter without value)
282 3
        if (is_bool($value) && $value) {
283 3
            if ($value) {
284 3
                $value = null;
285
            } else {
286
                // If false then skip this step
287
                return $this;
288
            }
289
        }
290
291
        // Set new value
292 3
        $this->parameters[$name] = $value;
293
294 3
        return $this;
295
    }
296
297
    /**
298
     * Get some custom element
299
     *
300
     * @param string|null $name Name of parameter
301
     *
302
     * @return mixed
303
     */
304
    public function get(string $name)
305
    {
306
        return $this->parameters[$name] ?? null;
307
    }
308
309
    /**
310
     * Generate config by parameters in memory
311
     *
312
     * @return string
313
     */
314 1
    public function generate(): string
315
    {
316 1
        $generator = new Generator($this);
317 1
        return $generator->generate();
318
    }
319
320
    /**
321
     * @param string $name
322
     *
323
     * @return bool
324
     */
325
    public function __isset(string $name): bool
326
    {
327
        // Inform about deleting push
328
        if ($name === 'push') {
329
            throw new RuntimeException("Not possible to remove push, use 'unsetPush' instead");
330
        }
331
332
        // Inform about deleting route
333
        if ($name === 'route') {
334
            throw new RuntimeException("Not possible to remove route, use 'unsetRoute' instead");
335
        }
336
337
        return isset($this->parameters[$name]);
338
    }
339
340
    /**
341
     * @param string                   $name
342
     * @param string|bool|integer|null $value
343
     */
344 3
    public function __set(string $name, $value = null): void
345
    {
346 3
        $name = Helpers::decamelize($name);
347 3
        $this->set($name, $value);
348 3
    }
349
350
    /**
351
     * @param string $name
352
     *
353
     * @return string|bool|null
354
     */
355
    public function __get(string $name)
356
    {
357
        return $this->get($name);
358
    }
359
360
    /**
361
     * Remove some parameter from array by name
362
     *
363
     * @param string $name Name of parameter
364
     *
365
     * @return void
366
     * @throws \RuntimeException
367
     */
368
    public function __unset(string $name)
369
    {
370
        // Inform about deleting push
371
        if ($name === 'push') {
372
            throw new RuntimeException("Not possible to remove push, use 'unsetPush' instead");
373
        }
374
375
        // Inform about deleting route
376
        if ($name === 'route') {
377
            throw new RuntimeException("Not possible to remove route, use 'unsetRoute' instead");
378
        }
379
380
        // Check if key is certificate or push, or classic parameter
381
        if (in_array($name, self::ALLOWED_TYPES_OF_CERTS, true)) {
382
            $this->unsetCert($name);
383
            return;
384
        }
385
386
        // Update list of parameters
387
        $this->parameters = array_map(
388
            static function ($param) use ($name) {
389
                return ($param['name'] === $name) ? null : $param;
390
            },
391
            $this->parameters
392
        );
393
    }
394
395
    /**
396
     * Remove selected certificate from array
397
     *
398
     * @param string $type Type of certificate [ca, cert, key, dh, tls-auth]
399
     *
400
     * @return \OpenVPN\Interfaces\ConfigInterface
401
     * @throws \RuntimeException
402
     */
403 2
    public function unsetCert(string $type): ConfigInterface
404
    {
405 2
        $type = mb_strtolower($type);
406 2
        Helpers::isCertAllowed($type);
407 2
        unset($this->certs[$type]);
408 2
        return $this;
409
    }
410
411
    /**
412
     * Set scope of certs
413
     *
414
     * @param \OpenVPN\Types\Cert[] $certs
415
     * @param bool                  $loadCertificates
416
     *
417
     * @return \OpenVPN\Interfaces\ConfigInterface
418
     */
419 3
    public function setCerts(array $certs, bool $loadCertificates = false): ConfigInterface
420
    {
421
        // Pass list of certs from array to variable
422 3
        foreach ($certs as $type => $path) {
423 3
            $this->setCert($type, $path);
0 ignored issues
show
Documentation introduced by
$path is of type object<OpenVPN\Types\Cert>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
424
        }
425
426
        // If need to load content of files from disk
427 3
        if ($loadCertificates) {
428
            $this->loadCertificates();
429
        }
430
431 3
        return $this;
432
    }
433
434
    /**
435
     * Set scope of unique pushes
436
     *
437
     * @param \OpenVPN\Types\Push[] $pushes
438
     *
439
     * @return \OpenVPN\Interfaces\ConfigInterface
440
     */
441 3
    public function setPushes(array $pushes): ConfigInterface
442
    {
443 3
        foreach ($pushes as $push) {
444 3
            $this->setPush($push);
0 ignored issues
show
Documentation introduced by
$push is of type object<OpenVPN\Types\Push>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
445
        }
446
447 3
        return $this;
448
    }
449
450
    /**
451
     * Set scope of unique routes
452
     *
453
     * @param \OpenVPN\Types\Route[] $routes
454
     *
455
     * @return \OpenVPN\Interfaces\ConfigInterface
456
     */
457 3
    public function setRoutes(array $routes): ConfigInterface
458
    {
459 3
        foreach ($routes as $route) {
460 3
            $this->setRoute($route);
0 ignored issues
show
Documentation introduced by
$route is of type object<OpenVPN\Types\Route>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
461
        }
462
463 3
        return $this;
464
    }
465
466
    /**
467
     * Set scope of unique parameters
468
     *
469
     * @param \OpenVPN\Types\Parameter[] $parameters
470
     *
471
     * @return \OpenVPN\Interfaces\ConfigInterface
472
     */
473 6
    public function setParams(array $parameters): ConfigInterface
474
    {
475 6
        foreach ($parameters as $name => $value) {
476
            $this->set($name, $value);
0 ignored issues
show
Documentation introduced by
$value is of type object<OpenVPN\Types\Parameter>, but the function expects a string|boolean|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
477
        }
478
479 6
        return $this;
480
    }
481
482
    /**
483
     * Export array of all certificates
484
     *
485
     * @return array
486
     */
487 6
    public function getCerts(): array
488
    {
489 6
        return $this->certs;
490
    }
491
492
    /**
493
     * Export array of all pushes
494
     *
495
     * @return array
496
     */
497 3
    public function getPushes(): array
498
    {
499 3
        return $this->pushes;
500
    }
501
502
    /**
503
     * Export array of all routes
504
     *
505
     * @return array
506
     */
507 3
    public function getRoutes(): array
508
    {
509 3
        return $this->routes;
510
    }
511
512
    /**
513
     * Export array of all parameters
514
     *
515
     * @return array
516
     */
517 3
    public function getParameters(): array
518
    {
519 3
        return $this->parameters;
520
    }
521
}
522