def check_value(term): if term is None: return False if isinstance(term, list): return any(check_value(t) for t in term) if isinstance(term, (bool, float, int)) or utils.is_string(term): v = value if utils.is_string(v) and isinstance(term, (bool, int, float)): if isinstance(v, bool): v = v == "false" if isinstance(term, int): v = int(v) elif isinstance(v, float): v = float(v) elif utils.is_string(term) and isinstance( v, (bool, int, float)): v = utils.to_unicode(v) return compare_function(term, v) else: raise KqlRuntimeError("Cannot compare value {}".format(term))
def _parse(text, start=None, preprocessor=None, implied_any=False, implied_base=False, pipes=True, subqueries=True): """Function for parsing EQL with arbitrary entry points. :param str text: EQL source text to parse :param str start: Entry point for the EQL grammar :param bool implied_any: Allow for event queries to match on any event type when a type is not specified. If enabled, the query ``process_name == "cmd.exe"`` becomes ``any where process_name == "cmd.exe"`` :param bool implied_base: Allow for queries to be built with only pipes. Base query becomes 'any where true' :param bool pipes: Toggle support for pipes :param bool subqueries: Toggle support for subqueries, which are required by ``sequence``, ``join``, ``descendant of``, ``child of`` and ``event of`` :param PreProcessor preprocessor: Optional preprocessor to expand definitions and constants :rtype: EqlNode """ global GRAMMAR, tatsu_parser if tatsu_parser is None: GRAMMAR = get_etc_file('eql.ebnf') tatsu_parser = tatsu.compile( GRAMMAR, parseinfo=True, semantics=tatsu.semantics.ModelBuilderSemantics()) if not text.strip(): raise ParseError("No text specified", 0, 0, text) # Convert everything to unicode text = to_unicode(text) walker = EqlWalker(implied_any=implied_any, implied_base=implied_base, preprocessor=preprocessor, pipes=pipes, subqueries=subqueries) try: model = tatsu_parser.parse(text, rule_name=start, start=start, parseinfo=True) eql_node = walker.walk(model) return eql_node except tatsu.exceptions.FailedParse as e: info = e.buf.line_info(e.pos) message = e.message line = info.line col = info.col source = info.text.rstrip() if not source: source = text.strip().splitlines()[-1].strip() col = max(len(source) - 1, 0) raise ParseError(message, line, col, source)
def _error(node, message, end=False, cls=ParseError): """Callback function to walk the AST.""" params = dict(node.ast) for k, value in params.items(): if isinstance(value, list): params[k] = ', '.join([ v.render() if isinstance(v, EqlNode) else to_unicode(v) for v in value ]) message = message.format(**params) lines = node.parseinfo.text_lines() line_number = node.parseinfo.line if line_number >= len(lines): line_number = len(lines) - 1 bad_line = lines[line_number].rstrip() pos = node.parseinfo.endpos if end else node.parseinfo.pos return cls(message, line_number, pos, bad_line)
def walk__literal(self, node): """Callback function to walk the AST.""" literal = self.walk(node.value) if literal is None: return literal elif is_string(literal): # If a 'raw' string is detected, then only unescape the quote character if node.text.startswith('?'): quote_char = node.text[-1] literal = literal.replace("\\" + quote_char, quote_char) else: literal = String.unescape(literal) return String(to_unicode(literal)) elif isinstance(literal, bool): return Boolean(literal) else: return Number(literal)
def _test_interactive_shell(self): """Test that commands can be executed via the interactive shell.""" class Arguments(object): config = None file = None actual_stdin = io.StringIO( to_unicode("\n".join([ "input %s" % EVENTS_FILE, "table process_path parent_process_path", "search\nprocess where serial_event_id in (32, 33);", ]))) expected_stdout_text = "\n".join([ BANNER, "eql> input %s" % EVENTS_FILE, "Using file %s with %d events" % (EVENTS_FILE, len(TestEngine.get_events())), "eql> table process_path parent_process_path", "eql> search process where serial_event_id in (32, 33)", Table([[ "C:\\Windows\\System32\\sppsvc.exe", "C:\\Windows\\System32\\services.exe" ], [ "C:\\Windows\\System32\\dwm.exe", "C:\\Windows\\System32\\svchost.exe" ]], names=["process_path", "parent_process_path"]).__unicode__() ]) actual_stdout = [] # Now actually run with redirected stdout and stdin with mock.patch('sys.stdin', new=actual_stdin): shell_main(Arguments()) actual_stdout_lines = "\n".join(actual_stdout).splitlines() self.assertListEqual(actual_stdout_lines, expected_stdout_text.splitlines())
def _concat(*args): return u"".join(to_unicode(arg) for arg in args)
def _render(self): return to_unicode(self.value)