def add_cookie(self, response=None, **kwargs): if response is None: response = self.current_response if not kwargs.has_key('secure'): if ESAPI.security_configuration().get_force_secure_cookies(): kwargs['secure'] = True if not kwargs.has_key('httponly'): if ESAPI.security_configuration().get_force_http_only_cookies(): kwargs['httponly'] = True # Validate the key and value errors = ValidationErrorList() safe_key = ESAPI.validator().get_valid_input("cookie name", kwargs['key'], "HTTPCookieName", 50, False, errors) safe_value = ESAPI.validator().get_valid_input("cookie value", kwargs['value'], "HTTPCookieValue", 5000, False, errors) kwargs['key'] = safe_key kwargs['value'] = safe_value # If no errors, set the cookie if len(errors) == 0: response.set_cookie(**kwargs) return # Error! self.logger.warning( Logger.SECURITY_FAILURE, _("Attempt to add unsafe data to cookie (skip mode). Skipping cookie and continuing.") )
def set_header(self, name, value, response=None): if response is None: response = self.current_response try: safe_name = ESAPI.validator().get_valid_input("setHeader", name.strip(), "HTTPHeaderName", 20, False) safe_value = ESAPI.validator().get_valid_input("setHeader", value.strip(), "HTTPHeaderValue", 500, False) response[safe_name] = safe_value except ValidationException, extra: self.logger( Logger.SECURITY_FAILURE, _("Attempt to set invalid header denied"), extra )
def set_header(self, name, value, response=None): if response is None: response = self.current_response try: safe_name = ESAPI.validator().get_valid_input( "setHeader", name.strip(), "HTTPHeaderName", 20, False) safe_value = ESAPI.validator().get_valid_input( "setHeader", value.strip(), "HTTPHeaderValue", 500, False) response[safe_name] = safe_value except ValidationException, extra: self.logger(Logger.SECURITY_FAILURE, _("Attempt to set invalid header denied"), extra)
def add_role(self, role): """ If role is a string, it will be lower()'d. """ if isinstance(role, str): role = role.lower() if ESAPI.validator().is_valid_input("addRole", role, "RoleName", DefaultUser.MAX_ROLE_LENGTH, False): if role not in self._roles: self._roles.append(role) self.logger.info( Logger.SECURITY_SUCCESS, _("Role %(role_name)s added to %(account_name)s") % { 'role_name': role, 'account_name': self.account_name }) else: # Role already assigned pass else: raise AuthenticationAccountsException( _("Add role failed"), _("Attempt to add invalid role %(role_name)s to %(account_name)s" ) % { 'role_name': role, 'account_name': self.account_name })
def add_role(self, role): """ If role is a string, it will be lower()'d. """ if isinstance(role, str): role = role.lower() if ESAPI.validator().is_valid_input("addRole", role, "RoleName", DefaultUser.MAX_ROLE_LENGTH, False): if role not in self._roles: self._roles.append(role) self.logger.info(Logger.SECURITY_SUCCESS, _("Role %(role_name)s added to %(account_name)s") % {'role_name' : role, 'account_name' : self.account_name}) else: # Role already assigned pass else: raise AuthenticationAccountsException( _("Add role failed"), _("Attempt to add invalid role %(role_name)s to %(account_name)s") % {'role_name' : role, 'account_name' : self.account_name})
def validate_roles(self, roles): """ Checks that the roles passed in contain only letters, numbers, and underscores. Also checks that roles are no more than 10 characters long. If a role does not pass validation, it is not included in the list of roles returned by this method. A log warning is also generated for any invalid roles. @param roles: the list of roles to validate according to the criteria stated above. @return: a list of roles that are valid according to the criteria stated above. """ ret = [] for role in roles: canonical = '' try: stripped = role.strip() canonical = ESAPI.encoder().canonicalize(stripped) except EncodingException, extra: self.logger.warning( Logger.SECURITY_FAILURE, _("Failed to canonicalize role: %(role)s") % {'role' : stripped}, extra ) if not ESAPI.validator().is_valid_input( "Roles in FileBasedAccessController", canonical, "AccessControlRule", 200, False ): self.logger.warning( Logger.SECURITY_FAILURE, _("Role is invalid, and was not added to the list of roles for this rule: %(role)s") % {'role' : stripped} ) else:
def test_is_valid_cc(self): instance = ESAPI.validator() self.assertTrue(instance.is_valid_credit_card("cctest1", "1234 9876 0000 0008", False)) self.assertTrue(instance.is_valid_credit_card("cctest2", "1234987600000008", False)) self.assertFalse(instance.is_valid_credit_card("cctest3", "12349876000000081", False)) self.assertFalse(instance.is_valid_credit_card("cctest4", "4417 1234 5678 9112", False))
def validate_roles(self, roles): """ Checks that the roles passed in contain only letters, numbers, and underscores. Also checks that roles are no more than 10 characters long. If a role does not pass validation, it is not included in the list of roles returned by this method. A log warning is also generated for any invalid roles. @param roles: the list of roles to validate according to the criteria stated above. @return: a list of roles that are valid according to the criteria stated above. """ ret = [] for role in roles: canonical = '' try: stripped = role.strip() canonical = ESAPI.encoder().canonicalize(stripped) except EncodingException, extra: self.logger.warning( Logger.SECURITY_FAILURE, _("Failed to canonicalize role: %(role)s") % {'role': stripped}, extra) if not ESAPI.validator().is_valid_input( "Roles in FileBasedAccessController", canonical, "AccessControlRule", 200, False): self.logger.warning( Logger.SECURITY_FAILURE, _("Role is invalid, and was not added to the list of roles for this rule: %(role)s" ) % {'role': stripped}) else: ret.append(stripped)
def add_header(self, name, value, response=None): if response is None: response = self.current_response stripped_name = name.strip() stripped_value = value.strip() try: safe_name = ESAPI.validator().get_valid_input("addHeader", stripped_name, "HTTPHeaderName", 20, False) safe_value = ESAPI.validator().get_valid_input("addHeader", stripped_value, "HTTPHeaderValue", 500, False) response.headers[safe_name] = safe_value except ValidationException, extra: self.logger.warning( Logger.SECURITY_FAILURE, _("Attempt to add invalid header denied"), extra )
def test_is_valid_number(self): instance = ESAPI.validator() # testing negative range self.assertFalse(instance.is_valid_number("test", int, "-4", 1, 10, False)) self.assertTrue(instance.is_valid_number("test", int, "-4", -10, 10, False)) # testing null value self.assertTrue(instance.is_valid_number("test", int, None, -10, 10, True)) self.assertFalse(instance.is_valid_number("test", int, None, -10, 10, False)) # testing empty string self.assertTrue(instance.is_valid_number("test", int, "", -10, 10, True)) self.assertFalse(instance.is_valid_number("test", int, "", -10, 10, False)) # testing improper range self.assertFalse(instance.is_valid_number("test", int, "5", 10, -10, False)) # testing non-integers self.assertTrue(instance.is_valid_number("test", float, "4.3214", -10, 10, True)) self.assertTrue(instance.is_valid_number("test", float, "-1.65", -10, 10, True)) # other testing self.assertTrue(instance.is_valid_number("test", int, "4", 1, 10, False)) self.assertTrue(instance.is_valid_number("test", int, "400", 1, 10000, False)) self.assertTrue(instance.is_valid_number("test", int, "400000000", 1, 400000000, False)) self.assertFalse(instance.is_valid_number("test", int, "4000000000000", 1, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "alsdkf", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "--10", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "14.1414234x", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "Infinity", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "-Infinity", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "NaN", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "-NaN", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "+NaN", 10, 10000, False))
def get_header(self, name, request=None): if request is None: request = self.current_request value = request[name] return ESAPI.validator().get_valid_input( _("HTTP header value: %(value)s") % {'value': value}, value, "HTTPHeaderValue", 150, False)
def add_header(self, name, value, response=None): if response is None: response = self.current_response stripped_name = name.strip() stripped_value = value.strip() try: safe_name = ESAPI.validator().get_valid_input( "addHeader", stripped_name, "HTTPHeaderName", 20, False) safe_value = ESAPI.validator().get_valid_input( "addHeader", stripped_value, "HTTPHeaderValue", 500, False) response.headers[safe_name] = safe_value except ValidationException, extra: self.logger.warning(Logger.SECURITY_FAILURE, _("Attempt to add invalid header denied"), extra)
def get_header(self, name, request=None): if request is None: request = self.current_request value = request[name] return ESAPI.validator().get_valid_input( _("HTTP header value: %(value)s") % {'value' : value}, value, "HTTPHeaderValue", 150, False )
def test_get_valid_file_content(self): instance = ESAPI.validator() errors = ValidationErrorList() content = "12345" instance.get_valid_file_content("test", content, 5, True, errors) self.assertEquals(0, len(errors)) instance.get_valid_file_content("test", content, 4, True, errors) self.assertEquals(1, len(errors))
def test_get_valid_date(self): instance = ESAPI.validator() errors = ValidationErrorList() self.assertTrue(instance.get_valid_date("datetest1", "June 23, 1967", "%B %d, %Y", False )) instance.get_valid_date("datetest2", "freakshow", "%B %d, %Y", False, errors ) self.assertEquals( 1, len(errors) ) instance.get_valid_date( "test", "June 32, 2008", "%B %d, %Y", False, errors ) self.assertEquals( 2, len(errors) )
def get_cookie(self, name, request=None): if request is None: request = self.current_request morsel = request.cookies.get(name, None) if morsel is None: return None return ESAPI.validator().get_valid_input( "HTTP cookie value: %s " % morsel.value, morsel.value, "HTTPCookieValue", 1000, False)
def get_cookie(self, name, request=None): if request is None: request = self.current_request morsel = request.cookies.get(name, None) if morsel is None: return None return ESAPI.validator().get_valid_input( "HTTP cookie value: %s " % morsel.value, morsel.value, "HTTPCookieValue", 1000, False )
def get_parameter(self, name, request=None): if request is None: request = self.current_request raw = None if name in request.POST: raw = request.POST[name] elif name in request.GET: raw = request.GET[name] return ESAPI.validator().get_valid_input( _("HTTP parameter value: %(val)s") % {'val': raw}, raw, "HTTPParameterValue", 2000, False)
def get_parameter(self, name, request=None): if request is None: request = self.current_request raw = None if name in request.POST: raw = request.POST[name] elif name in request.GET: raw = request.GET[name] return ESAPI.validator().get_valid_input( _("HTTP parameter value: %(val)s") % {'val' : raw}, raw, "HTTPParameterValue", 2000, False )
def test_is_valid_file_upload(self): directory_path = os.path.expanduser('~') if os.name == 'nt': # Windows parent = "c:\\" else: parent = "/" filename = "aspect.txt" content = "This is some file content" instance = ESAPI.validator() self.assertTrue(instance.is_valid_file_upload("test", directory_path, parent, filename, content, 100, False)) # Test invalid directory path directory_path = "c:\\ridiculous" self.assertFalse(instance.is_valid_file_upload("test", directory_path, parent, filename, content, 100, False))
def test_get_valid_cc(self): instance = ESAPI.validator() errors = ValidationErrorList() # Verify method strips spaces self.assertEquals("1234987600000008", instance.get_valid_credit_card("cctest1", "1234 9876 0000 0008", False )) instance.get_valid_credit_card("cctest5", "1234 9876 0000 0008", False, errors) self.assertEquals( 0, len(errors) ) instance.get_valid_credit_card("cctest6", "1234987600000008", False, errors) self.assertEquals( 0, len(errors) ) instance.get_valid_credit_card("cctest7", "12349876000000081", False, errors) self.assertEquals( 1, len(errors) ) instance.get_valid_credit_card("cctest8", "4417 1234 5678 9112", False, errors) self.assertEquals( 2, len(errors) )
def add_cookie(self, response=None, **kwargs): if response is None: response = self.current_response if not kwargs.has_key('secure'): if ESAPI.security_configuration().get_force_secure_cookies(): kwargs['secure'] = True if not kwargs.has_key('httponly'): if ESAPI.security_configuration().get_force_http_only_cookies(): kwargs['httponly'] = True # Validate the key and value errors = ValidationErrorList() safe_key = ESAPI.validator().get_valid_input("cookie name", kwargs['key'], "HTTPCookieName", 50, False, errors) safe_value = ESAPI.validator().get_valid_input("cookie value", kwargs['value'], "HTTPCookieValue", 5000, False, errors) kwargs['key'] = safe_key kwargs['value'] = safe_value # If no errors, set the cookie if len(errors) == 0: response.set_cookie(**kwargs) return # Error! self.logger.warning( Logger.SECURITY_FAILURE, _("Attempt to add unsafe data to cookie (skip mode). Skipping cookie and continuing." ))
def test_get_valid_number(self): instance = ESAPI.validator() errors = ValidationErrorList(); # Floats instance.get_valid_number("dtest1", float, "1.0", 0, 20, True, errors ); self.assertEquals( 0, len(errors) ); instance.get_valid_number("dtest2", float, None, 0, 20, True, errors ); self.assertEquals( 0, len(errors) ); instance.get_valid_number("dtest3", float, None, 0, 20, False, errors ); self.assertEquals( 1, len(errors) ); instance.get_valid_number("dtest4", float, "ridiculous", 0, 20, True, errors ); self.assertEquals( 2, len(errors) ); instance.get_valid_number("dtest5", float, "99999999.9", 0, 20, True, errors ); self.assertEquals( 3, len(errors) );
def test_get_valid_dir_path(self): instance = ESAPI.validator() errors = ValidationErrorList() parent = "c:\\" if os.name == 'nt' else "/" # path of this file full_path = os.path.abspath(__file__) path, filename = os.path.split(full_path) instance.get_valid_directory_path("dirtest1", path, parent, True, errors); self.assertEquals( 0, len(errors) ); instance.get_valid_directory_path("dirtest2", None, parent, False, errors); self.assertEquals( 1, len(errors) ); instance.get_valid_directory_path("dirtest3", "ridicul%00ous", parent, False, errors); self.assertEquals( 2, len(errors) );
def test_is_valid_filename(self): instance = ESAPI.validator() # .txt extension is allowed by default # Simple valid filename with a valid extension self.assertTrue(instance.is_valid_filename("test", "aspect.txt", False)) # Testing case insensitivity of extensions self.assertTrue(instance.is_valid_filename("test", "aspect.TXT", False)) # All valid filename characters are accepted self.assertTrue(instance.is_valid_filename("test", "!@#$%^&{}[]()_+-=,.~'` abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.txt", False)) # Input that decodes to legal filenames are accepted self.assertTrue(instance.is_valid_filename("test", "aspe%20ct.txt", False)) # Valid filename but not in the allowed extension list ext = ['.doc', '.xls', '.jpg'] self.assertFalse(instance.is_valid_filename("test", "aspect.jar", False, ext))
def test_is_valid_input(self): instance = ESAPI.validator() self.assertTrue(instance.is_valid_input("test", "*****@*****.**", "Email", 100, False)); self.assertFalse(instance.is_valid_input("test", "jeff.williams@@aspectsecurity.com", "Email", 100, False)); self.assertFalse(instance.is_valid_input("test", "jeff.williams@aspectsecurity", "Email", 100, False)); self.assertTrue(instance.is_valid_input("test", "123.168.100.234", "IPAddress", 100, False)); self.assertTrue(instance.is_valid_input("test", "192.168.1.234", "IPAddress", 100, False)); self.assertFalse(instance.is_valid_input("test", "..168.1.234", "IPAddress", 100, False)); self.assertFalse(instance.is_valid_input("test", "10.x.1.234", "IPAddress", 100, False)); self.assertTrue(instance.is_valid_input("test", "http://www.aspectsecurity.com", "URL", 100, False)); self.assertFalse(instance.is_valid_input("test", "http:///www.aspectsecurity.com", "URL", 100, False)); self.assertFalse(instance.is_valid_input("test", "http://www.aspect security.com", "URL", 100, False)); self.assertTrue(instance.is_valid_input("test", "078-05-1120", "SSN", 100, False)); self.assertTrue(instance.is_valid_input("test", "078 05 1120", "SSN", 100, False)); self.assertTrue(instance.is_valid_input("test", "078051120", "SSN", 100, False)); self.assertFalse(instance.is_valid_input("test", "987-65-4320", "SSN", 100, False)); self.assertFalse(instance.is_valid_input("test", "000-00-0000", "SSN", 100, False)); self.assertFalse(instance.is_valid_input("test", "(555) 555-5555", "SSN", 100, False)); self.assertFalse(instance.is_valid_input("test", "test", "SSN", 100, False)); self.assertTrue(instance.is_valid_input("test", None, "Email", 100, True)); self.assertFalse(instance.is_valid_input("test", None, "Email", 100, False));
def clean_adv_acct_post_data(request): """ Clean the data posted to the advertiser account view. business_id = The business we are working with. ajax_mode = The flavor of what we are doing. coupon_id = The coupon we are turning on or off for a slot. headline = The headline of the coupon. """ instance = ESAPI.validator() error_list = ValidationErrorList() temp_headline = request.POST.get('headline', None) if temp_headline: for char in temp_headline: if ord(char) > 127: temp_headline = 'Your coupon' break clean_data = { 'business_id': instance.get_valid_number('business_id', int, request.POST.get('business_id', None), 1, 999999, True, error_list), 'ajax_mode': instance.get_valid_input('ajax_mode', request.POST.get('ajax_mode', None), 'SafeDisplay', 24, True, error_list), 'coupon_id': instance.get_valid_number('coupon_id', int, request.POST.get('coupon_id', None), 1, 999999, True, error_list), 'display_id': instance.get_valid_number('display_id', int, request.POST.get('display_id', None), 1, 999999, True, error_list), 'headline': instance.get_valid_input('headline', temp_headline, 'SafeDisplay', 100, True, error_list), } if len(error_list): LOG.error(error_list) return clean_data, error_list
def execute_system_command(self, executable, params, parent_dir, working_dir=None, codec=None, log_params=True): if codec is None: codec = self.codec if working_dir is None: working_dir = self.working_dir try: # Executable must exist if not os.path.exists(executable): raise ExecutorException( _("Execution failure"), _("No such executable: %(executable)s") % {'executable': executable}) directory, filename = os.path.split(executable) # executable must use canonical path if not ESAPI.validator().is_valid_directory_path( "Executor", directory, parent_dir, False): raise ExecutorException( _("Execution failure"), _("Directory did not pass validation: %(dir)s") % {'dir': directory}) # Must be in approved list approved = ESAPI.security_configuration().get_allowed_executables() if executable not in approved: raise ExecutorException( _("Execution failure"), _("Attempt to invoke executable that is not listed as an approved executable in configuration: %(executable)s" ) % {'executable': executable}) # Escape parameters params = [ ESAPI.encoder().encode_for_os(codec, param) for param in params ] # Working directory must exist if not os.path.exists(working_dir): raise ExecutorException( _("Execution failure"), _("No such working directory for running executable: %(dir)s" ) % {'dir': working_dir}) args = params args.insert(0, executable) start_time = datetime.now() proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=working_dir) if log_params: self.logger.warning( Logger.SECURITY_SUCCESS, _("Initiating executable %(args)s in %(dir)s") % { 'args': str(args), 'dir': working_dir }) else: self.logger.warning( Logger.SECURITY_SUCCESS, _("Initiating executable %(executable)s in %(dir)s") % { 'executable': args[0], 'dir': working_dir }) while (proc.poll() is None and datetime.now() - start_time < self.max_running_time): time.sleep(1) if proc.poll() is None: # Kill the process because it ran too long proc.terminate() time.sleep(1) if proc.poll() is None: proc.kill() raise ExecutorException( _("Execution failure"), _("Process exceeded maximum running time and was killed: %(executable)s" ) % {'executable': executable}) else: # Process terminated in allotted timeframe stdout_and_err = proc.communicate() return stdout_and_err except Exception, extra: raise ExecutorException( _("Execution failure"), _("Exception thrown during execution of system command"), extra)
def load_rules(self, rule_file): """ Loads the access rules by storing them in a dictionary. This method reads the file specified by the rule_file parameter, ignoring any lines that begin with the '#' character as comments. Sections of the access rules file are split by the '|' character. The method loads all paths, replacing '\\\\' characters with '/' for uniformity, then loads the list of comma separated roles. The roles are validated to be sure they are within the length and character set limitations specified in the validate_roles method. Then the permissions are stored for each item in the rules list. If the word 'allow' appears on the line, the specified roles are granted access to the data - otherwise, they will be denied access. Each path may only appear once in the access rules file. Any entry, after the first, containing the same path will be logged and ignored. @param rule_file: the name of the file that contains the access rules @return: a dictionary mapping path -> Rule object """ ret = {} input_file = None try: filename = ESAPI.security_configuration().get_resource_file( rule_file) input_file = open(filename, 'r') line = ESAPI.validator().safe_read_line(input_file, 500) while line != '': line = line.strip() if len(line) > 0 and line[0] != '#': rule = Rule() parts = line.split('|') rule.path = parts[0].strip().replace("\\\\", "/") roles = parts[1].strip().lower().split(',') roles = self.validate_roles(roles) for role in roles: rule.roles.append(role.strip()) action = parts[2].strip().lower() if action == 'allow' or action == 'deny': rule.allow = action == 'allow' else: for act in action.split(','): rule.actions.append(act.strip()) if ret.has_key(rule.path): self.logger.warning( Logger.SECURITY_FAILURE, _("Problem in access control file. Duplicate rule ignored: %(rule)s" ) % {'rule': rule}) else: ret[rule.path] = rule line = ESAPI.validator().safe_read_line(input_file, 500) except Exception, extra: raise self.logger.warning( Logger.SECURITY_FAILURE, _("Problem in access control file: %(file)s") % {'file': rule_file}, extra)
def test_get_valid_filename(self): instance = ESAPI.validator() # Percent encoding is not changed test_name = "aspe%20ct.txt" self.assertEquals(test_name, instance.get_valid_filename("test", test_name, False))
def load_rules(self, rule_file): """ Loads the access rules by storing them in a dictionary. This method reads the file specified by the rule_file parameter, ignoring any lines that begin with the '#' character as comments. Sections of the access rules file are split by the '|' character. The method loads all paths, replacing '\\\\' characters with '/' for uniformity, then loads the list of comma separated roles. The roles are validated to be sure they are within the length and character set limitations specified in the validate_roles method. Then the permissions are stored for each item in the rules list. If the word 'allow' appears on the line, the specified roles are granted access to the data - otherwise, they will be denied access. Each path may only appear once in the access rules file. Any entry, after the first, containing the same path will be logged and ignored. @param rule_file: the name of the file that contains the access rules @return: a dictionary mapping path -> Rule object """ ret = {} input_file = None try: filename = ESAPI.security_configuration().get_resource_file(rule_file) input_file = open(filename, 'r') line = ESAPI.validator().safe_read_line(input_file, 500) while line != '': line = line.strip() if len(line) > 0 and line[0] != '#': rule = Rule() parts = line.split('|') rule.path = parts[0].strip().replace("\\\\", "/") roles = parts[1].strip().lower().split(',') roles = self.validate_roles(roles) for role in roles: rule.roles.append(role.strip()) action = parts[2].strip().lower() if action == 'allow' or action == 'deny': rule.allow = action == 'allow' else: for act in action.split(','): rule.actions.append(act.strip()) if ret.has_key(rule.path): self.logger.warning( Logger.SECURITY_FAILURE, _("Problem in access control file. Duplicate rule ignored: %(rule)s") % {'rule' : rule} ) else: ret[rule.path] = rule line = ESAPI.validator().safe_read_line(input_file, 500) except Exception, extra: raise self.logger.warning( Logger.SECURITY_FAILURE, _("Problem in access control file: %(file)s") % {'file' : rule_file},
def test_is_valid_file_content(self): instance = ESAPI.validator() content = "This is some file content" self.assertTrue(instance.is_valid_file_content("test", content, 100, False))
def test_is_valid_date(self): instance = ESAPI.validator() format = "%B %d, %Y" self.assertTrue(instance.is_valid_date("datetest1", "September 11, 2001", format, True ) ) self.assertFalse( instance.is_valid_date("datetest2", None, format, False ) ) self.assertFalse( instance.is_valid_date("datetest3", "", format, False ) )
def execute_system_command(self, executable, params, parent_dir, working_dir=None, codec=None, log_params=True): if codec is None: codec = self.codec if working_dir is None: working_dir = self.working_dir try: # Executable must exist if not os.path.exists(executable): raise ExecutorException( _("Execution failure"), _("No such executable: %(executable)s") % {"executable": executable} ) directory, filename = os.path.split(executable) # executable must use canonical path if not ESAPI.validator().is_valid_directory_path("Executor", directory, parent_dir, False): raise ExecutorException( _("Execution failure"), _("Directory did not pass validation: %(dir)s") % {"dir": directory} ) # Must be in approved list approved = ESAPI.security_configuration().get_allowed_executables() if executable not in approved: raise ExecutorException( _("Execution failure"), _( "Attempt to invoke executable that is not listed as an approved executable in configuration: %(executable)s" ) % {"executable": executable}, ) # Escape parameters params = [ESAPI.encoder().encode_for_os(codec, param) for param in params] # Working directory must exist if not os.path.exists(working_dir): raise ExecutorException( _("Execution failure"), _("No such working directory for running executable: %(dir)s") % {"dir": working_dir}, ) args = params args.insert(0, executable) start_time = datetime.now() proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=working_dir) if log_params: self.logger.warning( Logger.SECURITY_SUCCESS, _("Initiating executable %(args)s in %(dir)s") % {"args": str(args), "dir": working_dir}, ) else: self.logger.warning( Logger.SECURITY_SUCCESS, _("Initiating executable %(executable)s in %(dir)s") % {"executable": args[0], "dir": working_dir}, ) while proc.poll() is None and datetime.now() - start_time < self.max_running_time: time.sleep(1) if proc.poll() is None: # Kill the process because it ran too long proc.terminate() time.sleep(1) if proc.poll() is None: proc.kill() raise ExecutorException( _("Execution failure"), _("Process exceeded maximum running time and was killed: %(executable)s") % {"executable": executable}, ) else: # Process terminated in allotted timeframe stdout_and_err = proc.communicate() return stdout_and_err except Exception, extra: raise ExecutorException( _("Execution failure"), _("Exception thrown during execution of system command"), extra )