import os
import re
import os
from gspylib.common.ErrorCode import ErrorCode
class ValidationError(Exception):
"""
validation base error
"""
def __init__(self, error_info):
super().__init__(self)
self.error_info = error_info
def __str__(self):
return self.error_info
class SecurityChecker(object):
"""check security conditions"""
INJECTION_CHAR_LIST = ["|", ";", "&", "$", "<", ">", "`", "\\", "'", "\"", "{", "}", "(", ")",
"[", "]", "~", "*", "?", " ", "!", "\n"]
FORBIDDEN_CLEANUP_ROOTS = (
'/', '/etc', '/usr', '/var', '/boot', '/root', '/sbin', '/bin',
'/lib', '/lib64', '/opt', '/home',
)
PWD_VALIDATION_PATTERN = r'^[A-Za-z0-9~!@#%^*\-_=+?,]+$'
IP_PATTERN = (
r'^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(?:\.(?!$)|$)){4}$|'
r'^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|'
r'^::1$|^::$'
)
@staticmethod
def check_injection_char(check_value):
"""
function: check suspicious injection value
input : check_value
output: NA
"""
if not check_value.strip():
return
if any(rac in check_value for rac in SecurityChecker.INJECTION_CHAR_LIST):
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % check_value +
" There are illegal characters.")
@staticmethod
def check_safe_cleanup_directory(path):
"""
Reject cleanup of system-critical directories.
"""
if not path or not str(path).strip():
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % path +
" Cleanup path is empty.")
real_path = os.path.realpath(path)
if real_path in SecurityChecker.FORBIDDEN_CLEANUP_ROOTS:
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % real_path +
" Refusing to clean system directory.")
return real_path
@staticmethod
def check_is_string(description, value):
"""
Check is string
"""
if not isinstance(value, str):
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50022'] % (description, 'string'))
@staticmethod
def check_max_length(description, value, max_length):
"""
Check max length
"""
if len(value) > max_length:
raise ValidationError(ErrorCode.GAUSS_500["GAUSS_50023"] % (description, max_length))
@staticmethod
def check_db_injection(description, value):
"""
Check db injection
"""
for rac in SecurityChecker.INJECTION_CHAR_LIST:
if value.find(rac) >= 0:
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50025'] % (rac, description))
@staticmethod
def check_password(description, value):
if not re.match(SecurityChecker.PWD_VALIDATION_PATTERN, value):
raise ValidationError(ErrorCode.GAUSS_500["GAUSS_50024"] % description)
@staticmethod
def check_db_user(description, value):
SecurityChecker.check_is_string(description, value)
SecurityChecker.check_max_length(description, value, 256)
SecurityChecker.check_db_injection(description, value)
@staticmethod
def check_db_password(description, value):
SecurityChecker.check_is_string(description, value)
SecurityChecker.check_max_length(description, value, 256)
SecurityChecker.check_password(description, value)
@staticmethod
def check_is_digit(description, value):
if isinstance(value, int):
return
elif isinstance(value, str):
if not value.isdigit():
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50022']
% (description, 'integer'))
else:
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50022']
% (description, 'int or string'))
@staticmethod
def check_is_list(description, value):
if not isinstance(value, list):
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50022'] % (description, 'list'))
@staticmethod
def check_is_dict(description, value):
if not isinstance(value, dict):
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50022'] % (description, 'dict'))
@staticmethod
def check_ip_valid(description, value):
SecurityChecker.check_is_string(description, value)
if not re.match(SecurityChecker.IP_PATTERN, value):
raise ValidationError(ErrorCode.GAUSS_500["GAUSS_50024"] % description)
@staticmethod
def check_port_valid(description, value, max_value=65535, des2=''):
SecurityChecker.check_is_digit(description, value)
value = int(value) if not isinstance(value, int) else value
if value > max_value or value < 0:
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50022'] %
(description, 'between 0 and {}{}'.format(
str(max_value), des2)))
@staticmethod
def check_is_ip(value):
"""
check ip valid
"""
if not re.match(SecurityChecker.IP_PATTERN, value):
return False
return True
@staticmethod
def check_path(description, value):
"""
Path security check function, prevent path injection and directory traversal attacks
Args:
description: Description of the path for error messages
value: The path value to be validated
Returns:
Safe and normalized path string
Validation Steps:
1. Check if the path is a string type
2. Filter dangerous characters to prevent command injection
3. Normalize the path format to eliminate ambiguity
4. Prevent directory traversal and restrict access scope
"""
SecurityChecker.check_is_string(description, value)
SecurityChecker.check_db_injection(description, value)
if '..' in value:
raise ValidationError(ErrorCode.GAUSS_500['GAUSS_50025'] % ('..', description))
normalized_path = os.path.normpath(value)
return normalized_path