Bug fixes and better regex checks

This commit is contained in:
DomySh
2022-06-15 08:47:13 +02:00
parent d2d2b2c408
commit 3ec0879608
5 changed files with 31 additions and 20 deletions

View File

@@ -1,3 +1,4 @@
from base64 import b64decode
import sqlite3, subprocess, sys, threading, bcrypt, secrets, time, re import sqlite3, subprocess, sys, threading, bcrypt, secrets, time, re
from flask import Flask, jsonify, request, abort, session from flask import Flask, jsonify, request, abort, session
from functools import wraps from functools import wraps
@@ -262,7 +263,6 @@ def get_regex_delete(regex_id):
return {'status': 'ok'} return {'status': 'ok'}
@app.route('/api/regexes/add', methods = ['POST']) @app.route('/api/regexes/add', methods = ['POST'])
@login_required @login_required
def post_regexes_add(): def post_regexes_add():
@@ -283,9 +283,17 @@ def post_regexes_add():
return abort(400) return abort(400)
except Exception: except Exception:
return abort(400) return abort(400)
db.query("INSERT INTO regexes (service_id, regex, is_blacklist, mode) VALUES (?, ?, ?, ?);",
try:
re.compile(b64decode(req["regex"]))
except Exception:
return {"status":"Invalid regex"}
try:
db.query("INSERT INTO regexes (service_id, regex, is_blacklist, mode) VALUES (?, ?, ?, ?);",
(req['service_id'], req['regex'], req['is_blacklist'], req['mode'])) (req['service_id'], req['regex'], req['is_blacklist'], req['mode']))
except sqlite3.IntegrityError:
return {'status': 'An identical regex already exists'}
firewall.fire_update(req['service_id']) firewall.fire_update(req['service_id'])
return {'status': 'ok'} return {'status': 'ok'}
@@ -345,6 +353,7 @@ if __name__ == '__main__':
'value': 'VARCHAR(100) NOT NULL', 'value': 'VARCHAR(100) NOT NULL',
}, },
}) })
db.query("CREATE UNIQUE INDEX IF NOT EXISTS unique_regex_service ON regexes (regex,service_id,is_blacklist,mode);")
if DEBUG: if DEBUG:
app.run(host="0.0.0.0", port=8080 ,debug=True) app.run(host="0.0.0.0", port=8080 ,debug=True)

View File

@@ -1,6 +1,6 @@
from asyncore import file_dispatcher from asyncore import file_dispatcher
from proxy import Filter, Proxy from proxy import Filter, Proxy
import random, string, os, threading, sqlite3, time import random, string, os, threading, sqlite3, time, atexit
from kthread import KThread from kthread import KThread
from base64 import b64decode from base64 import b64decode
@@ -68,12 +68,13 @@ class STATUS:
STOP = "stop" STOP = "stop"
PAUSE = "pause" PAUSE = "pause"
ACTIVE = "active" ACTIVE = "active"
class ProxyManager: class ProxyManager:
def __init__(self, db:SQLite): def __init__(self, db:SQLite):
self.db = db self.db = db
self.proxy_table = {} self.proxy_table = {}
self.lock = threading.Lock() self.lock = threading.Lock()
atexit.register(self.clear)
def __clear_proxy_table(self): def __clear_proxy_table(self):
with self.lock: with self.lock:
@@ -81,6 +82,13 @@ class ProxyManager:
if not self.proxy_table[key]["thread"].is_alive(): if not self.proxy_table[key]["thread"].is_alive():
del self.proxy_table[key] del self.proxy_table[key]
def clear(self):
with self.lock:
for key in list(self.proxy_table.keys()):
if self.proxy_table[key]["thread"].is_alive():
self.proxy_table[key]["thread"].kill()
del self.proxy_table[key]
def reload(self): def reload(self):
self.__clear_proxy_table() self.__clear_proxy_table()
with self.lock: with self.lock:

View File

@@ -2,7 +2,7 @@ import { Button, Group, Space, TextInput, Notification, Switch, NativeSelect, To
import { useForm } from '@mantine/hooks'; import { useForm } from '@mantine/hooks';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { RegexAddForm } from '../js/models'; import { RegexAddForm } from '../js/models';
import { addregex, b64encode, getHumanReadableRegex, okNotify, validateRegex } from '../js/utils'; import { addregex, b64encode, getHumanReadableRegex, okNotify } from '../js/utils';
import { ImCross } from "react-icons/im" import { ImCross } from "react-icons/im"
import FilterTypeSelector from './FilterTypeSelector'; import FilterTypeSelector from './FilterTypeSelector';
@@ -26,7 +26,7 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=>
percentage_encoding:false percentage_encoding:false
}, },
validationRules:{ validationRules:{
regex: (value) => value !== "" && validateRegex(value), regex: (value) => value !== "",
type: (value) => ["blacklist","whitelist"].includes(value), type: (value) => ["blacklist","whitelist"].includes(value),
mode: (value) => ['C -> S', 'S -> C', 'C <-> S'].includes(value) mode: (value) => ['C -> S', 'S -> C', 'C <-> S'].includes(value)
} }
@@ -35,6 +35,7 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=>
const close = () =>{ const close = () =>{
onClose() onClose()
form.reset() form.reset()
setError(null)
} }
const [submitLoading, setSubmitLoading] = useState(false) const [submitLoading, setSubmitLoading] = useState(false)
@@ -64,9 +65,12 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=>
setSubmitLoading(false) setSubmitLoading(false)
close(); close();
okNotify(`Regex ${getHumanReadableRegex(request.regex)} has been added`, `Successfully added ${request.is_blacklist?"blacklist":"whitelist"} regex to ${request.service_id} service`) okNotify(`Regex ${getHumanReadableRegex(request.regex)} has been added`, `Successfully added ${request.is_blacklist?"blacklist":"whitelist"} regex to ${request.service_id} service`)
}else if (res.toLowerCase() === "invalid regex"){
setSubmitLoading(false)
form.setFieldError("regex", "Invalid Regex")
}else{ }else{
setSubmitLoading(false) setSubmitLoading(false)
setError("Invalid request! [ "+res+" ]") setError("Error: [ "+res+" ]")
} }
}).catch( err => { }).catch( err => {
setSubmitLoading(false) setSubmitLoading(false)
@@ -84,7 +88,7 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=>
{...form.getInputProps('regex')} {...form.getInputProps('regex')}
/> />
<Space h="md" /> <Space h="md" />
<Tooltip label="To represent binary data use URL encoding. Example: %01" transition="slide-left" openDelay={600} transitionDuration={250} transitionTimingFunction="ease" <Tooltip label="To represent binary data use URL encoding. Example: %01" transition="slide-left" openDelay={1500} transitionDuration={250} transitionTimingFunction="ease"
color="gray" wrapLines width={220} withArrow position='right'> color="gray" wrapLines width={220} withArrow position='right'>
<Switch <Switch
label="Use percentage encoding for binary values" label="Use percentage encoding for binary values"

View File

@@ -21,6 +21,7 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
const close = () =>{ const close = () =>{
onClose() onClose()
form.reset() form.reset()
setError(null)
} }
const [submitLoading, setSubmitLoading] = useState(false) const [submitLoading, setSubmitLoading] = useState(false)

View File

@@ -159,17 +159,6 @@ export function okNotify(title:string, description:string ){
}); });
} }
export function validateRegex(pattern:string) {
return true; // TO TEST
try {
new RegExp(pattern);
return true;
}
catch(e) {
return false;
}
}
export function b64encode(data:string){ export function b64encode(data:string){
return Buffer.from(data).toString('base64') return Buffer.from(data).toString('base64')
} }