From 4caf7c2bce23f04daf06507b679439662a8dddf9 Mon Sep 17 00:00:00 2001 From: nik012003 Date: Fri, 17 Jun 2022 20:48:27 +0200 Subject: [PATCH] Added case-insensitve regex --- README.md | 3 ++ backend/app.py | 12 +++++--- backend/proxy/__init__.py | 8 +++-- backend/proxy/proxy.cpp | 34 +++++++++++++-------- backend/utils.py | 2 ++ frontend/src/components/AddNewRegex.tsx | 10 +++++- frontend/src/components/RegexView/index.tsx | 2 ++ frontend/src/js/models.ts | 2 ++ 8 files changed, 53 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 68f56b8..dc08a9a 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ "service_id": , "regex": , "is_blacklist": , + "is_case_sensitive": , "n_packets": , "mode": <"C"|"S"|"B"> // Client to server, server to client or both }, @@ -140,6 +141,7 @@ "service_id": , "regex": , "is_blacklist": , + "is_case_sensitive": , "n_packets": , "mode": <"C"|"S"|"B"> // Client to server, server to client or both } @@ -162,6 +164,7 @@ "service_id": , "regex": , "is_blacklist": , + "is_case_sensitive": , "mode": <"C"|"S"|"B"> // Client to server, server to client or both } ``` diff --git a/backend/app.py b/backend/app.py index decbbfc..84c50b8 100644 --- a/backend/app.py +++ b/backend/app.py @@ -242,6 +242,7 @@ def get_service_regexes(serv): 'service_id': row[2], 'regex': row[0], 'is_blacklist': True if row[3] == "1" else False, + 'is_case_sensitive' : True if row[6] == "1" else False, 'mode': row[1], 'n_packets': row[4], } for row in db.query('SELECT * FROM regexes WHERE service_id = ?;', (serv,)) @@ -258,6 +259,7 @@ def get_regex_id(regex_id): 'service_id': q[0][2], 'regex': q[0][0], 'is_blacklist': True if q[0][3] == "1" else False, + 'is_case_sensitive' : True if q[0][7] == "1" else False, 'mode': q[0][1], 'n_packets': q[0][4], } @@ -290,6 +292,7 @@ def post_regexes_add(): "regex" : {"type" : "string"}, "is_blacklist" : {"type" : "boolean"}, "mode" : {"type" : "string"}, + "is_case_sensitive" : {"type" : "boolean"} }, }) if not re.match("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$",req["regex"]): @@ -302,8 +305,8 @@ def post_regexes_add(): 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'])) + db.query("INSERT INTO regexes (service_id, regex, is_blacklist, mode, is_case_sensitive ) VALUES (?, ?, ?, ?, ?);", + (req['service_id'], req['regex'], req['is_blacklist'], req['mode'], req['is_case_sensitive'])) except sqlite3.IntegrityError: return {'status': 'An identical regex already exists'} @@ -359,14 +362,15 @@ if __name__ == '__main__': 'is_blacklist': 'VARCHAR(1) NOT NULL', 'blocked_packets': 'INTEGER UNSIGNED NOT NULL DEFAULT 0', 'regex_id': 'INTEGER PRIMARY KEY', - 'FOREIGN KEY (service_id)':'REFERENCES services (service_id)' + 'is_case_sensitive' : 'VARCHAR(1) NOT NULL', + 'FOREIGN KEY (service_id)':'REFERENCES services (service_id)', }, 'keys_values': { 'key': 'VARCHAR(100) PRIMARY KEY', 'value': 'VARCHAR(100) NOT NULL', }, }) - db.query("CREATE UNIQUE INDEX IF NOT EXISTS unique_regex_service ON regexes (regex,service_id,is_blacklist,mode);") + db.query("CREATE UNIQUE INDEX IF NOT EXISTS unique_regex_service ON regexes (regex,service_id,is_blacklist,mode,is_case_sensitive);") if DEBUG: app.run(host="0.0.0.0", port=8080 ,debug=True) else: diff --git a/backend/proxy/__init__.py b/backend/proxy/__init__.py index d97b695..ca6ab50 100755 --- a/backend/proxy/__init__.py +++ b/backend/proxy/__init__.py @@ -3,8 +3,9 @@ import subprocess, re, os #c++ -o proxy proxy.cpp class Filter: - def __init__(self, regex, is_blacklist=True, c_to_s=False, s_to_c=False, blocked_packets=0, code=None): + def __init__(self, regex, is_case_sensitive=True, is_blacklist=True, c_to_s=False, s_to_c=False, blocked_packets=0, code=None): self.regex = regex + self.is_case_sensitive = is_case_sensitive self.is_blacklist = is_blacklist if c_to_s == s_to_c: c_to_s = s_to_c = True # (False, False) == (True, True) self.c_to_s = c_to_s @@ -16,10 +17,11 @@ class Filter: if isinstance(self.regex, str): self.regex = self.regex.encode() if not isinstance(self.regex, bytes): raise Exception("Invalid Regex Paramether") re.compile(self.regex) # raise re.error if is invalid! + case_sensitive = "1" if self.is_case_sensitive else "0" if self.c_to_s: - yield "C"+self.regex.hex() if self.is_blacklist else "c"+self.regex.hex() + yield case_sensitive + "C" + self.regex.hex() if self.is_blacklist else case_sensitive + "c"+ self.regex.hex() if self.s_to_c: - yield "S"+self.regex.hex() if self.is_blacklist else "s"+self.regex.hex() + yield case_sensitive + "S" + self.regex.hex() if self.is_blacklist else case_sensitive + "s"+ self.regex.hex() class Proxy: def __init__(self, internal_port, public_port, filters=None, public_host="0.0.0.0", internal_host="127.0.0.1"): diff --git a/backend/proxy/proxy.cpp b/backend/proxy/proxy.cpp index 419d2a1..2ba48e6 100644 --- a/backend/proxy/proxy.cpp +++ b/backend/proxy/proxy.cpp @@ -308,20 +308,26 @@ namespace tcp_proxy }; } -void push_regex(char* arg, vector> &v){ - size_t expr_len = (strlen(arg)-1)/2; +void push_regex(char* arg, bool case_sensitive, vector> &v){ + size_t expr_len = (strlen(arg)-2)/2; char expr[expr_len]; - unhexlify(arg+1, arg+strlen(arg)-1, expr); - boost::regex regex(reinterpret_cast(expr), + unhexlify(arg+2, arg+strlen(arg)-1, expr); + if (case_sensitive){ + boost::regex regex(reinterpret_cast(expr), reinterpret_cast(expr) + expr_len); - v.push_back(make_pair(string(arg), regex)); + v.push_back(make_pair(string(arg), regex)); + } else { + boost::regex regex(reinterpret_cast(expr), + reinterpret_cast(expr) + expr_len, boost::regex::icase); + v.push_back(make_pair(string(arg), regex)); + } } int main(int argc, char* argv[]) { if (argc < 5) { - std::cerr << "usage: tcpproxy_server C..... S....." << std::endl; + std::cerr << "usage: tcpproxy_server 0C..... 1S....." << std::endl; return 1; } @@ -330,22 +336,26 @@ int main(int argc, char* argv[]) const std::string local_host = argv[1]; const std::string forward_host = argv[3]; for (int i=5;i= 1){ - switch(argv[i][0]){ + if (strlen(argv[i]) >= 2){ + bool case_sensitive = true; + if(argv[i][0] == '0'){ + case_sensitive = false; + } + switch(argv[i][1]){ case 'C': { // Client to server Blacklist - push_regex(argv[i], regex_c_s_b); + push_regex(argv[i], case_sensitive, regex_c_s_b); break; } case 'c': { // Client to server Whitelist - push_regex(argv[i], regex_c_s_w); + push_regex(argv[i], case_sensitive, regex_c_s_w); break; } case 'S': { // Server to client Blacklist - push_regex(argv[i], regex_s_c_b); + push_regex(argv[i], case_sensitive, regex_s_c_b); break; } case 's': { // Server to client Whitelist - push_regex(argv[i], regex_s_c_w); + push_regex(argv[i], case_sensitive, regex_s_c_w); break; } } diff --git a/backend/utils.py b/backend/utils.py index 2fa6a36..123850d 100755 --- a/backend/utils.py +++ b/backend/utils.py @@ -115,6 +115,7 @@ class ProxyManager: 'id': row[5], 'regex': row[0], 'is_blacklist': True if row[3] == "1" else False, + 'is_case_sensitive' : True if row[6] == "1" else False, 'mode': row[1], 'n_packets': row[4], } for row in self.db.query('SELECT * FROM regexes WHERE service_id = ?;', (id,))] @@ -203,6 +204,7 @@ class ProxyManager: restart_required = True filter_info = [ele for ele in data['filters'] if ele["id"] == f][0] filters[f] = Filter( + is_case_sensitive=filter_info["is_case_sensitive"], c_to_s=filter_info["mode"] in ["C","B"], s_to_c=filter_info["mode"] in ["S","B"], is_blacklist=filter_info["is_blacklist"], diff --git a/frontend/src/components/AddNewRegex.tsx b/frontend/src/components/AddNewRegex.tsx index b91942b..e30e761 100755 --- a/frontend/src/components/AddNewRegex.tsx +++ b/frontend/src/components/AddNewRegex.tsx @@ -11,6 +11,7 @@ type RegexAddInfo = { regex:string, type:string, mode:string, + is_case_sensitive:boolean, regex_exact:boolean, percentage_encoding:boolean } @@ -22,6 +23,7 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=> regex:"", type:"blacklist", mode:"C <-> S", + is_case_sensitive:true, regex_exact:false, percentage_encoding:false }, @@ -55,6 +57,7 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=> const request:RegexAddForm = { is_blacklist:values.type !== "whitelist", + is_case_sensitive: values.is_case_sensitive, service_id: service, mode: filter_mode?filter_mode:"B", regex: b64encode(final_regex) @@ -65,7 +68,7 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=> setSubmitLoading(false) close(); fireUpdateRequest(); - 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_case_sensitive?"case sensitive":"case insensitive"} ${request.is_blacklist?"blacklist":"whitelist"} regex to ${request.service_id} service`) }else if (res.toLowerCase() === "invalid regex"){ setSubmitLoading(false) form.setFieldError("regex", "Invalid Regex") @@ -97,6 +100,11 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=> /> + + Match: {exact_regex?"EXACT":"FIND"} + Case: {regexInfo.is_case_sensitive?"SENSIIVE":"INSENSITIVE"} + Packets filtered: {regexInfo.n_packets} Mode: {mode_string} diff --git a/frontend/src/js/models.ts b/frontend/src/js/models.ts index b0b1e79..a245254 100755 --- a/frontend/src/js/models.ts +++ b/frontend/src/js/models.ts @@ -42,6 +42,7 @@ export type RegexFilter = { service_id:string, regex:string is_blacklist:boolean, + is_case_sensitive:boolean, mode:string //C S B => C->S S->C BOTH n_packets:number } @@ -49,6 +50,7 @@ export type RegexFilter = { export type RegexAddForm = { service_id:string, regex:string, + is_case_sensitive:boolean, is_blacklist:boolean, mode:string // C->S S->C BOTH } \ No newline at end of file