def analyze(self): tcontext = self.tcontext.to_string() scontext = self.scontext.to_string() access_tuple = tuple( self.accesses) self.data = [] if (scontext, tcontext, self.tclass, access_tuple) in avcdict.keys(): self.type, self.data = avcdict[(scontext, tcontext, self.tclass, access_tuple)] else: self.type, self.data = audit2why.analyze(scontext, tcontext, self.tclass, self.accesses); if self.type == audit2why.NOPOLICY: self.type = audit2why.TERULE if self.type == audit2why.BADTCON: raise ValueError("Invalid Target Context %s\n" % tcontext) if self.type == audit2why.BADSCON: raise ValueError("Invalid Source Context %s\n" % scontext) if self.type == audit2why.BADSCON: raise ValueError("Invalid Type Class %s\n" % self.tclass) if self.type == audit2why.BADPERM: raise ValueError("Invalid permission %s\n" % " ".join(self.accesses)) if self.type == audit2why.BADCOMPUTE: raise ValueError("Error during access vector computation") if self.type == audit2why.CONSTRAINT: self.data = [ self.data ] if self.scontext.user != self.tcontext.user: self.data.append(("user (%s)" % self.scontext.user, 'user (%s)' % self.tcontext.user)) if self.scontext.role != self.tcontext.role and self.tcontext.role != "object_r": self.data.append(("role (%s)" % self.scontext.role, 'role (%s)' % self.tcontext.role)) if self.scontext.level != self.tcontext.level: self.data.append(("level (%s)" % self.scontext.level, 'level (%s)' % self.tcontext.level)) avcdict[(scontext, tcontext, self.tclass, access_tuple)] = (self.type, self.data)
def derive_avc_info_from_audit_event(self): self.tpath = None self.spath = None self.source = None self.a1 = None self.success = False self.syscall_paths = [] exe = comm = arch = syscall = None self.avc_record = self.audit_event.get_avc_record() syscall_record = self.audit_event.get_record_of_type('SYSCALL') self.access = self.avc_record.get_field('seperms') if not isinstance(self.scontext, AvcContext): self.scontext = AvcContext(self.avc_record.get_field('scontext')) if not isinstance(self.tcontext, AvcContext): self.tcontext = AvcContext(self.avc_record.get_field('tcontext')) self.tclass = self.avc_record.get_field('tclass') if self.avc_record.get_field('dest') is None: self.port = self.avc_record.get_field('src') else: self.port = self.avc_record.get_field('dest') self._set_tpath() self.kmod = self.avc_record.get_field('kmod') self.pid = self.avc_record.get_field('pid') # exe, cwd, name, path, key, dir, comm, ocomm, key_desc if syscall_record: exe = syscall_record.get_field('exe') try: exe.decode("hex") except: pass comm = syscall_record.get_field('comm') self.syscall = syscall_record.get_field('syscall') self.success = (syscall_record.get_field('success') == "yes") self.a1 = syscall_record.get_field('a1') if comm is None: comm = self.avc_record.get_field('comm') if exe is None: exe = self.avc_record.get_field('exe') try: self.spath = exe.decode("hex") except: self.spath = exe if comm: self.source = comm elif exe: self.source = self.spath if not self.spath: self.spath = self.source if not self.spath: self.spath = self.scontext.type cwd_record = self.audit_event.get_record_of_type('CWD') if cwd_record: cwd = cwd_record.get_field('cwd') else: cwd = None path_records = self.audit_event.get_records_of_type('PATH') for path_record in path_records: path = path_record.get_field('name') if os.path.isabs(path) or not cwd: self.syscall_paths.append(path) else: self.syscall_paths.append(os.path.join(cwd, path)) self.src_rpms = [] self.tgt_rpms = [] self.host = self.audit_event.event_id.host self.why, bools = audit2why.analyze(str(self.scontext), str(self.tcontext), str(self.tclass), self.access) if self.why == audit2why.ALLOW: raise ValueError( _("%s \n**** Invalid AVC allowed in current policy ***\n") % self.avc_record) if self.why == audit2why.DONTAUDIT: raise ValueError( _("%s \n**** Invalid AVC dontaudited in current policy. 'semodule -B' will turn on dontaudit rules. ***\n" ) % self.avc_record) if self.why == audit2why.NOPOLICY: raise ValueError(_("Must call policy_init first")) if self.why == audit2why.BADTCON: raise ValueError( _("%s \n**** Invalid AVC bad target context. ***\n") % self.avc_record) if self.why == audit2why.BADSCON: raise ValueError( _("%s \n**** Invalid AVC bad source context. ***\n") % self.avc_record) if self.why == audit2why.BADSCON: raise ValueError( _("%s \n**** Invalid AVC bad type class ***\n") % self.avc_record) if self.why == audit2why.BADPERM: raise ValueError( _("%s \n**** Invalid AVC bad permission ***\n") % self.avc_record) if self.why == audit2why.BADCOMPUTE: raise ValueError(_("Error during access vector computation")) if self.why == audit2why.BOOLEAN: self.bools = bools
def RunFaultServer(timeout=10): # FIXME audit2why.init() global host_database, analysis_queue, email_recipients signal.signal(signal.SIGHUP, sighandler) signal.signal(signal.SIGQUIT, sighandler) signal.signal(signal.SIGTERM, sighandler) signal.signal(signal.SIGALRM, sighandler) #interface_registry.dump_interfaces() try: # FIXME: should this be using our logging objects in log.py? # currently syslog is only used for putting an alert into # the syslog with it's id pkg_name = get_config('general', 'pkg_name') syslog.openlog(pkg_name) # Create an object responsible for sending notifications to clients client_notifier = ClientNotifier(connection_pool) # Create a database local to this host database_filename = get_config('database', 'filename') database_filepath = make_database_filepath(database_filename) assure_file_ownership_permissions(database_filepath, 0600, 'setroubleshoot') host_database = SETroubleshootDatabase( database_filepath, database_filename, friendly_name=_("Audit Listener")) host_database.set_notify(client_notifier) atexit.register(goodbye, host_database) deleted = False for i in host_database.sigs.signature_list: why, bools = audit2why.analyze(str(i.sig.scontext), str(i.sig.tcontext), str(i.sig.tclass), i.sig.access) if why == audit2why.ALLOW or why == audit2why.DONTAUDIT: if why == audit2why.ALLOW: reason = "allowed" else: reason = "dontaudit'd" syslog.syslog( syslog.LOG_ERR, "Deleting alert %s, it is %s in current policy" % (i.local_id, reason)) deleted = True host_database.delete_signature(i.sig) if deleted: host_database.save(prune=True) # Attach the local database to an object which will send alerts # specific to this host if not get_config('test', 'analyze', bool): alert_receiver = AlertPluginReportReceiver(host_database) else: alert_receiver = TestPluginReportReceiver(host_database) # Create a synchronized queue for analysis requests import Queue analysis_queue = Queue.Queue(0) # Create a thread to peform analysis, it takes AVC objects off # the analysis queue and runs the plugins against the # AVC. Analysis requests in the queue may arrive from a # variety of places; from the audit system, from a log file # scan, etc. The disposition of the analysis (e.g. where the # results of the analysis are to go) are included in the queued # object along with the data to analyze. analyze_thread = AnalyzeThread(analysis_queue) analyze_thread.setDaemon(True) analyze_thread.start() # Create a thread to receive messages from the audit system. # This is a time sensitive operation, the primary job of this # thread is to receive the audit message as quickly as # possible and return to listening on the audit socket. When # it receives a complete audit event it places it in the # analysis queue where another thread will process it # independently. # audit_socket_thread = AuditSocketReceiverThread(analysis_queue, alert_receiver) # audit_socket_thread.setDaemon(True) # audit_socket_thread.start() # Initialize the email recipient list from setroubleshoot.signature import SEEmailRecipientSet email_recipients = SEEmailRecipientSet() assure_file_ownership_permissions(email_recipients_filepath, 0600, 'setroubleshoot') try: email_recipients.parse_recipient_file(email_recipients_filepath) except ProgramError, e: if e.errno == ERR_FILE_OPEN: log_debug(e.strerror) else: raise e # Create a server to listen for alert clients and then run. listen_addresses = get_socket_list_from_config('listen_for_client') for listen_address in listen_addresses: listening_server = ListeningServer( listen_address, SetroubleshootdClientConnectionHandler) listening_server.open() dbus.glib.init_threads() setroubleshootd_dbus = SetroubleshootdDBus(analysis_queue, alert_receiver, timeout) main_loop = gobject.MainLoop() main_loop.run()
def RunFaultServer(timeout=10): # FIXME audit2why.init() global host_database, analysis_queue, email_recipients signal.signal(signal.SIGHUP, sighandler) signal.signal(signal.SIGQUIT, sighandler) signal.signal(signal.SIGTERM, sighandler) signal.signal(signal.SIGALRM, sighandler) #interface_registry.dump_interfaces() try: # FIXME: should this be using our logging objects in log.py? # currently syslog is only used for putting an alert into # the syslog with it's id pkg_name = get_config('general','pkg_name') syslog.openlog(pkg_name) # Create an object responsible for sending notifications to clients client_notifier = ClientNotifier(connection_pool) # Create a database local to this host database_filename = get_config('database','filename') database_filepath = make_database_filepath(database_filename) assure_file_ownership_permissions(database_filepath, 0600, 'root', 'root') host_database = SETroubleshootDatabase(database_filepath, database_filename, friendly_name=_("Audit Listener")) host_database.set_notify(client_notifier) atexit.register(goodbye, host_database) deleted = False for i in host_database.sigs.signature_list: why, bools = audit2why.analyze(str(i.sig.scontext), str(i.sig.tcontext), str(i.sig.tclass), i.sig.access) if why == audit2why.ALLOW or why == audit2why.DONTAUDIT: if why == audit2why.ALLOW: reason = "allowed" else: reason = "dontaudit'd" syslog.syslog(syslog.LOG_ERR, "Deleting alert %s, it is %s in current policy" % (i.local_id, reason) ) deleted = True host_database.delete_signature(i.sig) if deleted: host_database.save(prune=True) # Attach the local database to an object which will send alerts # specific to this host if not get_config('test', 'analyze', bool): alert_receiver = AlertPluginReportReceiver(host_database) else: alert_receiver = TestPluginReportReceiver(host_database) # Create a synchronized queue for analysis requests import Queue analysis_queue = Queue.Queue(0) # Create a thread to peform analysis, it takes AVC objects off # the analysis queue and runs the plugins against the # AVC. Analysis requests in the queue may arrive from a # variety of places; from the audit system, from a log file # scan, etc. The disposition of the analysis (e.g. where the # results of the analysis are to go) are included in the queued # object along with the data to analyze. analyze_thread = AnalyzeThread(analysis_queue) analyze_thread.setDaemon(True) analyze_thread.start() # Create a thread to receive messages from the audit system. # This is a time sensitive operation, the primary job of this # thread is to receive the audit message as quickly as # possible and return to listening on the audit socket. When # it receives a complete audit event it places it in the # analysis queue where another thread will process it # independently. # audit_socket_thread = AuditSocketReceiverThread(analysis_queue, alert_receiver) # audit_socket_thread.setDaemon(True) # audit_socket_thread.start() # Initialize the email recipient list from setroubleshoot.signature import SEEmailRecipientSet email_recipients = SEEmailRecipientSet() assure_file_ownership_permissions(email_recipients_filepath, 0600, 'root', 'root') try: email_recipients.parse_recipient_file(email_recipients_filepath) except ProgramError, e: if e.errno == ERR_FILE_OPEN: syslog.syslog(syslog.LOG_DEBUG, e.strerror) else: raise e # Create a server to listen for alert clients and then run. listen_addresses = get_socket_list_from_config('listen_for_client') for listen_address in listen_addresses: listening_server = ListeningServer(listen_address, SetroubleshootdClientConnectionHandler) listening_server.open() dbus.glib.init_threads() setroubleshootd_dbus = SetroubleshootdDBus(analysis_queue, alert_receiver, timeout) main_loop = gobject.MainLoop() main_loop.run()
def derive_avc_info_from_audit_event(self): self.tpath = None self.spath = None self.source = None self.a1 = None self.success = False self.syscall_paths = [] exe = comm = arch = syscall = None self.avc_record = self.audit_event.get_avc_record() syscall_record = self.audit_event.get_record_of_type('SYSCALL') self.access = self.avc_record.get_field('seperms') if not isinstance(self.scontext, AvcContext): self.scontext = AvcContext(self.avc_record.get_field('scontext')) if not isinstance(self.tcontext, AvcContext): self.tcontext = AvcContext(self.avc_record.get_field('tcontext')) self.tclass = self.avc_record.get_field('tclass') if self.avc_record.get_field('dest') is None: self.port = self.avc_record.get_field('src') else: self.port = self.avc_record.get_field('dest') self._set_tpath() self.kmod = self.avc_record.get_field('kmod') self.pid = self.avc_record.get_field('pid') # exe, cwd, name, path, key, dir, comm, ocomm, key_desc if syscall_record: exe = syscall_record.get_field('exe') try: exe.decode("hex") except: pass comm = syscall_record.get_field('comm') self.syscall = syscall_record.get_field('syscall') self.success = (syscall_record.get_field('success') == "yes") self.a1 = syscall_record.get_field('a1') if comm is None: comm = self.avc_record.get_field('comm') if exe is None: exe = self.avc_record.get_field('exe') try: self.spath = exe.decode("hex") except: self.spath = exe if comm: self.source = comm elif exe: self.source = self.spath if not self.spath: self.spath = self.source if not self.spath: self.spath = self.scontext.type cwd_record = self.audit_event.get_record_of_type('CWD') if cwd_record: cwd = cwd_record.get_field('cwd') else: cwd = None path_records = self.audit_event.get_records_of_type('PATH') for path_record in path_records: path = path_record.get_field('name') if os.path.isabs(path) or not cwd: self.syscall_paths.append(path) else: self.syscall_paths.append(os.path.join(cwd, path)) self.src_rpms = [] self.tgt_rpms = [] self.host = self.audit_event.event_id.host self.why, bools = audit2why.analyze(str(self.scontext), str(self.tcontext), str(self.tclass), self.access) if self.why == audit2why.ALLOW: raise ValueError(_("%s \n**** Invalid AVC allowed in current policy ***\n") % self.avc_record) if self.why == audit2why.DONTAUDIT: raise ValueError(_("%s \n**** Invalid AVC dontaudited in current policy. 'semodule -B' will turn on dontaudit rules. ***\n") % self.avc_record) if self.why == audit2why.NOPOLICY: raise ValueError(_("Must call policy_init first")) if self.why == audit2why.BADTCON: raise ValueError(_("%s \n**** Invalid AVC bad target context. ***\n") % self.avc_record) if self.why == audit2why.BADSCON: raise ValueError(_("%s \n**** Invalid AVC bad source context. ***\n") % self.avc_record) if self.why == audit2why.BADSCON: raise ValueError(_("%s \n**** Invalid AVC bad type class ***\n") % self.avc_record) if self.why == audit2why.BADPERM: raise ValueError(_("%s \n**** Invalid AVC bad permission ***\n") % self.avc_record) if self.why == audit2why.BADCOMPUTE: raise ValueError(_("Error during access vector computation")) if self.why == audit2why.BOOLEAN: self.bools = bools
def RunFaultServer(timeout=10): signal.alarm(timeout) sigalrm_handler = signal.signal(signal.SIGALRM, polling_failed_handler) # polling for /sys/fs/selinux/policy file while True: try: audit2why.init() signal.alarm(0) break # retry if init() failed to open /sys/fs/selinux/policy except ValueError as e: # The value error contains the following error message, # followed by strerror string (which can differ with localization) if "unable to open /sys/fs/selinux/policy" in str(e): continue raise e except SystemError as e: # As a result of a bug in audit2why.c, SystemError is raised instead of ValueError. # Python reports: "SystemError occurs as a direct cause of ValueError" # Error message of the ValueError is stored in __context__ # TODO: remove this except clause when the bug in audti2why is fixed if "unable to open /sys/fs/selinux/policy" in str(getattr(e, "__context__", "")): continue raise e global host_database, analysis_queue, email_recipients signal.signal(signal.SIGALRM, sigalrm_handler) signal.signal(signal.SIGHUP, sighandler) #interface_registry.dump_interfaces() try: # FIXME: should this be using our logging objects in log.py? # currently syslog is only used for putting an alert into # the syslog with it's id pkg_name = get_config('general', 'pkg_name') syslog.openlog(pkg_name) # Create an object responsible for sending notifications to clients client_notifier = ClientNotifier(connection_pool) # Create a database local to this host database_filename = get_config('database', 'filename') database_filepath = make_database_filepath(database_filename) assure_file_ownership_permissions(database_filepath, 0o600, 'setroubleshoot') host_database = SETroubleshootDatabase(database_filepath, database_filename, friendly_name=_("Audit Listener")) host_database.set_notify(client_notifier) atexit.register(goodbye, host_database) deleted = False for i in host_database.sigs.signature_list: why, bools = audit2why.analyze(str(i.sig.scontext), str(i.sig.tcontext), str(i.sig.tclass), i.sig.access) if why == audit2why.ALLOW or why == audit2why.DONTAUDIT: if why == audit2why.ALLOW: reason = "allowed" else: reason = "dontaudit'd" syslog.syslog(syslog.LOG_ERR, "Deleting alert %s, it is %s in current policy" % (i.local_id, reason)) deleted = True host_database.delete_signature(i.sig) if deleted: host_database.save(prune=True) # Attach the local database to an object which will send alerts # specific to this host if not get_config('test', 'analyze', bool): alert_receiver = AlertPluginReportReceiver(host_database) else: alert_receiver = TestPluginReportReceiver(host_database) # Create a synchronized queue for analysis requests import six.moves.queue analysis_queue = six.moves.queue.Queue(0) # Create a thread to peform analysis, it takes AVC objects off # the analysis queue and runs the plugins against the # AVC. Analysis requests in the queue may arrive from a # variety of places; from the audit system, from a log file # scan, etc. The disposition of the analysis (e.g. where the # results of the analysis are to go) are included in the queued # object along with the data to analyze. analyze_thread = AnalyzeThread(analysis_queue) analyze_thread.setDaemon(True) analyze_thread.start() # Create a thread to receive messages from the audit system. # This is a time sensitive operation, the primary job of this # thread is to receive the audit message as quickly as # possible and return to listening on the audit socket. When # it receives a complete audit event it places it in the # analysis queue where another thread will process it # independently. # audit_socket_thread = AuditSocketReceiverThread(analysis_queue, alert_receiver) # audit_socket_thread.setDaemon(True) # audit_socket_thread.start() # Initialize the email recipient list from setroubleshoot.signature import SEEmailRecipientSet email_recipients = SEEmailRecipientSet() assure_file_ownership_permissions(email_recipients_filepath, 0o600, 'setroubleshoot') try: email_recipients.parse_recipient_file(email_recipients_filepath) except ProgramError as e: if e.errno == ERR_FILE_OPEN: log_debug(e.strerror) else: raise e # Create a server to listen for alert clients and then run. listen_addresses = get_socket_list_from_config('listen_for_client') for listen_address in listen_addresses: listening_server = ListeningServer(listen_address, SetroubleshootdClientConnectionHandler) listening_server.open() dbus.glib.init_threads() setroubleshootd_dbus = SetroubleshootdDBus(analysis_queue, alert_receiver, timeout) main_loop = GLib.MainLoop() main_loop.run() except KeyboardInterrupt as e: log_debug("KeyboardInterrupt in RunFaultServer") except SystemExit as e: log_debug("raising SystemExit in RunFaultServer") except Exception as e: import traceback syslog_trace(traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, "exception %s: %s" % (e.__class__.__name__, str(e)))