Passed
Push — develop ( 587507...8e8581 )
by Портнов
05:45 queued 12s
created

FirewallManagementProcessor::getBanIpWithTime()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 34
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 27
c 1
b 0
f 0
dl 0
loc 34
rs 9.1768
cc 5
nc 16
nop 0
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright (C) 2017-2020 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\PBXCoreREST\Lib;
21
22
23
use MikoPBX\Common\Models\Fail2BanRules;
24
use MikoPBX\Core\System\Configs\Fail2BanConf;
25
use MikoPBX\Core\System\Processes;
26
use MikoPBX\Core\System\Util;
27
use MikoPBX\Core\System\Verify;
28
use Phalcon\Di\Injectable;
29
30
use SQLite3;
31
use Throwable;
32
33
class FirewallManagementProcessor extends Injectable
34
{
35
    /**
36
     * Удалить адрес из бана.
37
     *
38
     * @param string $ip
39
     *
40
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
41
     */
42
    public static function fail2banUnbanAll(string $ip): PBXApiResult
43
    {
44
        $ip     = trim($ip);
45
        $res = new PBXApiResult();
46
        $res->processor = __METHOD__;
47
        $res->success = true;
48
        if ( ! Verify::isIpAddress($ip)) {
49
            $res->success = false;
50
            $res->messages[]="Not valid ip '{$ip}'.";
51
        }
52
        $fail2ban        = new Fail2BanConf();
53
        if ($fail2ban->fail2ban_enable) {
54
            $fail2ban = Util::which('fail2ban-client');
55
            $res->success  = (Processes::mwExec("{$fail2ban} unban {$ip}") === 0);
56
        } else {
57
            $res = self::fail2banUnbanDb($ip);
58
        }
59
60
        return $res;
61
    }
62
63
    /**
64
     * Возвращает массив забаненных ip. Либо данные по конкретному адресу.
65
     *
66
     * @param ?string $ip
67
     *
68
     * @return PBXApiResult
69
     */
70
    public static function getBanIp(?string $ip = null): PBXApiResult
0 ignored issues
show
Unused Code introduced by
The parameter $ip is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

70
    public static function getBanIp(/** @scrutinizer ignore-unused */ ?string $ip = null): PBXApiResult

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

Loading history...
71
    {
72
        $res = new PBXApiResult();
73
        $res->processor = __METHOD__;
74
        $res->success = true;
75
        $res->data = self::getBanIpWithTime();
76
        return $res;
77
    }
78
79
    public static function getBanIpWithTime():array
80
    {
81
        $result = [];
82
        $sep = '"|"';
83
        $sepSpace = '" "';
84
        $fail2banPath = Util::which('fail2ban-client');
85
        $awkPath      = Util::which('awk');
86
        try {
87
            $shellData = str_replace("'", '"', shell_exec("$fail2banPath banned"));
88
            $data = json_decode($shellData, true, 512, JSON_THROW_ON_ERROR);
89
            $data = array_merge(... $data);
90
        }catch (\Throwable $e){
91
            $data = [];
92
        }
93
        $jails = array_keys($data);
94
        foreach ($jails as $jail){
95
            $data = [];
96
            Processes::mwExec("$fail2banPath get $jail banip --with-time | $awkPath '{print $1 $sep $2 $sepSpace $3 $sep $7 $sepSpace $8 }'", $data);
97
            foreach ($data as $ipData){
98
                $ipData = explode('|', $ipData);
99
                $ip = $ipData[0]??'';
100
                if(empty($ip)){
101
                    continue;
102
                }
103
                $result[] = [
104
                    'ip' => $ip,
105
                    'jail' => "{$jail}_v2",
106
                    'timeofban' => self::time2stamp($ipData[1]),
107
                    'timeunban' => self::time2stamp($ipData[2]),
108
                    'v' => '2',
109
                ];
110
            }
111
        }
112
        return $result;
113
    }
114
115
    /**
116
     * Конвертация даты.
117
     * @param $strTime
118
     * @return int
119
     */
120
    public static function time2stamp($strTime):int
121
    {
122
        $result = 0;
123
        $d = \DateTime::createFromFormat('Y-m-d H:i:s', $strTime);
124
        if ($d !== false) {
125
            $result = $d->getTimestamp();
126
        }
127
        return $result;
128
    }
129
130
    /**
131
     * Удаление бана из базы.
132
     *
133
     * @param string $ip
134
     * @param string $jail
135
     *
136
     * @return PBXApiResult
137
     */
138
    public static function fail2banUnbanDb(string $ip, string $jail = ''): PBXApiResult
139
    {
140
        $res = new PBXApiResult();
141
        $res->processor = __METHOD__;
142
143
        $jail_q  = ($jail === '') ? '' : "AND jail = '{$jail}'";
144
        $path_db = Fail2BanConf::FAIL2BAN_DB_PATH;
145
        if(!file_exists($path_db)){
146
            // Таблица не существует. Бана нет.
147
            $res->success    = false;
148
            $res->messages[] = "DB {$path_db} not found";
149
            return $res;
150
        }
151
        $db      = new SQLite3($path_db);
152
        $db->busyTimeout(3000);
153
        $fail2ban = new Fail2BanConf();
154
        if (false === $fail2ban->tableBanExists($db)) {
155
            // Таблица не существует. Бана нет.
156
            $res->success = true;
157
            return $res;
158
        }
159
        $q = 'DELETE' . " FROM bans WHERE ip = '{$ip}' {$jail_q}";
160
        $db->query($q);
161
162
        $err = $db->lastErrorMsg();
163
164
        $res->success = ($err === 'not an error');
165
        $res->messages[] = $err;
166
        return $res;
167
    }
168
}