Passed
Push — master ( 6427d5...5783a1 )
by Nikolay
13:52 queued 05:42
created

FirewallManagementProcessor::fail2banUnbanAll()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 14
c 2
b 0
f 0
dl 0
loc 19
rs 9.7998
cc 3
nc 4
nop 1
1
<?php
2
/*
3
 * Copyright © MIKO LLC - All Rights Reserved
4
 * Unauthorized copying of this file, via any medium is strictly prohibited
5
 * Proprietary and confidential
6
 * Written by Alexey Portnov, 10 2020
7
 */
8
9
namespace MikoPBX\PBXCoreREST\Lib;
10
11
12
use MikoPBX\Common\Models\Fail2BanRules;
13
use MikoPBX\Core\System\Configs\Fail2BanConf;
14
use MikoPBX\Core\System\Util;
15
use MikoPBX\Core\System\Verify;
16
use Phalcon\Di\Injectable;
17
18
use SQLite3;
19
20
class FirewallManagementProcessor extends Injectable
21
{
22
    /**
23
     * Удалить адрес из бана.
24
     *
25
     * @param string $ip
26
     *
27
     * @return \MikoPBX\PBXCoreREST\Lib\PBXApiResult
28
     */
29
    public static function fail2banUnbanAll(string $ip): PBXApiResult
30
    {
31
        $ip     = trim($ip);
32
        $res = new PBXApiResult();
33
        $res->processor = __METHOD__;
34
        $res->success = true;
35
        if ( ! Verify::isIpAddress($ip)) {
36
            $res->success = false;
37
            $res->messages[]="Not valid ip '{$ip}'.";
38
        }
39
        $fail2ban        = new Fail2BanConf();
40
        if ($fail2ban->fail2ban_enable) {
41
            $fail2ban = Util::which('fail2ban-client');
42
            $res->success  = (Util::mwExec("{$fail2ban} unban {$ip}") === 0);
43
        } else {
44
            $res = self::fail2banUnbanDb($ip);
45
        }
46
47
        return $res;
48
    }
49
50
    /**
51
     * Возвращает массив забаненных ip. Либо данные по конкретному адресу.
52
     *
53
     * @param ?string $ip
54
     *
55
     * @return PBXApiResult
56
     */
57
    public static function getBanIp(?string $ip = null): PBXApiResult
58
    {
59
        $res = new PBXApiResult();
60
        $res->processor = __METHOD__;
61
62
        $db = self::getDbConnection();
63
        if(!$db){
64
            // Таблица не существует. Бана нет.
65
            $res->success    = false;
66
            $res->messages[] = 'DB '.Fail2BanConf::FAIL2BAN_DB_PATH.' not found';
67
            return $res;
68
        }
69
        $query   = self::getQueryBanIp($ip);
70
        $results = $db->query($query);
71
        $result  = [];
72
        if (false !== $results && $results->numColumns() > 0) {
73
            while ($banRule = $results->fetchArray(SQLITE3_ASSOC)) {
74
                $result[] = $banRule;
75
            }
76
        }
77
        $res->success = true;
78
        $res->data = $result;
79
        return $res;
80
    }
81
82
     public static function getDbConnection(){
83
         if(!file_exists(Fail2BanConf::FAIL2BAN_DB_PATH)){
84
             return null;
85
         }
86
         try {
87
             $db      = new SQLite3(Fail2BanConf::FAIL2BAN_DB_PATH);
88
         }catch (\Exception $e){
89
             return null;
90
         }
91
         $db->busyTimeout(5000);
92
         $fail2ban = new Fail2BanConf();
93
         if (false === $fail2ban->tableBanExists($db)) {
94
             return null;
95
         }
96
97
         return $db;
98
    }
99
100
    /**
101
     * Возвращает запрос SQL для получения забаненных IP.
102
     * @param $ip
103
     * @return string
104
     */
105
    public static function getQueryBanIp($ip):string{
106
        $banRule = Fail2BanRules::findFirst("id = '1'");
107
        if ($banRule !== null) {
108
            $ban_time = $banRule->bantime;
109
        } else {
110
            $ban_time = '43800';
111
        }
112
        // Добавленн фильтр по времени бана. возвращаем только адреса, которые еще НЕ разбанены.
113
        $q = 'SELECT' . ' DISTINCT jail,ip,MAX(timeofban) AS timeofban, MAX(timeofban+' . $ban_time . ') AS timeunban FROM bans where (timeofban+' . $ban_time . ')>' . time();
114
        if ($ip !== null) {
115
            $q .= " AND ip='{$ip}'";
116
        }
117
        $q .= ' GROUP BY jail,ip';
118
        return $q;
119
    }
120
121
    /**
122
     * Удаление бана из базы.
123
     *
124
     * @param string $ip
125
     * @param string $jail
126
     *
127
     * @return PBXApiResult
128
     */
129
    public static function fail2banUnbanDb(string $ip, string $jail = ''): PBXApiResult
130
    {
131
        $res = new PBXApiResult();
132
        $res->processor = __METHOD__;
133
134
        $jail_q  = ($jail === '') ? '' : "AND jail = '{$jail}'";
135
        $path_db = Fail2BanConf::FAIL2BAN_DB_PATH;
136
        if(!file_exists($path_db)){
137
            // Таблица не существует. Бана нет.
138
            $res->success    = false;
139
            $res->messages[] = "DB {$path_db} not found";
140
            return $res;
141
        }
142
        $db      = new SQLite3($path_db);
143
        $db->busyTimeout(3000);
144
        $fail2ban = new Fail2BanConf();
145
        if (false === $fail2ban->tableBanExists($db)) {
146
            // Таблица не существует. Бана нет.
147
            $res->success = true;
148
            return $res;
149
        }
150
        $q = 'DELETE' . " FROM bans WHERE ip = '{$ip}' {$jail_q}";
151
        $db->query($q);
152
153
        $err = $db->lastErrorMsg();
154
155
        $res->success = ($err === 'not an error');
156
        $res->messages[] = $err;
157
        return $res;
158
    }
159
}