?????????????? ?????????????? ?????????????? ?????????????? __pycache__/rpc.cpython-36.opt-1.pyc000064400000070511152572267760013154 0ustar003 Úh>`û“ã@s8ddlmZddlmZddlZddlZddlZddlZddlZddl m Z m Z ddl Z ddl ZddlZddlZddlTddlmZddlTddlmZmZddlTdd d d d d ddddddddgZejdƒZejdƒZejdƒZeddƒZdAdd „Zdd„Z dd„Z!dd„Z"dd „Z#d!d"„Z$d#d$„Z%d%d&„Z&d'd(„Z'Gd)d„de j ƒZ(e j)e(ƒGd*d+„d+e*ƒZ+e+d,e,ƒe+d-e-ƒe+d.e,ƒgZ.Gd/d0„d0e*ƒZ/Gd1d2„d2e*ƒZ0e0ƒZ1d3d„Z2d4d „Z3d5d „Z4d6d „Z5Gd7d„de*ƒZ6Gd8d9„d9e*ƒZ7Gd:d„de7ƒZ8Gd;d<„d<ƒZ9Gd=d„de*ƒZ:Gd>d„de7e:ƒZ;Gd?d@„d@e*ƒZq4|j|ƒ}|rŠ|jdƒjƒ}|jdƒ}tj|ƒ} | dkr”td||fƒq4n t j } |}t| ||ƒ} |j | ƒq4Wtd|| fƒ|S)Nz\s*{(unix|inet)}(.+)z%parse_socket_address_list: input='%s'z[\s,]+ééz(unknown socket family - %s in address %sz$parse_socket_address_list: %s --> %s) ÚreÚcompileÚ log_debugÚsplitÚsearchÚgroupÚlowerrÚ map_familyÚSocketÚAF_INETÚappend) Ú addr_stringÚ default_portÚsocket_addressesZ family_reZaddrsZcfg_addrÚmatchZ family_tagÚaddressÚfamilyÚsocket_address©r-ú/usr/lib/python3.6/rpc.pyrEs.        cCstddtƒ}|S)NZ connectionr')rÚint)r'r-r-r.rds cCst|dƒ}t|ƒ}|S)NZ address_list)rr)Z cfg_sectionr&r(r-r-r.ris cCs tdƒ}t|ƒdkrdS|dS)NZclient_connect_tor)rÚlen)Z addr_listr-r-r.ros cCsŽg}|tj@r|jdƒ|tj@r,|jdƒ|tj@r@|jdƒ|tj@rT|jdƒ|tj@rh|jdƒ|tj@r||jdƒd|dj|ƒfS) NÚINZOUTZPRIZERRÚHUPZNVALz(%d)[%s]ú,) rÚIO_INr%ZIO_OUTZIO_PRIÚIO_ERRÚIO_HUPÚIO_NVALÚjoin)Ú io_conditionÚnamesr-r-r.Úio_condition_to_stringvs            r;cKsBdt|ƒ}x(t|jƒƒD]\}}|d||f7}qW|d7}|S)Nzcontent-length: %d z%s: %s z )r0ÚlistÚitems)ÚbodyÚkwdsÚhdrÚkeyÚvaluer-r-r.Ú rpc_header‰s  rCcCst|||d�}||S)N)Úrpc_idÚtype)rC)rDrEr>r@r-r-r.Ú rpc_message‘srFc Csòd}}}}zÄtj|ƒ}|jƒ}|jdƒ}|jdƒ}tj||ƒ}t|dƒ}tt|ƒƒ}xv|D]n}|jdƒ}|jdƒ} t |jdƒƒ} |j | } | j dk rÀ| dkr²| j ||d�} qÆ| j |j ƒ} n|j } | || <q`WWd|dk ræ|j ƒX|||fS) NÚ interfaceÚmethodÚargÚnamerEÚpositionÚxml)Zobj_name)Úlibxml2ZparseDocZgetRootElementZproprÚ get_rpc_defr Úpreextend_listr0r/Úpositional_argsÚobj_typeZcontentÚfreeDoc) ÚcmdrGrHÚargsÚdocÚrpc_defZ arg_nodesÚarg_nodeÚarg_nameZarg_typeZ arg_positionÚrpc_argÚ arg_valuer-r-r.Úconvert_rpc_xml_to_args–s.           r[c GsJd}}�z&|j}|j}tjdƒ}tjdƒ}|jd|ƒ|jd|ƒ|j|ƒd}x¼|jD]²} | j} ||} tjdƒ} |j | ƒ| jd| ƒ| jdt |ƒƒt | tj ƒrÀ| jd d ƒ| j | ƒnDt | d ƒrê| jd d ƒ| j | j|| ƒƒn| jd d ƒ| jt | ƒƒ|d 7}qZW|jdt |ƒƒ|jtd d�}Wd|dk �rD|jƒX|S)Nz1.0rSrGrHrrIrJrKrErLÚ get_xml_nodesÚstringrZ arg_count)ÚencodingÚformat)rGrHrMZnewDocZnewNodeZsetPropZsetRootElementrPrJZaddChildÚstrÚ isinstanceZxmlNodeÚhasattrr\Z addContentZ serializerrR) rDrVrTZtext_docrUrGrHÚrootrKrYrXrZrWr-r-r.Úconvert_rpc_to_xml¿s>                  rdc@sîeZdZd#Zd$Zd%Zd&Zd'Zd(Zd)Z eeBeBeBeBeBe BZ eeBZ eeBeBe BZ eded ed ed ed ed e diZ eeeeeee gZdejjdejejejffiZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd*d!d"„ZdS)+rrréééééÚ CONNECTINGÚOPENÚ AUTHENTICATEDr2ÚERRORÚTIMEOUTÚRETRYÚchangedNcCs*tjj|ƒd|_d|_d|_|jƒdS)Nr)rÚ__init__ÚflagsÚ result_codeÚ result_msgÚ clear_result)Úselfr-r-r.rqs  zConnectionState.__init__cCsd|j|jƒ|j|jfS)Nz'flags=%s, result_code=%d, result_msg=%s)Úflags_to_stringrrrsrt)rvr-r-r.Ú__str__ szConnectionState.__str__cCs|jd|jƒdS)Nr)ÚupdateÚ ALL_FLAGS)rvr-r-r.ÚclearszConnectionState.clearcCsB|dkr d}g}x&tjD]}||@r|jtj|ƒqWdj|ƒS)Nrr3)rÚconnection_statesr%Úmap_connection_enum_to_stringr8)rvÚvalr:Ústater-r-r.rws zConnectionState.flags_to_stringcCsd|_d|_dS)NrÚ)rsrt)rvr-r-r.ruszConnectionState.clear_resultcCs||_||_dS)N)rsrt)rvrsrtr-r-r.Ú set_result!szConnectionState.set_resultcCs |j|jfS)N)rsrt)rvr-r-r.Ú get_result%szConnectionState.get_resultrr€c Csf|j}|j|O_|j|M_||_||_||jA}|j|@}||@}|rb|jd|j||ƒdS)Nrp)rrrsrtÚemit) rvÚ add_flagsÚ remove_flagsrsrtZprevious_flagsÚ differenceZ flags_addedZ flags_removedr-r-r.ry(s  zConnectionState.updaterrfééé é@é€)rrrr€)Ú__name__Ú __module__Ú __qualname__rjrkrlr2rmrnrorzÚ GOOD_FLAGSÚ PROBLEM_FLAGSr}r|rZ SignalFlagsZRUN_LASTZTYPE_INTZ __gsignals__rqrxr{rwrur�r‚ryr-r-r-r.rès8 c@seZdZddd„Zdd„ZdS)ÚRpcArgNcCs||_||_dS)N)rJrQ)rvrJrQr-r-r.rq@szRpcArg.__init__cCs6|jdkrd}n|j}|jdkr$|Sd||jfSdS)NZname_undefinedz%s:%s)rJrQ)rvrJr-r-r.rxDs   zRpcArg.__str__)NN)rŒr�rŽrqrxr-r-r-r.r‘>s r‘rHÚerr_codeÚerr_msgc@sLeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dS)Ú RpcDefinitioncCs2||_||_||_d|_|dkr(g|_n||_dS)N)rErGrHÚcallbackrP)rvrErGrHZrpc_argsr-r-r.rqUszRpcDefinition.__init__cCs„g}|jdk rLx<|jD]2}|jdk r<|jd|j|jfƒq|j|jƒqWd|j|j|jdj|ƒf}|jdkr€|d|j7}|S)Nz%s:%sz[%s] %s:%s (%s)r3rHz callback=%s) rPrQr%rJrErGrHr8r•)rvrTrYÚtextr-r-r.rx_s    zRpcDefinition.__str__cCs ||_dS)N)rE)rvrEr-r-r.Úset_typelszRpcDefinition.set_typecCs(|jdk rtj|jƒ}||j=||_dS)N)r•rÚ get_interfacerG)rvr•Úinterface_dictr-r-r.Ú set_callbackos  zRpcDefinition.set_callbackcCsf|jdkrtd|jƒ‚|jdkrVd|j}td|j|dƒ}tj|j||ƒ||_|Stj|j|jƒS)NrHz"%s rpc types do not have callbacksz%s_default_callbackÚ method_return) rEÚ ValueErrorr•rHr”rGrÚregister_rpc_defrN)rvZ callback_nameZ callback_defr-r-r.Úget_callback_defus   zRpcDefinition.get_callback_defcCsJ|dk rFtt|ƒ|jtƒ|_d}x$|D]}|j|}||_|d7}q&WdS)Nrr)rOr0rPr‘rJ)rvZ arg_namesrKrXrYr-r-r.Úset_positional_args€s  z!RpcDefinition.set_positional_argscGsJ|dk rFtt|ƒ|jtƒ|_d}x$|D]}|j|}||_|d7}q&WdS)Nrr)rOr0rPr‘rQ)rvZ obj_typesrKrQrYr-r-r.Úset_arg_obj_types‰s  zRpcDefinition.set_arg_obj_typescCsdd„|jDƒS)NcSsg|] }|j‘qSr-)rJ)Ú.0rYr-r-r.ú “sz:RpcDefinition.get_positional_arg_names..)rP)rvr-r-r.Úget_positional_arg_names’sz&RpcDefinition.get_positional_arg_namesN) rŒr�rŽrqrxr—ršržrŸr r£r-r-r-r.r”Ss     r”c@sLeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dS)ÚInterfaceRegistrycCs i|_dS)N)Ú interfaces)rvr-r-r.rqšszInterfaceRegistry.__init__cCstd|dtƒ}d|iS)NÚ error_returnÚ _error_return)r”Úerror_positional_args)rvrGZerror_return_defr-r-r.Ú new_interface�szInterfaceRegistry.new_interfacecCs,|jj|ƒ}|dkr(|j|ƒ}||j|<|S)N)r¥Úgetr©)rvÚinterface_namerGr-r-r.r˜¡s    zInterfaceRegistry.get_interfacecCsRddl}|j}|j|ƒd}|ddkr.|d=|j||ƒ}|j|ƒ|j|ƒ|S)Nrrv)ÚinspectrŒZ getargspecrNr—rŸ)rvrErGÚ method_ptrr¬rHrPrVr-r-r.Ú set_rpc_def¨s    zInterfaceRegistry.set_rpc_defcCsL|j|ƒ}t|tƒr|j}|j|ƒ}|dkrHtd||dƒ}|j|||ƒ|S)N)r˜raÚ MethodTyperŒrªr”r�)rvrGrHr™rVr-r-r.rN´s   zInterfaceRegistry.get_rpc_defcCs&|j|ƒ}t|tƒr|j}|||<dS)N)r˜rar¯rŒ)rvrGrHrVr™r-r-r.r�¾s  z"InterfaceRegistry.register_rpc_defcCs|j|ƒ}|dS)Nr§)r˜)rvrGr™r-r-r.Úget_error_rpc_defÄs z#InterfaceRegistry.get_error_rpc_defcCsxt|jjƒƒ}|jƒx\|D]T}|j|}td|ƒt|jƒƒ}|jƒx$|D]}||}tdt|ƒƒqPWqWdS)Nz Interface: %sz %s)r<r¥ÚkeysÚsortÚprintr`)rvZinterface_namesr«rGZ method_namesZ method_namerHr-r-r.Údump_interfacesÈs     z!InterfaceRegistry.dump_interfacesN) rŒr�rŽrqr©r˜r®rNr�r°r´r-r-r-r.r¤˜s  r¤cs‡fdd„}|S)Ncs,tjdˆ|ƒ}|j‰‡‡fdd„}d|_|S)NrHcs@|jƒ}tjˆˆƒ}t||ƒ}||j|<|j|d|f|žŽ|S)NrH)Ú new_rpc_idrrNÚAsyncRpcÚasync_rpc_cacheÚemit_rpc)rvrTrDrVÚ async_rpc)rGrHr-r.Úrpc_funcÞs    z/rpc_method..decorator..rpc_funcT)rr®rŒÚ_rpc_definition)r­rVrº)rG)rHr.Ú decoratorÚs zrpc_method..decoratorr-)rGr¼r-)rGr.r Ùs cs‡‡fdd„}|S)Ncs |j}tjˆ|ƒ}|jˆŽ|S)N)rŒrrNr )r­rHrV)Ú arg_typesrGr-r.r¼ës  zrpc_arg_type..decoratorr-)rGr½r¼r-)r½rGr.r êscs‡‡fdd„}|S)Ncs0tjdˆ|ƒ}tjˆˆƒ}|j|jƒd|_|S)Nr›T)rr®rNršrHr»)r­Úrpc_callback_defrV)rGrHr-r.r¼ôs   zrpc_callback..decoratorr-)rGrHr¼r-)rGrHr.r óscs‡fdd„}|S)Ncs,tjdˆ|ƒ}|j‰‡‡fdd„}d|_|S)NÚsignalcs,|jƒ}tjˆˆƒ}|j|d|f|žŽdS)Nr¿)rµrrNr¸)rvrTrDrV)rGrHr-r.rºs z/rpc_signal..decorator..rpc_funcT)rr®rŒr»)r­rVrº)rG)rHr.r¼þs zrpc_signal..decoratorr-)rGr¼r-)rGr.r ýs c@sdeZdZddeƒdfdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z e dd„ƒZ dd„Z dd„Z dS)rNcCsLtj|ƒ|_||_||_||_tj|_d|_ ||_ |dk rH|j |j|ƒdS)N) rr"r+r*Úportr'r#Z SOCK_STREAMrEÚsocketÚ friendly_nameÚparse)rvr+r*r'rÂr-r-r.rqs zSocketAddress.__init__cCsbtjddt|jƒƒ}|jdkr"dS|jtjkr$z\1ÚNonez{unix}%s socket=%sz{inet}%s:%s socket=%sÚunknown) rÚsubÚreprrÁr+r#ÚAF_UNIXr*r$rÀ)rvZ socket_reprr-r-r.rxs   zSocketAddress.__str__cCsL|jdkrdS|jtjkr$d|jS|jtjkr@d|j|jfStdƒSdS)NrÄz%sz%s:%sZUnknown)r+r#rÈr*r$rÀÚ_)rvr-r-r.Ú_get_default_friendly_name&s    z(SocketAddress._get_default_friendly_namecCs|jdkr|jƒS|jS)N)rÂrÊ)rvr-r-r.Úget_friendly_name0s zSocketAddress.get_friendly_namecCsddl}|j|ƒS)Nr)Úcopy)rvrÌr-r-r.rÌ5szSocketAddress.copycCs2|jtjkr|jS|jtjkr*|j|jfSdSdS)N)r+r#rÈr*r$rÀ)rvr-r-r.Úget_py_address9s    zSocketAddress.get_py_addresscCs0t|tjƒr,|jƒ}tjtjdœj|ƒ}|S|S)N)ZunixZinet)raÚsixZ string_typesr!r#rÈr$rª)r+r-r-r.r"As  zSocketAddress.map_familycCs6||_|tjkr||_d|_n|tjkr2|j|ƒdS)N)r+r#rÈr*rÀr$Úparse_inet_addr)rvr+Úaddrr-r-r.rÃIs   zSocketAddress.parsecCs^tjd|ƒ}|rN|jdƒ}|jdƒ}|dkr2|j}|dkr@tƒ}||_||_n d|_d|_dS)Nz^\s*([^:\s]+)\s*(:\s*([^\s]+))?rreZhostname)rrr r'Z get_hostnamer*rÀ)rvrÐr)rÀr-r-r.rÏQs   zSocketAddress.parse_inet_addr)rŒr�rŽrrqrxrÊrËrÌrÍÚ staticmethodr"rÃrÏr-r-r-r.r s    c@sNeZdZejejBejBejBZdde ƒfdd„Z dd„Z dd„Z dd „Z dS) Ú ConnectionIONcCs$tƒ|_||_||_||_d|_dS)N)rÚconnection_stater,Ú channel_typeÚ channel_nameÚ io_watch_id)rvrÔrÕr,r-r-r.rqhs zConnectionIO.__init__cCs&|jƒtj|jjtj|j|ƒ|_dS)z-callback signature: (io_object, io_condition)N)Úio_watch_removerZ io_add_watchr,rÁZPRIORITY_DEFAULTÚio_input_conditionsrÖ)rvr•r-r-r.Ú io_watch_addos zConnectionIO.io_watch_addcCs |jdk rtj|jƒd|_dS)N)rÖrZ source_remove)rvr-r-r.r×vs  zConnectionIO.io_watch_removecCsš|tjtjBtjB@r’|tj@r>t}t|ƒ}|jtjd||ƒ|tj@rft }t|ƒ}|jtj d||ƒ|tj@rŽt }t|ƒ}|jtj d||ƒdSdSdS)NrFT) rr6r5r7ÚERR_SOCKET_HUPZ get_strerrorÚclose_connectionrr2ZERR_SOCKET_ERRORrmZERR_IO_INVALID)rvr9ÚerrnoÚstrerrorr-r-r.Úvalid_io_condition{s   zConnectionIO.valid_io_condition)rŒr�rŽrr4r6r5r7rØrrqrÙr×rÞr-r-r-r.rÒes rÒc@s4eZdZdZdZdd„Zdd„Zdd„Zd d „Zd S) rFrgcCstj|dd|d�||_dS)NZ listeningZserver_listening)rÔrÕr,)rÒrqÚclient_connection_handler_class)rvr,rßr-r-r.rq˜szListeningServer.__init__cCsð||_|jjtjkrXtjj|jjƒr4tj|jjƒn$tjj |jƒ}tjj|ƒsXtj |ƒtj |jj|jj ƒ|j_ t j |jj jƒt jt jƒ|jr¦|jj jtjtjdƒ|jj j|jjƒƒ|jjtjkrØtj|jjdƒ|jj j|jƒ|jj S)Nri¶)r,r+r#rÈÚosÚpathÚexistsr*ÚremoveÚdirnameÚmakedirsrÁrEÚfcntlÚfilenoÚF_SETFDÚ FD_CLOEXECÚallow_reuse_addressZ setsockoptZ SOL_SOCKETZ SO_REUSEADDRZbindrÍÚchmodZlistenÚrequest_queue_size)rvr,rár-r-r.Únew_listening_socketœs   z$ListeningServer.new_listening_socketcCs`y |j|jƒ|j_|j|jƒWn:tk rZ}z|jjtj tj dt |ƒƒdSd}~XnXdS)NrFTéÿÿÿÿ) rír,rÁrÙÚhandle_client_connectÚ ExceptionrÓryrrmrkr`)rvÚer-r-r.Úopen²szListeningServer.openc CsRyÞ|j|ƒsdS|tj@rÜyN|jƒ\}}tj|jƒtjtjƒ|j|j ƒ}|j ||ƒ|j j dt jƒWnrtjk rÚ}zTt|ƒ\}}tjtjd|j |fƒ|tjkr²t j} nt j} |j j | d||ƒWYdd}~XnXWnntk �rL}zPtjtjd|jjt|ƒfƒddl} t| jƒƒ|j j t jddt|ƒƒWYdd}~XnXdS)NFrz5closing client connection due to socket error(%s): %szexception %s: %srTrî)rÞrr4Zacceptrærçrèrérßr,ròrÓryrr�r#ÚerrorÚget_error_from_socket_exceptionÚsyslogÚLOG_ERRÚErrnoÚEPIPEr2rmrðÚ __class__rŒr`Ú tracebackÚ syslog_traceÚ format_exc) rvrÁr9Z client_socketZclient_addressZclient_handlerrñrÜrÝr„rúr-r-r.rï»s.       ( *z%ListeningServer.handle_client_connectN) rŒr�rŽrêrìrqríròrïr-r-r-r.r“s  c@s4eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd S) ÚRequestReceivercCs||_|jƒdS)N)Ú dispatchFuncÚreset)rvrþr-r-r.rqÞszRequestReceiver.__init__cCs"d|_d|_d|_d|_d|_dS)Nrrr€rî)Ú headerLenÚbodyLenÚheaderr>Úfeed_buf)rvr-r-r.rÿâs zRequestReceiver.resetcCs¶t|jƒdkrdSxž|jdkrFtj|jƒ}|rD|jƒ|_|jƒqnPt|jƒ|j|jkr¬|j}|j|j}|j||…|_|j|d…|_d|_d|_|j |j |jƒqPqWdS)Nrrrîrî) r0rrÚ header_end_rerÚendÚ parse_headerrr>rþr)rvr)Z bodyBeginZbodyEndr-r-r.Úprocessés(    zRequestReceiver.processcCs|j|7_|jƒdS)N)rr)rvÚdatar-r-r.ÚfeedszRequestReceiver.feedcCsli|_d}xLtj|j||jdƒ}|rR|jdƒ}|jdƒjƒ}||j|<|jƒ}q Pq Wt|jdƒ|_ dS)Nrrrzcontent-length) rÚheader_field_rerrrr Ústriprr/r)rvZbeginr)rArBr-r-r.r s   zRequestReceiver.parse_headerN)rŒr�rŽrqrÿrr rr-r-r-r.rýÜs rýc@sDeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dS)rcCsi|_i|_d|_dS)Nr)r·Ú rpc_handlersrD)rvr-r-r.rqszRpcManage.__init__cCs|jd7_t|jƒS)Nr)rDr`)rvr-r-r.rµ#szRpcManage.new_rpc_idcCsVtdt|jƒ|jfƒt|jjƒƒ}|jƒx"|D]}td||j|fƒq4WdS)Nz*async_rpc_cache: %d entries, cur rpc_id=%sz%s: %s)rr0r·rDr<r±r²)rvZrpc_idsrDr-r-r.Údump_async_rpc_cache's  zRpcManage.dump_async_rpc_cachecCs|jjƒdS)N)r·r{)rvr-r-r.Úflush_async_rpc_cache.szRpcManage.flush_async_rpc_cachecCstjtjd|||fƒdS)Nz [%s] %d %s)rõrö)rvrHr’r“r-r-r.Údefault_errback1szRpcManage.default_errbackcCsˆ|dkrtjtjdtƒdS|jdkrDxZ|jD]}||jŽq0Wn@|jdkr„t|jƒdkrxx&|jD]}||jŽqdWn |j|jŽdS)Nz8process_async_return(): rpc_id=%s not in async_rpc_cacher›r¦r) rõrörDÚ return_typeÚ callbacksÚ return_argsr0Úerrbacksr)rvr¹r•r-r-r.Úprocess_async_return4s    zRpcManage.process_async_returncCs||j|<dS)N)r )rvrGZhandlerr-r-r.Úconnect_rpc_interfaceBszRpcManage.connect_rpc_interfaceN) rŒr�rŽrqrµr rrrrr-r-r-r.rsc@s�eZdZeddeƒZeddeƒZd!dd„Zdd„Zd d „Z d d „Z d d„Z dd„Z d"dd„Z dd„Zdd„Zdd„Zdd„Zdd„Zdd „ZdS)#rrÁZbuf_sizeÚtimeoutNcCs6tj|||dd�tj|ƒtjƒ|_t|jƒ|_dS)N)rÔrÕr,) rÒrqrÚ threadingZLockÚ write_lockrýÚdefault_request_handlerÚreceiver)rvrÔrÕr-r-r.rqLs  zRpcChannel.__init__cCsd|j|j|jfS)Nz channel: name=%s addr=%s type=%s)rÕr,rÔ)rvr-r-r.rxRszRpcChannel.__str__cCs|jjƒdS)N)rÚacquire)rvr-r-r.Úacquire_write_lockUszRpcChannel.acquire_write_lockcCs|jjƒdS)N)rÚrelease)rvr-r-r.Úrelease_write_lockXszRpcChannel.release_write_lockcCs ||_dS)N)rÔ)rvrÔr-r-r.Úset_channel_type[szRpcChannel.set_channel_typecCs|jS)N)rÔ)rvr-r-r.Úget_channel_type^szRpcChannel.get_channel_typerr€cCs¬td|jƒ|jƒ|jjdkr&dS|jjdk rˆy(|jjjtjƒ|jjjƒd|j_Wn,tjk r†}zd|j_WYdd}~XnX|j j ||t j B||ƒ|j ƒdS)Nzclose_connection: %s)rr,rrÁZshutdownr#Z SHUT_RDWRÚcloserórÓryrr�r×)rvr„r…rsrtrñr-r-r.rÛas    zRpcChannel.close_connectioncCs*|jj|dƒ}|dkrdSt||dƒ}|S)N)r rªÚgetattr)rvrGrHZ handler_objr­r-r-r.Úget_method_implementationrs  z$RpcChannel.get_method_implementationcGsZt|jƒt|ƒkr0tjtjdt|ƒ|fƒdSt||f|žŽ}t|||ƒ}|j|ƒdS)Nz3emit_rpc() arg length=%s does not match rpc_def(%s))r0rPrõrördrFÚ send_data)rvrDrErVrTZrpc_xmlZrpc_datar-r-r.r¸ys  zRpcChannel.emit_rpccCs\|jjtj@sdS|jƒy`d}xV|t|ƒkrv|jjjt ||d…dƒƒ}|dkrl|j tj ƒt t |jd�‚||}q"WWnÄtjk rÆ}z.tjtjd|jƒ|jƒ|jjtjƒdSd}~Xnztjk �r>}zZt|ƒ\}}tjtjd|j|fƒ|jƒ|tjk�rtj }ntj}|j |d||ƒdSd}~XnX|jjdtjƒ|jƒdS)NrzUTF-8)Zdetailzsocket timeout: (%s)z&could not send data on socket (%s): %s)rÓrrrrkrr0r,rÁÚsendÚbytesrÛr2Ú ProgramErrorrÚr#rrõrörryrnrórôr÷rørmr�)rvrZ totalSentZsentrñrÜrÝr„r-r-r.r$�s6   zRpcChannel.send_datac CsNyÞ|j|ƒsdS|tj@rÜy6|j|jƒ}|jdƒ}t|ƒdkrN|jtj ƒdSWnnt j k r¾}zPt |ƒ\}}t j t jd|j|fƒ|tjkrštj }ntj}|j|d||ƒdSd}~XnX|jjdtjƒ|jj|ƒWnjtk �rH}zLt j t jd|jjt|ƒfƒddl}t|jƒƒ|jtjddt|ƒƒdSd}~XnXdS) NFzutf-8rzsocket error (%s): %szexception %s: %srTrî)rÞrr4ZrecvÚsocket_buf_sizeÚdecoder0rÛrr2r#rórôrõrör,r÷rørmrÓryr�rr rðrùrŒr`rúrûrü) rvrÁr9rrñrÜrÝr„rúr-r-r.Úhandle_client_ioŸs6         zRpcChannel.handle_client_iocCsx|jj|dƒ}|dkr,tjtjd|ƒdStd|jj|||jj|jj |fƒt |ƒ\}}}||_ ||_ |j |ƒdS)Nz1handle_return(): rpc_id=%s not in async_rpc_cachez/%s.handle_return: rpc_id=%s type=%s %s.%s, {%s})r·ÚpoprõrörrùrŒrVrGrHr[rrr)rvrErDr>r¹rGrHrTr-r-r.Ú handle_returnÁs$zRpcChannel.handle_returncCsð|jddƒ}|jddƒ}td|jj|||fƒ|dks@|dkrR|j|||ƒ�nš|dk�rrDrErGrHrTr­rZrpc_method_defr¾rñZ rpc_error_defr’r“r-r-r.rÎsH      ,     z"RpcChannel.default_request_handler)NN)rrrr€)rŒr�rŽrr/r(Zsocket_timeoutrqrxrrrr rÛr#r¸r$r*r,rr-r-r-r.rHs    " c@s$eZdZdd„Zdd„Zdd„ZdS)r¶cCs(||_||_d|_d|_g|_g|_dS)N)rVrDrrrr)rvrVrDr-r-r.rqþs zAsyncRpc.__init__cCs|jj|ƒdS)N)rr%)rvr•r-r-r.Ú add_callbackszAsyncRpc.add_callbackcCs|jj|ƒdS)N)rr%)rvZerrbackr-r-r.Ú add_errback szAsyncRpc.add_errbackN)rŒr�rŽrqr-r.r-r-r-r.r¶üsr¶)N)=Z __future__rrrÎrMrrõrÜr÷Z gi.repositoryrrràrÁr#rærÚtypesZsetroubleshoot.configrZsetroubleshoot.errcodeZsetroubleshoot.xml_serializerr Zsetroubleshoot.utilÚ__all__rZcontent_length_rerr rrrrrr;rCrFr[rdrZ type_registerÚobjectr‘r`r/r¨r”r¤rr r r r rrÒrrýrrr¶r-r-r-r.Ús|        ))Q E<  X.I@,5__pycache__/rpc.cpython-36.pyc000064400000070511152572267760012215 0ustar003 Úh>`û“ã@s8ddlmZddlmZddlZddlZddlZddlZddlZddl m Z m Z ddl Z ddl ZddlZddlZddlTddlmZddlTddlmZmZddlTdd d d d d ddddddddgZejdƒZejdƒZejdƒZeddƒZdAdd „Zdd„Z dd„Z!dd„Z"dd „Z#d!d"„Z$d#d$„Z%d%d&„Z&d'd(„Z'Gd)d„de j ƒZ(e j)e(ƒGd*d+„d+e*ƒZ+e+d,e,ƒe+d-e-ƒe+d.e,ƒgZ.Gd/d0„d0e*ƒZ/Gd1d2„d2e*ƒZ0e0ƒZ1d3d„Z2d4d „Z3d5d „Z4d6d „Z5Gd7d„de*ƒZ6Gd8d9„d9e*ƒZ7Gd:d„de7ƒZ8Gd;d<„d<ƒZ9Gd=d„de*ƒZ:Gd>d„de7e:ƒZ;Gd?d@„d@e*ƒZq4|j|ƒ}|rŠ|jdƒjƒ}|jdƒ}tj|ƒ} | dkr”td||fƒq4n t j } |}t| ||ƒ} |j | ƒq4Wtd|| fƒ|S)Nz\s*{(unix|inet)}(.+)z%parse_socket_address_list: input='%s'z[\s,]+ééz(unknown socket family - %s in address %sz$parse_socket_address_list: %s --> %s) ÚreÚcompileÚ log_debugÚsplitÚsearchÚgroupÚlowerrÚ map_familyÚSocketÚAF_INETÚappend) Ú addr_stringÚ default_portÚsocket_addressesZ family_reZaddrsZcfg_addrÚmatchZ family_tagÚaddressÚfamilyÚsocket_address©r-ú/usr/lib/python3.6/rpc.pyrEs.        cCstddtƒ}|S)NZ connectionr')rÚint)r'r-r-r.rds cCst|dƒ}t|ƒ}|S)NZ address_list)rr)Z cfg_sectionr&r(r-r-r.ris cCs tdƒ}t|ƒdkrdS|dS)NZclient_connect_tor)rÚlen)Z addr_listr-r-r.ros cCsŽg}|tj@r|jdƒ|tj@r,|jdƒ|tj@r@|jdƒ|tj@rT|jdƒ|tj@rh|jdƒ|tj@r||jdƒd|dj|ƒfS) NÚINZOUTZPRIZERRÚHUPZNVALz(%d)[%s]ú,) rÚIO_INr%ZIO_OUTZIO_PRIÚIO_ERRÚIO_HUPÚIO_NVALÚjoin)Ú io_conditionÚnamesr-r-r.Úio_condition_to_stringvs            r;cKsBdt|ƒ}x(t|jƒƒD]\}}|d||f7}qW|d7}|S)Nzcontent-length: %d z%s: %s z )r0ÚlistÚitems)ÚbodyÚkwdsÚhdrÚkeyÚvaluer-r-r.Ú rpc_header‰s  rCcCst|||d�}||S)N)Úrpc_idÚtype)rC)rDrEr>r@r-r-r.Ú rpc_message‘srFc Csòd}}}}zÄtj|ƒ}|jƒ}|jdƒ}|jdƒ}tj||ƒ}t|dƒ}tt|ƒƒ}xv|D]n}|jdƒ}|jdƒ} t |jdƒƒ} |j | } | j dk rÀ| dkr²| j ||d�} qÆ| j |j ƒ} n|j } | || <q`WWd|dk ræ|j ƒX|||fS) NÚ interfaceÚmethodÚargÚnamerEÚpositionÚxml)Zobj_name)Úlibxml2ZparseDocZgetRootElementZproprÚ get_rpc_defr Úpreextend_listr0r/Úpositional_argsÚobj_typeZcontentÚfreeDoc) ÚcmdrGrHÚargsÚdocÚrpc_defZ arg_nodesÚarg_nodeÚarg_nameZarg_typeZ arg_positionÚrpc_argÚ arg_valuer-r-r.Úconvert_rpc_xml_to_args–s.           r[c GsJd}}�z&|j}|j}tjdƒ}tjdƒ}|jd|ƒ|jd|ƒ|j|ƒd}x¼|jD]²} | j} ||} tjdƒ} |j | ƒ| jd| ƒ| jdt |ƒƒt | tj ƒrÀ| jd d ƒ| j | ƒnDt | d ƒrê| jd d ƒ| j | j|| ƒƒn| jd d ƒ| jt | ƒƒ|d 7}qZW|jdt |ƒƒ|jtd d�}Wd|dk �rD|jƒX|S)Nz1.0rSrGrHrrIrJrKrErLÚ get_xml_nodesÚstringrZ arg_count)ÚencodingÚformat)rGrHrMZnewDocZnewNodeZsetPropZsetRootElementrPrJZaddChildÚstrÚ isinstanceZxmlNodeÚhasattrr\Z addContentZ serializerrR) rDrVrTZtext_docrUrGrHÚrootrKrYrXrZrWr-r-r.Úconvert_rpc_to_xml¿s>                  rdc@sîeZdZd#Zd$Zd%Zd&Zd'Zd(Zd)Z eeBeBeBeBeBe BZ eeBZ eeBeBe BZ eded ed ed ed ed e diZ eeeeeee gZdejjdejejejffiZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd*d!d"„ZdS)+rrréééééÚ CONNECTINGÚOPENÚ AUTHENTICATEDr2ÚERRORÚTIMEOUTÚRETRYÚchangedNcCs*tjj|ƒd|_d|_d|_|jƒdS)Nr)rÚ__init__ÚflagsÚ result_codeÚ result_msgÚ clear_result)Úselfr-r-r.rqs  zConnectionState.__init__cCsd|j|jƒ|j|jfS)Nz'flags=%s, result_code=%d, result_msg=%s)Úflags_to_stringrrrsrt)rvr-r-r.Ú__str__ szConnectionState.__str__cCs|jd|jƒdS)Nr)ÚupdateÚ ALL_FLAGS)rvr-r-r.ÚclearszConnectionState.clearcCsB|dkr d}g}x&tjD]}||@r|jtj|ƒqWdj|ƒS)Nrr3)rÚconnection_statesr%Úmap_connection_enum_to_stringr8)rvÚvalr:Ústater-r-r.rws zConnectionState.flags_to_stringcCsd|_d|_dS)NrÚ)rsrt)rvr-r-r.ruszConnectionState.clear_resultcCs||_||_dS)N)rsrt)rvrsrtr-r-r.Ú set_result!szConnectionState.set_resultcCs |j|jfS)N)rsrt)rvr-r-r.Ú get_result%szConnectionState.get_resultrr€c Csf|j}|j|O_|j|M_||_||_||jA}|j|@}||@}|rb|jd|j||ƒdS)Nrp)rrrsrtÚemit) rvÚ add_flagsÚ remove_flagsrsrtZprevious_flagsÚ differenceZ flags_addedZ flags_removedr-r-r.ry(s  zConnectionState.updaterrfééé é@é€)rrrr€)Ú__name__Ú __module__Ú __qualname__rjrkrlr2rmrnrorzÚ GOOD_FLAGSÚ PROBLEM_FLAGSr}r|rZ SignalFlagsZRUN_LASTZTYPE_INTZ __gsignals__rqrxr{rwrur�r‚ryr-r-r-r.rès8 c@seZdZddd„Zdd„ZdS)ÚRpcArgNcCs||_||_dS)N)rJrQ)rvrJrQr-r-r.rq@szRpcArg.__init__cCs6|jdkrd}n|j}|jdkr$|Sd||jfSdS)NZname_undefinedz%s:%s)rJrQ)rvrJr-r-r.rxDs   zRpcArg.__str__)NN)rŒr�rŽrqrxr-r-r-r.r‘>s r‘rHÚerr_codeÚerr_msgc@sLeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dS)Ú RpcDefinitioncCs2||_||_||_d|_|dkr(g|_n||_dS)N)rErGrHÚcallbackrP)rvrErGrHZrpc_argsr-r-r.rqUszRpcDefinition.__init__cCs„g}|jdk rLx<|jD]2}|jdk r<|jd|j|jfƒq|j|jƒqWd|j|j|jdj|ƒf}|jdkr€|d|j7}|S)Nz%s:%sz[%s] %s:%s (%s)r3rHz callback=%s) rPrQr%rJrErGrHr8r•)rvrTrYÚtextr-r-r.rx_s    zRpcDefinition.__str__cCs ||_dS)N)rE)rvrEr-r-r.Úset_typelszRpcDefinition.set_typecCs(|jdk rtj|jƒ}||j=||_dS)N)r•rÚ get_interfacerG)rvr•Úinterface_dictr-r-r.Ú set_callbackos  zRpcDefinition.set_callbackcCsf|jdkrtd|jƒ‚|jdkrVd|j}td|j|dƒ}tj|j||ƒ||_|Stj|j|jƒS)NrHz"%s rpc types do not have callbacksz%s_default_callbackÚ method_return) rEÚ ValueErrorr•rHr”rGrÚregister_rpc_defrN)rvZ callback_nameZ callback_defr-r-r.Úget_callback_defus   zRpcDefinition.get_callback_defcCsJ|dk rFtt|ƒ|jtƒ|_d}x$|D]}|j|}||_|d7}q&WdS)Nrr)rOr0rPr‘rJ)rvZ arg_namesrKrXrYr-r-r.Úset_positional_args€s  z!RpcDefinition.set_positional_argscGsJ|dk rFtt|ƒ|jtƒ|_d}x$|D]}|j|}||_|d7}q&WdS)Nrr)rOr0rPr‘rQ)rvZ obj_typesrKrQrYr-r-r.Úset_arg_obj_types‰s  zRpcDefinition.set_arg_obj_typescCsdd„|jDƒS)NcSsg|] }|j‘qSr-)rJ)Ú.0rYr-r-r.ú “sz:RpcDefinition.get_positional_arg_names..)rP)rvr-r-r.Úget_positional_arg_names’sz&RpcDefinition.get_positional_arg_namesN) rŒr�rŽrqrxr—ršržrŸr r£r-r-r-r.r”Ss     r”c@sLeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dS)ÚInterfaceRegistrycCs i|_dS)N)Ú interfaces)rvr-r-r.rqšszInterfaceRegistry.__init__cCstd|dtƒ}d|iS)NÚ error_returnÚ _error_return)r”Úerror_positional_args)rvrGZerror_return_defr-r-r.Ú new_interface�szInterfaceRegistry.new_interfacecCs,|jj|ƒ}|dkr(|j|ƒ}||j|<|S)N)r¥Úgetr©)rvÚinterface_namerGr-r-r.r˜¡s    zInterfaceRegistry.get_interfacecCsRddl}|j}|j|ƒd}|ddkr.|d=|j||ƒ}|j|ƒ|j|ƒ|S)Nrrv)ÚinspectrŒZ getargspecrNr—rŸ)rvrErGÚ method_ptrr¬rHrPrVr-r-r.Ú set_rpc_def¨s    zInterfaceRegistry.set_rpc_defcCsL|j|ƒ}t|tƒr|j}|j|ƒ}|dkrHtd||dƒ}|j|||ƒ|S)N)r˜raÚ MethodTyperŒrªr”r�)rvrGrHr™rVr-r-r.rN´s   zInterfaceRegistry.get_rpc_defcCs&|j|ƒ}t|tƒr|j}|||<dS)N)r˜rar¯rŒ)rvrGrHrVr™r-r-r.r�¾s  z"InterfaceRegistry.register_rpc_defcCs|j|ƒ}|dS)Nr§)r˜)rvrGr™r-r-r.Úget_error_rpc_defÄs z#InterfaceRegistry.get_error_rpc_defcCsxt|jjƒƒ}|jƒx\|D]T}|j|}td|ƒt|jƒƒ}|jƒx$|D]}||}tdt|ƒƒqPWqWdS)Nz Interface: %sz %s)r<r¥ÚkeysÚsortÚprintr`)rvZinterface_namesr«rGZ method_namesZ method_namerHr-r-r.Údump_interfacesÈs     z!InterfaceRegistry.dump_interfacesN) rŒr�rŽrqr©r˜r®rNr�r°r´r-r-r-r.r¤˜s  r¤cs‡fdd„}|S)Ncs,tjdˆ|ƒ}|j‰‡‡fdd„}d|_|S)NrHcs@|jƒ}tjˆˆƒ}t||ƒ}||j|<|j|d|f|žŽ|S)NrH)Ú new_rpc_idrrNÚAsyncRpcÚasync_rpc_cacheÚemit_rpc)rvrTrDrVÚ async_rpc)rGrHr-r.Úrpc_funcÞs    z/rpc_method..decorator..rpc_funcT)rr®rŒÚ_rpc_definition)r­rVrº)rG)rHr.Ú decoratorÚs zrpc_method..decoratorr-)rGr¼r-)rGr.r Ùs cs‡‡fdd„}|S)Ncs |j}tjˆ|ƒ}|jˆŽ|S)N)rŒrrNr )r­rHrV)Ú arg_typesrGr-r.r¼ës  zrpc_arg_type..decoratorr-)rGr½r¼r-)r½rGr.r êscs‡‡fdd„}|S)Ncs0tjdˆ|ƒ}tjˆˆƒ}|j|jƒd|_|S)Nr›T)rr®rNršrHr»)r­Úrpc_callback_defrV)rGrHr-r.r¼ôs   zrpc_callback..decoratorr-)rGrHr¼r-)rGrHr.r óscs‡fdd„}|S)Ncs,tjdˆ|ƒ}|j‰‡‡fdd„}d|_|S)NÚsignalcs,|jƒ}tjˆˆƒ}|j|d|f|žŽdS)Nr¿)rµrrNr¸)rvrTrDrV)rGrHr-r.rºs z/rpc_signal..decorator..rpc_funcT)rr®rŒr»)r­rVrº)rG)rHr.r¼þs zrpc_signal..decoratorr-)rGr¼r-)rGr.r ýs c@sdeZdZddeƒdfdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z e dd„ƒZ dd„Z dd„Z dS)rNcCsLtj|ƒ|_||_||_||_tj|_d|_ ||_ |dk rH|j |j|ƒdS)N) rr"r+r*Úportr'r#Z SOCK_STREAMrEÚsocketÚ friendly_nameÚparse)rvr+r*r'rÂr-r-r.rqs zSocketAddress.__init__cCsbtjddt|jƒƒ}|jdkr"dS|jtjkr$z\1ÚNonez{unix}%s socket=%sz{inet}%s:%s socket=%sÚunknown) rÚsubÚreprrÁr+r#ÚAF_UNIXr*r$rÀ)rvZ socket_reprr-r-r.rxs   zSocketAddress.__str__cCsL|jdkrdS|jtjkr$d|jS|jtjkr@d|j|jfStdƒSdS)NrÄz%sz%s:%sZUnknown)r+r#rÈr*r$rÀÚ_)rvr-r-r.Ú_get_default_friendly_name&s    z(SocketAddress._get_default_friendly_namecCs|jdkr|jƒS|jS)N)rÂrÊ)rvr-r-r.Úget_friendly_name0s zSocketAddress.get_friendly_namecCsddl}|j|ƒS)Nr)Úcopy)rvrÌr-r-r.rÌ5szSocketAddress.copycCs2|jtjkr|jS|jtjkr*|j|jfSdSdS)N)r+r#rÈr*r$rÀ)rvr-r-r.Úget_py_address9s    zSocketAddress.get_py_addresscCs0t|tjƒr,|jƒ}tjtjdœj|ƒ}|S|S)N)ZunixZinet)raÚsixZ string_typesr!r#rÈr$rª)r+r-r-r.r"As  zSocketAddress.map_familycCs6||_|tjkr||_d|_n|tjkr2|j|ƒdS)N)r+r#rÈr*rÀr$Úparse_inet_addr)rvr+Úaddrr-r-r.rÃIs   zSocketAddress.parsecCs^tjd|ƒ}|rN|jdƒ}|jdƒ}|dkr2|j}|dkr@tƒ}||_||_n d|_d|_dS)Nz^\s*([^:\s]+)\s*(:\s*([^\s]+))?rreZhostname)rrr r'Z get_hostnamer*rÀ)rvrÐr)rÀr-r-r.rÏQs   zSocketAddress.parse_inet_addr)rŒr�rŽrrqrxrÊrËrÌrÍÚ staticmethodr"rÃrÏr-r-r-r.r s    c@sNeZdZejejBejBejBZdde ƒfdd„Z dd„Z dd„Z dd „Z dS) Ú ConnectionIONcCs$tƒ|_||_||_||_d|_dS)N)rÚconnection_stater,Ú channel_typeÚ channel_nameÚ io_watch_id)rvrÔrÕr,r-r-r.rqhs zConnectionIO.__init__cCs&|jƒtj|jjtj|j|ƒ|_dS)z-callback signature: (io_object, io_condition)N)Úio_watch_removerZ io_add_watchr,rÁZPRIORITY_DEFAULTÚio_input_conditionsrÖ)rvr•r-r-r.Ú io_watch_addos zConnectionIO.io_watch_addcCs |jdk rtj|jƒd|_dS)N)rÖrZ source_remove)rvr-r-r.r×vs  zConnectionIO.io_watch_removecCsš|tjtjBtjB@r’|tj@r>t}t|ƒ}|jtjd||ƒ|tj@rft }t|ƒ}|jtj d||ƒ|tj@rŽt }t|ƒ}|jtj d||ƒdSdSdS)NrFT) rr6r5r7ÚERR_SOCKET_HUPZ get_strerrorÚclose_connectionrr2ZERR_SOCKET_ERRORrmZERR_IO_INVALID)rvr9ÚerrnoÚstrerrorr-r-r.Úvalid_io_condition{s   zConnectionIO.valid_io_condition)rŒr�rŽrr4r6r5r7rØrrqrÙr×rÞr-r-r-r.rÒes rÒc@s4eZdZdZdZdd„Zdd„Zdd„Zd d „Zd S) rFrgcCstj|dd|d�||_dS)NZ listeningZserver_listening)rÔrÕr,)rÒrqÚclient_connection_handler_class)rvr,rßr-r-r.rq˜szListeningServer.__init__cCsð||_|jjtjkrXtjj|jjƒr4tj|jjƒn$tjj |jƒ}tjj|ƒsXtj |ƒtj |jj|jj ƒ|j_ t j |jj jƒt jt jƒ|jr¦|jj jtjtjdƒ|jj j|jjƒƒ|jjtjkrØtj|jjdƒ|jj j|jƒ|jj S)Nri¶)r,r+r#rÈÚosÚpathÚexistsr*ÚremoveÚdirnameÚmakedirsrÁrEÚfcntlÚfilenoÚF_SETFDÚ FD_CLOEXECÚallow_reuse_addressZ setsockoptZ SOL_SOCKETZ SO_REUSEADDRZbindrÍÚchmodZlistenÚrequest_queue_size)rvr,rár-r-r.Únew_listening_socketœs   z$ListeningServer.new_listening_socketcCs`y |j|jƒ|j_|j|jƒWn:tk rZ}z|jjtj tj dt |ƒƒdSd}~XnXdS)NrFTéÿÿÿÿ) rír,rÁrÙÚhandle_client_connectÚ ExceptionrÓryrrmrkr`)rvÚer-r-r.Úopen²szListeningServer.openc CsRyÞ|j|ƒsdS|tj@rÜyN|jƒ\}}tj|jƒtjtjƒ|j|j ƒ}|j ||ƒ|j j dt jƒWnrtjk rÚ}zTt|ƒ\}}tjtjd|j |fƒ|tjkr²t j} nt j} |j j | d||ƒWYdd}~XnXWnntk �rL}zPtjtjd|jjt|ƒfƒddl} t| jƒƒ|j j t jddt|ƒƒWYdd}~XnXdS)NFrz5closing client connection due to socket error(%s): %szexception %s: %srTrî)rÞrr4Zacceptrærçrèrérßr,ròrÓryrr�r#ÚerrorÚget_error_from_socket_exceptionÚsyslogÚLOG_ERRÚErrnoÚEPIPEr2rmrðÚ __class__rŒr`Ú tracebackÚ syslog_traceÚ format_exc) rvrÁr9Z client_socketZclient_addressZclient_handlerrñrÜrÝr„rúr-r-r.rï»s.       ( *z%ListeningServer.handle_client_connectN) rŒr�rŽrêrìrqríròrïr-r-r-r.r“s  c@s4eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd S) ÚRequestReceivercCs||_|jƒdS)N)Ú dispatchFuncÚreset)rvrþr-r-r.rqÞszRequestReceiver.__init__cCs"d|_d|_d|_d|_d|_dS)Nrrr€rî)Ú headerLenÚbodyLenÚheaderr>Úfeed_buf)rvr-r-r.rÿâs zRequestReceiver.resetcCs¶t|jƒdkrdSxž|jdkrFtj|jƒ}|rD|jƒ|_|jƒqnPt|jƒ|j|jkr¬|j}|j|j}|j||…|_|j|d…|_d|_d|_|j |j |jƒqPqWdS)Nrrrîrî) r0rrÚ header_end_rerÚendÚ parse_headerrr>rþr)rvr)Z bodyBeginZbodyEndr-r-r.Úprocessés(    zRequestReceiver.processcCs|j|7_|jƒdS)N)rr)rvÚdatar-r-r.ÚfeedszRequestReceiver.feedcCsli|_d}xLtj|j||jdƒ}|rR|jdƒ}|jdƒjƒ}||j|<|jƒ}q Pq Wt|jdƒ|_ dS)Nrrrzcontent-length) rÚheader_field_rerrrr Ústriprr/r)rvZbeginr)rArBr-r-r.r s   zRequestReceiver.parse_headerN)rŒr�rŽrqrÿrr rr-r-r-r.rýÜs rýc@sDeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dS)rcCsi|_i|_d|_dS)Nr)r·Ú rpc_handlersrD)rvr-r-r.rqszRpcManage.__init__cCs|jd7_t|jƒS)Nr)rDr`)rvr-r-r.rµ#szRpcManage.new_rpc_idcCsVtdt|jƒ|jfƒt|jjƒƒ}|jƒx"|D]}td||j|fƒq4WdS)Nz*async_rpc_cache: %d entries, cur rpc_id=%sz%s: %s)rr0r·rDr<r±r²)rvZrpc_idsrDr-r-r.Údump_async_rpc_cache's  zRpcManage.dump_async_rpc_cachecCs|jjƒdS)N)r·r{)rvr-r-r.Úflush_async_rpc_cache.szRpcManage.flush_async_rpc_cachecCstjtjd|||fƒdS)Nz [%s] %d %s)rõrö)rvrHr’r“r-r-r.Údefault_errback1szRpcManage.default_errbackcCsˆ|dkrtjtjdtƒdS|jdkrDxZ|jD]}||jŽq0Wn@|jdkr„t|jƒdkrxx&|jD]}||jŽqdWn |j|jŽdS)Nz8process_async_return(): rpc_id=%s not in async_rpc_cacher›r¦r) rõrörDÚ return_typeÚ callbacksÚ return_argsr0Úerrbacksr)rvr¹r•r-r-r.Úprocess_async_return4s    zRpcManage.process_async_returncCs||j|<dS)N)r )rvrGZhandlerr-r-r.Úconnect_rpc_interfaceBszRpcManage.connect_rpc_interfaceN) rŒr�rŽrqrµr rrrrr-r-r-r.rsc@s�eZdZeddeƒZeddeƒZd!dd„Zdd„Zd d „Z d d „Z d d„Z dd„Z d"dd„Z dd„Zdd„Zdd„Zdd„Zdd„Zdd „ZdS)#rrÁZbuf_sizeÚtimeoutNcCs6tj|||dd�tj|ƒtjƒ|_t|jƒ|_dS)N)rÔrÕr,) rÒrqrÚ threadingZLockÚ write_lockrýÚdefault_request_handlerÚreceiver)rvrÔrÕr-r-r.rqLs  zRpcChannel.__init__cCsd|j|j|jfS)Nz channel: name=%s addr=%s type=%s)rÕr,rÔ)rvr-r-r.rxRszRpcChannel.__str__cCs|jjƒdS)N)rÚacquire)rvr-r-r.Úacquire_write_lockUszRpcChannel.acquire_write_lockcCs|jjƒdS)N)rÚrelease)rvr-r-r.Úrelease_write_lockXszRpcChannel.release_write_lockcCs ||_dS)N)rÔ)rvrÔr-r-r.Úset_channel_type[szRpcChannel.set_channel_typecCs|jS)N)rÔ)rvr-r-r.Úget_channel_type^szRpcChannel.get_channel_typerr€cCs¬td|jƒ|jƒ|jjdkr&dS|jjdk rˆy(|jjjtjƒ|jjjƒd|j_Wn,tjk r†}zd|j_WYdd}~XnX|j j ||t j B||ƒ|j ƒdS)Nzclose_connection: %s)rr,rrÁZshutdownr#Z SHUT_RDWRÚcloserórÓryrr�r×)rvr„r…rsrtrñr-r-r.rÛas    zRpcChannel.close_connectioncCs*|jj|dƒ}|dkrdSt||dƒ}|S)N)r rªÚgetattr)rvrGrHZ handler_objr­r-r-r.Úget_method_implementationrs  z$RpcChannel.get_method_implementationcGsZt|jƒt|ƒkr0tjtjdt|ƒ|fƒdSt||f|žŽ}t|||ƒ}|j|ƒdS)Nz3emit_rpc() arg length=%s does not match rpc_def(%s))r0rPrõrördrFÚ send_data)rvrDrErVrTZrpc_xmlZrpc_datar-r-r.r¸ys  zRpcChannel.emit_rpccCs\|jjtj@sdS|jƒy`d}xV|t|ƒkrv|jjjt ||d…dƒƒ}|dkrl|j tj ƒt t |jd�‚||}q"WWnÄtjk rÆ}z.tjtjd|jƒ|jƒ|jjtjƒdSd}~Xnztjk �r>}zZt|ƒ\}}tjtjd|j|fƒ|jƒ|tjk�rtj }ntj}|j |d||ƒdSd}~XnX|jjdtjƒ|jƒdS)NrzUTF-8)Zdetailzsocket timeout: (%s)z&could not send data on socket (%s): %s)rÓrrrrkrr0r,rÁÚsendÚbytesrÛr2Ú ProgramErrorrÚr#rrõrörryrnrórôr÷rørmr�)rvrZ totalSentZsentrñrÜrÝr„r-r-r.r$�s6   zRpcChannel.send_datac CsNyÞ|j|ƒsdS|tj@rÜy6|j|jƒ}|jdƒ}t|ƒdkrN|jtj ƒdSWnnt j k r¾}zPt |ƒ\}}t j t jd|j|fƒ|tjkrštj }ntj}|j|d||ƒdSd}~XnX|jjdtjƒ|jj|ƒWnjtk �rH}zLt j t jd|jjt|ƒfƒddl}t|jƒƒ|jtjddt|ƒƒdSd}~XnXdS) NFzutf-8rzsocket error (%s): %szexception %s: %srTrî)rÞrr4ZrecvÚsocket_buf_sizeÚdecoder0rÛrr2r#rórôrõrör,r÷rørmrÓryr�rr rðrùrŒr`rúrûrü) rvrÁr9rrñrÜrÝr„rúr-r-r.Úhandle_client_ioŸs6         zRpcChannel.handle_client_iocCsx|jj|dƒ}|dkr,tjtjd|ƒdStd|jj|||jj|jj |fƒt |ƒ\}}}||_ ||_ |j |ƒdS)Nz1handle_return(): rpc_id=%s not in async_rpc_cachez/%s.handle_return: rpc_id=%s type=%s %s.%s, {%s})r·ÚpoprõrörrùrŒrVrGrHr[rrr)rvrErDr>r¹rGrHrTr-r-r.Ú handle_returnÁs$zRpcChannel.handle_returncCsð|jddƒ}|jddƒ}td|jj|||fƒ|dks@|dkrR|j|||ƒ�nš|dk�rrDrErGrHrTr­rZrpc_method_defr¾rñZ rpc_error_defr’r“r-r-r.rÎsH      ,     z"RpcChannel.default_request_handler)NN)rrrr€)rŒr�rŽrr/r(Zsocket_timeoutrqrxrrrr rÛr#r¸r$r*r,rr-r-r-r.rHs    " c@s$eZdZdd„Zdd„Zdd„ZdS)r¶cCs(||_||_d|_d|_g|_g|_dS)N)rVrDrrrr)rvrVrDr-r-r.rqþs zAsyncRpc.__init__cCs|jj|ƒdS)N)rr%)rvr•r-r-r.Ú add_callbackszAsyncRpc.add_callbackcCs|jj|ƒdS)N)rr%)rvZerrbackr-r-r.Ú add_errback szAsyncRpc.add_errbackN)rŒr�rŽrqr-r.r-r-r-r.r¶üsr¶)N)=Z __future__rrrÎrMrrõrÜr÷Z gi.repositoryrrràrÁr#rærÚtypesZsetroubleshoot.configrZsetroubleshoot.errcodeZsetroubleshoot.xml_serializerr Zsetroubleshoot.utilÚ__all__rZcontent_length_rerr rrrrrr;rCrFr[rdrZ type_registerÚobjectr‘r`r/r¨r”r¤rr r r r rrÒrrýrrr¶r-r-r-r.Ús|        ))Q E<  X.I@,5__pycache__/rpc_interfaces.cpython-36.opt-1.pyc000064400000011373152572267760015360 0ustar003 Úh>`¸ã@shddlmZmZmZmZddlTddddgZGdd„dƒZGdd„dƒZGd d„dƒZ Gd d„dƒZ d S) é)Ú rpc_methodÚ rpc_arg_typeÚ rpc_callbackÚ rpc_signal)Ú*ÚSETroubleshootServerInterfaceÚSETroubleshootDatabaseInterfaceÚ%SETroubleshootDatabaseNotifyInterfaceÚSEAlertInterfacec@s eZdZedƒdd„ƒZeddƒedeƒdd„ƒƒZedƒdd„ƒZ edd ƒd d „ƒZ edƒd d „ƒZ eddƒede ƒdd„ƒƒZ edƒede ƒdd„ƒƒZdS)rZSETroubleshootServercCsdS)N©)ÚselfZ database_namer r ú$/usr/lib/python3.6/rpc_interfaces.pyÚ database_bind&sz+SETroubleshootServerInterface.database_bindrcCsdS)Nr )r Ú propertiesr r r Údatabase_bind_callback*sz4SETroubleshootServerInterface.database_bind_callbackcCsdS)Nr )r ÚtypeÚusernameZpasswordr r r Úlogon2sz#SETroubleshootServerInterface.logonrcCsdS)Nr )Z pkg_versionZ rpc_versionr r r Úlogon_callback6sz,SETroubleshootServerInterface.logon_callbackcCsdS)Nr )r r r r Úquery_email_recipients=sz4SETroubleshootServerInterface.query_email_recipientsrcCsdS)Nr )r Ú recipientsr r r Úquery_email_recipients_callbackAsz=SETroubleshootServerInterface.query_email_recipients_callbackcCsdS)Nr )r rr r r Úset_email_recipientsFsz2SETroubleshootServerInterface.set_email_recipientsN)Ú__name__Ú __module__Ú __qualname__rrrrÚSEDatabasePropertiesrrrrZSEEmailRecipientSetrrr r r r r!sc@seZdZedƒedeƒdd„ƒƒZedƒedeeƒdd„ƒƒZe ddƒdd„ƒZ edƒd d „ƒZ e dd ƒede ƒd d „ƒƒZ edƒdd„ƒZe ddƒedeƒdd„ƒƒZedƒdd„ƒZe ddƒedeƒdd„ƒƒZedƒedeeeeƒdd„ƒƒZedƒedeeeeƒdd„ƒƒZdS)rZSETroubleshootDatabasecCsdS)Nr )r Úsigr r r Údelete_signatureSsz0SETroubleshootDatabaseInterface.delete_signaturecCsdS)Nr )r rrr r r Úevaluate_alert_filter[sz5SETroubleshootDatabaseInterface.evaluate_alert_filterrcCsdS)Nr )r Úresultr r r Úevaluate_alert_filter_callback`sz>SETroubleshootDatabaseInterface.evaluate_alert_filter_callbackcCsdS)Nr )r r r r Úget_propertiesgsz.SETroubleshootDatabaseInterface.get_propertiesr"cCsdS)Nr )r rr r r Úget_properties_callbackksz7SETroubleshootDatabaseInterface.get_properties_callbackcCsdS)Nr )r Zlocal_idr r r Úlookup_local_idssz/SETroubleshootDatabaseInterface.lookup_local_idr$cCsdS)Nr )r Úsiginfor r r Úlookup_local_id_callbackwsz8SETroubleshootDatabaseInterface.lookup_local_id_callbackcCsdS)Nr )r Zcriteriar r r Ú query_alertssz,SETroubleshootDatabaseInterface.query_alertsr'cCsdS)Nr )r Zsigsr r r Úquery_alerts_callbackƒsz5SETroubleshootDatabaseInterface.query_alerts_callbackcCsdS)Nr )r rrZ filter_typeÚdatar r r Ú set_filter‹sz*SETroubleshootDatabaseInterface.set_filtercCsdS)Nr )r rrÚkeyÚvaluer r r Ú set_user_data“sz-SETroubleshootDatabaseInterface.set_user_dataN)rrrrrZSEFaultSignaturerÚstrrrr!r"rr#r$ÚSEFaultSignatureInfor&r'ZSEFaultSignatureSetr(Úintr*r-r r r r rNs$c@seZdZedƒdd„ƒZdS)r ZSETroubleshootDatabaseNotifycCsdS)Nr )rÚitemr r r Úsignatures_updatedŸsz8SETroubleshootDatabaseNotifyInterface.signatures_updatedN)rrrrr2r r r r r šsc@s&eZdZedƒedeƒdd„ƒƒZdS)r ZSEAlertcCsdS)Nr )r%r r r Úalert«szSEAlertInterface.alertN)rrrrrr/r3r r r r r ¦sN) Zsetroubleshoot.rpcrrrrZsetroubleshoot.signatureÚ__all__rrr r r r r r Ús-L __pycache__/rpc_interfaces.cpython-36.pyc000064400000011373152572267760014421 0ustar003 Úh>`¸ã@shddlmZmZmZmZddlTddddgZGdd„dƒZGdd„dƒZGd d„dƒZ Gd d„dƒZ d S) é)Ú rpc_methodÚ rpc_arg_typeÚ rpc_callbackÚ rpc_signal)Ú*ÚSETroubleshootServerInterfaceÚSETroubleshootDatabaseInterfaceÚ%SETroubleshootDatabaseNotifyInterfaceÚSEAlertInterfacec@s eZdZedƒdd„ƒZeddƒedeƒdd„ƒƒZedƒdd„ƒZ edd ƒd d „ƒZ edƒd d „ƒZ eddƒede ƒdd„ƒƒZ edƒede ƒdd„ƒƒZdS)rZSETroubleshootServercCsdS)N©)ÚselfZ database_namer r ú$/usr/lib/python3.6/rpc_interfaces.pyÚ database_bind&sz+SETroubleshootServerInterface.database_bindrcCsdS)Nr )r Ú propertiesr r r Údatabase_bind_callback*sz4SETroubleshootServerInterface.database_bind_callbackcCsdS)Nr )r ÚtypeÚusernameZpasswordr r r Úlogon2sz#SETroubleshootServerInterface.logonrcCsdS)Nr )Z pkg_versionZ rpc_versionr r r Úlogon_callback6sz,SETroubleshootServerInterface.logon_callbackcCsdS)Nr )r r r r Úquery_email_recipients=sz4SETroubleshootServerInterface.query_email_recipientsrcCsdS)Nr )r Ú recipientsr r r Úquery_email_recipients_callbackAsz=SETroubleshootServerInterface.query_email_recipients_callbackcCsdS)Nr )r rr r r Úset_email_recipientsFsz2SETroubleshootServerInterface.set_email_recipientsN)Ú__name__Ú __module__Ú __qualname__rrrrÚSEDatabasePropertiesrrrrZSEEmailRecipientSetrrr r r r r!sc@seZdZedƒedeƒdd„ƒƒZedƒedeeƒdd„ƒƒZe ddƒdd„ƒZ edƒd d „ƒZ e dd ƒede ƒd d „ƒƒZ edƒdd„ƒZe ddƒedeƒdd„ƒƒZedƒdd„ƒZe ddƒedeƒdd„ƒƒZedƒedeeeeƒdd„ƒƒZedƒedeeeeƒdd„ƒƒZdS)rZSETroubleshootDatabasecCsdS)Nr )r Úsigr r r Údelete_signatureSsz0SETroubleshootDatabaseInterface.delete_signaturecCsdS)Nr )r rrr r r Úevaluate_alert_filter[sz5SETroubleshootDatabaseInterface.evaluate_alert_filterrcCsdS)Nr )r Úresultr r r Úevaluate_alert_filter_callback`sz>SETroubleshootDatabaseInterface.evaluate_alert_filter_callbackcCsdS)Nr )r r r r Úget_propertiesgsz.SETroubleshootDatabaseInterface.get_propertiesr"cCsdS)Nr )r rr r r Úget_properties_callbackksz7SETroubleshootDatabaseInterface.get_properties_callbackcCsdS)Nr )r Zlocal_idr r r Úlookup_local_idssz/SETroubleshootDatabaseInterface.lookup_local_idr$cCsdS)Nr )r Úsiginfor r r Úlookup_local_id_callbackwsz8SETroubleshootDatabaseInterface.lookup_local_id_callbackcCsdS)Nr )r Zcriteriar r r Ú query_alertssz,SETroubleshootDatabaseInterface.query_alertsr'cCsdS)Nr )r Zsigsr r r Úquery_alerts_callbackƒsz5SETroubleshootDatabaseInterface.query_alerts_callbackcCsdS)Nr )r rrZ filter_typeÚdatar r r Ú set_filter‹sz*SETroubleshootDatabaseInterface.set_filtercCsdS)Nr )r rrÚkeyÚvaluer r r Ú set_user_data“sz-SETroubleshootDatabaseInterface.set_user_dataN)rrrrrZSEFaultSignaturerÚstrrrr!r"rr#r$ÚSEFaultSignatureInfor&r'ZSEFaultSignatureSetr(Úintr*r-r r r r rNs$c@seZdZedƒdd„ƒZdS)r ZSETroubleshootDatabaseNotifycCsdS)Nr )rÚitemr r r Úsignatures_updatedŸsz8SETroubleshootDatabaseNotifyInterface.signatures_updatedN)rrrrr2r r r r r šsc@s&eZdZedƒedeƒdd„ƒƒZdS)r ZSEAlertcCsdS)Nr )r%r r r Úalert«szSEAlertInterface.alertN)rrrrrr/r3r r r r r ¦sN) Zsetroubleshoot.rpcrrrrZsetroubleshoot.signatureÚ__all__rrr r r r r r Ús-L __pycache__/server.cpython-36.opt-1.pyc000064400000062055152572267760013702 0ustar003 ¹Qf4„ã@s2ddlmZdddddgZddlmZmZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZdd lmZmZed d ƒZed d ƒZiZe jdBkr´ded<e jfeedœe—Že jeedd�Zy ejZWnek �rej ZYnXddlmZddlm Z m!Z!m"Z"m#Z#ddl$TddlmZddl$m%Z%ddl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-ddl.m/Z/m0Z0m1Z1m2Z2ddl3m4Z4m5Z5m6Z6ddl7m8Z8m9Z9m:Z:m;Z;mZ>e„ZfdCd@d„ZgehdAk�r.egƒdS)Dé)Úabsolute_importÚRunFaultServerÚClientConnectionHandlerÚget_host_databaseÚsend_alert_notificationÚConnectionPool)ÚGObjectÚGLibN)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_diréTZunicode)ÚdomainÚ localedir)r rZfallback)Ú ServerAccess)ÚPluginReportReceiverÚSETroubleshootDatabaseÚTestPluginReportReceiverÚ AnalyzeThread)Ú*)r )ÚAuditRecordReceiver)Ú ProgramErrorÚERR_NOT_AUTHENTICATEDÚERR_USER_LOOKUPÚERR_USER_PROHIBITEDÚERR_USER_PERMISSIONÚ ERR_FILE_OPENÚERR_DATABASE_NOT_FOUND)Ú RpcChannelÚConnectionStateÚget_socket_list_from_configÚListeningServer)ÚSETroubleshootServerInterfaceÚ%SETroubleshootDatabaseNotifyInterfaceÚSEAlertInterface)Ú get_hostnameÚmake_database_filepathÚ!assure_file_ownership_permissionsÚ get_identityÚlog_initÚ log_debugÚ syslog_traceÚsetroubleshootd_logcCs8td|ƒddlj}|tjkr4tdƒ|jƒdSdS)Nzreceived signal=%srzreloading configuration file)r)Úsetroubleshoot.configÚconfigÚsignalÚSIGHUPZ config_init)ÚsignumÚframer-©r2ú/usr/lib/python3.6/server.pyÚ sighandlerms    r4cCs(td|ƒtjtjdƒtjdƒdS)Nzreceived signal=%sz=/sys/fs/selinux/policy is in use by another process. Exiting!é)r)ÚsyslogÚLOG_ERRÚosÚ_exit)r0r1r2r2r3Úpolling_failed_handlervs r:cCs0ddl}tƒ}tjƒ}t|jƒƒ}d|||fS)Nrz%s:%s:%s)Útimer$r8ÚgetpidÚstr)r;ZhostnameÚpidZstampr2r2r3Úmake_instance_id}s  r?cCstS)N)Ú host_databaser2r2r2r3r…sZ system_dbusZbus_nameÚ object_pathZ interfacecCsTtjjttdƒ}|j|jƒ|j|jƒtj |ƒxt j dƒD]}|j |ƒq>WdS)NÚalertÚsealert) ÚdbusZlowlevelZ SignalMessageÚdbus_system_object_pathÚdbus_system_interfaceÚappendÚlevelÚlocal_idÚ system_busZ send_messageÚconnection_poolÚclientsrB)ÚsiginforBÚclientr2r2r3r’s    ZemailZrecipients_filepathÚpkg_nameÚ pkg_versionÚ rpc_versionc@s8eZdZdd„Zdd„Zdd„Zd dd „Zd d d „ZdS)rcCs i|_dS)N)Ú client_pool)Úselfr2r2r3Ú__init__«szConnectionPool.__init__cCs(||jkrtd|ƒdSd|j|<dS)Nz.add_client: client (%s) already in client pool)rRr))rSÚhandlerr2r2r3Ú add_client®s  zConnectionPool.add_clientcCs&||jkrtd|ƒdS|j|=dS)Nz-remove_client: client (%s) not in client pool)rRr))rSrUr2r2r3Ú remove_client´s  zConnectionPool.remove_clientNccs4x.|jD]$}|dkr|Vq|j|kr|VqWdS)N)rRÚ channel_type)rSrXrNr2r2r3rLºs   zConnectionPool.clientscCs&x |jD]}|j|kr|jƒqWdS)N)rRrXZclose_connection)rSrXrNr2r2r3Ú close_allÁs  zConnectionPool.close_all)N)N)Ú__name__Ú __module__Ú __qualname__rTrVrWrLrYr2r2r2r3r©s  cs(eZdZ‡fdd„Z‡fdd„Z‡ZS)ÚAlertPluginReportReceivercstt|ƒj|ƒdS)N)Úsuperr]rT)rSÚdatabase)Ú __class__r2r3rTÍsz"AlertPluginReportReceiver.__init__c s^tt|ƒj|ƒ}tdk rŽg}xHtjD]>}d|j}|j||jƒ}|dkr$td|j ƒ|j |jƒq$Wt |ƒr„ddl m }|||ƒ|jjƒtdƒddlm}tjtj|jƒtdƒ|jƒx&|jjD]}|jd krÌ|jd } PqÌWtd d tƒ�rtjj|j ƒ| t!d �xB|j"D]8} | j#dd…dk�r2�q|j| j#ƒ}|dk�r|S�qWt$|ƒ|S)Nzemail:%sÚignorezEmail: siginfo.sig=%sr)Ú email_alertzsending alert to all clients)Ú html_to_textz1 For complete SELinux messages run: sealert -l %sÚAVCr>r+Zlog_full_report)Z OBJECT_PIDZSYSLOG_IDENTIFIERézemail:)%r^r]Úreport_problemÚemail_recipientsZrecipient_listZaddressÚevaluate_filter_for_userÚ filter_typer)ÚsigrGÚlenZsetroubleshoot.email_alertrbr_Z mark_modifiedZsetroubleshoot.html_utilrcr6r7ÚsummaryÚ_rIÚ audit_eventÚrecordsÚ record_typeÚfieldsr ÚboolÚsystemdZjournalÚsendZ format_textrOZusersÚusernamer) rSrMZto_addrsZ recipientruÚactionrbrcÚ audit_recordr>Úu)r`r2r3rfÐs<             z(AlertPluginReportReceiver.report_problem)rZr[r\rTrfÚ __classcell__r2r2)r`r3r]Ës r]c@s$eZdZdd„Zdd„Zdd„ZdS)rcCs*tj|dƒ|jƒ|_|jjd|jƒdS)NrCZchanged)rrTÚcopyÚsocket_addressÚconnection_stateZconnectÚon_connection_state_change)rSr{r2r2r3rTýs  z ClientConnectionHandler.__init__cCsTtd|jj||j|ƒ|j|ƒ|jfƒ|tj@r|D]6} | j |krPq@| j |ƒ|kr@|j | j | jƒ| jfƒq@W|S)Ni@Br)r'rÂrÃrÚsetroubleshootÚutilZ TimeStampÚfloatr›Úsignature_listÚlast_seen_daterhrGrIrlÚ report_count) rSÚsincer¼Ú alert_actionrur_Z since_alertsÚdatabase_alertsZalertsrBr2r2r3Ú_get_all_alerts_since s   z/SetroubleshootdDBusObject._get_all_alerts_sinceÚtza(ssi)cCs |j||ƒS)N)rÓ)rSrÐr¼r2r2r3Úget_all_alerts_sincesz.SetroubleshootdDBusObject.get_all_alerts_sincer�cCs |jd|ƒS)aº Return array of *local_id*'s, *summary*'s, and *report_count*'s of all current alerts in a setroubleshoot database returns list of: * `local_id(s)`: a report id in a setroubleshoot database * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert r)rÓ)rSr¼r2r2r3Úget_all_alertss z(SetroubleshootdDBusObject.get_all_alertscCs|jd|dd�S)a¾ Return array of *local_id*'s, *summary*'s, and *report_count*'s of all alerts which a user set to be ignored by a user returns list of: * `local_id(s)`: a report id in a setroubleshoot database * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert rra)rÑ)rÓ)rSr¼r2r2r3Úget_all_alerts_ignored(s z0SetroubleshootdDBusObject.get_all_alerts_ignoredcCsFy|j|ƒ}Wn&tk r4}z |‚WYdd}~XnX|jƒjƒ}|S)N)r›rrÄÚ__next__)rSrIr_rÒr·rBr2r2r3Ú _get_alert4s  z$SetroubleshootdDBusObject._get_alertzssiasa(ssssbbi)ttsc Csît|jj|ƒƒ}tƒ}|j||ƒ}|jƒ|jj}dd„|Dƒ}|jƒ\}} g} xZ| D]R\} } | j |j | j || ƒƒ|j | j || ƒƒ|j | j || ƒƒ| j| j| j| jfƒqVW|j|jƒ|j|| t|jjdƒƒdt|jjdƒƒd|jpêdfS)ar Return an alert with summary, audit events, fix suggestions ##### arguments * `local_id(s)`: an alert id ##### return values * `local_id(s)`: an alert id * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert * `audit_event(as)`: an array of audit events (AVC, SYSCALL) connected to the alert * `plugin_analysis(a(ssssbb)`: an array of plugin analysis structure * `if_text(s)`: * `then_text(s)` * `do_text(s)` * `analysis_id(s)`: plugin id. It can be used in `org.fedoraproject.SetroubleshootFixit.run_fix()` * `fixable(b)`: True when an alert is fixable by a plugin * `report_bug(b)`: True when an alert should be reported to bugzilla * `priority(i)`: An analysis priority. Typically the value is between 1 - 100. * `first_seen_date(t)`: when the alert was seen for the first time, number of microseconds since the Epoch * `last_seen_date(t)`: when the alert was seen for the last time, number of microseconds since the Epoch * `level(s)`: "green", "yellow" or "red" cSsg|] }|jƒ‘qSr2)Zto_text)Ú.0Zeventr2r2r3ú ^sz7SetroubleshootdDBusObject.get_alert..z%si@Br�)r'rÂrÃrrÙZ%update_derived_template_substitutionsrnroZ get_pluginsrGZ substituteZ get_if_textZ get_then_textZ get_do_textZ analysis_idZfixableZ report_bugZpriorityrIrlrÏÚintZfirst_seen_dateÚformatrÎrH) rSrIr¼rur_rBr¶Z audit_eventsZtotal_priorityZ alert_pluginsZpluginsZpluginÚargsr2r2r3Ú get_alert<s,  z#SetroubleshootdDBusObject.get_alertÚbc CsXyHt|jj|ƒƒ}tƒ}|j||ƒ}ddlm}|j|j|||dƒdSdSdS)zö Sets a filter on an alert. The alert can be "always" filtered, "never" filtered or "after_first" filtered. ##### arguments * `local_id(s)`: an alert id * `filter_type(s)`: "always", "never", "after_first" ##### return values * `success(b)`: r)Úmap_filter_name_to_valueNTF) r'rÂrÃrrÙÚsetroubleshoot.signatureráržrj)rSrIrir¼rur_rBrár2r2r3ržts  z$SetroubleshootdDBusObject.set_filterc Cs2y"tƒ}|j||ƒ}|j|jƒdSdSdS)zz Deletes an alert from the database. ##### arguments * `local_id(s)`: an alert id ##### return values * `success(b)`: TFN)rrÙr—rj)rSrIr¼r_rBr2r2r3Ú delete_alertŒs   z&SetroubleshootdDBusObject.delete_alert)r¾r¿c Cst|ƒ}|jdƒ|jd7_td||jfƒx^|jjt|ƒƒD]J\}}}}}t|||||ƒ}|jƒx"|jj|ƒD]}|j t |ƒƒqxWqDWx\|jj dƒD]L}y|j t |ƒƒWq t k rê} zt j t jd| ƒWYdd} ~ Xq Xq W|jd8_|j|jƒtdƒS)Nrr5z#dbus avc(%s) called: %d ConnectionszUnable to add audit event: %srd)r=r«r©r)r®ZfeedZ AuditRecordZaudispd_rectifyr¯r¸rdÚflushrµr6r7rªrm) rSrŸrpZevent_idZ body_textrqZ line_numberrwrnr·r2r2r3r¶¡s"  ( zSetroubleshootdDBusObject.avccCs,|jd8_td|jƒ|j|jƒdS)Nr5z*dbus iface finish() called: %d Connectionsr�)r©r)r«rª)rSr2r2r3Úfinish¸s z SetroubleshootdDBusObject.finishcCs|jdkrtj|ƒdS)Nr)r©r.r«)rSrªr2r2r3r«¿s zSetroubleshootdDBusObject.alarmN)r¥)rÉ)r¥)rZr[r\rTr¸rDr¦r.rFrºrBÚmethodr»rÈrÓrÕrÖr×rÙrßržrãr¶rår«r2r2r2r3r¤Æs"    8r¤cCs|jS)N)rÎ)Úar2r2r3rÆÄsrÆc@seZdZdd„Zdd„ZdS)ÚSetroubleshootdDBuscCsdy&tdtttfƒtt|||ƒ|_Wn8tk r^}ztjtjd|ƒ|‚WYdd}~XnXdS)Nz=creating system dbus: bus_name=%s object_path=%s interface=%sz$cannot start system DBus service: %s) r)Údbus_system_bus_namerErFr¤Údbus_objÚ Exceptionr6r7)rSr°r±rªr·r2r2r3rTÊs zSetroubleshootdDBus.__init__cCs|jjdƒdS)Nzdaemon requestT)rêrº)rSr2r2r3Ú do_restartÒs zSetroubleshootdDBus.do_restartN)rZr[r\rTrìr2r2r2r3rèÈsrècCs|jƒtjƒdS)N)ÚsaveÚ audit2whyrå)r_r2r2r3ÚgoodbyeÛsrïcCstdƒtjƒdS)Nz SIGALRM raised in RunFaultServer)r)Ú main_loopÚquit)r0r1r2r2r3Ú alarm_handlerãsròr¥cCsˆtj|ƒtjtjtƒxŒytjƒtjdƒPWqtk rf}zdt|ƒkrRw|‚WYdd}~Xqtk r }z dtt |ddƒƒkrŒw|‚WYdd}~XqXqWtjtjt ƒtjtj t ƒ�yt jtƒttƒ}tddƒ}t|ƒ}t|ddƒt||td ƒd �atj|ƒtjttƒd }x˜tjjD]Œ}tjt|jj ƒt|jj!ƒt|jj"ƒ|jj#ƒ\}}|tj$k�sx|tj%k�r,|tj$k�rŠd } nd } t j t j&d|j'| fƒd}tj(|jƒ�q,W|�rÎtj)dd�tddt*ƒ�sæt+tƒ} nt,tƒ} ddl-} | j.j/j0dƒa1t2t1|ƒ} | j3dƒ| j4ƒddl5m6} | ƒa7tt8ddƒyt7j9t8ƒWn@t:k �rŒ}z"|j;tƒn|‚WYdd}~XnXt?dƒ}x |D]}t@|tAƒ}|jBƒ�qœWtCjDjEƒtFt1| |ƒ}tGjHƒWnªtIk �r}zt=dƒWYdd}~Xn€tJk �r.}zt=dƒWYdd}~XnVtKk �r‚}z8ddlL}tM|jNƒƒt j t j&d|jOjPt|ƒfƒWYdd}~XnXdS)Nrz%unable to open /sys/fs/selinux/policyÚ __context__r�r_Úfilenamei€rÊzAudit Listener)Z friendly_nameFZallowedz dontaudit'dz-Deleting alert %s, it is %s in current policyT)ZpruneZtestÚanalyze)ÚSEEmailRecipientSetZlisten_for_clientz#KeyboardInterrupt in RunFaultServerz$raising SystemExit in RunFaultServerzexception %s: %s)Qr.r«ÚSIGALRMr:rîZinitrµr=Ú SystemErrorÚgetattrròr/r4r6ZopenlogrOr¢rKr r%r&rrmr@Z set_notifyÚatexitÚregisterrïrœrÍrõrjZscontextZtcontextZtclassr‰ZALLOWZ DONTAUDITr7rIr—rírrr]rZsix.moves.queueZmovesr¬ZQueuer°rZ setDaemonr»rârörgr•Zparse_recipient_filerÚerrnorr)Ústrerrorrr rˆr‡rDZglibZ init_threadsrèrðZrunÚKeyboardInterruptÚ SystemExitrëÚ tracebackr*Ú format_excr`rZ)rªr·Zclient_notifierZdatabase_filenameZdatabase_filepathZdeletedÚiZwhyZboolsr¹r±ZsixZanalyze_threadröZlisten_addressesZlisten_addressZlistening_serverZsetroubleshootd_dbusrr2r2r3rèsŽ         0               Ú__main__)r )r¥)iZ __future__rÚ__all__Z gi.repositoryrr rDZ dbus.serviceZ dbus.glibÚgettextr8r.rúÚsysr6Zsystemd.journalrsr,r r r rÚkwargsÚ version_infoZinstallZ translationZugettextrmÚAttributeErrorZsetroubleshoot.access_controlrZsetroubleshoot.analyzerrrrZsetroubleshoot.avc_auditrZsetroubleshoot.errcoderrrrrrrZsetroubleshoot.rpcrrrr Zsetroubleshoot.rpc_interfacesr!r"r#Zsetroubleshoot.utilr$r%r&r'r(r)r*r4r:r?rrérErFr¨rJZ request_namerr@r°rgr•rOrPrQZ instance_idÚobjectrrKr]rrˆr¢Zsetroubleshoot.audit_datarÊr¦r§r¤rÆrèr²Zselinux.audit2whyrîrïZMainLooprðròrrZr2r2r2r3Ús¬         $ $          0     __pycache__/server.cpython-36.pyc000064400000062055152572267760012743 0ustar003 ¹Qf4„ã@s2ddlmZdddddgZddlmZmZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZdd lmZmZed d ƒZed d ƒZiZe jdBkr´ded<e jfeedœe—Že jeedd�Zy ejZWnek �rej ZYnXddlmZddlm Z m!Z!m"Z"m#Z#ddl$TddlmZddl$m%Z%ddl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-ddl.m/Z/m0Z0m1Z1m2Z2ddl3m4Z4m5Z5m6Z6ddl7m8Z8m9Z9m:Z:m;Z;mZ>e„ZfdCd@d„ZgehdAk�r.egƒdS)Dé)Úabsolute_importÚRunFaultServerÚClientConnectionHandlerÚget_host_databaseÚsend_alert_notificationÚConnectionPool)ÚGObjectÚGLibN)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_diréTZunicode)ÚdomainÚ localedir)r rZfallback)Ú ServerAccess)ÚPluginReportReceiverÚSETroubleshootDatabaseÚTestPluginReportReceiverÚ AnalyzeThread)Ú*)r )ÚAuditRecordReceiver)Ú ProgramErrorÚERR_NOT_AUTHENTICATEDÚERR_USER_LOOKUPÚERR_USER_PROHIBITEDÚERR_USER_PERMISSIONÚ ERR_FILE_OPENÚERR_DATABASE_NOT_FOUND)Ú RpcChannelÚConnectionStateÚget_socket_list_from_configÚListeningServer)ÚSETroubleshootServerInterfaceÚ%SETroubleshootDatabaseNotifyInterfaceÚSEAlertInterface)Ú get_hostnameÚmake_database_filepathÚ!assure_file_ownership_permissionsÚ get_identityÚlog_initÚ log_debugÚ syslog_traceÚsetroubleshootd_logcCs8td|ƒddlj}|tjkr4tdƒ|jƒdSdS)Nzreceived signal=%srzreloading configuration file)r)Úsetroubleshoot.configÚconfigÚsignalÚSIGHUPZ config_init)ÚsignumÚframer-©r2ú/usr/lib/python3.6/server.pyÚ sighandlerms    r4cCs(td|ƒtjtjdƒtjdƒdS)Nzreceived signal=%sz=/sys/fs/selinux/policy is in use by another process. Exiting!é)r)ÚsyslogÚLOG_ERRÚosÚ_exit)r0r1r2r2r3Úpolling_failed_handlervs r:cCs0ddl}tƒ}tjƒ}t|jƒƒ}d|||fS)Nrz%s:%s:%s)Útimer$r8ÚgetpidÚstr)r;ZhostnameÚpidZstampr2r2r3Úmake_instance_id}s  r?cCstS)N)Ú host_databaser2r2r2r3r…sZ system_dbusZbus_nameÚ object_pathZ interfacecCsTtjjttdƒ}|j|jƒ|j|jƒtj |ƒxt j dƒD]}|j |ƒq>WdS)NÚalertÚsealert) ÚdbusZlowlevelZ SignalMessageÚdbus_system_object_pathÚdbus_system_interfaceÚappendÚlevelÚlocal_idÚ system_busZ send_messageÚconnection_poolÚclientsrB)ÚsiginforBÚclientr2r2r3r’s    ZemailZrecipients_filepathÚpkg_nameÚ pkg_versionÚ rpc_versionc@s8eZdZdd„Zdd„Zdd„Zd dd „Zd d d „ZdS)rcCs i|_dS)N)Ú client_pool)Úselfr2r2r3Ú__init__«szConnectionPool.__init__cCs(||jkrtd|ƒdSd|j|<dS)Nz.add_client: client (%s) already in client pool)rRr))rSÚhandlerr2r2r3Ú add_client®s  zConnectionPool.add_clientcCs&||jkrtd|ƒdS|j|=dS)Nz-remove_client: client (%s) not in client pool)rRr))rSrUr2r2r3Ú remove_client´s  zConnectionPool.remove_clientNccs4x.|jD]$}|dkr|Vq|j|kr|VqWdS)N)rRÚ channel_type)rSrXrNr2r2r3rLºs   zConnectionPool.clientscCs&x |jD]}|j|kr|jƒqWdS)N)rRrXZclose_connection)rSrXrNr2r2r3Ú close_allÁs  zConnectionPool.close_all)N)N)Ú__name__Ú __module__Ú __qualname__rTrVrWrLrYr2r2r2r3r©s  cs(eZdZ‡fdd„Z‡fdd„Z‡ZS)ÚAlertPluginReportReceivercstt|ƒj|ƒdS)N)Úsuperr]rT)rSÚdatabase)Ú __class__r2r3rTÍsz"AlertPluginReportReceiver.__init__c s^tt|ƒj|ƒ}tdk rŽg}xHtjD]>}d|j}|j||jƒ}|dkr$td|j ƒ|j |jƒq$Wt |ƒr„ddl m }|||ƒ|jjƒtdƒddlm}tjtj|jƒtdƒ|jƒx&|jjD]}|jd krÌ|jd } PqÌWtd d tƒ�rtjj|j ƒ| t!d �xB|j"D]8} | j#dd…dk�r2�q|j| j#ƒ}|dk�r|S�qWt$|ƒ|S)Nzemail:%sÚignorezEmail: siginfo.sig=%sr)Ú email_alertzsending alert to all clients)Ú html_to_textz1 For complete SELinux messages run: sealert -l %sÚAVCr>r+Zlog_full_report)Z OBJECT_PIDZSYSLOG_IDENTIFIERézemail:)%r^r]Úreport_problemÚemail_recipientsZrecipient_listZaddressÚevaluate_filter_for_userÚ filter_typer)ÚsigrGÚlenZsetroubleshoot.email_alertrbr_Z mark_modifiedZsetroubleshoot.html_utilrcr6r7ÚsummaryÚ_rIÚ audit_eventÚrecordsÚ record_typeÚfieldsr ÚboolÚsystemdZjournalÚsendZ format_textrOZusersÚusernamer) rSrMZto_addrsZ recipientruÚactionrbrcÚ audit_recordr>Úu)r`r2r3rfÐs<             z(AlertPluginReportReceiver.report_problem)rZr[r\rTrfÚ __classcell__r2r2)r`r3r]Ës r]c@s$eZdZdd„Zdd„Zdd„ZdS)rcCs*tj|dƒ|jƒ|_|jjd|jƒdS)NrCZchanged)rrTÚcopyÚsocket_addressÚconnection_stateZconnectÚon_connection_state_change)rSr{r2r2r3rTýs  z ClientConnectionHandler.__init__cCsTtd|jj||j|ƒ|j|ƒ|jfƒ|tj@r|D]6} | j |krPq@| j |ƒ|kr@|j | j | jƒ| jfƒq@W|S)Ni@Br)r'rÂrÃrÚsetroubleshootÚutilZ TimeStampÚfloatr›Úsignature_listÚlast_seen_daterhrGrIrlÚ report_count) rSÚsincer¼Ú alert_actionrur_Z since_alertsÚdatabase_alertsZalertsrBr2r2r3Ú_get_all_alerts_since s   z/SetroubleshootdDBusObject._get_all_alerts_sinceÚtza(ssi)cCs |j||ƒS)N)rÓ)rSrÐr¼r2r2r3Úget_all_alerts_sincesz.SetroubleshootdDBusObject.get_all_alerts_sincer�cCs |jd|ƒS)aº Return array of *local_id*'s, *summary*'s, and *report_count*'s of all current alerts in a setroubleshoot database returns list of: * `local_id(s)`: a report id in a setroubleshoot database * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert r)rÓ)rSr¼r2r2r3Úget_all_alertss z(SetroubleshootdDBusObject.get_all_alertscCs|jd|dd�S)a¾ Return array of *local_id*'s, *summary*'s, and *report_count*'s of all alerts which a user set to be ignored by a user returns list of: * `local_id(s)`: a report id in a setroubleshoot database * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert rra)rÑ)rÓ)rSr¼r2r2r3Úget_all_alerts_ignored(s z0SetroubleshootdDBusObject.get_all_alerts_ignoredcCsFy|j|ƒ}Wn&tk r4}z |‚WYdd}~XnX|jƒjƒ}|S)N)r›rrÄÚ__next__)rSrIr_rÒr·rBr2r2r3Ú _get_alert4s  z$SetroubleshootdDBusObject._get_alertzssiasa(ssssbbi)ttsc Csît|jj|ƒƒ}tƒ}|j||ƒ}|jƒ|jj}dd„|Dƒ}|jƒ\}} g} xZ| D]R\} } | j |j | j || ƒƒ|j | j || ƒƒ|j | j || ƒƒ| j| j| j| jfƒqVW|j|jƒ|j|| t|jjdƒƒdt|jjdƒƒd|jpêdfS)ar Return an alert with summary, audit events, fix suggestions ##### arguments * `local_id(s)`: an alert id ##### return values * `local_id(s)`: an alert id * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert * `audit_event(as)`: an array of audit events (AVC, SYSCALL) connected to the alert * `plugin_analysis(a(ssssbb)`: an array of plugin analysis structure * `if_text(s)`: * `then_text(s)` * `do_text(s)` * `analysis_id(s)`: plugin id. It can be used in `org.fedoraproject.SetroubleshootFixit.run_fix()` * `fixable(b)`: True when an alert is fixable by a plugin * `report_bug(b)`: True when an alert should be reported to bugzilla * `priority(i)`: An analysis priority. Typically the value is between 1 - 100. * `first_seen_date(t)`: when the alert was seen for the first time, number of microseconds since the Epoch * `last_seen_date(t)`: when the alert was seen for the last time, number of microseconds since the Epoch * `level(s)`: "green", "yellow" or "red" cSsg|] }|jƒ‘qSr2)Zto_text)Ú.0Zeventr2r2r3ú ^sz7SetroubleshootdDBusObject.get_alert..z%si@Br�)r'rÂrÃrrÙZ%update_derived_template_substitutionsrnroZ get_pluginsrGZ substituteZ get_if_textZ get_then_textZ get_do_textZ analysis_idZfixableZ report_bugZpriorityrIrlrÏÚintZfirst_seen_dateÚformatrÎrH) rSrIr¼rur_rBr¶Z audit_eventsZtotal_priorityZ alert_pluginsZpluginsZpluginÚargsr2r2r3Ú get_alert<s,  z#SetroubleshootdDBusObject.get_alertÚbc CsXyHt|jj|ƒƒ}tƒ}|j||ƒ}ddlm}|j|j|||dƒdSdSdS)zö Sets a filter on an alert. The alert can be "always" filtered, "never" filtered or "after_first" filtered. ##### arguments * `local_id(s)`: an alert id * `filter_type(s)`: "always", "never", "after_first" ##### return values * `success(b)`: r)Úmap_filter_name_to_valueNTF) r'rÂrÃrrÙÚsetroubleshoot.signatureráržrj)rSrIrir¼rur_rBrár2r2r3ržts  z$SetroubleshootdDBusObject.set_filterc Cs2y"tƒ}|j||ƒ}|j|jƒdSdSdS)zz Deletes an alert from the database. ##### arguments * `local_id(s)`: an alert id ##### return values * `success(b)`: TFN)rrÙr—rj)rSrIr¼r_rBr2r2r3Ú delete_alertŒs   z&SetroubleshootdDBusObject.delete_alert)r¾r¿c Cst|ƒ}|jdƒ|jd7_td||jfƒx^|jjt|ƒƒD]J\}}}}}t|||||ƒ}|jƒx"|jj|ƒD]}|j t |ƒƒqxWqDWx\|jj dƒD]L}y|j t |ƒƒWq t k rê} zt j t jd| ƒWYdd} ~ Xq Xq W|jd8_|j|jƒtdƒS)Nrr5z#dbus avc(%s) called: %d ConnectionszUnable to add audit event: %srd)r=r«r©r)r®ZfeedZ AuditRecordZaudispd_rectifyr¯r¸rdÚflushrµr6r7rªrm) rSrŸrpZevent_idZ body_textrqZ line_numberrwrnr·r2r2r3r¶¡s"  ( zSetroubleshootdDBusObject.avccCs,|jd8_td|jƒ|j|jƒdS)Nr5z*dbus iface finish() called: %d Connectionsr�)r©r)r«rª)rSr2r2r3Úfinish¸s z SetroubleshootdDBusObject.finishcCs|jdkrtj|ƒdS)Nr)r©r.r«)rSrªr2r2r3r«¿s zSetroubleshootdDBusObject.alarmN)r¥)rÉ)r¥)rZr[r\rTr¸rDr¦r.rFrºrBÚmethodr»rÈrÓrÕrÖr×rÙrßržrãr¶rår«r2r2r2r3r¤Æs"    8r¤cCs|jS)N)rÎ)Úar2r2r3rÆÄsrÆc@seZdZdd„Zdd„ZdS)ÚSetroubleshootdDBuscCsdy&tdtttfƒtt|||ƒ|_Wn8tk r^}ztjtjd|ƒ|‚WYdd}~XnXdS)Nz=creating system dbus: bus_name=%s object_path=%s interface=%sz$cannot start system DBus service: %s) r)Údbus_system_bus_namerErFr¤Údbus_objÚ Exceptionr6r7)rSr°r±rªr·r2r2r3rTÊs zSetroubleshootdDBus.__init__cCs|jjdƒdS)Nzdaemon requestT)rêrº)rSr2r2r3Ú do_restartÒs zSetroubleshootdDBus.do_restartN)rZr[r\rTrìr2r2r2r3rèÈsrècCs|jƒtjƒdS)N)ÚsaveÚ audit2whyrå)r_r2r2r3ÚgoodbyeÛsrïcCstdƒtjƒdS)Nz SIGALRM raised in RunFaultServer)r)Ú main_loopÚquit)r0r1r2r2r3Ú alarm_handlerãsròr¥cCsˆtj|ƒtjtjtƒxŒytjƒtjdƒPWqtk rf}zdt|ƒkrRw|‚WYdd}~Xqtk r }z dtt |ddƒƒkrŒw|‚WYdd}~XqXqWtjtjt ƒtjtj t ƒ�yt jtƒttƒ}tddƒ}t|ƒ}t|ddƒt||td ƒd �atj|ƒtjttƒd }x˜tjjD]Œ}tjt|jj ƒt|jj!ƒt|jj"ƒ|jj#ƒ\}}|tj$k�sx|tj%k�r,|tj$k�rŠd } nd } t j t j&d|j'| fƒd}tj(|jƒ�q,W|�rÎtj)dd�tddt*ƒ�sæt+tƒ} nt,tƒ} ddl-} | j.j/j0dƒa1t2t1|ƒ} | j3dƒ| j4ƒddl5m6} | ƒa7tt8ddƒyt7j9t8ƒWn@t:k �rŒ}z"|j;tƒn|‚WYdd}~XnXt?dƒ}x |D]}t@|tAƒ}|jBƒ�qœWtCjDjEƒtFt1| |ƒ}tGjHƒWnªtIk �r}zt=dƒWYdd}~Xn€tJk �r.}zt=dƒWYdd}~XnVtKk �r‚}z8ddlL}tM|jNƒƒt j t j&d|jOjPt|ƒfƒWYdd}~XnXdS)Nrz%unable to open /sys/fs/selinux/policyÚ __context__r�r_Úfilenamei€rÊzAudit Listener)Z friendly_nameFZallowedz dontaudit'dz-Deleting alert %s, it is %s in current policyT)ZpruneZtestÚanalyze)ÚSEEmailRecipientSetZlisten_for_clientz#KeyboardInterrupt in RunFaultServerz$raising SystemExit in RunFaultServerzexception %s: %s)Qr.r«ÚSIGALRMr:rîZinitrµr=Ú SystemErrorÚgetattrròr/r4r6ZopenlogrOr¢rKr r%r&rrmr@Z set_notifyÚatexitÚregisterrïrœrÍrõrjZscontextZtcontextZtclassr‰ZALLOWZ DONTAUDITr7rIr—rírrr]rZsix.moves.queueZmovesr¬ZQueuer°rZ setDaemonr»rârörgr•Zparse_recipient_filerÚerrnorr)Ústrerrorrr rˆr‡rDZglibZ init_threadsrèrðZrunÚKeyboardInterruptÚ SystemExitrëÚ tracebackr*Ú format_excr`rZ)rªr·Zclient_notifierZdatabase_filenameZdatabase_filepathZdeletedÚiZwhyZboolsr¹r±ZsixZanalyze_threadröZlisten_addressesZlisten_addressZlistening_serverZsetroubleshootd_dbusrr2r2r3rèsŽ         0               Ú__main__)r )r¥)iZ __future__rÚ__all__Z gi.repositoryrr rDZ dbus.serviceZ dbus.glibÚgettextr8r.rúÚsysr6Zsystemd.journalrsr,r r r rÚkwargsÚ version_infoZinstallZ translationZugettextrmÚAttributeErrorZsetroubleshoot.access_controlrZsetroubleshoot.analyzerrrrZsetroubleshoot.avc_auditrZsetroubleshoot.errcoderrrrrrrZsetroubleshoot.rpcrrrr Zsetroubleshoot.rpc_interfacesr!r"r#Zsetroubleshoot.utilr$r%r&r'r(r)r*r4r:r?rrérErFr¨rJZ request_namerr@r°rgr•rOrPrQZ instance_idÚobjectrrKr]rrˆr¢Zsetroubleshoot.audit_datarÊr¦r§r¤rÆrèr²Zselinux.audit2whyrîrïZMainLooprðròrrZr2r2r2r3Ús¬         $ $          0     __pycache__/serverconnection.cpython-36.opt-1.pyc000064400000012361152572267760015755 0ustar003 Úh>`�ã@sìddlmZddlZddlZejd kr.ddlZddlmZddl Z ddl Z ddl Z ddl ZddlZddlZddlZddlZddlZddlmZmZddlmZmZddlmZddlmZdd lmZm Z d gZ!Gd d „d eeeejƒZ"dS) é)Úabsolute_importNé)ÚGObject)Úparse_config_settingÚ get_config)Ú RpcChannelÚConnectionState)ÚSETroubleshootServerInterface)ÚSETroubleshootDatabaseInterface)ÚRetryÚget_error_from_socket_exceptionÚServerConnectionHandlerc @sØeZdZejjdejffejjdejejejejffejjdejejffejjdejejffejjdejejejffdœZ dd„Z dd„Z ddd„Z d d „Z d d „Zd d„Zdd„Zdd„Zdd„Zdd„Zdd„ZdS)r N)ÚalertÚconnection_state_changedÚsignatures_updatedÚ database_bindz async-errorcCsŠtj|dd�tjj|ƒ|jjd|jƒ|jd|ƒ|jd|ƒtddƒ|_tddƒ|_ ||_ d |_ t |j |jd d �|_d |_d |_dS)NZsealert)Ú channel_typeZchangedZSEAlertZSETroubleshootDatabaseNotifyZgeneralÚ pkg_versionÚ rpc_versionFgð?)Znotify_intervalTZaudit_listener)rÚ__init__rÚconnection_stateÚconnectÚon_connection_state_changeZconnect_rpc_interfacerrrÚusernameÚretry_connection_if_closedr Úretry_connectionÚget_connection_retry_intervalÚconnection_retryÚreport_connect_failureÚ database_name)Úselfr©r!ú&/usr/lib/python3.6/serverconnection.pyr0s     z ServerConnectionHandler.__init__cCsZ|jd||||ƒ|tj@s,|tjtjB@rV|jrV|tj@ rV|jjtjƒ|j j ƒdS)Nr) ÚemitrÚOPENÚHUPÚERRORrÚRETRYrÚupdaterÚstart)r rÚflagsZ flags_addedZ flags_removedr!r!r"r@s z2ServerConnectionHandler.on_connection_state_changecCsD|dk r||_|jjtj@r dSyž|jjtjtjtjBƒtj |jj |jj ƒ|j_ t j |jj j ƒt jt jƒ|jj j|jjƒƒ|j|jƒ|jjtjtjtjBƒ|jjƒd|_|jƒWn€tjk �r>}z`t|ƒ\}}|jdk�rtjtjd|ƒd|_|tjk�rtj}ntj}|j |tj||ƒdSd}~XnXdS)NTz,attempt to open server connection failed: %sF)!Úsocket_addressrr*rr$r(Z CONNECTINGr&ÚSocketÚsocketZfamilyÚtypeÚfcntlÚfilenoZF_SETFDZ FD_CLOEXECrZget_py_addressZ io_watch_addZhandle_client_ior'rÚstoprÚdo_logonÚerrorr ÚsyslogÚLOG_ERRÚErrnoZEPIPEr%Zclose_connection)r r+ÚeÚerrnoÚstrerrorÚ add_flagsr!r!r"ÚopenPs2      zServerConnectionHandler.opencCs|j|jƒrdSdSdS)NTF)r;r+)r ÚretryÚ user_datar!r!r"ros z(ServerConnectionHandler.retry_connectioncCs|jdkrdSdSdS)Néé é<)Zfailed_attempts)r r<r=r!r!r"rus z5ServerConnectionHandler.get_connection_retry_intervalcCs,tjtjd|||fƒ|jd|||ƒdS)Nz#async_error: method=%s errno=%s: %sz async-error)r4r5r#)r Úmethodr8r9r!r!r"Úasync_error_callback{sz,ServerConnectionHandler.async_error_callbackcs2‡fdd„}ˆjˆjƒ}|j|ƒ|jˆjƒdS)Ncsˆjdˆ|ƒdS)Nr)r#)Z properties)r r!r"Údatabase_bind_callback€sz.database_bind_callback)rrÚ add_callbackÚ add_errbackrB)r rCÚ async_rpcr!)r r"Úbinds   zServerConnectionHandler.bindcs@‡fdd„}ˆjˆ_ˆjˆjˆjdƒ}|j|ƒ|jˆjƒdS)NcsˆjjtjƒdS)N)rr(rZ AUTHENTICATED)rr)r r!r"Úlogon_callback‰sz8ServerConnectionHandler.do_logon..logon_callbackZpasswd)rZ channel_nameZlogonrrDrErB)r rHrFr!)r r"r2‡s   z ServerConnectionHandler.do_logoncCs"tj|||||ƒ}|j|jƒdS)N)r Ú set_filterrErB)r ZsigÚuserZ filter_typeÚdatarFr!r!r"rI‘sz"ServerConnectionHandler.set_filtercCs|jd|ƒdS)Nr)r#)r Zsiginfor!r!r"r—szServerConnectionHandler.alertcCs|jd||ƒdS)Nr)r#)r r.Úitemr!r!r"ršsz*ServerConnectionHandler.signatures_updated)N)Ú__name__Ú __module__Ú __qualname__rZ SignalFlagsZRUN_LASTZ TYPE_PYOBJECTZTYPE_INTZ TYPE_STRINGZ __gsignals__rrr;rrrBrGr2rIrrr!r!r!r"r s   )r)#Z __future__rr4ÚsysÚ version_infoZ$setroubleshoot.default_encoding_utf8ZsetroubleshootZ gi.repositoryrr8r6ÚgettextÚosZsix.moves.queueZsixÚreÚsignalZselinuxr-r,r/Zsetroubleshoot.configrrZsetroubleshoot.rpcrrZsetroubleshoot.rpc_interfacesr r Zsetroubleshoot.utilr r Ú__all__r r!r!r!r"Ús0      __pycache__/serverconnection.cpython-36.pyc000064400000012361152572267760015016 0ustar003 Úh>`�ã@sìddlmZddlZddlZejd kr.ddlZddlmZddl Z ddl Z ddl Z ddl ZddlZddlZddlZddlZddlZddlmZmZddlmZmZddlmZddlmZdd lmZm Z d gZ!Gd d „d eeeejƒZ"dS) é)Úabsolute_importNé)ÚGObject)Úparse_config_settingÚ get_config)Ú RpcChannelÚConnectionState)ÚSETroubleshootServerInterface)ÚSETroubleshootDatabaseInterface)ÚRetryÚget_error_from_socket_exceptionÚServerConnectionHandlerc @sØeZdZejjdejffejjdejejejejffejjdejejffejjdejejffejjdejejejffdœZ dd„Z dd„Z ddd„Z d d „Z d d „Zd d„Zdd„Zdd„Zdd„Zdd„Zdd„ZdS)r N)ÚalertÚconnection_state_changedÚsignatures_updatedÚ database_bindz async-errorcCsŠtj|dd�tjj|ƒ|jjd|jƒ|jd|ƒ|jd|ƒtddƒ|_tddƒ|_ ||_ d |_ t |j |jd d �|_d |_d |_dS)NZsealert)Ú channel_typeZchangedZSEAlertZSETroubleshootDatabaseNotifyZgeneralÚ pkg_versionÚ rpc_versionFgð?)Znotify_intervalTZaudit_listener)rÚ__init__rÚconnection_stateÚconnectÚon_connection_state_changeZconnect_rpc_interfacerrrÚusernameÚretry_connection_if_closedr Úretry_connectionÚget_connection_retry_intervalÚconnection_retryÚreport_connect_failureÚ database_name)Úselfr©r!ú&/usr/lib/python3.6/serverconnection.pyr0s     z ServerConnectionHandler.__init__cCsZ|jd||||ƒ|tj@s,|tjtjB@rV|jrV|tj@ rV|jjtjƒ|j j ƒdS)Nr) ÚemitrÚOPENÚHUPÚERRORrÚRETRYrÚupdaterÚstart)r rÚflagsZ flags_addedZ flags_removedr!r!r"r@s z2ServerConnectionHandler.on_connection_state_changecCsD|dk r||_|jjtj@r dSyž|jjtjtjtjBƒtj |jj |jj ƒ|j_ t j |jj j ƒt jt jƒ|jj j|jjƒƒ|j|jƒ|jjtjtjtjBƒ|jjƒd|_|jƒWn€tjk �r>}z`t|ƒ\}}|jdk�rtjtjd|ƒd|_|tjk�rtj}ntj}|j |tj||ƒdSd}~XnXdS)NTz,attempt to open server connection failed: %sF)!Úsocket_addressrr*rr$r(Z CONNECTINGr&ÚSocketÚsocketZfamilyÚtypeÚfcntlÚfilenoZF_SETFDZ FD_CLOEXECrZget_py_addressZ io_watch_addZhandle_client_ior'rÚstoprÚdo_logonÚerrorr ÚsyslogÚLOG_ERRÚErrnoZEPIPEr%Zclose_connection)r r+ÚeÚerrnoÚstrerrorÚ add_flagsr!r!r"ÚopenPs2      zServerConnectionHandler.opencCs|j|jƒrdSdSdS)NTF)r;r+)r ÚretryÚ user_datar!r!r"ros z(ServerConnectionHandler.retry_connectioncCs|jdkrdSdSdS)Néé é<)Zfailed_attempts)r r<r=r!r!r"rus z5ServerConnectionHandler.get_connection_retry_intervalcCs,tjtjd|||fƒ|jd|||ƒdS)Nz#async_error: method=%s errno=%s: %sz async-error)r4r5r#)r Úmethodr8r9r!r!r"Úasync_error_callback{sz,ServerConnectionHandler.async_error_callbackcs2‡fdd„}ˆjˆjƒ}|j|ƒ|jˆjƒdS)Ncsˆjdˆ|ƒdS)Nr)r#)Z properties)r r!r"Údatabase_bind_callback€sz.database_bind_callback)rrÚ add_callbackÚ add_errbackrB)r rCÚ async_rpcr!)r r"Úbinds   zServerConnectionHandler.bindcs@‡fdd„}ˆjˆ_ˆjˆjˆjdƒ}|j|ƒ|jˆjƒdS)NcsˆjjtjƒdS)N)rr(rZ AUTHENTICATED)rr)r r!r"Úlogon_callback‰sz8ServerConnectionHandler.do_logon..logon_callbackZpasswd)rZ channel_nameZlogonrrDrErB)r rHrFr!)r r"r2‡s   z ServerConnectionHandler.do_logoncCs"tj|||||ƒ}|j|jƒdS)N)r Ú set_filterrErB)r ZsigÚuserZ filter_typeÚdatarFr!r!r"rI‘sz"ServerConnectionHandler.set_filtercCs|jd|ƒdS)Nr)r#)r Zsiginfor!r!r"r—szServerConnectionHandler.alertcCs|jd||ƒdS)Nr)r#)r r.Úitemr!r!r"ršsz*ServerConnectionHandler.signatures_updated)N)Ú__name__Ú __module__Ú __qualname__rZ SignalFlagsZRUN_LASTZ TYPE_PYOBJECTZTYPE_INTZ TYPE_STRINGZ __gsignals__rrr;rrrBrGr2rIrrr!r!r!r"r s   )r)#Z __future__rr4ÚsysÚ version_infoZ$setroubleshoot.default_encoding_utf8ZsetroubleshootZ gi.repositoryrr8r6ÚgettextÚosZsix.moves.queueZsixÚreÚsignalZselinuxr-r,r/Zsetroubleshoot.configrrZsetroubleshoot.rpcrrZsetroubleshoot.rpc_interfacesr r Zsetroubleshoot.utilr r Ú__all__r r!r!r!r"Ús0      __pycache__/signature.cpython-36.opt-1.pyc000064400000070126152572267760014373 0ustar003 Úh>`â„ã@sÜddlmZddlmZddlZddlZddlTddlmZddlm Z ddl Z ddl m Z m Z e je dd ƒe dd ƒd d �Zy ejaWnek r ej aYnXd ddddddddddddddddgZedkrêe je dd ƒe dd ƒd�dd l madd!l m Z ddlTddlTddlTddlTddljZddlTddlZddlTdd"l m!Z!ddl"Z"ddl#Z#d#d$„Z$dZ%d%Z&d&Z'e%td'ƒe&td(ƒe'td)ƒiZ(e%d*e&d+e'd,iZ)e%e&e'd-œZ*Gd.d „d e+ƒZ,Gd/d„de-ƒZ.Gd0d„de-ƒZ/Gd1d„de-ƒZ0iZ1td2ƒe1d3<td4ƒe1d5<td6ƒe1d7<td8ƒe1d9<td:ƒe1d;<td<ƒe1d<<td=ƒe1d=<td>ƒe1d><td?ƒe1d?<td@ƒe1d@<tdAƒe1dA<tdBƒe1dB<tdCƒe1dC<dDdE„Z2GdFdG„dGe-ƒZ3GdHd„de-ƒZ4GdId„de-ƒZ5GdJd„de-ƒZ6GdKd„de-ƒZ7GdLd„de-ƒZ8GdMd„de-ƒZ9GdNd„de-ƒZ:GdOd„de-ƒZ;GdPd„de-ƒZdQƒdRZ?e9ƒZ@e@jAe?dSƒe@jBdZCeCjDjEdZFeGeFjHƒeGdTeCjDƒeGe@ƒe=jIƒe=j>dQƒdk�r¾eGdUƒneGdVe=j>dQƒƒe=jJƒdS)Wé)Úabsolute_import)Úprint_functionN)Ú*)Úrange)Ú cmp_to_key)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_dirT)ÚdomainÚ localedirZfallbackÚSignatureMatchÚSEFilterÚSEFaultSignatureÚSEFaultSignatureInfoÚSEFaultSignatureSetÚSEFaultSignatureUserÚ SEEnvironmentÚSEDatabasePropertiesÚSEFaultUserInfoÚSEFaultUserSetÚSEPluginÚSEEmailRecipientÚSEEmailRecipientSetÚ FILTER_NEVERÚ FILTER_ALWAYSÚFILTER_AFTER_FIRSTÚ filter_textÚ__main__)r r )Úngettext)r)ÚTemplatecCs||k||kS)N©)ÚxÚyrrú/usr/lib/python3.6/signature.pyÚQsr#ééz Never Ignorez Ignore AlwayszIgnore After First AlertÚneverÚalwaysÚ after_first)r&r'r(c@seZdZdd„ZdS)r cCs||_||_dS)N)ÚsiginfoÚscore)Úselfr)r*rrr"Ú__init__oszSignatureMatch.__init__N)Ú__name__Ú __module__Ú __qualname__r,rrrr"r msc sŒeZdZddd„dœddiddiddiddiddiddidedœdedœddiddiddidœ Z‡fd d „Zd d „Zd d„Zdd„Z‡Z S)rÚ attributecCsdS)Nz1.0rrrrr"r#vszSEEnvironment.)ÚXMLFormÚdefaultr1Úelement)r1Úimport_typecast) ÚversionÚplatformÚkernelÚ policy_typeÚ policy_rpmÚlocal_policy_rpmÚenforceÚselinux_enabledÚselinux_mls_enabledÚ policyversÚhostnameÚunamecstt|ƒjƒ|jƒdS)N)Úsuperrr,Úupdate)r+)Ú __class__rr"r,„szSEEnvironment.__init__cCsªddl}ddl}tƒ\|_|_|jƒd|_td|jƒ|_|j|_t |j ƒƒ|_ |j ƒ}|dkrjd|_ nd|_ t|jƒƒ|_t|jƒƒ|_|jƒ|_dj|jƒƒ|_dS)Nréz/etc/selinux/%sÚ PermissiveZ Enforcingú )r6ÚselinuxZget_os_environmentr7Zselinux_getpolicytyper8Zget_package_nvr_by_file_pathr9r:ÚstrZsecurity_policyversr>Zsecurity_getenforcer;ÚboolZis_selinux_enabledr<Zis_selinux_mls_enabledr=Únoder?Újoinr@)r+r6rGr;rrr"rBˆs zSEEnvironment.updatecCs |j|ƒ S)N)Ú__eq__)r+Úotherrrr"Ú__ne__žszSEEnvironment.__ne__cCs4x.t|jjƒƒD]}t||ƒt||ƒkrdSqWdS)NFT)ÚlistÚ _xml_infoÚkeysÚgetattr)r+rMÚnamerrr"rL¡szSEEnvironment.__eq__) r-r.r/ÚbooleanrPr,rBrNrLÚ __classcell__rr)rCr"rts    csBeZdZdedd„dœdedd„dœdœZef‡fdd„ Z‡ZS) r r3cCstS)N)rrrrr"r#ªszSEFilter.)r1r4r2cCsdS)Nrrrrrr"r#«s)Ú filter_typeÚcountcstt|ƒjƒ||_dS)N)rAr r,rV)r+rV)rCrr"r,®szSEFilter.__init__)r-r.r/ÚintrPrr,rUrr)rCr"r ¨scsdeZdZddidedd„dœdedd„dœdedd„dœd œZ‡fd d „Zd d „Zddd„Z‡Z S)rr1r0cCsdS)NFrrrrr"r#¶szSEFaultSignatureUser.)r1r4r2cCsdS)NFrrrrr"r#·sr3cCstƒS)N)r rrrr"r#¸s)ÚusernameZ seen_flagZ delete_flagÚfiltercstt|ƒjƒ||_dS)N)rArr,rY)r+rY)rCrr"r,»szSEFaultSignatureUser.__init__cCs:||jkrttd|ƒ‚|dkr*ttdƒ‚t|||ƒdS)Nz!item (%s) is not a defined memberrYz changing the username is illegal)Z_namesÚ ProgramErrorZERR_NOT_MEMBERZERR_ILLEGAL_USER_CHANGEÚsetattr)r+ÚitemÚdatarrr"Ú update_item¿s   z SEFaultSignatureUser.update_itemNcCsXtdtj|dƒ|fƒ|tks0|tks0|tkrHtdƒt|d�|_dStd|ƒ‚dS)Nz%update_filter: filter_type=%s data=%sÚunknownzupdate_filter: !!!)rVTzBad filter_type (%s)) Ú log_debugÚmap_filter_value_to_nameÚgetrrrr rZÚ ValueError)r+rVr^rrr"Ú update_filterÈs z"SEFaultSignatureUser.update_filter)N) r-r.r/rTr rPr,r_rerUrr)rCr"r³s  Ú directoryÚdirZ semaphoreZsemz shared memoryZshmz message queueZmsgqÚmessageÚmsgÚfileZsocketÚprocessÚprocess2Z filesystemrJÚ capabilityÚ capability2cCs|ttjƒƒkrt|S|S)N)rOÚ class_dictrQ)Útclassrrr"Útranslate_classäsrqcs eZdZdZ‡fdd„Z‡ZS)ÚAttributeValueDictionaryZ unstructuredcstt|ƒjƒdS)N)rArrr,)r+)rCrr"r,ïsz!AttributeValueDictionary.__init__)r-r.r/rPr,rUrr)rCr"rrìsrrc sZeZdZddd„dœddidddœded œded œddided œd œZ‡fd d „Z‡ZS) r r0cCsdS)Nz4.0rrrrr"r#õszSEFaultSignature.)r1r2r1r3Z operation)r1rO)r1r4)r5ÚhostÚaccessÚscontextÚtcontextrpÚportc s8tt|ƒjƒx$t|jƒƒD]\}}t|||ƒqWdS)N)rAr r,rOÚitemsr\)r+ÚkwdsÚkÚv)rCrr"r,þszSEFaultSignature.__init__)r-r.r/Ú AvcContextrXrPr,rUrr)rCr"r ós cs8eZdZddidddœdœZ‡fdd„Zdd „Z‡ZS) rr1r3Úarg)r1rO)Ú analysis_idÚargscstt|ƒjƒ||_||_dS)N)rArr,r~r)r+r~r)rCrr"r, szSEPlugin.__init__cCst|j|jfƒS)N)rHr~r)r+rrr"Ú__str__szSEPlugin.__str__)r-r.r/rPr,r€rUrr)rCr"rs cs eZdZddedœdedœddiddiddidddœdddœdedœdedœddidedœdedœddiddiddidedœde dœde dœdedd „d œddidd e dœddiddiddid œZ d dddddddddg Z ‡fdd„Z dd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„ZdEd&d'„ZdFd(d)„Zd*d+„Zd,d-„Zd.d/„Zd0d1„Zd2d3„Zd4d5„Zd6d7„ZdGd9d:„Zd;d<„Zd=d>„ZdHd?d@„Z dAdB„Z!dIdCdD„Z"‡Z#S)Jrr3Zplugin)r1rOr4)r1r4r1Zrpm)r1rOcCsdS)Nrrrrrr"r#)szSEFaultSignatureInfo.)r1r4r2Úuser)Ú plugin_listÚ audit_eventÚsourceÚspathÚtpathÚ src_rpm_listÚ tgt_rpm_listrurvrprwÚsigZif_textZ then_textZdo_textÚ environmentÚfirst_seen_dateÚlast_seen_dateÚ report_countÚlocal_idÚusersÚlevelZfixableZ button_textrƒr†r‡rˆrurvrprwrŠrŒc s|tt|ƒjƒx$t|jƒƒD]\}}t|||ƒqWd|_g|_d}tj ƒdkrTd}yt |j |d�|j _ Wn YnXdS)NrDTrF)Úuse_dbus)rArr,rOrxr\r�r‚ÚosÚgetuidZget_rpm_nvr_by_scontextrurŠr:)r+ryrzr{r‘)rCrr"r,7s zSEFaultSignatureInfo.__init__cCsZ|j|jkr"|j|_|jd7_x |jD]}t||t||ƒƒq*W|jdkrV|j|_dS)NrD)rŒr�Ú merge_includer\rRr�)r+r)rSrrr"Ú update_mergeHs   z!SEFaultSignatureInfo.update_mergecCs|jjS)N)rŠr9)r+rrr"Úget_policy_rpmTsz#SEFaultSignatureInfo.get_policy_rpmcCs(d|j|jj|jj|jdj|jjƒfS)Nz%s,%s,%s,%s,%sú,)r„ruÚtypervrprKr‰rt)r+rrr"Ú get_hash_strWsz!SEFaultSignatureInfo.get_hash_strcCstj|jƒjdƒƒ}|jƒS)Nzutf-8)ÚhashlibZsha256r™ÚencodeZ hexdigest)r+Úhashrrr"Úget_hashZszSEFaultSignatureInfo.get_hashcCsBx|jD]}|j|kr|SqWtd|ƒt|ƒ}|jj|ƒ|S)Nznew SEFaultSignatureUser for %s)r�rYrarÚappend)r+rYr�rrr"Ú get_user_data^s    z"SEFaultSignatureInfo.get_user_datacCs,td|ƒd}|j|ƒ}|dk r(|j}|S)Nzfind_filter_by_username %s)rarŸrZ)r+rYrZÚ user_datarrr"Úfind_filter_by_usernamegs   z,SEFaultSignatureInfo.find_filter_by_usernameNcCs|j|ƒ}|j||ƒdS)N)rŸre)r+rYrVr^r rrr"Úupdate_user_filterps z'SEFaultSignatureInfo.update_user_filtercCsTd}|j|ƒ}td||fƒ|dk rP|dk r4||_|j|ƒ}td|||fƒ|S)NÚdisplayz5evaluate_filter_for_user: found %s user's filter = %sz4evaluate_filter_for_user: found filter for %s: %s %s)r¡rarVÚevaluate_filter)r+rYrVÚactionÚfrrr"Úevaluate_filter_for_userts  z-SEFaultSignatureInfo.evaluate_filter_for_usercCsb|j}d}|tkrd}n8|tkr6|jdkr0d}qPd}n|tkrDd}n td|ƒ‚|jd7_|S)Nr£rÚignorezunknown filter_type (%s)rD)rVrrrWrrd)r+rZrVr¥rrr"r¤s  z$SEFaultSignatureInfo.evaluate_filtercCs2t|tƒr&t|ƒdkr dj|ƒSdSntdƒSdS)NrrFÚ)Ú isinstancerOÚlenrKÚ default_text)r+Zrpm_listrrr"Úformat_rpm_list’s    z$SEFaultSignatureInfo.format_rpm_listcCsd|j|jfS)Nz %s [ %s ])r†rp)r+rrr"Úformat_target_object›sz)SEFaultSignatureInfo.format_target_objectcCsTd}|jjdƒ}|dkr<|jdƒdkrzSEFaultSignatureInfo.summaryFc stƒˆ_g}d}|r>x„ˆjD]}||j7}|j|d fƒqWn\xZˆjD]P}xJˆjD]@}|j|jkrR||j7}|jt|jƒƒ|j|t|jƒfƒPqRWqFW|j t ˆj ƒd�ddddg}d j ‡fd d „|Dƒƒ}x.|D]&}||krÖx|D]\}} d |_ qèWPqÖW||fS)NrÚ allow_ypbindÚ1)rºZmozilla_read_contentZ"mozilla_plugin_can_network_connectZmozilla_plugin_use_bluejeansZ$unconfined_mozilla_plugin_transitionrFcs g|]\}}|jˆjj|ƒ‘qSr)Ú get_do_textrƒÚrecords)Ú.0ÚpÚa)r+rr"ú úsz4SEFaultSignatureInfo.get_plugins..F)rÄrÅ)Z load_pluginsÚpluginsr¾ržr‚r~Z init_argsÚtuplerÚsortrr¿rKZ report_bug) r+ÚallrÌÚtotal_priorityrÉZsolutionZnoreport_booleansZdo_textsÚbrÊr)r+r"Ú get_pluginsãs0         z SEFaultSignatureInfo.get_pluginscCst|ƒj|jƒS)N)rZsafe_substituter´)r+Útxtrrr"Ú substituteszSEFaultSignatureInfo.substitutecs‡fdd„|DƒS)Ncsg|]}ˆj|ƒ‘qSr)rÔ)rÈrÓ)r+rr"rË sz9SEFaultSignatureInfo.substitute_array..r)r+rr)r+r"Úsubstitute_arraysz%SEFaultSignatureInfo.substitute_arrayc s–|j}tdƒ}|ttdƒ|jjƒƒ7}|ttdƒ|jjƒƒ7}|ttdƒ|jƒƒ7}|ttdƒt|jƒƒ7}|ttdƒt|j ƒƒ7}|ttdƒt|j ƒƒ7}|r´|ttdƒd ƒ7}n|ttdƒt|j j ƒƒ7}|ttd ƒt|j |jƒƒƒ7}|ttd ƒt|j |jƒƒƒ7}|ttd ƒt|jƒƒ7}|ttd ƒt|jƒƒ7}|ttdƒt|jƒƒ7}|ttdƒt|jƒƒ7}|ttdƒt|jƒƒ7}|�rœ|ttdƒd ƒ7}n|ttdƒt|jƒƒ7}|�rê|jjƒ}d |d<|ttdƒtdj|ƒƒƒ7}n|ttdƒt|jƒƒ7}|ttdƒt|jƒƒ7}d}|ttdƒ|jj|ƒƒ7}|ttdƒ|jj|ƒƒ7}|ttdƒt|jƒƒ7}|dtdƒ7}d}xj|jjD]^‰ˆjdk�r®|dˆj ƒd7}n6|dˆjˆj!f7}|dj‡fdd „ˆj"Dƒƒd7}�qˆW|d!|j#ƒ7}y~d"}t$j%j&|ƒ�rvd#}t'|gt(t(d$�} || j)|ƒd%7}t$j%j*d&ƒ�rn|d'7}t'|d(gt(t(d$�} || j)|ƒd%7}||7}Wn YnX||d7}|S))NzAdditional Information: zSource ContextzTarget ContextzTarget ObjectsZSourcez Source PathZPortZHostz (removed)zSource RPM PackageszTarget RPM PackageszSELinux Policy RPMzLocal Policy RPMzSelinux Enabledz Policy TypezEnforcing Modez Host NamerDZPlatformrFz Alert Countz%Y-%m-%d %H:%M:%S %Zz First Seenz Last SeenzLocal IDÚ zRaw Audit Messagesr©ZAVCz type=%s msg=%s: csg|]}d|ˆj|f‘qS)z%s=%s)Zfields)rÈrz)Ú audit_recordrr"rË8sz7SEFaultSignatureInfo.format_details..z Hash: z/usr/bin/audit2allowz audit2allow)ÚstdinÚstdoutrz /var/lib/sepolgen/interface_infoz audit2allow -Rz-R)+rŠr±Zformat_2_column_name_valueruÚformatrvr®r¬r„r…rwr‰rsr­r‡rˆr9r:r<r8r;r?r@ÚsplitrKr�r‹rŒrŽrƒrÇÚ record_typeZto_textZevent_idZ fields_ordr™r’rµZexistÚPopenÚPIPEZ communicateÚexists) r+ÚreplaceÚenvÚtextr@Z date_formatZavcbufZ audit2allowZnewbufrÉr)r×r"Úformat_details sl  (  z#SEFaultSignatureInfo.format_detailsc Os2t}t}zdd„add„a|||ŽS|a|aXdS)zdefine.*untranslated\(.*\ncSs|dkr |S|S)NrDr)r r!Úzrrr"r#Xsz3SEFaultSignatureInfo.untranslated..cSs|S)Nr)r rrr"r#YsN)rÂr±)r+ÚfuncrÚkwargsZsaved_translateP_Zsaved_translate_rrr"Ú untranslatedNs z!SEFaultSignatureInfo.untranslatedc Cs>|jƒ|jƒ}|j|ƒ\}}�x |D�]\}}tdƒ|jt|jƒt|ƒddf}||7}x"tt|ƒdƒD]} |tdƒ7}qpW|tdƒ7}|j |j |j j |ƒƒ} |tdƒ| 7}|j |j |j j |ƒƒ} |tdƒ| djƒ| d d…7}|j |j|j j |ƒƒ} |td ƒ| djƒ| d d…7}q&W|td ƒ7}|S) Nz0 ***** Plugin %s (%.4s confidence) suggests édgà?éPrrÖz Then rrDz Do z )r¼rÃrÒr±r~Úfloatr¾rr«rÔZ get_if_textrƒrÇZ get_then_textÚlowerrÆ) r+rÏràrârÐrÌrÉrÚtitleÚirÓrrr"Ú format_text_s"( $( z SEFaultSignatureInfo.format_text)N)N)F)F)FF)$r-r.r/rZ AuditEventr|rXr rZ TimeStamprrPr”r,r•r–r™r�rŸr¡r¢r§r¤r­r®r²r¼r¿rÃrÒrÔrÕrãrçrîrUrr)rCr"rsd          / " CcsReZdZddd„dœddidedd„dœdd d œd œZ‡fd d „Zdd„Z‡ZS)rr0cCsdS)Nz1.0rrrrr"r#zszSEFaultUserInfo.)r1r2r1r3cCsdS)NFrrrrr"r#|s)r1r4r2Ú email_address)r1rO)r5rYZ email_alertÚemail_address_listcstt|ƒjƒ||_dS)N)rArr,rY)r+rY)rCrr"r,€szSEFaultUserInfo.__init__cCs||jkr|jj|ƒdS)N)rðrž)r+rïrrr"Úadd_email_address„s z!SEFaultUserInfo.add_email_address)r-r.r/rTrPr,rñrUrr)rCr"rxs   csHeZdZddd„dœddedœdœZ‡fd d „Zd d „Zd d„Z‡ZS)rr0cCsdS)Nz1.0rrrrr"r#‹szSEFaultUserSet.)r1r2r3r�)r1rOr4)r5Ú user_listcstt|ƒjƒdS)N)rArr,)r+)rCrr"r,�szSEFaultUserSet.__init__cCs"x|jD]}||jkr|SqWdS)N)ròrY)r+rYr�rrr"Úget_user’s  zSEFaultUserSet.get_usercCs*|j|ƒdk rdSt|ƒ}|jj|ƒ|S)N)rórròrž)r+rYr�rrr"Úadd_user˜s  zSEFaultUserSet.add_user) r-r.r/rrPr,rórôrUrr)rCr"r‰s   cs†eZdZddd„dœdedd„dœdded œd œZ‡fd d „Zd d„Zdd„Zdd„Z dd„Z dd„Z dd„Z de jfdd„Z‡ZS)rr0cCs dttfS)Nz%d.%d)ZDATABASE_MAJOR_VERSIONZDATABASE_MINOR_VERSIONrrrr"r#¢szSEFaultSignatureSet.)r1r2r3cCstƒS)N)rrrrr"r#£s)r1r4r2r))r1rOr4)r5r�Úsignature_listcstt|ƒjƒdS)N)rArr,)r+)rCrr"r,§szSEFaultSignatureSet.__init__ccsx|jD] }|VqWdS)N)rõ)r+r)rrr"Úsiginfosªs zSEFaultSignatureSet.siginfoscCs|jj|ƒ|S)N)rõrž)r+r)rrr"Ú add_siginfo®s zSEFaultSignatureSet.add_siginfocCs|jj|ƒdS)N)rõÚremove)r+r)rrr"Úremove_siginfo²sz"SEFaultSignatureSet.remove_siginfocCs g|_dS)N)rõ)r+rrr"ÚclearµszSEFaultSignatureSet.clearcCs ttjƒƒS)N)rHÚuuidZuuid4)r+rrr"Úgenerate_local_id¸sz%SEFaultSignatureSet.generate_local_idcCs.|dkr dSx|jD]}|j|kr|SqWdS)N)rõrŽ)r+rŽr)rrr"Úlookup_local_id»s   z#SEFaultSignatureSet.lookup_local_idÚexactc Csòt|jƒƒ}d}|dkrd}n(t|tƒr:t|ƒ}d|}n td|ƒ‚g}xŽ|jD]„} d} | j} x>|D]6} t|| ƒt| | ƒkr’|rˆd} qœ| |7} qf|rfd} PqfW|r¾| dkrÖ|j t | | ƒƒqR| |krR|j t | | ƒƒqRW|j t dd„ƒd �|S) NFrþTgð?zunknown criteria = %sgcSst|j|jƒS)N)r½r*)rÊrÑrrr"r#äsz6SEFaultSignatureSet.match_signatures..)rº) rOrQrªrêr«rdrõr‰rRržr rÎr) r+ZpatZcriteriaZxml_infoZ match_targetsrþZnum_match_targetsZscore_per_match_targetZmatchesr)r*r‰rSrrr"Úmatch_signaturesÅs6       z$SEFaultSignatureSet.match_signatures)r-r.r/rrrPr,rör÷rùrúrürýr rÿrUrr)rCr"r s   cs6eZdZddiddiddidœZd‡fdd„ Z‡ZS)rr1r3)rSÚ friendly_nameÚfilepathNcs<tt|ƒjƒ|dk r||_|dk r*||_|dk r8||_dS)N)rArr,rSrr)r+rSrr)rCrr"r,ïszSEDatabaseProperties.__init__)NNN)r-r.r/rPr,rUrr)rCr"rès cs@eZdZddidedd„dœdœZd ‡fdd „ Zd d „Z‡ZS) rr1r3cCstS)N)rrrrr"r#üszSEEmailRecipient.)r1r4r2)ÚaddressrVNcs&tt|ƒjƒ||_|dk r"||_dS)N)rArr,rrV)r+rrV)rCrr"r,ÿszSEEmailRecipient.__init__cCsd|jtj|jdƒfS)Nz%s:%sr`)rrbrcrV)r+rrr"r€szSEEmailRecipient.__str__)N)r-r.r/rXrPr,r€rUrr)rCr"rùscsneZdZddd„dœddedœdœZd‡fd d „ Zd d „Zdd„Zefdd„Z dd„Z dd„Z dd„Z ‡Z S)rr0cCsdS)NrÅrrrrr"r# szSEEmailRecipientSet.)r1r2r3Ú recipient)r1rOr4)r5Úrecipient_listNcs tt|ƒjƒ|dk r||_dS)N)rArr,r)r+r)rCrr"r,szSEEmailRecipientSet.__init__cCsdjdd„|jDƒƒS)Nr—cSsg|] }t|ƒ‘qSr)rH)rÈr rrr"rËsz/SEEmailRecipientSet.__str__..)rKr)r+rrr"r€szSEEmailRecipientSet.__str__cCs*|jƒ}x|jD]}||jkr|SqWdS)N)Ústriprr)r+rrrrr"Ú find_addresss   z SEEmailRecipientSet.find_addresscCsP|jƒ}t|ƒs$ttd|d�‚dS|j|ƒ}|dk r:dS|jjt||ƒƒdS)Nz address='%s')Údetail)rZvalid_email_addressr[ÚERR_INVALID_EMAIL_ADDRrrržr)r+rrVrrrr"Ú add_addresss zSEEmailRecipientSet.add_addresscCs g|_dS)N)r)r+rrr"Úclear_recipient_list)sz(SEEmailRecipientSet.clear_recipient_listcCs°ddl}|jdƒ}|jdƒ}|jdƒ}dddddddddœ}y t|ƒ}Wn8tk r€}zttd||jfd �‚WYdd}~XnX|jƒ�x|jƒD�]} |j d | ƒ} | j ƒ} | r–|j | ƒ} | r–| j d ƒ} | j d ƒ} d} | �rNxl|j | ƒD]^} | j d ƒ}| j d ƒ}|dk�r:tj|jƒdƒ} | dk�rJtd|| fƒqìtd|| fƒqìWy|j| | ƒWq–tk �rž}z"|jtk�rŠt|jƒn|‚WYdd}~Xq–Xq–W|jƒdS)Nrz#.*z(\S+)(\s+(.+))?z(\w+)\s*=\s*(\S+)TF)ZenabledÚtruer°ZonZdisabledZfalseÚnoZoffz%s, %s)rr©rDéérVz(unknown email filter (%s) for address %sz(unknown email option (%s) for address %s)r·ÚcompileÚopenÚIOErrorr[Ú ERR_FILE_OPENÚstrerrorr Ú readlinesr¸rÚsearchÚgroupÚfinditerÚmap_filter_name_to_valuercrërar ÚerrnorÚclose)r+rr·Z comment_reZentry_reZ key_value_reZ map_booleanr¦ÚeÚlineÚmatchrZoptionsrVZoptionr»rrr"Úparse_recipient_file,sT    (          z(SEEmailRecipientSet.parse_recipient_filecCs‚yt|dƒ}Wn8tk rF}zttd||jfd�‚WYdd}~XnXx,|jD]"}t|j}|jd|j |fƒqPW|j ƒdS)NÚwz%s, %s)rz%-40s filter_type=%s ) rrr[rrrrbrVÚwriterr)r+rr¦rrrVrrr"Úwrite_recipient_fileds(  z(SEEmailRecipientSet.write_recipient_file)N)r-r.r/rrPr,r€rrr r rr!rUrr)rCr"r s  8rDzaudit_listener_database.xmlÚsigszsiginfo.audit_event=%sz Memory OKzMemory leak %d bytes)KZ __future__rrZsixZsyslogÚ subprocessZ six.movesrÚ functoolsrÚgettextZsetroubleshoot.configrrZ translationZugettextr±ÚAttributeErrorÚ__all__r-ZinstallrrÂZsetroubleshoot.errcodeZsetroubleshoot.utilZsetroubleshoot.xml_serializeZsetroubleshoot.html_utilZsetroubleshoot.uuidrûZsetroubleshoot.audit_dataršÚtypesÚstringrr·r’r½rrrrrbrÚobjectr Z XmlSerializerr rrorqrrr rrrrrrrrZlibxml2Z debugMemoryZxml_filer"Z read_xml_filerõr)rƒrÇÚrecordÚprintrÜZ cleanupParserZ dumpMemoryrrrr"ÚsØ             4 !             gHk       __pycache__/signature.cpython-36.pyc000064400000070126152572267760013434 0ustar003 Úh>`â„ã@sÜddlmZddlmZddlZddlZddlTddlmZddlm Z ddl Z ddl m Z m Z e je dd ƒe dd ƒd d �Zy ejaWnek r ej aYnXd ddddddddddddddddgZedkrêe je dd ƒe dd ƒd�dd l madd!l m Z ddlTddlTddlTddlTddljZddlTddlZddlTdd"l m!Z!ddl"Z"ddl#Z#d#d$„Z$dZ%d%Z&d&Z'e%td'ƒe&td(ƒe'td)ƒiZ(e%d*e&d+e'd,iZ)e%e&e'd-œZ*Gd.d „d e+ƒZ,Gd/d„de-ƒZ.Gd0d„de-ƒZ/Gd1d„de-ƒZ0iZ1td2ƒe1d3<td4ƒe1d5<td6ƒe1d7<td8ƒe1d9<td:ƒe1d;<td<ƒe1d<<td=ƒe1d=<td>ƒe1d><td?ƒe1d?<td@ƒe1d@<tdAƒe1dA<tdBƒe1dB<tdCƒe1dC<dDdE„Z2GdFdG„dGe-ƒZ3GdHd„de-ƒZ4GdId„de-ƒZ5GdJd„de-ƒZ6GdKd„de-ƒZ7GdLd„de-ƒZ8GdMd„de-ƒZ9GdNd„de-ƒZ:GdOd„de-ƒZ;GdPd„de-ƒZdQƒdRZ?e9ƒZ@e@jAe?dSƒe@jBdZCeCjDjEdZFeGeFjHƒeGdTeCjDƒeGe@ƒe=jIƒe=j>dQƒdk�r¾eGdUƒneGdVe=j>dQƒƒe=jJƒdS)Wé)Úabsolute_import)Úprint_functionN)Ú*)Úrange)Ú cmp_to_key)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_dirT)ÚdomainÚ localedirZfallbackÚSignatureMatchÚSEFilterÚSEFaultSignatureÚSEFaultSignatureInfoÚSEFaultSignatureSetÚSEFaultSignatureUserÚ SEEnvironmentÚSEDatabasePropertiesÚSEFaultUserInfoÚSEFaultUserSetÚSEPluginÚSEEmailRecipientÚSEEmailRecipientSetÚ FILTER_NEVERÚ FILTER_ALWAYSÚFILTER_AFTER_FIRSTÚ filter_textÚ__main__)r r )Úngettext)r)ÚTemplatecCs||k||kS)N©)ÚxÚyrrú/usr/lib/python3.6/signature.pyÚQsr#ééz Never Ignorez Ignore AlwayszIgnore After First AlertÚneverÚalwaysÚ after_first)r&r'r(c@seZdZdd„ZdS)r cCs||_||_dS)N)ÚsiginfoÚscore)Úselfr)r*rrr"Ú__init__oszSignatureMatch.__init__N)Ú__name__Ú __module__Ú __qualname__r,rrrr"r msc sŒeZdZddd„dœddiddiddiddiddiddidedœdedœddiddiddidœ Z‡fd d „Zd d „Zd d„Zdd„Z‡Z S)rÚ attributecCsdS)Nz1.0rrrrr"r#vszSEEnvironment.)ÚXMLFormÚdefaultr1Úelement)r1Úimport_typecast) ÚversionÚplatformÚkernelÚ policy_typeÚ policy_rpmÚlocal_policy_rpmÚenforceÚselinux_enabledÚselinux_mls_enabledÚ policyversÚhostnameÚunamecstt|ƒjƒ|jƒdS)N)Úsuperrr,Úupdate)r+)Ú __class__rr"r,„szSEEnvironment.__init__cCsªddl}ddl}tƒ\|_|_|jƒd|_td|jƒ|_|j|_t |j ƒƒ|_ |j ƒ}|dkrjd|_ nd|_ t|jƒƒ|_t|jƒƒ|_|jƒ|_dj|jƒƒ|_dS)Nréz/etc/selinux/%sÚ PermissiveZ Enforcingú )r6ÚselinuxZget_os_environmentr7Zselinux_getpolicytyper8Zget_package_nvr_by_file_pathr9r:ÚstrZsecurity_policyversr>Zsecurity_getenforcer;ÚboolZis_selinux_enabledr<Zis_selinux_mls_enabledr=Únoder?Újoinr@)r+r6rGr;rrr"rBˆs zSEEnvironment.updatecCs |j|ƒ S)N)Ú__eq__)r+Úotherrrr"Ú__ne__žszSEEnvironment.__ne__cCs4x.t|jjƒƒD]}t||ƒt||ƒkrdSqWdS)NFT)ÚlistÚ _xml_infoÚkeysÚgetattr)r+rMÚnamerrr"rL¡szSEEnvironment.__eq__) r-r.r/ÚbooleanrPr,rBrNrLÚ __classcell__rr)rCr"rts    csBeZdZdedd„dœdedd„dœdœZef‡fdd„ Z‡ZS) r r3cCstS)N)rrrrr"r#ªszSEFilter.)r1r4r2cCsdS)Nrrrrrr"r#«s)Ú filter_typeÚcountcstt|ƒjƒ||_dS)N)rAr r,rV)r+rV)rCrr"r,®szSEFilter.__init__)r-r.r/ÚintrPrr,rUrr)rCr"r ¨scsdeZdZddidedd„dœdedd„dœdedd„dœd œZ‡fd d „Zd d „Zddd„Z‡Z S)rr1r0cCsdS)NFrrrrr"r#¶szSEFaultSignatureUser.)r1r4r2cCsdS)NFrrrrr"r#·sr3cCstƒS)N)r rrrr"r#¸s)ÚusernameZ seen_flagZ delete_flagÚfiltercstt|ƒjƒ||_dS)N)rArr,rY)r+rY)rCrr"r,»szSEFaultSignatureUser.__init__cCs:||jkrttd|ƒ‚|dkr*ttdƒ‚t|||ƒdS)Nz!item (%s) is not a defined memberrYz changing the username is illegal)Z_namesÚ ProgramErrorZERR_NOT_MEMBERZERR_ILLEGAL_USER_CHANGEÚsetattr)r+ÚitemÚdatarrr"Ú update_item¿s   z SEFaultSignatureUser.update_itemNcCsXtdtj|dƒ|fƒ|tks0|tks0|tkrHtdƒt|d�|_dStd|ƒ‚dS)Nz%update_filter: filter_type=%s data=%sÚunknownzupdate_filter: !!!)rVTzBad filter_type (%s)) Ú log_debugÚmap_filter_value_to_nameÚgetrrrr rZÚ ValueError)r+rVr^rrr"Ú update_filterÈs z"SEFaultSignatureUser.update_filter)N) r-r.r/rTr rPr,r_rerUrr)rCr"r³s  Ú directoryÚdirZ semaphoreZsemz shared memoryZshmz message queueZmsgqÚmessageÚmsgÚfileZsocketÚprocessÚprocess2Z filesystemrJÚ capabilityÚ capability2cCs|ttjƒƒkrt|S|S)N)rOÚ class_dictrQ)Útclassrrr"Útranslate_classäsrqcs eZdZdZ‡fdd„Z‡ZS)ÚAttributeValueDictionaryZ unstructuredcstt|ƒjƒdS)N)rArrr,)r+)rCrr"r,ïsz!AttributeValueDictionary.__init__)r-r.r/rPr,rUrr)rCr"rrìsrrc sZeZdZddd„dœddidddœded œded œddided œd œZ‡fd d „Z‡ZS) r r0cCsdS)Nz4.0rrrrr"r#õszSEFaultSignature.)r1r2r1r3Z operation)r1rO)r1r4)r5ÚhostÚaccessÚscontextÚtcontextrpÚportc s8tt|ƒjƒx$t|jƒƒD]\}}t|||ƒqWdS)N)rAr r,rOÚitemsr\)r+ÚkwdsÚkÚv)rCrr"r,þszSEFaultSignature.__init__)r-r.r/Ú AvcContextrXrPr,rUrr)rCr"r ós cs8eZdZddidddœdœZ‡fdd„Zdd „Z‡ZS) rr1r3Úarg)r1rO)Ú analysis_idÚargscstt|ƒjƒ||_||_dS)N)rArr,r~r)r+r~r)rCrr"r, szSEPlugin.__init__cCst|j|jfƒS)N)rHr~r)r+rrr"Ú__str__szSEPlugin.__str__)r-r.r/rPr,r€rUrr)rCr"rs cs eZdZddedœdedœddiddiddidddœdddœdedœdedœddidedœdedœddiddiddidedœde dœde dœdedd „d œddidd e dœddiddiddid œZ d dddddddddg Z ‡fdd„Z dd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„ZdEd&d'„ZdFd(d)„Zd*d+„Zd,d-„Zd.d/„Zd0d1„Zd2d3„Zd4d5„Zd6d7„ZdGd9d:„Zd;d<„Zd=d>„ZdHd?d@„Z dAdB„Z!dIdCdD„Z"‡Z#S)Jrr3Zplugin)r1rOr4)r1r4r1Zrpm)r1rOcCsdS)Nrrrrrr"r#)szSEFaultSignatureInfo.)r1r4r2Úuser)Ú plugin_listÚ audit_eventÚsourceÚspathÚtpathÚ src_rpm_listÚ tgt_rpm_listrurvrprwÚsigZif_textZ then_textZdo_textÚ environmentÚfirst_seen_dateÚlast_seen_dateÚ report_countÚlocal_idÚusersÚlevelZfixableZ button_textrƒr†r‡rˆrurvrprwrŠrŒc s|tt|ƒjƒx$t|jƒƒD]\}}t|||ƒqWd|_g|_d}tj ƒdkrTd}yt |j |d�|j _ Wn YnXdS)NrDTrF)Úuse_dbus)rArr,rOrxr\r�r‚ÚosÚgetuidZget_rpm_nvr_by_scontextrurŠr:)r+ryrzr{r‘)rCrr"r,7s zSEFaultSignatureInfo.__init__cCsZ|j|jkr"|j|_|jd7_x |jD]}t||t||ƒƒq*W|jdkrV|j|_dS)NrD)rŒr�Ú merge_includer\rRr�)r+r)rSrrr"Ú update_mergeHs   z!SEFaultSignatureInfo.update_mergecCs|jjS)N)rŠr9)r+rrr"Úget_policy_rpmTsz#SEFaultSignatureInfo.get_policy_rpmcCs(d|j|jj|jj|jdj|jjƒfS)Nz%s,%s,%s,%s,%sú,)r„ruÚtypervrprKr‰rt)r+rrr"Ú get_hash_strWsz!SEFaultSignatureInfo.get_hash_strcCstj|jƒjdƒƒ}|jƒS)Nzutf-8)ÚhashlibZsha256r™ÚencodeZ hexdigest)r+Úhashrrr"Úget_hashZszSEFaultSignatureInfo.get_hashcCsBx|jD]}|j|kr|SqWtd|ƒt|ƒ}|jj|ƒ|S)Nznew SEFaultSignatureUser for %s)r�rYrarÚappend)r+rYr�rrr"Ú get_user_data^s    z"SEFaultSignatureInfo.get_user_datacCs,td|ƒd}|j|ƒ}|dk r(|j}|S)Nzfind_filter_by_username %s)rarŸrZ)r+rYrZÚ user_datarrr"Úfind_filter_by_usernamegs   z,SEFaultSignatureInfo.find_filter_by_usernameNcCs|j|ƒ}|j||ƒdS)N)rŸre)r+rYrVr^r rrr"Úupdate_user_filterps z'SEFaultSignatureInfo.update_user_filtercCsTd}|j|ƒ}td||fƒ|dk rP|dk r4||_|j|ƒ}td|||fƒ|S)NÚdisplayz5evaluate_filter_for_user: found %s user's filter = %sz4evaluate_filter_for_user: found filter for %s: %s %s)r¡rarVÚevaluate_filter)r+rYrVÚactionÚfrrr"Úevaluate_filter_for_userts  z-SEFaultSignatureInfo.evaluate_filter_for_usercCsb|j}d}|tkrd}n8|tkr6|jdkr0d}qPd}n|tkrDd}n td|ƒ‚|jd7_|S)Nr£rÚignorezunknown filter_type (%s)rD)rVrrrWrrd)r+rZrVr¥rrr"r¤s  z$SEFaultSignatureInfo.evaluate_filtercCs2t|tƒr&t|ƒdkr dj|ƒSdSntdƒSdS)NrrFÚ)Ú isinstancerOÚlenrKÚ default_text)r+Zrpm_listrrr"Úformat_rpm_list’s    z$SEFaultSignatureInfo.format_rpm_listcCsd|j|jfS)Nz %s [ %s ])r†rp)r+rrr"Úformat_target_object›sz)SEFaultSignatureInfo.format_target_objectcCsTd}|jjdƒ}|dkr<|jdƒdkrzSEFaultSignatureInfo.summaryFc stƒˆ_g}d}|r>x„ˆjD]}||j7}|j|d fƒqWn\xZˆjD]P}xJˆjD]@}|j|jkrR||j7}|jt|jƒƒ|j|t|jƒfƒPqRWqFW|j t ˆj ƒd�ddddg}d j ‡fd d „|Dƒƒ}x.|D]&}||krÖx|D]\}} d |_ qèWPqÖW||fS)NrÚ allow_ypbindÚ1)rºZmozilla_read_contentZ"mozilla_plugin_can_network_connectZmozilla_plugin_use_bluejeansZ$unconfined_mozilla_plugin_transitionrFcs g|]\}}|jˆjj|ƒ‘qSr)Ú get_do_textrƒÚrecords)Ú.0ÚpÚa)r+rr"ú úsz4SEFaultSignatureInfo.get_plugins..F)rÄrÅ)Z load_pluginsÚpluginsr¾ržr‚r~Z init_argsÚtuplerÚsortrr¿rKZ report_bug) r+ÚallrÌÚtotal_priorityrÉZsolutionZnoreport_booleansZdo_textsÚbrÊr)r+r"Ú get_pluginsãs0         z SEFaultSignatureInfo.get_pluginscCst|ƒj|jƒS)N)rZsafe_substituter´)r+Útxtrrr"Ú substituteszSEFaultSignatureInfo.substitutecs‡fdd„|DƒS)Ncsg|]}ˆj|ƒ‘qSr)rÔ)rÈrÓ)r+rr"rË sz9SEFaultSignatureInfo.substitute_array..r)r+rr)r+r"Úsubstitute_arraysz%SEFaultSignatureInfo.substitute_arrayc s–|j}tdƒ}|ttdƒ|jjƒƒ7}|ttdƒ|jjƒƒ7}|ttdƒ|jƒƒ7}|ttdƒt|jƒƒ7}|ttdƒt|j ƒƒ7}|ttdƒt|j ƒƒ7}|r´|ttdƒd ƒ7}n|ttdƒt|j j ƒƒ7}|ttd ƒt|j |jƒƒƒ7}|ttd ƒt|j |jƒƒƒ7}|ttd ƒt|jƒƒ7}|ttd ƒt|jƒƒ7}|ttdƒt|jƒƒ7}|ttdƒt|jƒƒ7}|ttdƒt|jƒƒ7}|�rœ|ttdƒd ƒ7}n|ttdƒt|jƒƒ7}|�rê|jjƒ}d |d<|ttdƒtdj|ƒƒƒ7}n|ttdƒt|jƒƒ7}|ttdƒt|jƒƒ7}d}|ttdƒ|jj|ƒƒ7}|ttdƒ|jj|ƒƒ7}|ttdƒt|jƒƒ7}|dtdƒ7}d}xj|jjD]^‰ˆjdk�r®|dˆj ƒd7}n6|dˆjˆj!f7}|dj‡fdd „ˆj"Dƒƒd7}�qˆW|d!|j#ƒ7}y~d"}t$j%j&|ƒ�rvd#}t'|gt(t(d$�} || j)|ƒd%7}t$j%j*d&ƒ�rn|d'7}t'|d(gt(t(d$�} || j)|ƒd%7}||7}Wn YnX||d7}|S))NzAdditional Information: zSource ContextzTarget ContextzTarget ObjectsZSourcez Source PathZPortZHostz (removed)zSource RPM PackageszTarget RPM PackageszSELinux Policy RPMzLocal Policy RPMzSelinux Enabledz Policy TypezEnforcing Modez Host NamerDZPlatformrFz Alert Countz%Y-%m-%d %H:%M:%S %Zz First Seenz Last SeenzLocal IDÚ zRaw Audit Messagesr©ZAVCz type=%s msg=%s: csg|]}d|ˆj|f‘qS)z%s=%s)Zfields)rÈrz)Ú audit_recordrr"rË8sz7SEFaultSignatureInfo.format_details..z Hash: z/usr/bin/audit2allowz audit2allow)ÚstdinÚstdoutrz /var/lib/sepolgen/interface_infoz audit2allow -Rz-R)+rŠr±Zformat_2_column_name_valueruÚformatrvr®r¬r„r…rwr‰rsr­r‡rˆr9r:r<r8r;r?r@ÚsplitrKr�r‹rŒrŽrƒrÇÚ record_typeZto_textZevent_idZ fields_ordr™r’rµZexistÚPopenÚPIPEZ communicateÚexists) r+ÚreplaceÚenvÚtextr@Z date_formatZavcbufZ audit2allowZnewbufrÉr)r×r"Úformat_details sl  (  z#SEFaultSignatureInfo.format_detailsc Os2t}t}zdd„add„a|||ŽS|a|aXdS)zdefine.*untranslated\(.*\ncSs|dkr |S|S)NrDr)r r!Úzrrr"r#Xsz3SEFaultSignatureInfo.untranslated..cSs|S)Nr)r rrr"r#YsN)rÂr±)r+ÚfuncrÚkwargsZsaved_translateP_Zsaved_translate_rrr"Ú untranslatedNs z!SEFaultSignatureInfo.untranslatedc Cs>|jƒ|jƒ}|j|ƒ\}}�x |D�]\}}tdƒ|jt|jƒt|ƒddf}||7}x"tt|ƒdƒD]} |tdƒ7}qpW|tdƒ7}|j |j |j j |ƒƒ} |tdƒ| 7}|j |j |j j |ƒƒ} |tdƒ| djƒ| d d…7}|j |j|j j |ƒƒ} |td ƒ| djƒ| d d…7}q&W|td ƒ7}|S) Nz0 ***** Plugin %s (%.4s confidence) suggests édgà?éPrrÖz Then rrDz Do z )r¼rÃrÒr±r~Úfloatr¾rr«rÔZ get_if_textrƒrÇZ get_then_textÚlowerrÆ) r+rÏràrârÐrÌrÉrÚtitleÚirÓrrr"Ú format_text_s"( $( z SEFaultSignatureInfo.format_text)N)N)F)F)FF)$r-r.r/rZ AuditEventr|rXr rZ TimeStamprrPr”r,r•r–r™r�rŸr¡r¢r§r¤r­r®r²r¼r¿rÃrÒrÔrÕrãrçrîrUrr)rCr"rsd          / " CcsReZdZddd„dœddidedd„dœdd d œd œZ‡fd d „Zdd„Z‡ZS)rr0cCsdS)Nz1.0rrrrr"r#zszSEFaultUserInfo.)r1r2r1r3cCsdS)NFrrrrr"r#|s)r1r4r2Ú email_address)r1rO)r5rYZ email_alertÚemail_address_listcstt|ƒjƒ||_dS)N)rArr,rY)r+rY)rCrr"r,€szSEFaultUserInfo.__init__cCs||jkr|jj|ƒdS)N)rðrž)r+rïrrr"Úadd_email_address„s z!SEFaultUserInfo.add_email_address)r-r.r/rTrPr,rñrUrr)rCr"rxs   csHeZdZddd„dœddedœdœZ‡fd d „Zd d „Zd d„Z‡ZS)rr0cCsdS)Nz1.0rrrrr"r#‹szSEFaultUserSet.)r1r2r3r�)r1rOr4)r5Ú user_listcstt|ƒjƒdS)N)rArr,)r+)rCrr"r,�szSEFaultUserSet.__init__cCs"x|jD]}||jkr|SqWdS)N)ròrY)r+rYr�rrr"Úget_user’s  zSEFaultUserSet.get_usercCs*|j|ƒdk rdSt|ƒ}|jj|ƒ|S)N)rórròrž)r+rYr�rrr"Úadd_user˜s  zSEFaultUserSet.add_user) r-r.r/rrPr,rórôrUrr)rCr"r‰s   cs†eZdZddd„dœdedd„dœdded œd œZ‡fd d „Zd d„Zdd„Zdd„Z dd„Z dd„Z dd„Z de jfdd„Z‡ZS)rr0cCs dttfS)Nz%d.%d)ZDATABASE_MAJOR_VERSIONZDATABASE_MINOR_VERSIONrrrr"r#¢szSEFaultSignatureSet.)r1r2r3cCstƒS)N)rrrrr"r#£s)r1r4r2r))r1rOr4)r5r�Úsignature_listcstt|ƒjƒdS)N)rArr,)r+)rCrr"r,§szSEFaultSignatureSet.__init__ccsx|jD] }|VqWdS)N)rõ)r+r)rrr"Úsiginfosªs zSEFaultSignatureSet.siginfoscCs|jj|ƒ|S)N)rõrž)r+r)rrr"Ú add_siginfo®s zSEFaultSignatureSet.add_siginfocCs|jj|ƒdS)N)rõÚremove)r+r)rrr"Úremove_siginfo²sz"SEFaultSignatureSet.remove_siginfocCs g|_dS)N)rõ)r+rrr"ÚclearµszSEFaultSignatureSet.clearcCs ttjƒƒS)N)rHÚuuidZuuid4)r+rrr"Úgenerate_local_id¸sz%SEFaultSignatureSet.generate_local_idcCs.|dkr dSx|jD]}|j|kr|SqWdS)N)rõrŽ)r+rŽr)rrr"Úlookup_local_id»s   z#SEFaultSignatureSet.lookup_local_idÚexactc Csòt|jƒƒ}d}|dkrd}n(t|tƒr:t|ƒ}d|}n td|ƒ‚g}xŽ|jD]„} d} | j} x>|D]6} t|| ƒt| | ƒkr’|rˆd} qœ| |7} qf|rfd} PqfW|r¾| dkrÖ|j t | | ƒƒqR| |krR|j t | | ƒƒqRW|j t dd„ƒd �|S) NFrþTgð?zunknown criteria = %sgcSst|j|jƒS)N)r½r*)rÊrÑrrr"r#äsz6SEFaultSignatureSet.match_signatures..)rº) rOrQrªrêr«rdrõr‰rRržr rÎr) r+ZpatZcriteriaZxml_infoZ match_targetsrþZnum_match_targetsZscore_per_match_targetZmatchesr)r*r‰rSrrr"Úmatch_signaturesÅs6       z$SEFaultSignatureSet.match_signatures)r-r.r/rrrPr,rör÷rùrúrürýr rÿrUrr)rCr"r s   cs6eZdZddiddiddidœZd‡fdd„ Z‡ZS)rr1r3)rSÚ friendly_nameÚfilepathNcs<tt|ƒjƒ|dk r||_|dk r*||_|dk r8||_dS)N)rArr,rSrr)r+rSrr)rCrr"r,ïszSEDatabaseProperties.__init__)NNN)r-r.r/rPr,rUrr)rCr"rès cs@eZdZddidedd„dœdœZd ‡fdd „ Zd d „Z‡ZS) rr1r3cCstS)N)rrrrr"r#üszSEEmailRecipient.)r1r4r2)ÚaddressrVNcs&tt|ƒjƒ||_|dk r"||_dS)N)rArr,rrV)r+rrV)rCrr"r,ÿszSEEmailRecipient.__init__cCsd|jtj|jdƒfS)Nz%s:%sr`)rrbrcrV)r+rrr"r€szSEEmailRecipient.__str__)N)r-r.r/rXrPr,r€rUrr)rCr"rùscsneZdZddd„dœddedœdœZd‡fd d „ Zd d „Zdd„Zefdd„Z dd„Z dd„Z dd„Z ‡Z S)rr0cCsdS)NrÅrrrrr"r# szSEEmailRecipientSet.)r1r2r3Ú recipient)r1rOr4)r5Úrecipient_listNcs tt|ƒjƒ|dk r||_dS)N)rArr,r)r+r)rCrr"r,szSEEmailRecipientSet.__init__cCsdjdd„|jDƒƒS)Nr—cSsg|] }t|ƒ‘qSr)rH)rÈr rrr"rËsz/SEEmailRecipientSet.__str__..)rKr)r+rrr"r€szSEEmailRecipientSet.__str__cCs*|jƒ}x|jD]}||jkr|SqWdS)N)Ústriprr)r+rrrrr"Ú find_addresss   z SEEmailRecipientSet.find_addresscCsP|jƒ}t|ƒs$ttd|d�‚dS|j|ƒ}|dk r:dS|jjt||ƒƒdS)Nz address='%s')Údetail)rZvalid_email_addressr[ÚERR_INVALID_EMAIL_ADDRrrržr)r+rrVrrrr"Ú add_addresss zSEEmailRecipientSet.add_addresscCs g|_dS)N)r)r+rrr"Úclear_recipient_list)sz(SEEmailRecipientSet.clear_recipient_listcCs°ddl}|jdƒ}|jdƒ}|jdƒ}dddddddddœ}y t|ƒ}Wn8tk r€}zttd||jfd �‚WYdd}~XnX|jƒ�x|jƒD�]} |j d | ƒ} | j ƒ} | r–|j | ƒ} | r–| j d ƒ} | j d ƒ} d} | �rNxl|j | ƒD]^} | j d ƒ}| j d ƒ}|dk�r:tj|jƒdƒ} | dk�rJtd|| fƒqìtd|| fƒqìWy|j| | ƒWq–tk �rž}z"|jtk�rŠt|jƒn|‚WYdd}~Xq–Xq–W|jƒdS)Nrz#.*z(\S+)(\s+(.+))?z(\w+)\s*=\s*(\S+)TF)ZenabledÚtruer°ZonZdisabledZfalseÚnoZoffz%s, %s)rr©rDéérVz(unknown email filter (%s) for address %sz(unknown email option (%s) for address %s)r·ÚcompileÚopenÚIOErrorr[Ú ERR_FILE_OPENÚstrerrorr Ú readlinesr¸rÚsearchÚgroupÚfinditerÚmap_filter_name_to_valuercrërar ÚerrnorÚclose)r+rr·Z comment_reZentry_reZ key_value_reZ map_booleanr¦ÚeÚlineÚmatchrZoptionsrVZoptionr»rrr"Úparse_recipient_file,sT    (          z(SEEmailRecipientSet.parse_recipient_filecCs‚yt|dƒ}Wn8tk rF}zttd||jfd�‚WYdd}~XnXx,|jD]"}t|j}|jd|j |fƒqPW|j ƒdS)NÚwz%s, %s)rz%-40s filter_type=%s ) rrr[rrrrbrVÚwriterr)r+rr¦rrrVrrr"Úwrite_recipient_fileds(  z(SEEmailRecipientSet.write_recipient_file)N)r-r.r/rrPr,r€rrr r rr!rUrr)rCr"r s  8rDzaudit_listener_database.xmlÚsigszsiginfo.audit_event=%sz Memory OKzMemory leak %d bytes)KZ __future__rrZsixZsyslogÚ subprocessZ six.movesrÚ functoolsrÚgettextZsetroubleshoot.configrrZ translationZugettextr±ÚAttributeErrorÚ__all__r-ZinstallrrÂZsetroubleshoot.errcodeZsetroubleshoot.utilZsetroubleshoot.xml_serializeZsetroubleshoot.html_utilZsetroubleshoot.uuidrûZsetroubleshoot.audit_dataršÚtypesÚstringrr·r’r½rrrrrbrÚobjectr Z XmlSerializerr rrorqrrr rrrrrrrrZlibxml2Z debugMemoryZxml_filer"Z read_xml_filerõr)rƒrÇÚrecordÚprintrÜZ cleanupParserZ dumpMemoryrrrr"ÚsØ             4 !             gHk       __pycache__/util.cpython-36.opt-1.pyc000064400000063353152572267760013353 0ustar003 ¹QfË}ã+@süddlmZddlmZddddddd d d d d ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-g+Zdd.lZdd.lZdd.lZdd/lm Z dd.l Z dd0l m Z dd.l Z dd.lZdd.lZdd.lZdd.lZdd.lZdd.lZdd.lZdd.lZdd1lTdd.lZdd2lmZdd3lmZmZdd4lmZdd1lTd5d6„Zd7d8„Z d9Z!dZ"d.Z#ej$d:ƒ�r`d:Z#nej$d;ƒ�rpdƒZ)ej(d?ƒZ*ej(d@ƒZ+ej(dAƒZ,ej(dBƒZ-ej(dCƒZ.d.a/ej0a1ej2ej3ej0ej4ej5dDœZ6dEdF„Z7dGd#„Z8dHd*„Z9dId)„Z:dJd„Z;dKd„Zd€dNd„Z?dOd„Z@d�dRd„ZAd‚dSd „ZBdƒdUd „ZCdVd „ZDdWd „ZEdXd „ZFdYd„ZGdZd„ZHd[d„ZId\d„ZJydd]lKmLZLeLƒZMWngZMYnXd^d„ZNd_d„ZOd`da„ZPdbdc„ZQd„ded„ZRdfd„ZSdgd„ZTdhd „ZUdid!„ZVdjd$„ZWd…dkd%„ZXdld"„ZYd†dmd„ZZdndo„Z[d‡dpd„Z\dqd„Z]dˆdrd„Z^dsd„Z_dtd„Z`dud„Zadvd&„Zbejcejd dw�Zeejf�rˆejcejg dw�ZhneeZheheeZiejcdƒZjejcdxdy�ZkGdzd{„d{ejlƒZmGd|d}„d}ejlƒZnGd~d+„d+ƒZoGdd,„d,e j ƒZpe jqepƒd.S)‰é)Úabsolute_import)ÚrangeÚaudit_msg_decodeÚ merge_listsÚpreextend_listÚfmt_objÚformat_elapsed_timeÚformat_2_column_name_valueÚ wrap_textÚ format_msgÚremove_linebreaksÚ default_textÚdefault_date_textÚget_standard_directoriesÚget_rpm_nvr_from_headerÚget_package_nvr_by_nameÚget_package_nvr_by_file_pathÚget_rpm_nvr_by_typeÚget_rpm_nvr_by_scontextÚget_rpm_source_packageÚis_hexÚ split_rpm_nvrÚ file_typesÚget_user_home_dirÚget_plugin_namesÚ load_pluginsÚget_os_environmentÚ find_programÚ get_identityÚ get_hostnameÚmake_database_filepathÚvalid_email_addressÚlaunch_web_browser_on_urlÚabstractÚ log_debugÚget_error_from_socket_exceptionÚ!assure_file_ownership_permissionsÚparse_datetime_offsetÚDATABASE_MAJOR_VERSIONÚDATABASE_MINOR_VERSIONÚdatabase_version_compatibleÚ syslog_traceÚ TimeStampÚRetryÚPACKAGE_MANAGERN)Ú SystemBus)ÚGObject)Ú*)Ú cmp_to_key)Ú FunctionTypeÚ MethodType)Ú get_configcCs||k||kS)N©)ÚxÚyr6r6ú/usr/lib/python3.6/util.pyÚ\sr:c Cs*y t|tƒStk r$t|tƒSXdS)N)Ú isinstanceZTypeTypeÚ NameErrorÚtype)Úobjr6r6r9Úis_type_s r?éÚrpmÚdpkgÚdebz/etc/redhat-releasez \s*\n+\s*z^[A-Fa-f0-9]+$zz^([^\s@]+)@([^\s@]+)$z^\s*"([^"]+)"\s*$z\s*\(\s*type\s+([\w-]+)\s*\)\s*)ZCRITICALZERRORZWARNINGÚINFOÚDEBUGcCs&tjt|dƒjƒƒatdkr"tjadS)NÚlevel)Ú log_levelsÚgetr5ÚupperÚ log_levelÚsyslogÚ LOG_WARNING)Zsectionr6r6r9Úlog_init‡srMcCsttjkrtjtj|ƒdS)N)rJrKÚ LOG_DEBUG)Úmsgr6r6r9r$Žs cCs.|jdƒ}x|D]}t|ƒrtj|ƒqWdS)NÚ )ÚsplitÚlenrK)ZtraceZ log_linesÚliner6r6r9r+”s  cCszd}}|jdƒ}t|ƒdkr*t|dƒ}t|ƒdkrBt|dƒ}|tkr`td|ttfƒdStd|ttfƒdSdS) NÚ.éréz=database version %s not compatible with current %d.%d versionFz9database version %s compatible with current %d.%d versionT)rQrRÚintr(r$r))ÚversionÚmajorÚminorÚ componentsr6r6r9r*›s     cCs´|dkr dSddl}|j|ƒ\}}t|ƒ}|d}||d}|d}||d}|d}||d}|r~d|||||fS|r”d||||fS|r¨d|||fSd||S) Nri€Qié<z%dd:%dh:%dm:%.3fsz %dh:%dm:%.3fsz %dm:%.3fsz%.3fs)ÚmathZmodfrW)Z elapsed_timer]ZfractionZwholeÚdaysÚhoursÚminutesÚsecondsr6r6r9r«s$   cCstj|ƒrdSdSdS)NTF)Úhex_reÚmatch)Ústrr6r6r9rÅs c Csj|dkr dStj|ƒ}|r&|jdƒ}n@y.tjddkrB|jdƒ}ntj|ƒjdƒ}Wn|}YnX|S)NrUrr@Úhexzutf-8)Úaudit_decode_reÚsearchÚgroupÚsysÚ version_infoÚdecodeÚ bytearrayÚfromhex)rOrcZdecodedr6r6r9rÌs    cCsP|s|S|s|Si}x|D] }d||<qWx|D] }d||<q0Wt|jƒƒ}|S)z2return a list containing the unique members of a+bN)ÚlistÚkeys)ÚaÚbÚdÚiÚmr6r6r9rãs     cs^|dkr g}t|ƒ}||}|dkrZtˆƒrJ|j‡fdd„t|ƒDƒƒn|jˆg|ƒ|S)Nrcsg|] }ˆƒ‘qSr6r6)Ú.0r7)Údefaultr6r9ú ùsz"preextend_list..)rRr?Úextendr)Zrequested_lengthZ_listrvZ cur_lengthZdeltar6)rvr9ròscs„tˆtjƒrˆStˆttfƒr:ddjdd„ˆDƒƒdStˆtƒrxtˆjƒƒ}|jƒddj‡fdd„|DƒƒdSt ˆƒSdS) Nú[ú cSsg|]}dt|ƒ‘qS)z%s)r)rur7r6r6r9rwszfmt_obj..ú]ú{cs$g|]}dt|ƒtˆ|ƒf‘qS)z%s=%s)r)ruÚkey)r>r6r9rwsú}) r;ÚsixÚ string_typesrnÚtupleÚjoinÚdictroÚsortrd)r>ror6)r>r9rÿs    ééPcCsxt|ƒ|kr"|d|d…d}n|d|t|ƒ}| sD|jƒrP||dS|t_d|t_|t_tj|ƒdSdS)NrrUrzrP)rRÚisspaceÚ text_wrapperÚinitial_indentÚsubsequent_indentÚwidthÚfill)ÚnameÚvalueZ value_indentZ page_widthr‰r6r6r9r s   cCs(d|}|t_|t_|t_tj|ƒdS)NrzrP)rˆr‰rŠr‹rŒ)Úsr‹ÚindentÚprefixr6r6r9r s écCsD|dkr d}|jƒ}d|}|t_|t_dt_|dtj|ƒdS)NÚrzr†rPz )Ústriprˆr‰rŠr‹rŒ)ÚtitlerOr�Z indentStringr6r6r9r #scCs$tjd|ƒjƒ}|dkrdS|SdS)Nrzr“)Úfix_newline_reÚsubr”)rdZnew_strr6r6r9r .scCs |dkrdtdƒd}t|ƒS)Nú)Ú_rd)Úvalr6r6r9r 6scCs|dkrt|ƒS|jƒS)N)r Úformat)Zdater6r6r9r<sc Cszg}yPtdkr,tjdddgdd�jƒjdƒ}tdkrRtjdd d gdd�jƒjdƒ}Wn tjtjd jtƒƒYnX|S) z3 >>> get_standard_directories() [...'/bin'...] rAz-qlZ filesystemT)Úuniversal_newlinesrPrCrBz-Lz base-fileszfailed to get list from {})r.Ú subprocessÚ check_outputÚrstriprQrKÚLOG_ERRrœ)Zlstr6r6r9rBs"cCs&|d}|d}|d}d|||fS)z6Given an RPM header return the package NVR as a stringr�rXÚreleasez%s-%s-%sr6)Zhdrr�rXr¢r6r6r9rTsc Csz|dkr dSd}yFtdkr2tjdd|gdd�jƒ}tdkrTtjddd |gdd�jƒ}Wntjtjd |ƒYnX|S) zJ >>> get_package_nvr_by_name("coreutils") 'coreutils-8.30-3+b1:amd64' NrAz-qT)r�rCz dpkg-queryz(-f=${Package}-${Version}:${Architecture}z-Wz"failed to retrieve rpm info for %s)r.ržrŸr rKr¡)r�Únvrr6r6r9r\sc Cs´|dkr dStjj|ƒ}tjj|ƒs(dSd}ydtdkrNtjdd|gdd�jƒ}tdkrŽtjdd|gƒjƒj d ƒd }tjd d d |gdd�jƒ}Wnt j t j d|ƒYnX|S)zM >>> get_package_nvr_by_file_path("/bin/ls") 'coreutils-8.30-3+b1:amd64' NrAz-qfT)r�rCrBz-Sz: rz dpkg-queryz(-f=${Package}-${Version}:${Architecture}z-Wz"failed to retrieve rpm info for %s) ÚosÚpathÚabspathÚexistsr.ržrŸr rkrQrKr¡)r�r£Z package_namer6r6r9rrs   )Úget_all_file_typescCs6|jdƒ}|d}|d}dj|dd…ƒ}|||fS)Nú-rUrVéÿÿÿÿéþÿÿÿr«)rQr‚)r£r[r¢rXr�r6r6r9r–s  cCs.tdkrtƒtdkrdStj|dƒ}t|ƒS)aV Finds an SELinux module which defines given SELinux type ##### arguments * `selinux_type(s)`: an SELinux type ##### return values * `nvr(s)`: nvr of rpm which ships module where `selinux_type` is defined ##### usage >>> get_rpm_nvr_by_type("sshd_t") 'selinux-policy-... >>> get_rpm_nvr_by_type("mysqld_log_t") 'mysql-selinux-... N)Úmodule_type_cacheÚbuild_module_type_cacherHr)Z selinux_typer¥r6r6r9r�s  c Csy t|ƒdSdSdS)NTF)rW)rdr6r6r9Ú __str_is_int½s r®c Cstjƒ\}}|dkrdStƒ}g}tjdj|ƒƒ� }tdd„|Dƒdd„d�}WdQRXx®|D]¦}x tjd j||ƒƒD]Š\}}}d |krvyjytj d j|ƒd d �} Wnt d j|ƒƒ} YnXx(| D] } t j | ƒ} | rÄ||| j dƒ<qÄW| j ƒWqvYqvXqvWq^W|adS)zË Creates a dictionary with all types defined in the module store as keys and corresponding module paths as values. The dictionary is stored in "module_type_cache" to be used by "get_rpm_nvr_by_type" rNz"/var/lib/selinux/{}/active/modulescSs$g|]}|jƒrt|jƒr|j‘qSr6)Úis_dirr®r�)rur7r6r6r9rwÖsz+build_module_type_cache..cSst|ƒS)N)rW)r7r6r6r9r:Ösz)build_module_type_cache..)r}z%/var/lib/selinux/{}/active/modules/{}Zcilz{}/cilZrt)ÚmoderU)ÚselinuxZselinux_getpolicytyperƒr¤ÚscandirrœÚsortedÚwalkÚbz2ÚopenÚtypedef_regexprcrhÚcloser¬) ZretvalZ policytypeZmodule_type_dictZ prioritiesZ module_storeÚdirÚdirpathZdirnamesÚ filenamesÚfrSÚresultr6r6r9r­Äs. $    r­FcCsJ|r&tƒ}|jdƒ}t|jt|ƒƒƒStjt|ƒƒ}tttj|ƒƒƒSdS)a Finds an SELinux module which defines given SELinux context ##### arguments * `scontext(s)`: an SELinux context ##### return values * `nvr(s)`: nvr of rpm which ships module where SELinux type used in `scontext` is defined ##### usage >>> get_rpm_nvr_by_scontext("system_u:system_r:syslogd_t:s0") 'selinux-policy-... >>> get_rpm_nvr_by_scontext("system_u:system_r:mysqld_log_t:s0") 'mysql-selinux-... >>> get_rpm_nvr_by_scontext("system_u:system_r:timedatex_t:s0", use_dbus=True) 'selinux-policy-... z*org.fedoraproject.SetroubleshootPrivilegedN)r/rHrdrr±Z context_newrZcontext_type_get)ZscontextZuse_dbusZbusZ remote_objectÚcontextr6r6r9rôs  c Csd|dkr dSd}y0ddl}|jdddd|gdd�jd d ƒd}Wntjtjd |ƒYnX|S) zÙ Find a source package for `name` rpm >>> get_rpm_source_package("policycoreutils-python-utils") 'policycoreutils' >>> get_rpm_source_package("selinux-policy-targeted") 'selinux-policy' NrrAz-qz--qfz %{SOURCERPM}T)r�r©rVz"failed to retrieve rpm info for %s)ržrŸÚrsplitrKr¡)r�Úsrcržr6r6r9rs (c Cs6tjƒ}ytj|ƒ}Wntk r*dSX|j}|S)N)r¤ÚgetuidÚpwdÚgetpwuidÚKeyErrorÚpw_dir)ÚuidZpwZhome_dirr6r6r9r+scCstj|ƒ}|rdSdSdS)NTF)Úname_at_domain_rerg)Zaddressrcr6r6r9r!5s cCs tddƒ}tjtj|||ƒdS)NZ helper_appsÚweb_browser_launcher)r5r¤ÚspawnlÚP_NOWAIT)ZurlrÈr6r6r9r"=s cCs6t|ddƒ}|r"|d}|d}n t}t|ƒ}||fS)NÚargsrrU)ÚgetattrZERR_SOCKET_ERRORZ get_strerror)ÚerËÚerrnoÚstrerrorr6r6r9r%Bs  c /Cs€d}tjj|ƒsfyt|dƒ}|jƒWn>tk rd}z"d}tjtjd||jfƒWYdd}~XnXytj ||ƒWn@t k r¶}z$d}tjtjd|||jfƒWYdd}~XnXybt |t ƒrÊ|}nt j|ƒd}|dkrä|}t |t ƒrô|}nddl} | j|ƒd}tj|||ƒWn`t k �rz}zBd}ddl} tjtjd|t j|ƒd| j|ƒd|jfƒWYdd}~XnX|S) NTÚwFzcannot create file %s [%s]zcannot chmod %s to %o [%s]rVrzcannot chown %s to %s:%s [%s])r¤r¥r§r¶r¸Ú ExceptionrKr¡rÏÚchmodÚOSErrorr;rWrÂÚgetpwnamÚgrpZgetgrnamÚchownrÃZgetgrgid) Úfilepathr°Úownerrhr½r¼rÍrÆÚgidrÕr6r6r9r&Ms:   *,  BcCs<ddl}|j|jƒƒdd}|jj}td|||fƒ‚dS)NrrUr@z=%s must be implemented in subclass %s or ancestor class of %s)ÚinspectZgetouterframesZ currentframeÚ __class__Ú__name__ÚNotImplementedError)r>rÚÚmethodÚsubclassr6r6r9r#ws cCsˆ|dkrd}ntjdd|ƒ}tddƒ}g}xXtjtjj||dƒƒD]<}tjj|ƒ}|d kr^qDtjjtjj|ƒƒd}|j |ƒqDW|S) Nr1z.py$r“ÚpluginsÚ plugin_dirz.pyú __init__.pyr)râ) Úrer—r5Úglobr¤r¥r‚ÚbasenameÚsplitextÚappend)Ú filter_globráÚ plugin_namesÚpÚ plugin_namer6r6r9r�s  cCs|jƒ|jƒS)N)Z get_priority)r7r8r6r6r9Ú sort_plugins’srìc Csvtddƒ}tjj|ƒ}g}t|ƒ}td|ƒ|}d}|tjkr¤y0ddl}|j ||gƒ\}} } |j ||| | ƒ} Wn&t k r–t j t j d|ƒgSX|r¤|jƒx¼|D]´}d||f}tjj|ƒ} | dk rêtd|ƒ|j| jƒƒqªy>ddl}|j ||gƒ\}} } |j ||| | ƒ} |j| jƒƒWn(t k �rPt j t j d |ƒYnX|rª|jƒqªW|jttƒd �|S) Nràrázload_plugins() names=%sÚ__init__rz"failed to initialize plugins in %sz%s.%sz%load_plugins() %s previously importedzfailed to load %s plugin)r})r5r¤r¥rårr$riÚmodulesÚimpÚ find_moduleÚ load_modulerÑrKr¡r¸rHrçZpluginr„r2rì) rèráZ plugin_baseràréZ module_namerërïZmod_fpZmod_pathZmod_descriptionÚmodr6r6r9r–sF         cCs~yttƒjƒdjƒ}Wn8yddl}dj|jƒƒ}Wnd}YnXYnXtjƒ}|d}|d}d||f}||fS)NrrzÚunknownrVr’z%s %s) r¶Úredhat_release_pathÚ readlinesr”Údistror‚Zlinux_distributionr¤Úuname)Z myplatformrör÷Zkernel_releaseZcpuZos_descr6r6r9rÂs c Cs@|dkrtjƒ}ytj|ƒ}Wntk r2dSX|d}|S)Nr)r¤rÁrÂrÃrÄ)rÆZ pwd_entryZusernamer6r6r9rÕscCsLyddl}|jƒ}|Stk rF}ztjtjd|ƒdSd}~XnXdS)Nrzcannot lookup hostname: %s)ZsocketZ gethostnamerÑrKr¡)ZSocketZhostnamerÍr6r6r9ráscCs\tjj|ƒr|Stjj|ƒ}tddƒjdƒ}x*|D]"}tjj||ƒ}tjj|ƒr2|Sq2WdS)NZ fix_commandZprog_search_pathú:)r¤r¥Úisabsrår5rQr‚r§)ÚprogråZ search_pathrrr¥r6r6r9rës    cCs2tddƒ}tjdd|ƒ}|d}tjj||ƒ}|S)NZdatabaseÚ database_dirz\.xml$r“z _database.xml)r5rãr—r¤r¥r‚)r�rûÚfilenamer×r6r6r9r ÷s  c Cs$tjdƒ}d}d}d}d}d}|jƒ}x¶|j|ƒD]¨}|r2d}t|jdƒƒ}|jdƒ} | dk r2| dkrr||d 7}| d kr†||d 7}| d krš||d 7}| dkrª||7}| dkrº||7}| dkrÊ||7}| dkr2||7}q2W|�r tj||||d�} td|| fƒ| St j t j d|ƒdSdS)zìThe time offset may be specified as a sequence of integer unit pairs. Units may be one of year,month,week,day,hour,minute,second and may optionally be plural. Example: '2 weeks 1 day' sets the threshold at 15 days. z0(\d+)\s*(year|month|week|day|hour|minute|second)FrTrUrVNÚyearimÚmonthéZweekéÚdayÚhourÚminuteÚsecond)r^r_r`raz)parse_datetime_offset(%s) = time delta %sz$could not parse datetime offset (%s)) rãÚcompileÚlowerÚfinditerrWrhÚdatetimeÚ timedeltar$rKr¡) ÚtextZdatetime_offset_reÚfoundr^r_r`rarcZquantityZunitZtdr6r6r9r'sB      )rarU)r_c@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) Ú LocalTimezonecCs|j|ƒrtStSdS)N)Ú_isdstÚ DSTOFFSETÚ STDOFFSET)ÚselfÚdtr6r6r9Ú utcoffset=s zLocalTimezone.utcoffsetcCs|j|ƒrtStSdS)N)r ÚDSTDIFFÚZERO)rrr6r6r9ÚdstCs zLocalTimezone.dstcCstj|j|ƒS)N)ÚtimeÚtznamer )rrr6r6r9rIszLocalTimezone.tznamec CsD|j|j|j|j|j|j|jƒddf }tj|ƒ}tj |ƒ}|j dkS)NrrUrª) rýrþrrrrÚweekdayrZmktimeZ localtimeZtm_isdst)rrZttZstampr6r6r9r Ls     zLocalTimezone._isdstN)rÜÚ __module__Ú __qualname__rrrr r6r6r6r9r ;sr c@s(eZdZdZdd„Zdd„Zdd„ZdS)ÚUTCcCs tjdƒS)Nr)rr )rrr6r6r9rXsz UTC.utcoffsetcCsdS)Nrr6)rrr6r6r9r[sz UTC.tznamecCs tjdƒS)Nr)rr )rrr6r6r9r^szUTC.dstN)rÜrrÚ__doc__rrrr6r6r6r9rUsrc@s˜eZdZeƒZeƒZdZdZd#dd„Z dd„Z dd „Z d d „Z d d „Z dd„Zd$dd„Zdd„Zdd„Zdd„Zd%dd„Zdd„Zdd„Zd&d!d"„ZdS)'r,z%Y-%m-%dT%H:%M:%SZz%cNcCs‚|dkr|jdd�|_nft|tjƒr0|j|ƒnNt|tƒrNtjj||j ƒ|_n0t|tjƒrb||_nt|t ƒrv|j|_nt dƒ‚dS)NF)Úlocalz-must be string, float, datetime, or TimeStamp) ÚnowÚ_dtr;rr€ÚparseÚfloatrZ fromtimestampÚutc_tzr,Ú TypeError)rÚtr6r6r9ríjs      zTimeStamp.__init__cCs$t|tƒr|j|jkS|j|kSdS)N)r;r,r)rÚotherr6r6r9Ú__lt__xs  zTimeStamp.__lt__cCs$t|tƒr|j|jS|j|SdS)N)r;r,r)rr%r6r6r9Ú__add__~s  zTimeStamp.__add__cCs.t|tƒr|j|j7_n|j|7_|S)N)r;r,r)rr%r6r6r9Ú__iadd__„s zTimeStamp.__iadd__cCs$t|tƒr|j|jS|j|SdS)N)r;r,r)rr%r6r6r9Ú__sub__‹s  zTimeStamp.__sub__cCs.t|tƒr|j|j8_n|j|8_|S)N)r;r,r)rr%r6r6r9Ú__isub__‘s zTimeStamp.__isub__FcCs$|rtjj|jƒStjj|jƒSdS)N)rrÚlocal_tzr")rrr6r6r9r˜sz TimeStamp.nowcCs|jj|jƒS)N)rZ astimezoner+)rr6r6r9ržszTimeStamp.localcCs|j|jdd�S)NF)r)rœÚ iso8601_fmt)rr6r6r9Ú__str__¡szTimeStamp.__str__c CsBtj||jƒ\ }}}}}}}} } tj||||||d|jƒ|_|jS)Nr)rZstrptimer,rr"r) rrdrýrþrrrrrZyeardayrr6r6r9r ¤s  zTimeStamp.parsercCs |jtj||||d�7_dS)N)r^r_r`ra)rrr )rr^r_r`rar6r6r9Úadd«sz TimeStamp.addcCs|jƒ}||jkrdSdSdS)NTF)rr)rrr6r6r9Ú in_future¯s zTimeStamp.in_futurecCs|jƒ}||jkrdSdSdS)NTF)rr)rrr6r6r9Úin_past¶s zTimeStamp.in_pastTcCs0|dkr|j}|r |jƒj|ƒS|jj|ƒSdS)N)Ú locale_fmtrZstrftimer)rZfmtrr6r6r9rœ½s zTimeStamp.format)N)F)rrrr)NT)rÜrrrr"r r+r,r1rír&r'r(r)r*rrr-r r.r/r0rœr6r6r6r9r,bs$   c@sheZdZdZdejjdejejffiZ ddd„Z dd„Z ddd „Z dd d „Z d d„Zdd„Zdd„ZdS)r-al A class which schedules attempts until one succeeds. Intervals are expressed as floating point seconds. The retry attempt will be scheduled in the future based on the retry_interval which may be either a number of seconds or a callable object returning the number of seconds. The callable form of the retry_interval is useful when the interval should be adjusted based on prior history or other external factors, e.g. backing off the frequency of the retry attempts if initial attempts fail. The retry callback should return False if the attempt fails, in which case it will be scheduled again in the future based on the current value obtained from the retry_interval. If the retry callback returns True it indicates the retry attempt succeeded and no more attempts will be made. Retry's are started with the start() method and continues until the retry callback returns True or the stop() method is called. It is always safe to call stop() even if a retry is not pending. The retry callback, user_data and notify_interval may be specified in either the class init() or in the start() method for convenience. If notify_interval is set a 'pending_retry' signal will be emitted every time the notification interval elapses, this provides a countdown till the next retry attempt. The signature of the retry callback is: callback(retry_obj, user_data) The signature of the pending_retry signal handler is: callback(retry_obj, seconds_pending, user_data) The signature of the retry interval function is: interval(retry_obj, user_data) Ú pending_retryNcCs:tjj|ƒ||_||_||_d|_||_d|_d|_dS)Nr) r0ríÚcallbackÚretry_intervalÚ user_dataÚfailed_attemptsÚnotify_intervalÚ trigger_timeÚ timeout_id)rr3r4r5r7r6r6r9ríòs zRetry.__init__cCs |jdk rtj|jƒd|_dS)N)r9ZGLibZ source_remove)rr6r6r9Ústopüs  z Retry.stopcCsF|dk r||_|dk r||_|dk r*||_|jƒd|_|jdƒdS)NrT)r4r5r7r:r6Ú_schedule_alarm)rr4r5r7r6r6r9Ústartsz Retry.startFcCshtjƒ}|r||jƒ|_|j|}|jrH|jd||jƒt|j|ƒ}n|}tjt |dƒ|j ƒ|_ dS)Nr2iè) rÚ_get_retry_intervalr8r7Úemitr5Úminr0Z timeout_addrWÚ_alarm_callbackr9)rZ new_retryrÚseconds_pendingZ alarm_timer6r6r9r; s zRetry._schedule_alarmcCs6d|_tjƒ}|j|}|dkr*|jƒn|jƒdS)Ng{®Gázt?F)r9rr8Ú_attempt_retryr;)rrrAr6r6r9r@s  zRetry._alarm_callbackcCs4|j||jƒr|jƒn|jd7_|jdƒdS)NrUT)r3r5r:r6r;)rr6r6r9rB-s zRetry._attempt_retrycCs"ttttfƒr|j||jƒS|jS)N)r;Z interval_typer4r3r4r5)rr6r6r9r=4szRetry._get_retry_interval)NN)NNN)F)rÜrrrr0Z SignalFlagsZRUN_LASTZ TYPE_FLOATZ TYPE_PYOBJECTZ __gsignals__rír:r<r;r@rBr=r6r6r6r9r-Ès$  )NN)r…r†)r†r)r’)F)N)N)N)N)rZ __future__rZ six.movesrÚ__all__rµrrZpydbusr/räZ gi.repositoryr0r¤rÂrãZshutilr±ržriÚtextwraprÚtypesrKÚ functoolsr2r3r4Zsetroubleshoot.configr5Zsetroubleshoot.errcodeZcmpr?r(r)r.ZwhichrôZ TextWrapperrˆrr–rbZhref_rerÇrfr·r¬rLrJZLOG_CRITr¡ZLOG_INFOrNrGrMr$r+r*rrrrrrr r r r r rrrrrZsepolicyr¨rrrr®r­rrrr!r"r%r&r#rrìrrrrrr r'r ZtimezonerZdaylightZaltzonerrrZHOURZtzinfor rr,r-Z type_registerr6r6r6r9Ús&                       0   *  ,    /   fq__pycache__/util.cpython-36.pyc000064400000063353152572267760012414 0ustar003 ¹QfË}ã+@süddlmZddlmZddddddd d d d d ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-g+Zdd.lZdd.lZdd.lZdd/lm Z dd.l Z dd0l m Z dd.l Z dd.lZdd.lZdd.lZdd.lZdd.lZdd.lZdd.lZdd.lZdd1lTdd.lZdd2lmZdd3lmZmZdd4lmZdd1lTd5d6„Zd7d8„Z d9Z!dZ"d.Z#ej$d:ƒ�r`d:Z#nej$d;ƒ�rpdƒZ)ej(d?ƒZ*ej(d@ƒZ+ej(dAƒZ,ej(dBƒZ-ej(dCƒZ.d.a/ej0a1ej2ej3ej0ej4ej5dDœZ6dEdF„Z7dGd#„Z8dHd*„Z9dId)„Z:dJd„Z;dKd„Zd€dNd„Z?dOd„Z@d�dRd„ZAd‚dSd „ZBdƒdUd „ZCdVd „ZDdWd „ZEdXd „ZFdYd„ZGdZd„ZHd[d„ZId\d„ZJydd]lKmLZLeLƒZMWngZMYnXd^d„ZNd_d„ZOd`da„ZPdbdc„ZQd„ded„ZRdfd„ZSdgd„ZTdhd „ZUdid!„ZVdjd$„ZWd…dkd%„ZXdld"„ZYd†dmd„ZZdndo„Z[d‡dpd„Z\dqd„Z]dˆdrd„Z^dsd„Z_dtd„Z`dud„Zadvd&„Zbejcejd dw�Zeejf�rˆejcejg dw�ZhneeZheheeZiejcdƒZjejcdxdy�ZkGdzd{„d{ejlƒZmGd|d}„d}ejlƒZnGd~d+„d+ƒZoGdd,„d,e j ƒZpe jqepƒd.S)‰é)Úabsolute_import)ÚrangeÚaudit_msg_decodeÚ merge_listsÚpreextend_listÚfmt_objÚformat_elapsed_timeÚformat_2_column_name_valueÚ wrap_textÚ format_msgÚremove_linebreaksÚ default_textÚdefault_date_textÚget_standard_directoriesÚget_rpm_nvr_from_headerÚget_package_nvr_by_nameÚget_package_nvr_by_file_pathÚget_rpm_nvr_by_typeÚget_rpm_nvr_by_scontextÚget_rpm_source_packageÚis_hexÚ split_rpm_nvrÚ file_typesÚget_user_home_dirÚget_plugin_namesÚ load_pluginsÚget_os_environmentÚ find_programÚ get_identityÚ get_hostnameÚmake_database_filepathÚvalid_email_addressÚlaunch_web_browser_on_urlÚabstractÚ log_debugÚget_error_from_socket_exceptionÚ!assure_file_ownership_permissionsÚparse_datetime_offsetÚDATABASE_MAJOR_VERSIONÚDATABASE_MINOR_VERSIONÚdatabase_version_compatibleÚ syslog_traceÚ TimeStampÚRetryÚPACKAGE_MANAGERN)Ú SystemBus)ÚGObject)Ú*)Ú cmp_to_key)Ú FunctionTypeÚ MethodType)Ú get_configcCs||k||kS)N©)ÚxÚyr6r6ú/usr/lib/python3.6/util.pyÚ\sr:c Cs*y t|tƒStk r$t|tƒSXdS)N)Ú isinstanceZTypeTypeÚ NameErrorÚtype)Úobjr6r6r9Úis_type_s r?éÚrpmÚdpkgÚdebz/etc/redhat-releasez \s*\n+\s*z^[A-Fa-f0-9]+$zz^([^\s@]+)@([^\s@]+)$z^\s*"([^"]+)"\s*$z\s*\(\s*type\s+([\w-]+)\s*\)\s*)ZCRITICALZERRORZWARNINGÚINFOÚDEBUGcCs&tjt|dƒjƒƒatdkr"tjadS)NÚlevel)Ú log_levelsÚgetr5ÚupperÚ log_levelÚsyslogÚ LOG_WARNING)Zsectionr6r6r9Úlog_init‡srMcCsttjkrtjtj|ƒdS)N)rJrKÚ LOG_DEBUG)Úmsgr6r6r9r$Žs cCs.|jdƒ}x|D]}t|ƒrtj|ƒqWdS)NÚ )ÚsplitÚlenrK)ZtraceZ log_linesÚliner6r6r9r+”s  cCszd}}|jdƒ}t|ƒdkr*t|dƒ}t|ƒdkrBt|dƒ}|tkr`td|ttfƒdStd|ttfƒdSdS) NÚ.éréz=database version %s not compatible with current %d.%d versionFz9database version %s compatible with current %d.%d versionT)rQrRÚintr(r$r))ÚversionÚmajorÚminorÚ componentsr6r6r9r*›s     cCs´|dkr dSddl}|j|ƒ\}}t|ƒ}|d}||d}|d}||d}|d}||d}|r~d|||||fS|r”d||||fS|r¨d|||fSd||S) Nri€Qié<z%dd:%dh:%dm:%.3fsz %dh:%dm:%.3fsz %dm:%.3fsz%.3fs)ÚmathZmodfrW)Z elapsed_timer]ZfractionZwholeÚdaysÚhoursÚminutesÚsecondsr6r6r9r«s$   cCstj|ƒrdSdSdS)NTF)Úhex_reÚmatch)Ústrr6r6r9rÅs c Csj|dkr dStj|ƒ}|r&|jdƒ}n@y.tjddkrB|jdƒ}ntj|ƒjdƒ}Wn|}YnX|S)NrUrr@Úhexzutf-8)Úaudit_decode_reÚsearchÚgroupÚsysÚ version_infoÚdecodeÚ bytearrayÚfromhex)rOrcZdecodedr6r6r9rÌs    cCsP|s|S|s|Si}x|D] }d||<qWx|D] }d||<q0Wt|jƒƒ}|S)z2return a list containing the unique members of a+bN)ÚlistÚkeys)ÚaÚbÚdÚiÚmr6r6r9rãs     cs^|dkr g}t|ƒ}||}|dkrZtˆƒrJ|j‡fdd„t|ƒDƒƒn|jˆg|ƒ|S)Nrcsg|] }ˆƒ‘qSr6r6)Ú.0r7)Údefaultr6r9ú ùsz"preextend_list..)rRr?Úextendr)Zrequested_lengthZ_listrvZ cur_lengthZdeltar6)rvr9ròscs„tˆtjƒrˆStˆttfƒr:ddjdd„ˆDƒƒdStˆtƒrxtˆjƒƒ}|jƒddj‡fdd„|DƒƒdSt ˆƒSdS) Nú[ú cSsg|]}dt|ƒ‘qS)z%s)r)rur7r6r6r9rwszfmt_obj..ú]ú{cs$g|]}dt|ƒtˆ|ƒf‘qS)z%s=%s)r)ruÚkey)r>r6r9rwsú}) r;ÚsixÚ string_typesrnÚtupleÚjoinÚdictroÚsortrd)r>ror6)r>r9rÿs    ééPcCsxt|ƒ|kr"|d|d…d}n|d|t|ƒ}| sD|jƒrP||dS|t_d|t_|t_tj|ƒdSdS)NrrUrzrP)rRÚisspaceÚ text_wrapperÚinitial_indentÚsubsequent_indentÚwidthÚfill)ÚnameÚvalueZ value_indentZ page_widthr‰r6r6r9r s   cCs(d|}|t_|t_|t_tj|ƒdS)NrzrP)rˆr‰rŠr‹rŒ)Úsr‹ÚindentÚprefixr6r6r9r s écCsD|dkr d}|jƒ}d|}|t_|t_dt_|dtj|ƒdS)NÚrzr†rPz )Ústriprˆr‰rŠr‹rŒ)ÚtitlerOr�Z indentStringr6r6r9r #scCs$tjd|ƒjƒ}|dkrdS|SdS)Nrzr“)Úfix_newline_reÚsubr”)rdZnew_strr6r6r9r .scCs |dkrdtdƒd}t|ƒS)Nú)Ú_rd)Úvalr6r6r9r 6scCs|dkrt|ƒS|jƒS)N)r Úformat)Zdater6r6r9r<sc Cszg}yPtdkr,tjdddgdd�jƒjdƒ}tdkrRtjdd d gdd�jƒjdƒ}Wn tjtjd jtƒƒYnX|S) z3 >>> get_standard_directories() [...'/bin'...] rAz-qlZ filesystemT)Úuniversal_newlinesrPrCrBz-Lz base-fileszfailed to get list from {})r.Ú subprocessÚ check_outputÚrstriprQrKÚLOG_ERRrœ)Zlstr6r6r9rBs"cCs&|d}|d}|d}d|||fS)z6Given an RPM header return the package NVR as a stringr�rXÚreleasez%s-%s-%sr6)Zhdrr�rXr¢r6r6r9rTsc Csz|dkr dSd}yFtdkr2tjdd|gdd�jƒ}tdkrTtjddd |gdd�jƒ}Wntjtjd |ƒYnX|S) zJ >>> get_package_nvr_by_name("coreutils") 'coreutils-8.30-3+b1:amd64' NrAz-qT)r�rCz dpkg-queryz(-f=${Package}-${Version}:${Architecture}z-Wz"failed to retrieve rpm info for %s)r.ržrŸr rKr¡)r�Únvrr6r6r9r\sc Cs´|dkr dStjj|ƒ}tjj|ƒs(dSd}ydtdkrNtjdd|gdd�jƒ}tdkrŽtjdd|gƒjƒj d ƒd }tjd d d |gdd�jƒ}Wnt j t j d|ƒYnX|S)zM >>> get_package_nvr_by_file_path("/bin/ls") 'coreutils-8.30-3+b1:amd64' NrAz-qfT)r�rCrBz-Sz: rz dpkg-queryz(-f=${Package}-${Version}:${Architecture}z-Wz"failed to retrieve rpm info for %s) ÚosÚpathÚabspathÚexistsr.ržrŸr rkrQrKr¡)r�r£Z package_namer6r6r9rrs   )Úget_all_file_typescCs6|jdƒ}|d}|d}dj|dd…ƒ}|||fS)Nú-rUrVéÿÿÿÿéþÿÿÿr«)rQr‚)r£r[r¢rXr�r6r6r9r–s  cCs.tdkrtƒtdkrdStj|dƒ}t|ƒS)aV Finds an SELinux module which defines given SELinux type ##### arguments * `selinux_type(s)`: an SELinux type ##### return values * `nvr(s)`: nvr of rpm which ships module where `selinux_type` is defined ##### usage >>> get_rpm_nvr_by_type("sshd_t") 'selinux-policy-... >>> get_rpm_nvr_by_type("mysqld_log_t") 'mysql-selinux-... N)Úmodule_type_cacheÚbuild_module_type_cacherHr)Z selinux_typer¥r6r6r9r�s  c Csy t|ƒdSdSdS)NTF)rW)rdr6r6r9Ú __str_is_int½s r®c Cstjƒ\}}|dkrdStƒ}g}tjdj|ƒƒ� }tdd„|Dƒdd„d�}WdQRXx®|D]¦}x tjd j||ƒƒD]Š\}}}d |krvyjytj d j|ƒd d �} Wnt d j|ƒƒ} YnXx(| D] } t j | ƒ} | rÄ||| j dƒ<qÄW| j ƒWqvYqvXqvWq^W|adS)zË Creates a dictionary with all types defined in the module store as keys and corresponding module paths as values. The dictionary is stored in "module_type_cache" to be used by "get_rpm_nvr_by_type" rNz"/var/lib/selinux/{}/active/modulescSs$g|]}|jƒrt|jƒr|j‘qSr6)Úis_dirr®r�)rur7r6r6r9rwÖsz+build_module_type_cache..cSst|ƒS)N)rW)r7r6r6r9r:Ösz)build_module_type_cache..)r}z%/var/lib/selinux/{}/active/modules/{}Zcilz{}/cilZrt)ÚmoderU)ÚselinuxZselinux_getpolicytyperƒr¤ÚscandirrœÚsortedÚwalkÚbz2ÚopenÚtypedef_regexprcrhÚcloser¬) ZretvalZ policytypeZmodule_type_dictZ prioritiesZ module_storeÚdirÚdirpathZdirnamesÚ filenamesÚfrSÚresultr6r6r9r­Äs. $    r­FcCsJ|r&tƒ}|jdƒ}t|jt|ƒƒƒStjt|ƒƒ}tttj|ƒƒƒSdS)a Finds an SELinux module which defines given SELinux context ##### arguments * `scontext(s)`: an SELinux context ##### return values * `nvr(s)`: nvr of rpm which ships module where SELinux type used in `scontext` is defined ##### usage >>> get_rpm_nvr_by_scontext("system_u:system_r:syslogd_t:s0") 'selinux-policy-... >>> get_rpm_nvr_by_scontext("system_u:system_r:mysqld_log_t:s0") 'mysql-selinux-... >>> get_rpm_nvr_by_scontext("system_u:system_r:timedatex_t:s0", use_dbus=True) 'selinux-policy-... z*org.fedoraproject.SetroubleshootPrivilegedN)r/rHrdrr±Z context_newrZcontext_type_get)ZscontextZuse_dbusZbusZ remote_objectÚcontextr6r6r9rôs  c Csd|dkr dSd}y0ddl}|jdddd|gdd�jd d ƒd}Wntjtjd |ƒYnX|S) zÙ Find a source package for `name` rpm >>> get_rpm_source_package("policycoreutils-python-utils") 'policycoreutils' >>> get_rpm_source_package("selinux-policy-targeted") 'selinux-policy' NrrAz-qz--qfz %{SOURCERPM}T)r�r©rVz"failed to retrieve rpm info for %s)ržrŸÚrsplitrKr¡)r�Úsrcržr6r6r9rs (c Cs6tjƒ}ytj|ƒ}Wntk r*dSX|j}|S)N)r¤ÚgetuidÚpwdÚgetpwuidÚKeyErrorÚpw_dir)ÚuidZpwZhome_dirr6r6r9r+scCstj|ƒ}|rdSdSdS)NTF)Úname_at_domain_rerg)Zaddressrcr6r6r9r!5s cCs tddƒ}tjtj|||ƒdS)NZ helper_appsÚweb_browser_launcher)r5r¤ÚspawnlÚP_NOWAIT)ZurlrÈr6r6r9r"=s cCs6t|ddƒ}|r"|d}|d}n t}t|ƒ}||fS)NÚargsrrU)ÚgetattrZERR_SOCKET_ERRORZ get_strerror)ÚerËÚerrnoÚstrerrorr6r6r9r%Bs  c /Cs€d}tjj|ƒsfyt|dƒ}|jƒWn>tk rd}z"d}tjtjd||jfƒWYdd}~XnXytj ||ƒWn@t k r¶}z$d}tjtjd|||jfƒWYdd}~XnXybt |t ƒrÊ|}nt j|ƒd}|dkrä|}t |t ƒrô|}nddl} | j|ƒd}tj|||ƒWn`t k �rz}zBd}ddl} tjtjd|t j|ƒd| j|ƒd|jfƒWYdd}~XnX|S) NTÚwFzcannot create file %s [%s]zcannot chmod %s to %o [%s]rVrzcannot chown %s to %s:%s [%s])r¤r¥r§r¶r¸Ú ExceptionrKr¡rÏÚchmodÚOSErrorr;rWrÂÚgetpwnamÚgrpZgetgrnamÚchownrÃZgetgrgid) Úfilepathr°Úownerrhr½r¼rÍrÆÚgidrÕr6r6r9r&Ms:   *,  BcCs<ddl}|j|jƒƒdd}|jj}td|||fƒ‚dS)NrrUr@z=%s must be implemented in subclass %s or ancestor class of %s)ÚinspectZgetouterframesZ currentframeÚ __class__Ú__name__ÚNotImplementedError)r>rÚÚmethodÚsubclassr6r6r9r#ws cCsˆ|dkrd}ntjdd|ƒ}tddƒ}g}xXtjtjj||dƒƒD]<}tjj|ƒ}|d kr^qDtjjtjj|ƒƒd}|j |ƒqDW|S) Nr1z.py$r“ÚpluginsÚ plugin_dirz.pyú __init__.pyr)râ) Úrer—r5Úglobr¤r¥r‚ÚbasenameÚsplitextÚappend)Ú filter_globráÚ plugin_namesÚpÚ plugin_namer6r6r9r�s  cCs|jƒ|jƒS)N)Z get_priority)r7r8r6r6r9Ú sort_plugins’srìc Csvtddƒ}tjj|ƒ}g}t|ƒ}td|ƒ|}d}|tjkr¤y0ddl}|j ||gƒ\}} } |j ||| | ƒ} Wn&t k r–t j t j d|ƒgSX|r¤|jƒx¼|D]´}d||f}tjj|ƒ} | dk rêtd|ƒ|j| jƒƒqªy>ddl}|j ||gƒ\}} } |j ||| | ƒ} |j| jƒƒWn(t k �rPt j t j d |ƒYnX|rª|jƒqªW|jttƒd �|S) Nràrázload_plugins() names=%sÚ__init__rz"failed to initialize plugins in %sz%s.%sz%load_plugins() %s previously importedzfailed to load %s plugin)r})r5r¤r¥rårr$riÚmodulesÚimpÚ find_moduleÚ load_modulerÑrKr¡r¸rHrçZpluginr„r2rì) rèráZ plugin_baseràréZ module_namerërïZmod_fpZmod_pathZmod_descriptionÚmodr6r6r9r–sF         cCs~yttƒjƒdjƒ}Wn8yddl}dj|jƒƒ}Wnd}YnXYnXtjƒ}|d}|d}d||f}||fS)NrrzÚunknownrVr’z%s %s) r¶Úredhat_release_pathÚ readlinesr”Údistror‚Zlinux_distributionr¤Úuname)Z myplatformrör÷Zkernel_releaseZcpuZos_descr6r6r9rÂs c Cs@|dkrtjƒ}ytj|ƒ}Wntk r2dSX|d}|S)Nr)r¤rÁrÂrÃrÄ)rÆZ pwd_entryZusernamer6r6r9rÕscCsLyddl}|jƒ}|Stk rF}ztjtjd|ƒdSd}~XnXdS)Nrzcannot lookup hostname: %s)ZsocketZ gethostnamerÑrKr¡)ZSocketZhostnamerÍr6r6r9ráscCs\tjj|ƒr|Stjj|ƒ}tddƒjdƒ}x*|D]"}tjj||ƒ}tjj|ƒr2|Sq2WdS)NZ fix_commandZprog_search_pathú:)r¤r¥Úisabsrår5rQr‚r§)ÚprogråZ search_pathrrr¥r6r6r9rës    cCs2tddƒ}tjdd|ƒ}|d}tjj||ƒ}|S)NZdatabaseÚ database_dirz\.xml$r“z _database.xml)r5rãr—r¤r¥r‚)r�rûÚfilenamer×r6r6r9r ÷s  c Cs$tjdƒ}d}d}d}d}d}|jƒ}x¶|j|ƒD]¨}|r2d}t|jdƒƒ}|jdƒ} | dk r2| dkrr||d 7}| d kr†||d 7}| d krš||d 7}| dkrª||7}| dkrº||7}| dkrÊ||7}| dkr2||7}q2W|�r tj||||d�} td|| fƒ| St j t j d|ƒdSdS)zìThe time offset may be specified as a sequence of integer unit pairs. Units may be one of year,month,week,day,hour,minute,second and may optionally be plural. Example: '2 weeks 1 day' sets the threshold at 15 days. z0(\d+)\s*(year|month|week|day|hour|minute|second)FrTrUrVNÚyearimÚmonthéZweekéÚdayÚhourÚminuteÚsecond)r^r_r`raz)parse_datetime_offset(%s) = time delta %sz$could not parse datetime offset (%s)) rãÚcompileÚlowerÚfinditerrWrhÚdatetimeÚ timedeltar$rKr¡) ÚtextZdatetime_offset_reÚfoundr^r_r`rarcZquantityZunitZtdr6r6r9r'sB      )rarU)r_c@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) Ú LocalTimezonecCs|j|ƒrtStSdS)N)Ú_isdstÚ DSTOFFSETÚ STDOFFSET)ÚselfÚdtr6r6r9Ú utcoffset=s zLocalTimezone.utcoffsetcCs|j|ƒrtStSdS)N)r ÚDSTDIFFÚZERO)rrr6r6r9ÚdstCs zLocalTimezone.dstcCstj|j|ƒS)N)ÚtimeÚtznamer )rrr6r6r9rIszLocalTimezone.tznamec CsD|j|j|j|j|j|j|jƒddf }tj|ƒ}tj |ƒ}|j dkS)NrrUrª) rýrþrrrrÚweekdayrZmktimeZ localtimeZtm_isdst)rrZttZstampr6r6r9r Ls     zLocalTimezone._isdstN)rÜÚ __module__Ú __qualname__rrrr r6r6r6r9r ;sr c@s(eZdZdZdd„Zdd„Zdd„ZdS)ÚUTCcCs tjdƒS)Nr)rr )rrr6r6r9rXsz UTC.utcoffsetcCsdS)Nrr6)rrr6r6r9r[sz UTC.tznamecCs tjdƒS)Nr)rr )rrr6r6r9r^szUTC.dstN)rÜrrÚ__doc__rrrr6r6r6r9rUsrc@s˜eZdZeƒZeƒZdZdZd#dd„Z dd„Z dd „Z d d „Z d d „Z dd„Zd$dd„Zdd„Zdd„Zdd„Zd%dd„Zdd„Zdd„Zd&d!d"„ZdS)'r,z%Y-%m-%dT%H:%M:%SZz%cNcCs‚|dkr|jdd�|_nft|tjƒr0|j|ƒnNt|tƒrNtjj||j ƒ|_n0t|tjƒrb||_nt|t ƒrv|j|_nt dƒ‚dS)NF)Úlocalz-must be string, float, datetime, or TimeStamp) ÚnowÚ_dtr;rr€ÚparseÚfloatrZ fromtimestampÚutc_tzr,Ú TypeError)rÚtr6r6r9ríjs      zTimeStamp.__init__cCs$t|tƒr|j|jkS|j|kSdS)N)r;r,r)rÚotherr6r6r9Ú__lt__xs  zTimeStamp.__lt__cCs$t|tƒr|j|jS|j|SdS)N)r;r,r)rr%r6r6r9Ú__add__~s  zTimeStamp.__add__cCs.t|tƒr|j|j7_n|j|7_|S)N)r;r,r)rr%r6r6r9Ú__iadd__„s zTimeStamp.__iadd__cCs$t|tƒr|j|jS|j|SdS)N)r;r,r)rr%r6r6r9Ú__sub__‹s  zTimeStamp.__sub__cCs.t|tƒr|j|j8_n|j|8_|S)N)r;r,r)rr%r6r6r9Ú__isub__‘s zTimeStamp.__isub__FcCs$|rtjj|jƒStjj|jƒSdS)N)rrÚlocal_tzr")rrr6r6r9r˜sz TimeStamp.nowcCs|jj|jƒS)N)rZ astimezoner+)rr6r6r9ržszTimeStamp.localcCs|j|jdd�S)NF)r)rœÚ iso8601_fmt)rr6r6r9Ú__str__¡szTimeStamp.__str__c CsBtj||jƒ\ }}}}}}}} } tj||||||d|jƒ|_|jS)Nr)rZstrptimer,rr"r) rrdrýrþrrrrrZyeardayrr6r6r9r ¤s  zTimeStamp.parsercCs |jtj||||d�7_dS)N)r^r_r`ra)rrr )rr^r_r`rar6r6r9Úadd«sz TimeStamp.addcCs|jƒ}||jkrdSdSdS)NTF)rr)rrr6r6r9Ú in_future¯s zTimeStamp.in_futurecCs|jƒ}||jkrdSdSdS)NTF)rr)rrr6r6r9Úin_past¶s zTimeStamp.in_pastTcCs0|dkr|j}|r |jƒj|ƒS|jj|ƒSdS)N)Ú locale_fmtrZstrftimer)rZfmtrr6r6r9rœ½s zTimeStamp.format)N)F)rrrr)NT)rÜrrrr"r r+r,r1rír&r'r(r)r*rrr-r r.r/r0rœr6r6r6r9r,bs$   c@sheZdZdZdejjdejejffiZ ddd„Z dd„Z ddd „Z dd d „Z d d„Zdd„Zdd„ZdS)r-al A class which schedules attempts until one succeeds. Intervals are expressed as floating point seconds. The retry attempt will be scheduled in the future based on the retry_interval which may be either a number of seconds or a callable object returning the number of seconds. The callable form of the retry_interval is useful when the interval should be adjusted based on prior history or other external factors, e.g. backing off the frequency of the retry attempts if initial attempts fail. The retry callback should return False if the attempt fails, in which case it will be scheduled again in the future based on the current value obtained from the retry_interval. If the retry callback returns True it indicates the retry attempt succeeded and no more attempts will be made. Retry's are started with the start() method and continues until the retry callback returns True or the stop() method is called. It is always safe to call stop() even if a retry is not pending. The retry callback, user_data and notify_interval may be specified in either the class init() or in the start() method for convenience. If notify_interval is set a 'pending_retry' signal will be emitted every time the notification interval elapses, this provides a countdown till the next retry attempt. The signature of the retry callback is: callback(retry_obj, user_data) The signature of the pending_retry signal handler is: callback(retry_obj, seconds_pending, user_data) The signature of the retry interval function is: interval(retry_obj, user_data) Ú pending_retryNcCs:tjj|ƒ||_||_||_d|_||_d|_d|_dS)Nr) r0ríÚcallbackÚretry_intervalÚ user_dataÚfailed_attemptsÚnotify_intervalÚ trigger_timeÚ timeout_id)rr3r4r5r7r6r6r9ríòs zRetry.__init__cCs |jdk rtj|jƒd|_dS)N)r9ZGLibZ source_remove)rr6r6r9Ústopüs  z Retry.stopcCsF|dk r||_|dk r||_|dk r*||_|jƒd|_|jdƒdS)NrT)r4r5r7r:r6Ú_schedule_alarm)rr4r5r7r6r6r9Ústartsz Retry.startFcCshtjƒ}|r||jƒ|_|j|}|jrH|jd||jƒt|j|ƒ}n|}tjt |dƒ|j ƒ|_ dS)Nr2iè) rÚ_get_retry_intervalr8r7Úemitr5Úminr0Z timeout_addrWÚ_alarm_callbackr9)rZ new_retryrÚseconds_pendingZ alarm_timer6r6r9r; s zRetry._schedule_alarmcCs6d|_tjƒ}|j|}|dkr*|jƒn|jƒdS)Ng{®Gázt?F)r9rr8Ú_attempt_retryr;)rrrAr6r6r9r@s  zRetry._alarm_callbackcCs4|j||jƒr|jƒn|jd7_|jdƒdS)NrUT)r3r5r:r6r;)rr6r6r9rB-s zRetry._attempt_retrycCs"ttttfƒr|j||jƒS|jS)N)r;Z interval_typer4r3r4r5)rr6r6r9r=4szRetry._get_retry_interval)NN)NNN)F)rÜrrrr0Z SignalFlagsZRUN_LASTZ TYPE_FLOATZ TYPE_PYOBJECTZ __gsignals__rír:r<r;r@rBr=r6r6r6r9r-Ès$  )NN)r…r†)r†r)r’)F)N)N)N)N)rZ __future__rZ six.movesrÚ__all__rµrrZpydbusr/räZ gi.repositoryr0r¤rÂrãZshutilr±ržriÚtextwraprÚtypesrKÚ functoolsr2r3r4Zsetroubleshoot.configr5Zsetroubleshoot.errcodeZcmpr?r(r)r.ZwhichrôZ TextWrapperrˆrr–rbZhref_rerÇrfr·r¬rLrJZLOG_CRITr¡ZLOG_INFOrNrGrMr$r+r*rrrrrrr r r r r rrrrrZsepolicyr¨rrrr®r­rrrr!r"r%r&r#rrìrrrrrr r'r ZtimezonerZdaylightZaltzonerrrZHOURZtzinfor rr,r-Z type_registerr6r6r6r9Ús&                       0   *  ,    /   fq__pycache__/uuid.cpython-36.opt-1.pyc000064400000040200152572267760013326 0ustar003 Úh>`Bã@sødZdZdjƒdjddƒZdjƒdZddd d g\ZZZZ d d l Z e j d,krRe Z dd„ZGdd„deƒZdd„Zdd„Zdd„Zd ZZZdd„Zdd„Zdd„Zd add„Zd-d d!„Zd"d#„Zd$d%„Zd&d'„Zed(ƒZ ed)ƒZ!ed*ƒZ"ed+ƒZ#d S).aUUUID objects (universally unique identifiers) according to RFC 4122. This module provides immutable UUID objects (class UUID) and the functions uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 UUIDs as specified in RFC 4122. If all you want is a unique ID, you should probably call uuid1() or uuid4(). Note that uuid1() may compromise privacy since it creates a UUID containing the computer's network address. uuid4() creates a random UUID. Typical usage: >>> import uuid # make a UUID based on the host ID and current time >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') # make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') # make a random UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') # make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') # make a UUID from a string of hex digits (braces and hyphens ignored) >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') # convert a UUID to a string of hex digits in standard form >>> str(x) '00010203-0405-0607-0809-0a0b0c0d0e0f' # get the raw 16 bytes of the UUID >>> x.bytes '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' # make a UUID from a 16-byte string >>> uuid.UUID(bytes=x.bytes) UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') This module works with Python 2.3 or higher.zKa-Ping Yee z$Date: 2006/08/24 19:08:53 $éú/ú-z$Revision: 1.2 $zreserved for NCS compatibilityzspecified in RFC 4122z$reserved for Microsoft compatibilityzreserved for future definitionéNécCs||k||kS)N©)ÚxÚyrrú/usr/lib/python3.6/uuid.pyÚ=sr c@s*eZdZdZd-dd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z e e ƒZ dd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd „Ze eƒZd!d"„Ze eƒZd#d$„Ze eƒZd%d&„Z e e ƒZ!d'd(„Z"e e"ƒZ#d)d*„Z$e e$ƒZ%d+d,„Z&e e&ƒZ'dS).ÚUUIDaTInstances of the UUID class represent UUIDs as specified in RFC 4122. UUID objects are immutable, hashable, and usable as dictionary keys. Converting a UUID to a string with str() yields something in the form '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts four possible forms: a similar string of hexadecimal digits, or a string of 16 raw bytes as an argument named 'bytes', or a tuple of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 48-bit values respectively) as an argument named 'fields', or a single 128-bit integer as an argument named 'int'. UUIDs have these read-only attributes: bytes the UUID as a 16-byte string fields a tuple of the six integer fields of the UUID, which are also available as six individual attributes and two derived attributes: time_low the first 32 bits of the UUID time_mid the next 16 bits of the UUID time_hi_version the next 16 bits of the UUID clock_seq_hi_variant the next 8 bits of the UUID clock_seq_low the next 8 bits of the UUID node the last 48 bits of the UUID time the 60-bit timestamp clock_seq the 14-bit sequence number hex the UUID as a 32-character hexadecimal string int the UUID as a 128-bit integer urn the UUID as a URN as specified in RFC 4122 variant the UUID variant (one of the constants RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) version the UUID version number (1 through 5, meaningful only when the variant is RFC_4122) Nc Cs¶||||gjdƒdkrtdƒ‚|dk rj|jddƒjddƒ}|jdƒjddƒ}t|ƒd kr`td ƒ‚t|d ƒ}|dk r¢t|ƒd kr†td ƒ‚td d ttt |ƒƒd ƒ}|dk �rt|ƒdkrÀtdƒ‚|\}}}} } } d|koætd&ƒknsôtdƒ‚d|k�o td'ƒkn�stdƒ‚d|k�o4td(ƒkn�sDtdƒ‚d| k�o\td)ƒkn�sltdƒ‚d| k�o„td*ƒkn�s”tdƒ‚d| k�o¬td+ƒkn�s¼tdƒ‚| tdƒ>| B} |tdƒ>|tdƒ>B|tdƒ>B| tdƒ>B| B}|dk �r6d|k�o&dtdƒ>kn�s6tdƒ‚|dk �r¨d|k�oTdkn�sdtd ƒ‚|d!tdƒ>M}|d"tdƒ>O}|d#tdƒ>M}||td$ƒ>O}||j d%<dS),ažCreate a UUID from either a string of 32 hexadecimal digits, a string of 16 bytes as the 'bytes' argument, a tuple of six integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as the 'fields' argument, or a single 128-bit integer as the 'int' argument. When a string of hex digits is given, curly braces, hyphens, and a URN prefix are all optional. For example, these expressions all yield the same UUID: UUID('{12345678-1234-5678-1234-567812345678}') UUID('12345678123456781234567812345678') UUID('urn:uuid:12345678-1234-5678-1234-567812345678') UUID(bytes='\x12\x34\x56\x78'*4) UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) UUID(int=0x12345678123456781234567812345678) Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given. The 'version' argument is optional; if given, the resulting UUID will have its variant and version number set according to RFC 4122, overriding bits in the given 'hex', 'bytes', 'fields', or 'int'. Nrz+need just one of hex, bytes, fields, or intzurn:Úzuuid:z{}ré z$badly formed hexadecimal UUID stringézbytes is not a 16-char stringz%02xézfields is not a 6-tuplerrz*field 1 out of range (need a 32-bit value)z*field 2 out of range (need a 16-bit value)z*field 3 out of range (need a 16-bit value)éz*field 4 out of range (need an 8-bit value)z*field 5 out of range (need an 8-bit value)é0z*field 6 out of range (need a 48-bit value)é`éPé@é€z*int is out of range (need a 128-bit value)ézillegal version numberiÀi€iðéLÚintliiérl) ÚcountÚ TypeErrorÚreplaceÚstripÚlenÚ ValueErrorÚlongÚtupleÚmapÚordÚ__dict__) ÚselfÚhexÚbytesÚfieldsrÚversionÚtime_lowÚtime_midÚtime_hi_versionÚclock_seq_hi_variantÚ clock_seq_lowÚnodeÚ clock_seqrrr Ú__init__jsR          4 $ z UUID.__init__cCst|tƒr|j|jkStS)N)Ú isinstancer rÚNotImplemented)r%Úotherrrr Ú__lt__°s  z UUID.__lt__cCs t|jƒS)N)Úhashr)r%rrr Ú__hash__µsz UUID.__hash__cCs|jS)N)r)r%rrr Ú__int__¸sz UUID.__int__cCs dt|ƒS)NzUUID(%r))Ústr)r%rrr Ú__repr__»sz UUID.__repr__cCs tdƒ‚dS)NzUUID objects are immutable)r)r%ÚnameÚvaluerrr Ú __setattr__¾szUUID.__setattr__cCsDd|j}d|dd…|dd…|dd…|dd…|dd…fS)Nz%032xz%s-%s-%s-%s-%sré ré)r)r%r&rrr Ú__str__Ás z UUID.__str__cCs4d}x*tdddƒD]}t|j|?d@ƒ|}qW|S)Nr rrréÿ)ÚrangeÚchrr)r%r'Zshiftrrr Ú get_bytesÆszUUID.get_bytescCs|j|j|j|j|j|jfS)N)r*r+r,r-r.r/)r%rrr Ú get_fieldsÎs zUUID.get_fieldscCs|jtdƒ?S)Nr)rr )r%rrr Ú get_time_lowÔszUUID.get_time_lowcCs|jtdƒ?d@S)Nriÿÿ)rr )r%rrr Ú get_time_midÙszUUID.get_time_midcCs|jtdƒ?d@S)Nriÿÿ)rr )r%rrr Úget_time_hi_versionÞszUUID.get_time_hi_versioncCs|jtdƒ?d@S)Né8rA)rr )r%rrr Úget_clock_seq_hi_variantãszUUID.get_clock_seq_hi_variantcCs|jtdƒ?d@S)NrrA)rr )r%rrr Úget_clock_seq_lowèszUUID.get_clock_seq_lowcCs&|jd@tdƒ>|jtdƒ>B|jBS)Niÿrr )r,r r+r*)r%rrr Úget_timeísz UUID.get_timecCs|jtdƒ@tdƒ>|jBS)Né?r)r-r r.)r%rrr Ú get_clock_seqószUUID.get_clock_seqcCs |jd@S)Nlÿÿÿ)r)r%rrr Úget_nodeùsz UUID.get_nodecCs d|jS)Nz%032x)r)r%rrr Úget_hexþsz UUID.get_hexcCs dt|ƒS)Nz urn:uuid:)r9)r%rrr Úget_urnsz UUID.get_urncCsJ|jdtdƒ>@stS|jdtdƒ>@s,tS|jdtdƒ>@sBtStSdS)Ni€ri@i )rr Ú RESERVED_NCSÚRFC_4122ÚRESERVED_MICROSOFTÚRESERVED_FUTURE)r%rrr Ú get_variantszUUID.get_variantcCs$|jtkr t|jtdƒ?d@ƒSdS)Nré)ÚvariantrSrr )r%rrr Ú get_versions zUUID.get_version)NNNNN)(Ú__name__Ú __module__Ú __qualname__Ú__doc__r1r5r7r8r:r=r@rDÚpropertyr'rEr(rFr*rGr+rHr,rJr-rKr.rLÚtimerNr0rOr/rPr&rQZurnrVrXrYr)rrrr r @sJ( E r cCs ddl}x’d D]Š}y|j|jj|dƒƒ}Wntk r@wYnXxT|D]L}|jƒjƒ}x:tt|ƒƒD]*}||d krft ||d j d dƒd ƒSqfWqHWqWdS)z5Get the hardware address on Unix by running ifconfig.rNr ú/sbin/ú /usr/sbinZifconfigÚhwaddrÚetherrú:r)r r`ra)rbrc) ÚosÚpopenÚpathÚjoinÚIOErrorÚlowerÚsplitrBrrr)reÚdÚpipeÚlineZwordsÚirrr Ú_ifconfig_getnodes    rpc Csêddl}ddl}dddg}y:ddl}|jdƒ}|jjj|dƒ|jd|jj dƒƒWn YnXx‚|D]z}y|j |j j |dƒd ƒ}Wnt k ržwhYnXx@|D]8}|jd ƒdjƒjƒ}|jd |ƒr¦t|jd dƒdƒSq¦WqhWdS)z|dtdƒ>|dtd ƒ>|d tdƒ>|d td ƒ>|d SWdS)ztGet the hardware address on Windows using NetBIOS calls. See http://support.microsoft.com/kb/118623 for details.rNÚ*ré(rr éérérr)Ú win32wnetÚnetbiosZNCBZNCBENUMZCommandZ LANA_ENUMZBufferZ_packZNetbiosZ_unpackrBZlengthZResetZNCBRESETr#ZlanaZLana_numZNCBASTATÚljustZCallnameZADAPTER_STATUSr"Zadapter_addressr )r€r�ZncbZadaptersroZstatusr'rrr Ú_netbios_getnodeBs2  rƒcCsttƒttjd�jS)z.Get the hardware address on Unix using ctypes.)r')Ú_uuid_generate_timeÚ_bufferr Úrawr/rrrr Ú_unixdll_getnodedsr‡cCsttƒdkrttjd�jSdS)z1Get the hardware address on Windows using ctypes.r)r'N)Ú _UuidCreater…r r†r/rrrr Ú_windll_getnodejs r‰cCs$ddl}|jddtdƒ>ƒtdƒBS)zCGet a random node ID, with eighth bit set as suggested by RFC 4122.rNrrl)ÚrandomÚ randranger )rŠrrr Ú_random_getnodepsrŒc Csptdk r tSddl}|jdkr*tttg}nttg}x8|tgD]*}y |ƒaWnw>YnXtdk r>tSq>WdS)a!Get the hardware address as a 48-bit integer. The first time this runs, it may launch a separate program, which could be quite slow. If all attempts to obtain the hardware address fail, we choose a random 48-bit number with its eighth bit set to 1 as recommended in RFC 4122.NrZwin32) Ú_nodeÚsysÚplatformr‰rƒrzr‡rprŒ)rŽZgettersÚgetterrrr Úgetnodexs   r‘c Csøtr0||kodknr0ttƒttjd�Sddl}t|jƒdƒ}t|dƒtdƒ}|dkr~ddl}|jdtdƒ>ƒ}|td ƒ@}|td ƒ?td ƒ@}|td ƒ?td ƒ@}|tdƒ@} |tdƒ?tdƒ@} |dkràt ƒ}t|||| | |fdd�S)aGenerate a UUID from a host ID, sequence number, and the current time. If 'node' is not given, getnode() is used to obtain the hardware address. If 'clock_seq' is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen.N)r'rgeÍÍAédl@'Hw� rélÿÿr iÿÿriÿrArrM)r(r)) r„r…r r†r_rr rŠr‹r‘) r/r0r_Z nanosecondsZ timestamprŠr*r+r,r.r-rrr Úuuid1‘s$   r”cCs0ddl}|j|j|ƒjƒ}t|dd…dd�S)zAGenerate a UUID from the MD5 hash of a namespace UUID and a name.rNrr)r'r))Úmd5r'Údigestr )Ú namespacer;r•Úmy_hashrrr Úuuid3°sr™c shtrttƒttjd�Syddl}t|jdƒdd�Sddl‰‡fdd„tdƒDƒ}t|dd�SdS) zGenerate a random UUID.)r'rNrr)r'r)csg|]}tˆjdƒƒ‘qS)r)rCr‹)Ú.0ro)rŠrr ú Äszuuid4..)Ú_uuid_generate_randomr…r r†reÚurandomrŠrB)rer'r)rŠr Úuuid4·s ržcCs0ddl}|j|j|ƒjƒ}t|dd…dd�S)zCGenerate a UUID from the SHA-1 hash of a namespace UUID and a name.rNrr)r'r))Úshar'r–r )r—r;rŸr˜rrr Úuuid5Èsr z$6ba7b810-9dad-11d1-80b4-00c04fd430c8z$6ba7b811-9dad-11d1-80b4-00c04fd430c8z$6ba7b812-9dad-11d1-80b4-00c04fd430c8z$6ba7b814-9dad-11d1-80b4-00c04fd430c8)r)NN)$r]Ú __author__rkrZ__date__Ú __version__rRrSrTrUrŽÚ version_inforr ZcmpÚobjectr rprzrƒrœr„rˆr‡r‰rŒr�r‘r”r™ržr Z NAMESPACE_DNSZ NAMESPACE_URLZ NAMESPACE_OIDZNAMESPACE_X500rrrr Ú.s8  ]  __pycache__/uuid.cpython-36.pyc000064400000040200152572267760012367 0ustar003 Úh>`Bã@sødZdZdjƒdjddƒZdjƒdZddd d g\ZZZZ d d l Z e j d,krRe Z dd„ZGdd„deƒZdd„Zdd„Zdd„Zd ZZZdd„Zdd„Zdd„Zd add„Zd-d d!„Zd"d#„Zd$d%„Zd&d'„Zed(ƒZ ed)ƒZ!ed*ƒZ"ed+ƒZ#d S).aUUUID objects (universally unique identifiers) according to RFC 4122. This module provides immutable UUID objects (class UUID) and the functions uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 UUIDs as specified in RFC 4122. If all you want is a unique ID, you should probably call uuid1() or uuid4(). Note that uuid1() may compromise privacy since it creates a UUID containing the computer's network address. uuid4() creates a random UUID. Typical usage: >>> import uuid # make a UUID based on the host ID and current time >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') # make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') # make a random UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') # make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') # make a UUID from a string of hex digits (braces and hyphens ignored) >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') # convert a UUID to a string of hex digits in standard form >>> str(x) '00010203-0405-0607-0809-0a0b0c0d0e0f' # get the raw 16 bytes of the UUID >>> x.bytes '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' # make a UUID from a 16-byte string >>> uuid.UUID(bytes=x.bytes) UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') This module works with Python 2.3 or higher.zKa-Ping Yee z$Date: 2006/08/24 19:08:53 $éú/ú-z$Revision: 1.2 $zreserved for NCS compatibilityzspecified in RFC 4122z$reserved for Microsoft compatibilityzreserved for future definitionéNécCs||k||kS)N©)ÚxÚyrrú/usr/lib/python3.6/uuid.pyÚ=sr c@s*eZdZdZd-dd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z e e ƒZ dd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd„Ze eƒZdd „Ze eƒZd!d"„Ze eƒZd#d$„Ze eƒZd%d&„Z e e ƒZ!d'd(„Z"e e"ƒZ#d)d*„Z$e e$ƒZ%d+d,„Z&e e&ƒZ'dS).ÚUUIDaTInstances of the UUID class represent UUIDs as specified in RFC 4122. UUID objects are immutable, hashable, and usable as dictionary keys. Converting a UUID to a string with str() yields something in the form '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts four possible forms: a similar string of hexadecimal digits, or a string of 16 raw bytes as an argument named 'bytes', or a tuple of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 48-bit values respectively) as an argument named 'fields', or a single 128-bit integer as an argument named 'int'. UUIDs have these read-only attributes: bytes the UUID as a 16-byte string fields a tuple of the six integer fields of the UUID, which are also available as six individual attributes and two derived attributes: time_low the first 32 bits of the UUID time_mid the next 16 bits of the UUID time_hi_version the next 16 bits of the UUID clock_seq_hi_variant the next 8 bits of the UUID clock_seq_low the next 8 bits of the UUID node the last 48 bits of the UUID time the 60-bit timestamp clock_seq the 14-bit sequence number hex the UUID as a 32-character hexadecimal string int the UUID as a 128-bit integer urn the UUID as a URN as specified in RFC 4122 variant the UUID variant (one of the constants RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) version the UUID version number (1 through 5, meaningful only when the variant is RFC_4122) Nc Cs¶||||gjdƒdkrtdƒ‚|dk rj|jddƒjddƒ}|jdƒjddƒ}t|ƒd kr`td ƒ‚t|d ƒ}|dk r¢t|ƒd kr†td ƒ‚td d ttt |ƒƒd ƒ}|dk �rt|ƒdkrÀtdƒ‚|\}}}} } } d|koætd&ƒknsôtdƒ‚d|k�o td'ƒkn�stdƒ‚d|k�o4td(ƒkn�sDtdƒ‚d| k�o\td)ƒkn�sltdƒ‚d| k�o„td*ƒkn�s”tdƒ‚d| k�o¬td+ƒkn�s¼tdƒ‚| tdƒ>| B} |tdƒ>|tdƒ>B|tdƒ>B| tdƒ>B| B}|dk �r6d|k�o&dtdƒ>kn�s6tdƒ‚|dk �r¨d|k�oTdkn�sdtd ƒ‚|d!tdƒ>M}|d"tdƒ>O}|d#tdƒ>M}||td$ƒ>O}||j d%<dS),ažCreate a UUID from either a string of 32 hexadecimal digits, a string of 16 bytes as the 'bytes' argument, a tuple of six integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as the 'fields' argument, or a single 128-bit integer as the 'int' argument. When a string of hex digits is given, curly braces, hyphens, and a URN prefix are all optional. For example, these expressions all yield the same UUID: UUID('{12345678-1234-5678-1234-567812345678}') UUID('12345678123456781234567812345678') UUID('urn:uuid:12345678-1234-5678-1234-567812345678') UUID(bytes='\x12\x34\x56\x78'*4) UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) UUID(int=0x12345678123456781234567812345678) Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given. The 'version' argument is optional; if given, the resulting UUID will have its variant and version number set according to RFC 4122, overriding bits in the given 'hex', 'bytes', 'fields', or 'int'. Nrz+need just one of hex, bytes, fields, or intzurn:Úzuuid:z{}ré z$badly formed hexadecimal UUID stringézbytes is not a 16-char stringz%02xézfields is not a 6-tuplerrz*field 1 out of range (need a 32-bit value)z*field 2 out of range (need a 16-bit value)z*field 3 out of range (need a 16-bit value)éz*field 4 out of range (need an 8-bit value)z*field 5 out of range (need an 8-bit value)é0z*field 6 out of range (need a 48-bit value)é`éPé@é€z*int is out of range (need a 128-bit value)ézillegal version numberiÀi€iðéLÚintliiérl) ÚcountÚ TypeErrorÚreplaceÚstripÚlenÚ ValueErrorÚlongÚtupleÚmapÚordÚ__dict__) ÚselfÚhexÚbytesÚfieldsrÚversionÚtime_lowÚtime_midÚtime_hi_versionÚclock_seq_hi_variantÚ clock_seq_lowÚnodeÚ clock_seqrrr Ú__init__jsR          4 $ z UUID.__init__cCst|tƒr|j|jkStS)N)Ú isinstancer rÚNotImplemented)r%Úotherrrr Ú__lt__°s  z UUID.__lt__cCs t|jƒS)N)Úhashr)r%rrr Ú__hash__µsz UUID.__hash__cCs|jS)N)r)r%rrr Ú__int__¸sz UUID.__int__cCs dt|ƒS)NzUUID(%r))Ústr)r%rrr Ú__repr__»sz UUID.__repr__cCs tdƒ‚dS)NzUUID objects are immutable)r)r%ÚnameÚvaluerrr Ú __setattr__¾szUUID.__setattr__cCsDd|j}d|dd…|dd…|dd…|dd…|dd…fS)Nz%032xz%s-%s-%s-%s-%sré ré)r)r%r&rrr Ú__str__Ás z UUID.__str__cCs4d}x*tdddƒD]}t|j|?d@ƒ|}qW|S)Nr rrréÿ)ÚrangeÚchrr)r%r'Zshiftrrr Ú get_bytesÆszUUID.get_bytescCs|j|j|j|j|j|jfS)N)r*r+r,r-r.r/)r%rrr Ú get_fieldsÎs zUUID.get_fieldscCs|jtdƒ?S)Nr)rr )r%rrr Ú get_time_lowÔszUUID.get_time_lowcCs|jtdƒ?d@S)Nriÿÿ)rr )r%rrr Ú get_time_midÙszUUID.get_time_midcCs|jtdƒ?d@S)Nriÿÿ)rr )r%rrr Úget_time_hi_versionÞszUUID.get_time_hi_versioncCs|jtdƒ?d@S)Né8rA)rr )r%rrr Úget_clock_seq_hi_variantãszUUID.get_clock_seq_hi_variantcCs|jtdƒ?d@S)NrrA)rr )r%rrr Úget_clock_seq_lowèszUUID.get_clock_seq_lowcCs&|jd@tdƒ>|jtdƒ>B|jBS)Niÿrr )r,r r+r*)r%rrr Úget_timeísz UUID.get_timecCs|jtdƒ@tdƒ>|jBS)Né?r)r-r r.)r%rrr Ú get_clock_seqószUUID.get_clock_seqcCs |jd@S)Nlÿÿÿ)r)r%rrr Úget_nodeùsz UUID.get_nodecCs d|jS)Nz%032x)r)r%rrr Úget_hexþsz UUID.get_hexcCs dt|ƒS)Nz urn:uuid:)r9)r%rrr Úget_urnsz UUID.get_urncCsJ|jdtdƒ>@stS|jdtdƒ>@s,tS|jdtdƒ>@sBtStSdS)Ni€ri@i )rr Ú RESERVED_NCSÚRFC_4122ÚRESERVED_MICROSOFTÚRESERVED_FUTURE)r%rrr Ú get_variantszUUID.get_variantcCs$|jtkr t|jtdƒ?d@ƒSdS)Nré)ÚvariantrSrr )r%rrr Ú get_versions zUUID.get_version)NNNNN)(Ú__name__Ú __module__Ú __qualname__Ú__doc__r1r5r7r8r:r=r@rDÚpropertyr'rEr(rFr*rGr+rHr,rJr-rKr.rLÚtimerNr0rOr/rPr&rQZurnrVrXrYr)rrrr r @sJ( E r cCs ddl}x’d D]Š}y|j|jj|dƒƒ}Wntk r@wYnXxT|D]L}|jƒjƒ}x:tt|ƒƒD]*}||d krft ||d j d dƒd ƒSqfWqHWqWdS)z5Get the hardware address on Unix by running ifconfig.rNr ú/sbin/ú /usr/sbinZifconfigÚhwaddrÚetherrú:r)r r`ra)rbrc) ÚosÚpopenÚpathÚjoinÚIOErrorÚlowerÚsplitrBrrr)reÚdÚpipeÚlineZwordsÚirrr Ú_ifconfig_getnodes    rpc Csêddl}ddl}dddg}y:ddl}|jdƒ}|jjj|dƒ|jd|jj dƒƒWn YnXx‚|D]z}y|j |j j |dƒd ƒ}Wnt k ržwhYnXx@|D]8}|jd ƒdjƒjƒ}|jd |ƒr¦t|jd dƒdƒSq¦WqhWdS)z|dtdƒ>|dtd ƒ>|d tdƒ>|d td ƒ>|d SWdS)ztGet the hardware address on Windows using NetBIOS calls. See http://support.microsoft.com/kb/118623 for details.rNÚ*ré(rr éérérr)Ú win32wnetÚnetbiosZNCBZNCBENUMZCommandZ LANA_ENUMZBufferZ_packZNetbiosZ_unpackrBZlengthZResetZNCBRESETr#ZlanaZLana_numZNCBASTATÚljustZCallnameZADAPTER_STATUSr"Zadapter_addressr )r€r�ZncbZadaptersroZstatusr'rrr Ú_netbios_getnodeBs2  rƒcCsttƒttjd�jS)z.Get the hardware address on Unix using ctypes.)r')Ú_uuid_generate_timeÚ_bufferr Úrawr/rrrr Ú_unixdll_getnodedsr‡cCsttƒdkrttjd�jSdS)z1Get the hardware address on Windows using ctypes.r)r'N)Ú _UuidCreater…r r†r/rrrr Ú_windll_getnodejs r‰cCs$ddl}|jddtdƒ>ƒtdƒBS)zCGet a random node ID, with eighth bit set as suggested by RFC 4122.rNrrl)ÚrandomÚ randranger )rŠrrr Ú_random_getnodepsrŒc Csptdk r tSddl}|jdkr*tttg}nttg}x8|tgD]*}y |ƒaWnw>YnXtdk r>tSq>WdS)a!Get the hardware address as a 48-bit integer. The first time this runs, it may launch a separate program, which could be quite slow. If all attempts to obtain the hardware address fail, we choose a random 48-bit number with its eighth bit set to 1 as recommended in RFC 4122.NrZwin32) Ú_nodeÚsysÚplatformr‰rƒrzr‡rprŒ)rŽZgettersÚgetterrrr Úgetnodexs   r‘c Csøtr0||kodknr0ttƒttjd�Sddl}t|jƒdƒ}t|dƒtdƒ}|dkr~ddl}|jdtdƒ>ƒ}|td ƒ@}|td ƒ?td ƒ@}|td ƒ?td ƒ@}|tdƒ@} |tdƒ?tdƒ@} |dkràt ƒ}t|||| | |fdd�S)aGenerate a UUID from a host ID, sequence number, and the current time. If 'node' is not given, getnode() is used to obtain the hardware address. If 'clock_seq' is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen.N)r'rgeÍÍAédl@'Hw� rélÿÿr iÿÿriÿrArrM)r(r)) r„r…r r†r_rr rŠr‹r‘) r/r0r_Z nanosecondsZ timestamprŠr*r+r,r.r-rrr Úuuid1‘s$   r”cCs0ddl}|j|j|ƒjƒ}t|dd…dd�S)zAGenerate a UUID from the MD5 hash of a namespace UUID and a name.rNrr)r'r))Úmd5r'Údigestr )Ú namespacer;r•Úmy_hashrrr Úuuid3°sr™c shtrttƒttjd�Syddl}t|jdƒdd�Sddl‰‡fdd„tdƒDƒ}t|dd�SdS) zGenerate a random UUID.)r'rNrr)r'r)csg|]}tˆjdƒƒ‘qS)r)rCr‹)Ú.0ro)rŠrr ú Äszuuid4..)Ú_uuid_generate_randomr…r r†reÚurandomrŠrB)rer'r)rŠr Úuuid4·s ržcCs0ddl}|j|j|ƒjƒ}t|dd…dd�S)zCGenerate a UUID from the SHA-1 hash of a namespace UUID and a name.rNrr)r'r))Úshar'r–r )r—r;rŸr˜rrr Úuuid5Èsr z$6ba7b810-9dad-11d1-80b4-00c04fd430c8z$6ba7b811-9dad-11d1-80b4-00c04fd430c8z$6ba7b812-9dad-11d1-80b4-00c04fd430c8z$6ba7b814-9dad-11d1-80b4-00c04fd430c8)r)NN)$r]Ú __author__rkrZ__date__Ú __version__rRrSrTrUrŽÚ version_inforr ZcmpÚobjectr rprzrƒrœr„rˆr‡r‰rŒr�r‘r”r™ržr Z NAMESPACE_DNSZ NAMESPACE_URLZ NAMESPACE_OIDZNAMESPACE_X500rrrr Ú.s8  ]  __pycache__/xml_serialize.cpython-36.opt-1.pyc000064400000023614152572267760015241 0ustar003 Úh>`P?ã @s ddlmZdddddddd d d d d dg ZddlZddlTddlZddlZddlmZddl Tddl Tddl m Z m Z eddƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd „Zdd „Zdd „Zdd „Zd d „ZGd!d"„d"eƒZe eƒGd#d„deƒƒZdS)$é)Úabsolute_importÚstring_to_xmlnodeÚstring_to_cdata_xmlnodeÚvalidate_database_docÚbooleanÚxml_attributesÚxml_attribute_dictÚxml_child_elements_iterÚxml_child_elementsÚxml_get_child_element_by_nameÚxml_get_child_elements_by_nameÚxml_child_element_namesÚxml_has_child_elementsÚ XmlSerializeN)Ú*)Ú get_config)Ú add_metaclassÚ string_typesZgeneralÚ i18n_encodingcCsZ|dkrtdƒdS|jƒ}|dkr0tdƒdS|jdƒ}|dkrNtdƒdSt|ƒSdS)Nz3validate_database_doc: doc is empty, validate failsFz4validate_database_doc: root is empty, validate failsÚversionz7validate_database_doc: version is empty, validate fails)Ú log_debugÚgetRootElementÚpropZdatabase_version_compatible)ÚdocÚ root_noder©rú#/usr/lib/python3.6/xml_serialize.pyr>s cCsht|tƒr|St|tƒrF|jƒ}|d kr,dS|d kr8dStd |ƒ‚nt|tƒrXt|ƒStd |ƒ‚d S) zconvert value to boolÚtÚtrueÚ1TÚfÚfalseÚ0Fzcannot convert (%s) to booleanN)rrr)r r!r")Ú isinstanceÚboolrÚlowerÚ ValueErrorÚint)ÚvaluerrrrNs   cCstjt|ƒƒS)N)Úlibxml2ZnewTextÚstr)rr(rrrr`scCs|j|t|ƒƒS)N)Z newCDataBlockÚlen)rr(rrrrdsccs0|jƒ}x"|r*|jƒ|jƒfV|jƒ}q WdS)N)Zget_propertiesÚget_nameZ get_contentÚget_next)ÚnoderrrrrtscCs&i}xt|ƒD]\}}|||<qW|S)N)r)r.ZpropsÚnamer(rrrr{s ccs0|jƒ}x"|r*|jƒdkr |V|jƒ}q WdS)NÚelement)Ú get_childrenÚget_typer-)r.Úchildrrrr ‚s  cCs:|jƒ}x,|r4|jƒdkr*|jƒ|kr*|S|jƒ}q WdS)Nr0)r1r2r,r-)r.r/r3rrrr Šs   cCsDg}|jƒ}x2|r>|jƒdkr4|jƒ|kr4|j|ƒ|jƒ}qW|S)Nr0)r1r2r,Úappendr-)r.r/Úelementsr3rrrr ”s    cCs tt|ƒƒS)N)Úlistr )r.rrrr ŸscCsdd„t|ƒDƒS)NcSsg|] }|jƒ‘qSr)r,)Ú.0Úerrrú ¤sz+xml_child_element_names..)r )r.rrrr £scCs.|jƒ}x |r(|jƒdkrdS|jƒ}q WdS)Nr0TF)r1r2r-)r.r3rrrr§s   cs$eZdZdd„Z‡fdd„Z‡ZS)ÚXmlSerializeMetaDatacs’|dkrtj||||ƒS|jdƒ‰|jddƒ‰|jddƒ‰ˆdkrjx&|D]}|jjddƒ‰ˆdk rHPqHWn‡‡‡fdd„}||d<tj||||ƒS)NrÚ__init__Úinit_from_xml_nodeÚ_init_postprocesscsJt|ƒdkr.wrapped_init)ÚtypeÚ__new__ÚgetÚ__dict__)ÚclsÚ classnameÚbasesÚ classdictZbase_clsrDr)r=rBrCrrF´s    zXmlSerializeMetaData.__new__cs¤tt|ƒj|||ƒ|jdƒ‰ˆs&dSˆdkr6d|_njd|_‡fdd„tˆjƒƒDƒ|_‡fdd„tˆjƒƒDƒ|_|j|j|_ |jj ƒ|jj ƒ|j j ƒdS)NÚ _xml_infoÚ unstructuredTFcs g|]}ˆ|ddkr|‘qS)ÚXMLFormr0r)r7Úx)Úxml_inforrr9Þsz1XmlSerializeMetaData.__init__..cs g|]}ˆ|ddkr|‘qS)rOZ attributer)r7rP)rQrrr9ßs) Úsuperr:r;rGÚ _unstructuredr6ÚkeysÚ _elementsÚ _attributesÚ_namesÚsort)rIrJrKrL)Ú __class__)rQrr;Ós   zXmlSerializeMetaData.__init__)Ú__name__Ú __module__Ú __qualname__rFr;Ú __classcell__rr)rYrr:²sr:c@sreZdZdd„Zdd„Zdd„Zdd„Zdd d „Zdd d „Zddd„Z ddd„Z ddd„Z ddd„Z ddd„Z d S)rcCs |jƒdS)N)Ú_init_defaults)Úselfrrrr;êszXmlSerialize.__init__cCs|jƒS)N)Úget_xml_text_doc)r_rrrÚ__str__íszXmlSerialize.__str__cCst|jdkrdSx`|jD]V}|j|}|jddƒ}|dk rHt|||ƒƒq|jdƒr`t||gƒqt||dƒqWdS)NrNÚdefaultr6)rMrWrGÚsetattr)r_r/Ú name_inforbrrrr^ðs     zXmlSerialize._init_defaultscCs8|jr$dd„t|jjƒƒDƒ}g}n |j}|j}||fS)NcSsg|]}|jdƒs|‘qS)Ú_)Ú startswith)r7rPrrrr9sz.)rSr6rHrTrUrV)r_r5Ú attributesrrrÚget_elements_and_attributesÿs z(XmlSerialize.get_elements_and_attributesNcCs$tjdƒ}|j||ƒ}|j|ƒ|S)Nz1.0)r)ZnewDocÚ get_xml_nodesZsetRootElement)r_Úobj_namerÚrootrrrÚ get_xml_docs   zXmlSerialize.get_xml_docc Cs<d}}z|j|ƒ}|jtdd�}Wd|dk r6|jƒX|S)Nr?)ÚencodingÚformat)rlZ serializerÚfreeDoc)r_rjrZtext_docrrrr`s  zXmlSerialize.get_xml_text_doccCs|d}z`y&tj|jƒƒ}|jƒ}|j||ƒWn4tjk r`}ztjtjd|ƒdSd}~XnXWd|dk rv|jƒXdS)Nz"read_xml() libxml2.parserError: %s) r)ZparseDocÚstriprr<Ú parserErrorÚsyslogÚLOG_ERRro)r_Zbufrjrrr8rrrÚread_xmlszXmlSerialize.read_xmlcCs°d}z”y*tj|ƒ}|r"||ƒs"dS|j||ƒWndtjk rd}ztjtjd|ƒdSd}~Xn2tk r”}ztjtjd|ƒdSd}~XnXWd|dk rª|jƒXdS)NFz'read_xml_file() libxml2.parserError: %szread_xml_file() error: %sT)r)Z parseFiler<rqrrrsÚ Exceptionro)r_ZxmlfilerjZ validate_docrr8rrrÚ read_xml_file&s"  zXmlSerialize.read_xml_filecCs¤yfd}|dkrtj}n2t|tƒr0t|dƒ}d}nt|tƒrsJ      5__pycache__/xml_serialize.cpython-36.pyc000064400000023614152572267760014302 0ustar003 Úh>`P?ã @s ddlmZdddddddd d d d d dg ZddlZddlTddlZddlZddlmZddl Tddl Tddl m Z m Z eddƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd „Zdd „Zdd „Zdd „Zd d „ZGd!d"„d"eƒZe eƒGd#d„deƒƒZdS)$é)Úabsolute_importÚstring_to_xmlnodeÚstring_to_cdata_xmlnodeÚvalidate_database_docÚbooleanÚxml_attributesÚxml_attribute_dictÚxml_child_elements_iterÚxml_child_elementsÚxml_get_child_element_by_nameÚxml_get_child_elements_by_nameÚxml_child_element_namesÚxml_has_child_elementsÚ XmlSerializeN)Ú*)Ú get_config)Ú add_metaclassÚ string_typesZgeneralÚ i18n_encodingcCsZ|dkrtdƒdS|jƒ}|dkr0tdƒdS|jdƒ}|dkrNtdƒdSt|ƒSdS)Nz3validate_database_doc: doc is empty, validate failsFz4validate_database_doc: root is empty, validate failsÚversionz7validate_database_doc: version is empty, validate fails)Ú log_debugÚgetRootElementÚpropZdatabase_version_compatible)ÚdocÚ root_noder©rú#/usr/lib/python3.6/xml_serialize.pyr>s cCsht|tƒr|St|tƒrF|jƒ}|d kr,dS|d kr8dStd |ƒ‚nt|tƒrXt|ƒStd |ƒ‚d S) zconvert value to boolÚtÚtrueÚ1TÚfÚfalseÚ0Fzcannot convert (%s) to booleanN)rrr)r r!r")Ú isinstanceÚboolrÚlowerÚ ValueErrorÚint)ÚvaluerrrrNs   cCstjt|ƒƒS)N)Úlibxml2ZnewTextÚstr)rr(rrrr`scCs|j|t|ƒƒS)N)Z newCDataBlockÚlen)rr(rrrrdsccs0|jƒ}x"|r*|jƒ|jƒfV|jƒ}q WdS)N)Zget_propertiesÚget_nameZ get_contentÚget_next)ÚnoderrrrrtscCs&i}xt|ƒD]\}}|||<qW|S)N)r)r.ZpropsÚnamer(rrrr{s ccs0|jƒ}x"|r*|jƒdkr |V|jƒ}q WdS)NÚelement)Ú get_childrenÚget_typer-)r.Úchildrrrr ‚s  cCs:|jƒ}x,|r4|jƒdkr*|jƒ|kr*|S|jƒ}q WdS)Nr0)r1r2r,r-)r.r/r3rrrr Šs   cCsDg}|jƒ}x2|r>|jƒdkr4|jƒ|kr4|j|ƒ|jƒ}qW|S)Nr0)r1r2r,Úappendr-)r.r/Úelementsr3rrrr ”s    cCs tt|ƒƒS)N)Úlistr )r.rrrr ŸscCsdd„t|ƒDƒS)NcSsg|] }|jƒ‘qSr)r,)Ú.0Úerrrú ¤sz+xml_child_element_names..)r )r.rrrr £scCs.|jƒ}x |r(|jƒdkrdS|jƒ}q WdS)Nr0TF)r1r2r-)r.r3rrrr§s   cs$eZdZdd„Z‡fdd„Z‡ZS)ÚXmlSerializeMetaDatacs’|dkrtj||||ƒS|jdƒ‰|jddƒ‰|jddƒ‰ˆdkrjx&|D]}|jjddƒ‰ˆdk rHPqHWn‡‡‡fdd„}||d<tj||||ƒS)NrÚ__init__Úinit_from_xml_nodeÚ_init_postprocesscsJt|ƒdkr.wrapped_init)ÚtypeÚ__new__ÚgetÚ__dict__)ÚclsÚ classnameÚbasesÚ classdictZbase_clsrDr)r=rBrCrrF´s    zXmlSerializeMetaData.__new__cs¤tt|ƒj|||ƒ|jdƒ‰ˆs&dSˆdkr6d|_njd|_‡fdd„tˆjƒƒDƒ|_‡fdd„tˆjƒƒDƒ|_|j|j|_ |jj ƒ|jj ƒ|j j ƒdS)NÚ _xml_infoÚ unstructuredTFcs g|]}ˆ|ddkr|‘qS)ÚXMLFormr0r)r7Úx)Úxml_inforrr9Þsz1XmlSerializeMetaData.__init__..cs g|]}ˆ|ddkr|‘qS)rOZ attributer)r7rP)rQrrr9ßs) Úsuperr:r;rGÚ _unstructuredr6ÚkeysÚ _elementsÚ _attributesÚ_namesÚsort)rIrJrKrL)Ú __class__)rQrr;Ós   zXmlSerializeMetaData.__init__)Ú__name__Ú __module__Ú __qualname__rFr;Ú __classcell__rr)rYrr:²sr:c@sreZdZdd„Zdd„Zdd„Zdd„Zdd d „Zdd d „Zddd„Z ddd„Z ddd„Z ddd„Z ddd„Z d S)rcCs |jƒdS)N)Ú_init_defaults)Úselfrrrr;êszXmlSerialize.__init__cCs|jƒS)N)Úget_xml_text_doc)r_rrrÚ__str__íszXmlSerialize.__str__cCst|jdkrdSx`|jD]V}|j|}|jddƒ}|dk rHt|||ƒƒq|jdƒr`t||gƒqt||dƒqWdS)NrNÚdefaultr6)rMrWrGÚsetattr)r_r/Ú name_inforbrrrr^ðs     zXmlSerialize._init_defaultscCs8|jr$dd„t|jjƒƒDƒ}g}n |j}|j}||fS)NcSsg|]}|jdƒs|‘qS)Ú_)Ú startswith)r7rPrrrr9sz.)rSr6rHrTrUrV)r_r5Ú attributesrrrÚget_elements_and_attributesÿs z(XmlSerialize.get_elements_and_attributesNcCs$tjdƒ}|j||ƒ}|j|ƒ|S)Nz1.0)r)ZnewDocÚ get_xml_nodesZsetRootElement)r_Úobj_namerÚrootrrrÚ get_xml_docs   zXmlSerialize.get_xml_docc Cs<d}}z|j|ƒ}|jtdd�}Wd|dk r6|jƒX|S)Nr?)ÚencodingÚformat)rlZ serializerÚfreeDoc)r_rjrZtext_docrrrr`s  zXmlSerialize.get_xml_text_doccCs|d}z`y&tj|jƒƒ}|jƒ}|j||ƒWn4tjk r`}ztjtjd|ƒdSd}~XnXWd|dk rv|jƒXdS)Nz"read_xml() libxml2.parserError: %s) r)ZparseDocÚstriprr<Ú parserErrorÚsyslogÚLOG_ERRro)r_Zbufrjrrr8rrrÚread_xmlszXmlSerialize.read_xmlcCs°d}z”y*tj|ƒ}|r"||ƒs"dS|j||ƒWndtjk rd}ztjtjd|ƒdSd}~Xn2tk r”}ztjtjd|ƒdSd}~XnXWd|dk rª|jƒXdS)NFz'read_xml_file() libxml2.parserError: %szread_xml_file() error: %sT)r)Z parseFiler<rqrrrsÚ Exceptionro)r_ZxmlfilerjZ validate_docrr8rrrÚ read_xml_file&s"  zXmlSerialize.read_xml_filecCs¤yfd}|dkrtj}n2t|tƒr0t|dƒ}d}nt|tƒrsJ      5__pycache__/Plugin.cpython-36.opt-1.pyc000064400000012155152572267760013626 0ustar003 Úh>`¸ã @sŽddlZddlmZmZejeddƒeddƒdd�Zy ejZWnek rXejZYnXddlTddl Tddl Z ddl Z Gd d „d e ƒZdS) éN)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_dirT)ZdomainZ localedirZfallback)Ú*c@s”eZdZdZdZdZedƒZdZdZ dd„Z dd„Z d d „Z d d „Z d d„Zdd„Zdd„Zdd „Z ffdd„Zdd„Zdd„Zdd„Zdd„ZdS)ÚPluginaå Each plugin object recognizes one or more access denials and presents a description of the denial to the user. Optionally, the plugin can provide a suggestion for allowing the access to the user. There are four user visible strings that are part of each Plugin subclass (some or all of these can be changed by the plugin author): * summary: summary of the denial * problem_description: detailed description of the denial * fix_description: description of how to allow the denied access * fix_cmd: command that can be used to allow the access All of the strings will have a standard set of substitutions performed. Each keyword (proceeded by a '$' will be replace by a string) - see http://docs.python.org/lib/node109.html for more information. The keywords are: * $SOURCE_TYPE - type for the source of the avc (usually the process performing the operation). * $TARGET_TYPE - type for the target of the avc (the type of the object). * $SOURCE_PATH - source of the executable (from the exe or comm field of the exe). A full path is not always available. * $TARGET_PATH - path for the target object. A full path is not always available. * $TARGET_DIR - path of the containing directory for TARGET_PATH. Essentially os.path.dirname($TARGET_PATH) * $TARGET_CLASS - the object class for the target. * $PERMS - the permissions denied. * $SOURCE_PACKAGE - name of the package which contains the executable (from $SOURCE_PATH). * $PORT_NUMBER - the port number for the connection denied. Additional subtitutions can be added with set_template_substitutions. You can also optional pass the name for a single boolean which will be used to set the $BOOLEAN subtitution into Plugin.__init__. o You can also set the level, of the alert, if the plugin believes discovers a signature of an attack, the level should be set to red * level: Defines the level of the alert ** yellow default ** red Indicates troubleshooter believes machine is being attacked ** green Indicates a configuration issue. Browser will not display Report Bug button ** white Tells the troubleshooter to ignore the AVC ÚzdIf you want to allow $SOURCE_BASE_PATH to have $ACCESS access on the $TARGET_BASE_PATH $TARGET_CLASSz No defaultcCs2tjdd|ƒ|_d|_d|_d|_d|_d|_dS)Nz ^plugins\.ré ZyellowF)ÚreÚsubÚ analysis_idÚpriorityÚlevelZfixableZ button_textZ report_bug)ÚselfÚname©rú/usr/lib/python3.6/Plugin.pyÚ__init__`s zPlugin.__init__cCsdS)Nr)r ÚargsrrrÚ init_argshszPlugin.init_argscCs|jS)N)Úproblem_description)r ÚavcrrrrÚget_problem_descriptionkszPlugin.get_problem_descriptioncCs|jS)N)Úif_text)r rrrrrÚ get_if_textnszPlugin.get_if_textcCs|jS)N)Ú then_text)r rrrrrÚ get_then_textqszPlugin.get_then_textcCs|jS)N)Údo_text)r rrrrrÚ get_do_texttszPlugin.get_do_textcCs|jS)N)Zfix_cmd)r rrrrrÚ get_fix_cmdwszPlugin.get_fix_cmdcCs|jS)N)r)r rrrrrrzscCs t|j|ƒS)zC Report a denial and solution to the fault server. )ZSEPluginr )r rrrrÚreport}sz Plugin.reportcCsdS)NFr)r rrrrÚanalyze„szPlugin.analyzecCs ||_dS)N)r )r r rrrÚ set_priority‡szPlugin.set_prioritycCs|jS)N)r )r rrrÚ get_priorityŠszPlugin.get_prioritycCs*|jdƒdd}tjjd|ƒr&|SdS)NÚ_rZ_selinuxz/usr/share/man/man8/%s.8.gzr)ÚsplitÚosÚpathÚisfile)r rZman_pagerrrÚ check_for_man�szPlugin.check_for_manN)Ú__name__Ú __module__Ú __qualname__Ú__doc__Zsummaryrr"rrrrrrrrrrrrr r!r'rrrrr,s&- r)ÚgettextZsetroubleshoot.configrrZ translationZugettextr"ÚAttributeErrorZsetroubleshoot.signatureZsetroubleshoot.utilZos.pathr$rÚobjectrrrrrÚs   __pycache__/Plugin.cpython-36.pyc000064400000012155152572267760012667 0ustar003 Úh>`¸ã @sŽddlZddlmZmZejeddƒeddƒdd�Zy ejZWnek rXejZYnXddlTddl Tddl Z ddl Z Gd d „d e ƒZdS) éN)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_dirT)ZdomainZ localedirZfallback)Ú*c@s”eZdZdZdZdZedƒZdZdZ dd„Z dd„Z d d „Z d d „Z d d„Zdd„Zdd„Zdd „Z ffdd„Zdd„Zdd„Zdd„Zdd„ZdS)ÚPluginaå Each plugin object recognizes one or more access denials and presents a description of the denial to the user. Optionally, the plugin can provide a suggestion for allowing the access to the user. There are four user visible strings that are part of each Plugin subclass (some or all of these can be changed by the plugin author): * summary: summary of the denial * problem_description: detailed description of the denial * fix_description: description of how to allow the denied access * fix_cmd: command that can be used to allow the access All of the strings will have a standard set of substitutions performed. Each keyword (proceeded by a '$' will be replace by a string) - see http://docs.python.org/lib/node109.html for more information. The keywords are: * $SOURCE_TYPE - type for the source of the avc (usually the process performing the operation). * $TARGET_TYPE - type for the target of the avc (the type of the object). * $SOURCE_PATH - source of the executable (from the exe or comm field of the exe). A full path is not always available. * $TARGET_PATH - path for the target object. A full path is not always available. * $TARGET_DIR - path of the containing directory for TARGET_PATH. Essentially os.path.dirname($TARGET_PATH) * $TARGET_CLASS - the object class for the target. * $PERMS - the permissions denied. * $SOURCE_PACKAGE - name of the package which contains the executable (from $SOURCE_PATH). * $PORT_NUMBER - the port number for the connection denied. Additional subtitutions can be added with set_template_substitutions. You can also optional pass the name for a single boolean which will be used to set the $BOOLEAN subtitution into Plugin.__init__. o You can also set the level, of the alert, if the plugin believes discovers a signature of an attack, the level should be set to red * level: Defines the level of the alert ** yellow default ** red Indicates troubleshooter believes machine is being attacked ** green Indicates a configuration issue. Browser will not display Report Bug button ** white Tells the troubleshooter to ignore the AVC ÚzdIf you want to allow $SOURCE_BASE_PATH to have $ACCESS access on the $TARGET_BASE_PATH $TARGET_CLASSz No defaultcCs2tjdd|ƒ|_d|_d|_d|_d|_d|_dS)Nz ^plugins\.ré ZyellowF)ÚreÚsubÚ analysis_idÚpriorityÚlevelZfixableZ button_textZ report_bug)ÚselfÚname©rú/usr/lib/python3.6/Plugin.pyÚ__init__`s zPlugin.__init__cCsdS)Nr)r ÚargsrrrÚ init_argshszPlugin.init_argscCs|jS)N)Úproblem_description)r ÚavcrrrrÚget_problem_descriptionkszPlugin.get_problem_descriptioncCs|jS)N)Úif_text)r rrrrrÚ get_if_textnszPlugin.get_if_textcCs|jS)N)Ú then_text)r rrrrrÚ get_then_textqszPlugin.get_then_textcCs|jS)N)Údo_text)r rrrrrÚ get_do_texttszPlugin.get_do_textcCs|jS)N)Zfix_cmd)r rrrrrÚ get_fix_cmdwszPlugin.get_fix_cmdcCs|jS)N)r)r rrrrrrzscCs t|j|ƒS)zC Report a denial and solution to the fault server. )ZSEPluginr )r rrrrÚreport}sz Plugin.reportcCsdS)NFr)r rrrrÚanalyze„szPlugin.analyzecCs ||_dS)N)r )r r rrrÚ set_priority‡szPlugin.set_prioritycCs|jS)N)r )r rrrÚ get_priorityŠszPlugin.get_prioritycCs*|jdƒdd}tjjd|ƒr&|SdS)NÚ_rZ_selinuxz/usr/share/man/man8/%s.8.gzr)ÚsplitÚosÚpathÚisfile)r rZman_pagerrrÚ check_for_man�szPlugin.check_for_manN)Ú__name__Ú __module__Ú __qualname__Ú__doc__Zsummaryrr"rrrrrrrrrrrrr r!r'rrrrr,s&- r)ÚgettextZsetroubleshoot.configrrZ translationZugettextr"ÚAttributeErrorZsetroubleshoot.signatureZsetroubleshoot.utilZos.pathr$rÚobjectrrrrrÚs   __pycache__/__init__.cpython-36.opt-1.pyc000064400000000161152572267760014121 0ustar003 Úh>`åã@sdS)N©rrrú/usr/lib/python3.6/__init__.pyÚs__pycache__/__init__.cpython-36.pyc000064400000000161152572267760013162 0ustar003 Úh>`åã@sdS)N©rrrú/usr/lib/python3.6/__init__.pyÚs__pycache__/access_control.cpython-36.opt-1.pyc000064400000007616152572267760015377 0ustar003 Úh>`lã @sødZddlZddlZddlZddlmZddlmZdgZ y ej Z Wn e k räddl Z ddl Z e jƒdZe jdeƒr‚dZ n^e jd eƒr”dZ nLe jd eƒr¦d Z n:e jd eƒr¸d Z n(e jdeƒrÊdZ ne jdeƒrÜdZ ndZ YnXGdd„dƒZdS)z©Access control for setroubleshoot. For now this is only used for determining which users are allowed to connect to the server: see UserServerAccess for more information.éN)Ú get_config)Ú syslog_traceÚ ServerAccesséz^i\d86éz^x86_64z^(ppc|powerpc)éz ^(alpha|mips)éz^sparcé@z^parisci@c@sZeZdZdZddiddidœZdd„Zdd „Zd d „Zd d „Zdd„Z dd„Z dd„Z dS)rzg Determine if a user should be given access to the server based on the configuration file. ÚwildcardTF)ZclientZfix_cmdcCs2i|_x&ttjjƒƒD]}|j|ƒ|j|<qWdS)N)Ú privilegesÚlistrÚkeysÚinit_privilege)ÚselfÚ privilege©rú$/usr/lib/python3.6/access_control.pyÚ__init__LszServerAccess.__init__cCs"dd„tdd|ƒjdƒDƒ}|S)NcSsg|] }|jƒ‘qSr)Ústrip)Ú.0Únamerrrú Xsz/ServerAccess.init_privilege..Úaccessz%s_usersú,)rÚsplit)rrZ cfg_namesrrrrWszServerAccess.init_privilegecCs(|tjk}|rdStjtjd|ƒdS)NTzunknown access privilege (%s)F)rr ÚsyslogÚLOG_ERR)rrZvalidrrrÚvalid_privilege\s  zServerAccess.valid_privilegecCs.|j|ƒsdStj|ds dSd|j|kS)NFr Ú*)rrr )rrrrrÚunrestricted_privilegecs  z#ServerAccess.unrestricted_privilegecCs6|j|ƒsdS|j|ƒrdS||j|kr.dSdSdS)zƒ Determine if the given user name is allowed access. Returns True if access should be given, False if not. FTN)rrr )rrÚuserrrrÚ user_allowedks  zServerAccess.user_allowedc CsX|j|ƒsdS|j|ƒrdSyddl}|j|ƒ}Wntk rFdSX|j||dƒS)zÅ Determine if the given uid is allowed access. No error is returned if the uid is invalid (False is returned). Returns True if access should be given, False if not. FTrN)rrÚpwdÚgetpwuidÚKeyErrorr!)rrÚuidr"Z pwd_entryrrrÚ uid_allowedzs  zServerAccess.uid_allowedc Csôd}}}y|j}|tjkr&||fSWntk r<YnXd}tj|ƒ}yJ|jtjt|ƒ}tj ||ƒ\}}}|dkr|d}|dkrˆd}|dkr”d}WnTt k rê} z8d}}}ddl } t | j ƒƒtjtjd| ƒWYdd} ~ XnX||fS) zêObtain the effective user and group IDs of the process on the other end of a socket. SO_PEERCRED is used so the information returned is generally trustworthy (though root processes can impersonate any uid/gid).NZIIIérzget_credentials(): %séÿÿÿÿr(r()ÚfamilyÚSocketZAF_UNIXÚAttributeErrorÚstructÚcalcsizeZ getsockoptZ SOL_SOCKETÚ SO_PEERCREDÚunpackÚ ExceptionÚ tracebackrÚ format_excrr) rZsockÚpidr%Úgidr)Z format_ucredZ sizeof_ucredZucredÚer1rrrÚget_credentials�s0      $zServerAccess.get_credentialsN) Ú__name__Ú __module__Ú __qualname__Ú__doc__r rrrrr!r&r6rrrrrBs  )r:r,Zsocketr*rZsetroubleshoot.configrZsetroubleshoot.utilrÚ__all__r.r+ÚosÚreÚunameÚmachineÚsearchrrrrrÚs4            __pycache__/access_control.cpython-36.pyc000064400000007616152572267760014440 0ustar003 Úh>`lã @sødZddlZddlZddlZddlmZddlmZdgZ y ej Z Wn e k räddl Z ddl Z e jƒdZe jdeƒr‚dZ n^e jd eƒr”dZ nLe jd eƒr¦d Z n:e jd eƒr¸d Z n(e jdeƒrÊdZ ne jdeƒrÜdZ ndZ YnXGdd„dƒZdS)z©Access control for setroubleshoot. For now this is only used for determining which users are allowed to connect to the server: see UserServerAccess for more information.éN)Ú get_config)Ú syslog_traceÚ ServerAccesséz^i\d86éz^x86_64z^(ppc|powerpc)éz ^(alpha|mips)éz^sparcé@z^parisci@c@sZeZdZdZddiddidœZdd„Zdd „Zd d „Zd d „Zdd„Z dd„Z dd„Z dS)rzg Determine if a user should be given access to the server based on the configuration file. ÚwildcardTF)ZclientZfix_cmdcCs2i|_x&ttjjƒƒD]}|j|ƒ|j|<qWdS)N)Ú privilegesÚlistrÚkeysÚinit_privilege)ÚselfÚ privilege©rú$/usr/lib/python3.6/access_control.pyÚ__init__LszServerAccess.__init__cCs"dd„tdd|ƒjdƒDƒ}|S)NcSsg|] }|jƒ‘qSr)Ústrip)Ú.0Únamerrrú Xsz/ServerAccess.init_privilege..Úaccessz%s_usersú,)rÚsplit)rrZ cfg_namesrrrrWszServerAccess.init_privilegecCs(|tjk}|rdStjtjd|ƒdS)NTzunknown access privilege (%s)F)rr ÚsyslogÚLOG_ERR)rrZvalidrrrÚvalid_privilege\s  zServerAccess.valid_privilegecCs.|j|ƒsdStj|ds dSd|j|kS)NFr Ú*)rrr )rrrrrÚunrestricted_privilegecs  z#ServerAccess.unrestricted_privilegecCs6|j|ƒsdS|j|ƒrdS||j|kr.dSdSdS)zƒ Determine if the given user name is allowed access. Returns True if access should be given, False if not. FTN)rrr )rrÚuserrrrÚ user_allowedks  zServerAccess.user_allowedc CsX|j|ƒsdS|j|ƒrdSyddl}|j|ƒ}Wntk rFdSX|j||dƒS)zÅ Determine if the given uid is allowed access. No error is returned if the uid is invalid (False is returned). Returns True if access should be given, False if not. FTrN)rrÚpwdÚgetpwuidÚKeyErrorr!)rrÚuidr"Z pwd_entryrrrÚ uid_allowedzs  zServerAccess.uid_allowedc Csôd}}}y|j}|tjkr&||fSWntk r<YnXd}tj|ƒ}yJ|jtjt|ƒ}tj ||ƒ\}}}|dkr|d}|dkrˆd}|dkr”d}WnTt k rê} z8d}}}ddl } t | j ƒƒtjtjd| ƒWYdd} ~ XnX||fS) zêObtain the effective user and group IDs of the process on the other end of a socket. SO_PEERCRED is used so the information returned is generally trustworthy (though root processes can impersonate any uid/gid).NZIIIérzget_credentials(): %séÿÿÿÿr(r()ÚfamilyÚSocketZAF_UNIXÚAttributeErrorÚstructÚcalcsizeZ getsockoptZ SOL_SOCKETÚ SO_PEERCREDÚunpackÚ ExceptionÚ tracebackrÚ format_excrr) rZsockÚpidr%Úgidr)Z format_ucredZ sizeof_ucredZucredÚer1rrrÚget_credentials�s0      $zServerAccess.get_credentialsN) Ú__name__Ú __module__Ú __qualname__Ú__doc__r rrrrr!r&r6rrrrrBs  )r:r,Zsocketr*rZsetroubleshoot.configrZsetroubleshoot.utilrÚ__all__r.r+ÚosÚreÚunameÚmachineÚsearchrrrrrÚs4            __pycache__/analyze.cpython-36.opt-1.pyc000064400000054255152572267760014042 0ustar003 �Àn`œhã@sˆddlmZdddddddgZdd lZdd lmZmZdd lZdd lZdd l Z dd l Z dd l Z dd l Tdd l Z dd lmZdd lmZdd lTdd lTdd lTdd lTdd lTdd lTdd lTddlmZdd„ZGdd„deƒZGdd„deƒZGdd„deƒZGdd„dee j ƒZ!Gdd„deƒZ"Gdd„deƒZ#Gdd„deƒZ$Gdd„de%e&e'ejƒZ(ej)e(ƒGdd„dejƒZ*ej)e*ƒd S)é)Úprint_functionÚ AnalyzeThreadÚAnalyzeÚPluginReportReceiverÚTestPluginReportReceiverÚSETroubleshootDatabaseÚSETroubleshootDatabaseLocalÚLogfileAnalyzerN)ÚGObjectÚGLib)Ú*)Ú cmp_to_key)Ú get_config)Úvalidate_database_doccCs||k||kS)N©)ÚxÚyrrú/usr/lib/python3.6/analyze.pyÚ4src@s<eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd S)ÚPluginStatisticscCs0|j|_d|_d|_d|_d|_d|_d|_dS)N)Ú analysis_idÚnameÚanalyze_start_timeÚanalyze_end_timeÚanalyze_elapsed_timeÚreport_start_timeÚreport_end_timeÚreport_elapsed_time)ÚselfÚpluginrrrÚ__init__=szPluginStatistics.__init__cCsRt|jƒ}|jdkr"d|j|fSt|j|jƒ}t|jƒ}d|j|||fSdS)Nz%s: %s elapsedz5%s: %s elapsed, %s analyze elapsed, %s report elapsed)Úformat_elapsed_timerrrrr)rrZtotal_elapsed_timerrrrÚ__str__Fs   zPluginStatistics.__str__cCstjƒ|_dS)N)Útimer)rrrrÚ analyze_startRszPluginStatistics.analyze_startcCstjƒ|_|j|j|_dS)N)r#rrr)rrrrÚ analyze_endUs zPluginStatistics.analyze_endcCstjƒ|_dS)N)r#r)rrrrÚ report_startYszPluginStatistics.report_startcCstjƒ|_|j|j|_dS)N)r#rrr)rrrrÚ report_end\s zPluginStatistics.report_endN) Ú__name__Ú __module__Ú __qualname__r r"r$r%r&r'rrrrr;s   rc@s<eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd S)ÚAnalyzeStatisticscCs(||_d|_g|_d|_d|_d|_dS)N)Ú num_pluginsÚ cur_pluginÚcalled_pluginsÚ start_timeÚend_timeÚ elapsed_time)rr,rrrr es zAnalyzeStatistics.__init__cCsPd}d}t|jƒ}|jdk r8t|jƒ}|r8t|j|ƒ}d||j|||jƒfS)NzB%d/%d plugins in %s elapsed, avg plugin %s elapsed, plugins=[ %s ])Úlenr.r1r!r,Úcalled_plugins_to_string)rr1Zavg_plugin_timeZn_calledrrrr"ms    zAnalyzeStatistics.__str__cCsdjdd„|jDƒƒS)NÚ cSsg|] }t|ƒ‘qSr)Ústr)Ú.0rrrrú {sz>AnalyzeStatistics.called_plugins_to_string..)Újoinr.)rrrrr3zsz*AnalyzeStatistics.called_plugins_to_stringcCstjƒ|_dS)N)r#r/)rrrrÚstart}szAnalyzeStatistics.startcCstjƒ|_|j|j|_dS)N)r#r0r/r1)rrrrÚend€s zAnalyzeStatistics.endcCs&t|ƒ|_|jj|jƒ|jjƒdS)N)rr-r.Úappendr$)rrrrrÚ new_plugin„s zAnalyzeStatistics.new_pluginN) r(r)r*r r"r3r9r:r<rrrrr+cs  r+c@s.eZdZdd„Zdd„Zdd„Zd dd „Zd S) rcCstƒ|_tdt|jƒƒdS)NzNumber of Plugins = %d)Z load_pluginsÚpluginsÚ log_debugr2)rrrrr ŽszAnalyze.__init__cCstƒ}|r|jƒ|S)N)Z SEEnvironmentÚupdate)rÚquery_environmentÚ environmentrrrÚget_environment’szAnalyze.get_environmentcCs$t|j|j|j|j|j|jd�}|S)N)ÚhostÚaccessÚscontextÚtcontextÚtclassÚtpath)ZSEFaultSignaturerCrDrErFrGrH)rÚavcrAÚsigrrrÚ get_signature˜s zAnalyze.get_signatureTcCsÎtd|ƒ|jƒ|j|jƒ}ddlm}|jjdk rD|jjjƒt |j|j |j |j |j |j|j|j|j|j|j|j||ƒ||jjt|jjƒ|jƒdd�}�x |jD�]}yš|j|ƒ}|dk �rD|jdkrØtdƒdS|jdk oê|jdk�r|jdk�s|jd k�r|j|_t|tƒ�r8x(|D]} |jj| ƒ�q Wn |jj|ƒWq¦tk �rº} zVt | t!j"d �t#j#t#j$d |j%ƒt!j&ƒ\} } } td j't(j)| ƒƒƒ|jj*|ƒWYdd} ~ Xq¦Xq¦W|j+|ƒdS) Nzanalyze_avc() avc=%sr)ÚTemplateZyellow)Ú audit_eventÚsourceÚspathrHZ src_rpm_listZ tgt_rpm_listrErFrGÚportrCrJrAÚ line_numbersÚlast_seen_dateÚlocal_idÚlevelZwhitez!plugin level white, not reportingZredZgreen)ÚfilezPlugin Exception %s r4),r>r?rBr@ÚstringrLrMrQÚsortZSEFaultSignatureInforNrOrHZsrc_rpmsZtgt_rpmsrErFrGrPrCrKÚ TimeStampZ timestampÚ generate_idr=ÚanalyzerTÚ isinstanceÚlistZ plugin_listr;Ú ExceptionÚprintÚsysÚstderrÚsyslogÚLOG_ERRrÚexc_infor8Ú tracebackÚ format_tbÚremoveÚreport_problem)rrIÚreport_receiverr@rArLÚsiginforZreportÚrÚeZv1Zv2Zv3rrrÚ analyze_avc¢sZ            "zAnalyze.analyze_avcN)T)r(r)r*r rBrKrlrrrrrŒs c@seZdZddd„Zdd„ZdS)ré cCs&tjj|ƒtj|ƒ||_||_dS)N)Ú threadingÚThreadr rÚqueueÚtimeout)rrprqrrrr ås  zAnalyzeThread.__init__cCsÊxÄy6|jjƒ\}}tjtjdƒtjdƒ|j||ƒWnftk rl}ztjtjd|ƒWYdd}~Xn4t k rž}ztjtjd|ƒWYdd}~XnXtjtjdj |j ƒƒtj|j ƒqWdS)Nz)AnalyzeThread.run(): Cancel pending alarmrz!Exception during AVC analysis: %sz,AnalyzeThread.run(): Set alarm timeout to {}) rpÚgetraZ LOG_DEBUGÚsignalÚalarmrlr]rbÚ ValueErrorÚformatrq)rrIrhrkrrrÚrunís "$zAnalyzeThread.runN)rm)r(r)r*r rwrrrrrãs c@s$eZdZdd„Zdd„Zdd„ZdS)rcCs ||_dS)N)Údatabase)rrxrrrr szPluginReportReceiver.__init__cCs‚y0|jj|jƒ}|j|ƒ|jj|ƒtdƒWnLtk r|}z0|jtkrjtdƒ|j |_ |jj |ƒ}n‚WYdd}~XnX|S)Nzsignature found in databaseznot in database yet) rxÚlookup_signaturerJZ update_mergeÚmodify_siginfor>Ú ProgramErrorÚerrnoÚERR_NO_SIGNATURE_MATCHrRÚfirst_seen_dateÚ add_siginfo)rriZdatabase_siginforkrrrrgs    z#PluginReportReceiver.report_problemcCs |jjjƒS)N)rxÚsigsZgenerate_local_id)rrrrrYsz PluginReportReceiver.generate_idN)r(r)r*r rgrYrrrrrþscs$eZdZ‡fdd„Zdd„Z‡ZS)rcstt|ƒj|ƒdS)N)Úsuperrr )rrx)Ú __class__rrr sz!TestPluginReportReceiver.__init__cCstd|jjƒdS)NzAnalysis Result: %s)r^rJr)rrirrrrgsz'TestPluginReportReceiver.report_problem)r(r)r*r rgÚ __classcell__rr)r‚rrs c@sÎeZdZd2dd„Zdd„Zdd„Zdd „Zd d „Zd3d d„Zd4dd„Z dd„Z dd„Z dd„Z dd„Z dd„Zdd„Zdd„Zdd „Zd!d"„Zd5d#d$„Zd%d&„Zd'd(„Zd)d*„Zd6d,d-„Zd.d/„Zd0d1„ZdS)7rNcCsª||_d|_t|||jƒ|_tjƒ|_d|_d|_d|_ d|_ d|_ t ddt ƒ|_d|_t ddƒ}|dk r€|jƒ}|r€t|ƒ|_td|jj|jj|jjfƒ|jƒdS) NFrééÈrxÚ max_alertsÚ max_alert_agezrÚ friendly_nameÚload)rrˆrr“r‡rrrr $s$   zSETroubleshootDatabase.__init__cCs”|jp |jsdS|jjjtdd„ƒd�|j�rtƒ}||j8}d}x$|jjD]}|j|kr^P|d7}qNW|dk�rtd|j|j ƒfƒtd|jjdjj ƒ|jj|djj ƒfƒtd |jj|jj ƒ|jjdjj ƒfƒd d „|jjd|…Dƒ}x|D]}|j |d d ��qW|j�r�t |jjƒ|j}|dk�r�dd „|jjd|…Dƒ}td|t |ƒ|fƒx|D]}|j |d d ��qxWdS)NFcSst|j|jƒS)N)ÚcmprR)ÚaÚbrrrr?sz.SETroubleshootDatabase.prune..)Úkeyréz5prune by age: max_alert_age=%s min_time_to_survive=%szprune by age: pruning [%s - %s]zprune by age: keeping [%s - %s]cSsg|] }|j‘qSr)rJ)r6rirrrr7Osz0SETroubleshootDatabase.prune..T)ÚprunecSsg|] }|j‘qSr)rJ)r6rirrrr7Vsz*prune first %d alerts, len(sigs=%d sigs=%séÿÿÿÿ) r†r‡r€Úsignature_listrWr rXrRr>rvÚdelete_signaturer2)rZmin_time_to_surviveZkeeprir€rJrrrrš:s2     0,   zSETroubleshootDatabase.prunecCs ||_dS)N)r‰)rr‰rrrÚ set_notify[sz!SETroubleshootDatabase.set_notifycCs6x0|jjD]$}|j|jkr |j}|j|_||_q WdS)N)r€rœrRr~)rriZtmprrrÚvalidate^s  zSETroubleshootDatabase.validatecCshtƒ|_|jdkrdStjj|jƒrTtj|jƒ}|tdkrT|jj|jdt ƒrTd|_ |j ƒ|j ƒdS)Nrr€T) ÚSEFaultSignatureSetr€rˆÚosÚpathÚexistsÚstatÚST_SIZEZ read_xml_filerrŒrŸrš)rÚ stat_inforrrr”fs   zSETroubleshootDatabase.loadFcCsj|jdkrdStd|j|jfƒ|s.|jƒ|jjd|jƒd|_d|_|jdk rftj |jƒd|_dS)Nz'writing database (%s) modified_count=%sr€Tr) rˆr>r�ršr€Z write_xmlrŒr�r Z source_remove)rršrrrÚsaveus   zSETroubleshootDatabase.savecCs`|jd7_|jdkrdS|j|jks0|j r<|j|ƒn |jdkr\tj|jd|j ƒ|_dS)Nr™iè) r�rˆr�rŒr§r�r Z timeout_addrŽÚauto_save_callback)rršrrrÚ mark_modified„s    z$SETroubleshootDatabase.mark_modifiedcCs td|j|jfƒ|jƒdS)Nz)auto_save database (%s) modified_count=%sF)r>rˆr�r§)rrrrr¨�sz)SETroubleshootDatabase.auto_save_callbackcCs:|jdkrdStjj|jƒr6td|jƒtj|jƒdS)Nzdeleting database (%s))rˆr¡r¢r£r>rf)rrrrrf•s  zSETroubleshootDatabase.removecCs|jjƒdS)N)r‹Úacquire)rrrrrªœszSETroubleshootDatabase.acquirecCs|jjƒdS)N)r‹Úrelease)rrrrr«ŸszSETroubleshootDatabase.releasecCs†d}|jj|ƒ}tdt|ƒdjdd„|Dƒƒfƒt|ƒdkrHttƒ‚t|ƒdkrxtdt|ƒdjdd„|Dƒƒfƒ|dj}|S)Nz1lookup_signature: found %d matches with scores %sú,cSsg|]}d|j‘qS)z%.2f)Úscore)r6rrrrr7¦sz;SETroubleshootDatabase.lookup_signature..rr™cSsg|]}d|j‘qS)z%.2f)r­)r6rrrrr7ªs)r€Zmatch_signaturesr>r2r8r{r}ri)rrJriZmatchesrrrry¢s $  $ z'SETroubleshootDatabase.lookup_signaturecCs2|jj|ƒ}|dkr.td|ƒttd|ƒ‚|S)Nzlookup_local_id: %s not foundzid (%s) not found)r€Úlookup_local_idr>r{ZERR_SIGNATURE_ID_NOT_FOUND)rrSrirrrr®®s   z&SETroubleshootDatabase.lookup_local_idcCs.|jj|ƒ}|jr"|jjd|jƒ|jƒ|S)NÚadd)r€rr‰Úsignatures_updatedrSr©)rrirrrrµs  z"SETroubleshootDatabase.add_siginfocCs|jS)N)rŠ)rrrrÚget_properties¼sz%SETroubleshootDatabase.get_propertiescCs8td|ƒ|dkr|jStƒ}|j|ƒ}|j|ƒ|S)Nzquery_alerts: criteria=%sr )r>r€r r®r)rZcriteriar€rirrrÚ query_alerts¿s   z#SETroubleshootDatabase.query_alertscCs†td|ƒy|j|ƒ}Wn:tk rT}z|jtkrBtdƒdS‚WYdd}~XnX|jj|ƒ|jrx|jjd|j ƒ|j |ƒdS)Nzdelete_signature: sig=%szSignature not found!Údelete) r>ryr{r|r}r€Zremove_siginfor‰r°rSr©)rrJršrirkrrrr�Ës   z'SETroubleshootDatabase.delete_signaturecCs"|jr|jjd|jƒ|jƒdS)NZmodify)r‰r°rSr©)rrirrrrzÜsz%SETroubleshootDatabase.modify_siginfocCshtd||fƒy|j|ƒ}Wn:tk rX}z|jtkrFtdƒdS‚WYdd}~XnX|j|ƒ}|S)Nz)evaluate_alert_filter: username=%s sig=%szSignature not found!Úignore)r>ryr{r|r}Zevaluate_filter_for_user)rrJÚusernamerirkÚactionrrrÚevaluate_alert_filterás  z,SETroubleshootDatabase.evaluate_alert_filtercCs‚td||||fƒy|j|ƒ}Wn:tk r\}z|jtkrJtdƒdS‚WYdd}~XnX|j|ƒ}|j||ƒ|j|ƒdS)Nz2set_user_data: username=%s item=%s data=%s sig= %szSignature not found!)r>ryr{r|r}Z get_user_dataZ update_itemrz)rrJrµÚitemÚdatarirkZ user_datarrrÚ set_user_dataðs   z$SETroubleshootDatabase.set_user_dataÚcCsxtd|||fƒy|j|ƒ}Wn:tk rZ}z|jtkrHtdƒdS‚WYdd}~XnX|j|||ƒ|j|ƒdS)Nz.set_filter: username=%s filter_type=%s sig= %szSignature not found!)r>ryr{r|r}Zupdate_user_filterrz)rrJrµZ filter_typer¹rirkrrrÚ set_filters z!SETroubleshootDatabase.set_filtercCs|jjj|ƒ|_|jƒdS)N)r€ÚusersÚadd_userÚuserr©)rrµrrrr¾szSETroubleshootDatabase.add_usercCs|jjj|ƒS)N)r€r½Úget_user)rrµrrrrÀszSETroubleshootDatabase.get_user)N)F)F)F)r»)r(r)r*r ršržrŸr”r§r©r¨rfrªr«ryr®rr±r²r�rzr·rºr¼r¾rÀrrrrr"s. !     c@s^eZdZejjdejejffejjdejejejffdœZ dd„Z dd„Z dd„Z d d „Z dS) rN)r°z async-errorcCs,tjj|ƒtj|ƒ||_|jj|ƒdS)N)r r Ú RpcManagerxrž)rrxrrrr %s  z$SETroubleshootDatabaseLocal.__init__cCs|jj|ƒdS)N)rxrž)rr‰rrrrž+sz&SETroubleshootDatabaseLocal.set_notifycGsàtd|jj|jdjdd„|Dƒƒ|fƒ|j|}t|j|jdƒ}|dkrdtt d|j|jjfƒ‚y(||Ž|_ d|_ |j dk rŠ|j g|_ Wn6tk rÂ}z|j |j g|_ d|_ WYdd}~XnX|j dk rÜtj|j|ƒdS)Nz%s emit %s(%s) id=%sr¬cSsg|] }t|ƒ‘qSr)r5)r6Úargrrrr7/sz8SETroubleshootDatabaseLocal.emit_rpc..z'method %s not found in base class of %sZ method_returnZ error_return)r>r‚r(Úmethodr8Zasync_rpc_cacheÚgetattrrxr{ZERR_METHOD_NOT_FOUNDZ return_argsZ return_typer|Ústrerrorr Úidle_addZprocess_async_return)rZrpc_idÚtypeZrpc_defÚargsZ async_rpcÚfuncrkrrrÚemit_rpc.s *    z$SETroubleshootDatabaseLocal.emit_rpccCs"td||fƒ|jd||ƒdS)Nz4signatures_updated() database local: type=%s item=%sr°)r>Úemit)rrÇr¸rrrr°Asz.SETroubleshootDatabaseLocal.signatures_updated)r(r)r*r Ú SignalFlagsÚRUN_LASTÚ TYPE_PYOBJECTZ TYPE_STRINGZTYPE_INTÚ __gsignals__r ržrÊr°rrrrrs c@sneZdZejjdejffejjdejffdœZddd„Z ddd„Z dd„Z d d „Z d d „Z d d„Zdd„ZdS)r N)Úprogressz state-changedcCsftjj|ƒtd|jj|fƒ||_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_dS)Nz%s.__init__(%s)é€)r r r>r‚r(Ú logfile_pathrUÚfilenoÚ read_sizeÚ record_readerÚrecord_receiverÚanalyzerrhÚ idle_proc_idr|rÅ)rrÒrrrr Rs zLogfileAnalyzer.__init__cCsT|dk r||_td|jj|jfƒy2tj|jƒ}|t|_t|jƒ|_ |j j ƒ|_ WnRt k r¨}z6t j t j d|jj|jfƒ|j|_|j|_|‚WYdd}~XnXd|_d|_d|_d|_d|_|jd|jƒtjj|jƒ}dtjj|ƒd|_td||jd�|_ttjƒ|_tƒ|_ t!ƒ|_"t#d d t$ƒ�sDt%|jƒ|_&n t'|jƒ|_&d S) Nz %s.open(%s)z %s.open(): %srgFrÐzfile: %s)r“ZtestrZT)(rÒr>r‚r(r¡r¤r¥Ú file_sizeÚopenrUrÓÚEnvironmentErrorrarbrÅr|Ú n_bytes_readZ line_countÚ record_countrÐÚ cancelledrËr¢ÚbasenameÚsplitextr“rrxZAuditRecordReaderZ TEXT_FORMATrÕZAuditRecordReceiverrÖrr×rÚboolrrhr)rrÒr¦rkZlogfile_basenamerrrrÚfs:     zLogfileAnalyzer.opencs6td|jj|jfƒ|jƒ‰tj‡fdd„ƒ|_dS)Nz %s.run(%s)cstˆƒS)N)Únextr)Útask_generatorrrr�sz%LogfileAnalyzer.run..T)r>r‚r(rUÚtaskr rÆrØ)rr)rãrrwŠszLogfileAnalyzer.runcCs¢|jdk r&tj|j|jƒ}d|_d|_|j|jkrdddl}d|j|j|jf}t |ƒ|j |_||_ |j dk rŒx|j j ƒD]}|j|ƒqzW|jsž|jddƒdS)NrzFfailed to read complete file, %d bytes read out of total %d bytes (%s)rÐgð?)rUr¡ÚreadrÓrÔrÜrÙr|rÒr>ZEIOrÅrÖÚcloseÚavc_event_handlerrÞrË)rÚnew_dataZErrnorÅrMrrrræ�s    zLogfileAnalyzer.closeccsx|jddƒ�xR|j�r`y8tj|j|jƒjdƒ}|dkrNtd|jƒ|jƒWn|t k rœ}z0|j |_ |j |_ |jƒ|jddƒdVWYdd}~Xn2t k rÌ}zt d|tjd �WYdd}~XnX|jt|ƒ7_|jd k�rt|jƒt|jƒ|_|jd |jƒxF|jj|ƒD]6\}}}}}|j|||||ƒd V|j�rdV�qWd VqW|jddƒdVdS) Nz state-changedZrunningzutf-8r»z EOF on %sZstoppedFr4)rUrrÐT)rËrÓr¡rårÔÚdecoder>rÒrærÛr|rÅrur^r_r`rÜr2rÙÚfloatrÐrÕÚfeedÚnew_audit_record_handlerrÞ)rrèrkÚ record_typeÚevent_idÚ body_textÚfieldsÚ line_numberrrrrä§s6    "    zLogfileAnalyzer.taskcCsHtd|ƒ|jƒrD|jƒ rD|jƒdkrDt|ƒ}|jj||jdƒdS)Nz"avc_event_handler() audit_event=%srF)r>Zis_avcZ is_grantedZ num_recordsZAVCr×rlrh)rrMrIrrrrçÆs z!LogfileAnalyzer.avc_event_handlerc CsŠtd|||fƒ|jd7_t|||||ƒ}xT|jj|ƒD]D}y|j|ƒWq>tk r€}zt|tj d�WYdd}~Xq>Xq>WdS)z"called to enter a new audit recordzBnew_audit_record_handler() record_type=%s event_id=%s body_text=%sr™)rUN) r>rÝZ AuditRecordrÖrërçrur^r_r`) rrírîrïrðrñZ audit_recordrMrkrrrrìÍsz(LogfileAnalyzer.new_audit_record_handler)N)N)r(r)r*r rÌrÍZ TYPE_FLOATrÎrÏr rÚrwrærärçrìrrrrr Js  $)+Z __future__rÚ__all__raZ gi.repositoryr r r¡rsr#rnrdr¤r_Ú functoolsr Zsetroubleshoot.configrZsetroubleshoot.avc_auditZsetroubleshoot.errcodeZsetroubleshoot.rpcZsetroubleshoot.rpc_interfacesZsetroubleshoot.signatureZsetroubleshoot.utilZsetroubleshoot.audit_dataZsetroubleshoot.xml_serializerr•Úobjectrr+rrorrrrrÁZSETroubleshootDatabaseInterfaceZ%SETroubleshootDatabaseNotifyInterfacerZ type_registerr rrrrÚsV    ()W x ) __pycache__/analyze.cpython-36.pyc000064400000054255152572267760013103 0ustar003 �Àn`œhã@sˆddlmZdddddddgZdd lZdd lmZmZdd lZdd lZdd l Z dd l Z dd l Z dd l Tdd l Z dd lmZdd lmZdd lTdd lTdd lTdd lTdd lTdd lTdd lTddlmZdd„ZGdd„deƒZGdd„deƒZGdd„deƒZGdd„dee j ƒZ!Gdd„deƒZ"Gdd„deƒZ#Gdd„deƒZ$Gdd„de%e&e'ejƒZ(ej)e(ƒGdd„dejƒZ*ej)e*ƒd S)é)Úprint_functionÚ AnalyzeThreadÚAnalyzeÚPluginReportReceiverÚTestPluginReportReceiverÚSETroubleshootDatabaseÚSETroubleshootDatabaseLocalÚLogfileAnalyzerN)ÚGObjectÚGLib)Ú*)Ú cmp_to_key)Ú get_config)Úvalidate_database_doccCs||k||kS)N©)ÚxÚyrrú/usr/lib/python3.6/analyze.pyÚ4src@s<eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd S)ÚPluginStatisticscCs0|j|_d|_d|_d|_d|_d|_d|_dS)N)Ú analysis_idÚnameÚanalyze_start_timeÚanalyze_end_timeÚanalyze_elapsed_timeÚreport_start_timeÚreport_end_timeÚreport_elapsed_time)ÚselfÚpluginrrrÚ__init__=szPluginStatistics.__init__cCsRt|jƒ}|jdkr"d|j|fSt|j|jƒ}t|jƒ}d|j|||fSdS)Nz%s: %s elapsedz5%s: %s elapsed, %s analyze elapsed, %s report elapsed)Úformat_elapsed_timerrrrr)rrZtotal_elapsed_timerrrrÚ__str__Fs   zPluginStatistics.__str__cCstjƒ|_dS)N)Útimer)rrrrÚ analyze_startRszPluginStatistics.analyze_startcCstjƒ|_|j|j|_dS)N)r#rrr)rrrrÚ analyze_endUs zPluginStatistics.analyze_endcCstjƒ|_dS)N)r#r)rrrrÚ report_startYszPluginStatistics.report_startcCstjƒ|_|j|j|_dS)N)r#rrr)rrrrÚ report_end\s zPluginStatistics.report_endN) Ú__name__Ú __module__Ú __qualname__r r"r$r%r&r'rrrrr;s   rc@s<eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd S)ÚAnalyzeStatisticscCs(||_d|_g|_d|_d|_d|_dS)N)Ú num_pluginsÚ cur_pluginÚcalled_pluginsÚ start_timeÚend_timeÚ elapsed_time)rr,rrrr es zAnalyzeStatistics.__init__cCsPd}d}t|jƒ}|jdk r8t|jƒ}|r8t|j|ƒ}d||j|||jƒfS)NzB%d/%d plugins in %s elapsed, avg plugin %s elapsed, plugins=[ %s ])Úlenr.r1r!r,Úcalled_plugins_to_string)rr1Zavg_plugin_timeZn_calledrrrr"ms    zAnalyzeStatistics.__str__cCsdjdd„|jDƒƒS)NÚ cSsg|] }t|ƒ‘qSr)Ústr)Ú.0rrrrú {sz>AnalyzeStatistics.called_plugins_to_string..)Újoinr.)rrrrr3zsz*AnalyzeStatistics.called_plugins_to_stringcCstjƒ|_dS)N)r#r/)rrrrÚstart}szAnalyzeStatistics.startcCstjƒ|_|j|j|_dS)N)r#r0r/r1)rrrrÚend€s zAnalyzeStatistics.endcCs&t|ƒ|_|jj|jƒ|jjƒdS)N)rr-r.Úappendr$)rrrrrÚ new_plugin„s zAnalyzeStatistics.new_pluginN) r(r)r*r r"r3r9r:r<rrrrr+cs  r+c@s.eZdZdd„Zdd„Zdd„Zd dd „Zd S) rcCstƒ|_tdt|jƒƒdS)NzNumber of Plugins = %d)Z load_pluginsÚpluginsÚ log_debugr2)rrrrr ŽszAnalyze.__init__cCstƒ}|r|jƒ|S)N)Z SEEnvironmentÚupdate)rÚquery_environmentÚ environmentrrrÚget_environment’szAnalyze.get_environmentcCs$t|j|j|j|j|j|jd�}|S)N)ÚhostÚaccessÚscontextÚtcontextÚtclassÚtpath)ZSEFaultSignaturerCrDrErFrGrH)rÚavcrAÚsigrrrÚ get_signature˜s zAnalyze.get_signatureTcCsÎtd|ƒ|jƒ|j|jƒ}ddlm}|jjdk rD|jjjƒt |j|j |j |j |j |j|j|j|j|j|j|j||ƒ||jjt|jjƒ|jƒdd�}�x |jD�]}yš|j|ƒ}|dk �rD|jdkrØtdƒdS|jdk oê|jdk�r|jdk�s|jd k�r|j|_t|tƒ�r8x(|D]} |jj| ƒ�q Wn |jj|ƒWq¦tk �rº} zVt | t!j"d �t#j#t#j$d |j%ƒt!j&ƒ\} } } td j't(j)| ƒƒƒ|jj*|ƒWYdd} ~ Xq¦Xq¦W|j+|ƒdS) Nzanalyze_avc() avc=%sr)ÚTemplateZyellow)Ú audit_eventÚsourceÚspathrHZ src_rpm_listZ tgt_rpm_listrErFrGÚportrCrJrAÚ line_numbersÚlast_seen_dateÚlocal_idÚlevelZwhitez!plugin level white, not reportingZredZgreen)ÚfilezPlugin Exception %s r4),r>r?rBr@ÚstringrLrMrQÚsortZSEFaultSignatureInforNrOrHZsrc_rpmsZtgt_rpmsrErFrGrPrCrKÚ TimeStampZ timestampÚ generate_idr=ÚanalyzerTÚ isinstanceÚlistZ plugin_listr;Ú ExceptionÚprintÚsysÚstderrÚsyslogÚLOG_ERRrÚexc_infor8Ú tracebackÚ format_tbÚremoveÚreport_problem)rrIÚreport_receiverr@rArLÚsiginforZreportÚrÚeZv1Zv2Zv3rrrÚ analyze_avc¢sZ            "zAnalyze.analyze_avcN)T)r(r)r*r rBrKrlrrrrrŒs c@seZdZddd„Zdd„ZdS)ré cCs&tjj|ƒtj|ƒ||_||_dS)N)Ú threadingÚThreadr rÚqueueÚtimeout)rrprqrrrr ås  zAnalyzeThread.__init__cCsÊxÄy6|jjƒ\}}tjtjdƒtjdƒ|j||ƒWnftk rl}ztjtjd|ƒWYdd}~Xn4t k rž}ztjtjd|ƒWYdd}~XnXtjtjdj |j ƒƒtj|j ƒqWdS)Nz)AnalyzeThread.run(): Cancel pending alarmrz!Exception during AVC analysis: %sz,AnalyzeThread.run(): Set alarm timeout to {}) rpÚgetraZ LOG_DEBUGÚsignalÚalarmrlr]rbÚ ValueErrorÚformatrq)rrIrhrkrrrÚrunís "$zAnalyzeThread.runN)rm)r(r)r*r rwrrrrrãs c@s$eZdZdd„Zdd„Zdd„ZdS)rcCs ||_dS)N)Údatabase)rrxrrrr szPluginReportReceiver.__init__cCs‚y0|jj|jƒ}|j|ƒ|jj|ƒtdƒWnLtk r|}z0|jtkrjtdƒ|j |_ |jj |ƒ}n‚WYdd}~XnX|S)Nzsignature found in databaseznot in database yet) rxÚlookup_signaturerJZ update_mergeÚmodify_siginfor>Ú ProgramErrorÚerrnoÚERR_NO_SIGNATURE_MATCHrRÚfirst_seen_dateÚ add_siginfo)rriZdatabase_siginforkrrrrgs    z#PluginReportReceiver.report_problemcCs |jjjƒS)N)rxÚsigsZgenerate_local_id)rrrrrYsz PluginReportReceiver.generate_idN)r(r)r*r rgrYrrrrrþscs$eZdZ‡fdd„Zdd„Z‡ZS)rcstt|ƒj|ƒdS)N)Úsuperrr )rrx)Ú __class__rrr sz!TestPluginReportReceiver.__init__cCstd|jjƒdS)NzAnalysis Result: %s)r^rJr)rrirrrrgsz'TestPluginReportReceiver.report_problem)r(r)r*r rgÚ __classcell__rr)r‚rrs c@sÎeZdZd2dd„Zdd„Zdd„Zdd „Zd d „Zd3d d„Zd4dd„Z dd„Z dd„Z dd„Z dd„Z dd„Zdd„Zdd„Zdd „Zd!d"„Zd5d#d$„Zd%d&„Zd'd(„Zd)d*„Zd6d,d-„Zd.d/„Zd0d1„ZdS)7rNcCsª||_d|_t|||jƒ|_tjƒ|_d|_d|_d|_ d|_ d|_ t ddt ƒ|_d|_t ddƒ}|dk r€|jƒ}|r€t|ƒ|_td|jj|jj|jjfƒ|jƒdS) NFrééÈrxÚ max_alertsÚ max_alert_agezrÚ friendly_nameÚload)rrˆrr“r‡rrrr $s$   zSETroubleshootDatabase.__init__cCs”|jp |jsdS|jjjtdd„ƒd�|j�rtƒ}||j8}d}x$|jjD]}|j|kr^P|d7}qNW|dk�rtd|j|j ƒfƒtd|jjdjj ƒ|jj|djj ƒfƒtd |jj|jj ƒ|jjdjj ƒfƒd d „|jjd|…Dƒ}x|D]}|j |d d ��qW|j�r�t |jjƒ|j}|dk�r�dd „|jjd|…Dƒ}td|t |ƒ|fƒx|D]}|j |d d ��qxWdS)NFcSst|j|jƒS)N)ÚcmprR)ÚaÚbrrrr?sz.SETroubleshootDatabase.prune..)Úkeyréz5prune by age: max_alert_age=%s min_time_to_survive=%szprune by age: pruning [%s - %s]zprune by age: keeping [%s - %s]cSsg|] }|j‘qSr)rJ)r6rirrrr7Osz0SETroubleshootDatabase.prune..T)ÚprunecSsg|] }|j‘qSr)rJ)r6rirrrr7Vsz*prune first %d alerts, len(sigs=%d sigs=%séÿÿÿÿ) r†r‡r€Úsignature_listrWr rXrRr>rvÚdelete_signaturer2)rZmin_time_to_surviveZkeeprir€rJrrrrš:s2     0,   zSETroubleshootDatabase.prunecCs ||_dS)N)r‰)rr‰rrrÚ set_notify[sz!SETroubleshootDatabase.set_notifycCs6x0|jjD]$}|j|jkr |j}|j|_||_q WdS)N)r€rœrRr~)rriZtmprrrÚvalidate^s  zSETroubleshootDatabase.validatecCshtƒ|_|jdkrdStjj|jƒrTtj|jƒ}|tdkrT|jj|jdt ƒrTd|_ |j ƒ|j ƒdS)Nrr€T) ÚSEFaultSignatureSetr€rˆÚosÚpathÚexistsÚstatÚST_SIZEZ read_xml_filerrŒrŸrš)rÚ stat_inforrrr”fs   zSETroubleshootDatabase.loadFcCsj|jdkrdStd|j|jfƒ|s.|jƒ|jjd|jƒd|_d|_|jdk rftj |jƒd|_dS)Nz'writing database (%s) modified_count=%sr€Tr) rˆr>r�ršr€Z write_xmlrŒr�r Z source_remove)rršrrrÚsaveus   zSETroubleshootDatabase.savecCs`|jd7_|jdkrdS|j|jks0|j r<|j|ƒn |jdkr\tj|jd|j ƒ|_dS)Nr™iè) r�rˆr�rŒr§r�r Z timeout_addrŽÚauto_save_callback)rršrrrÚ mark_modified„s    z$SETroubleshootDatabase.mark_modifiedcCs td|j|jfƒ|jƒdS)Nz)auto_save database (%s) modified_count=%sF)r>rˆr�r§)rrrrr¨�sz)SETroubleshootDatabase.auto_save_callbackcCs:|jdkrdStjj|jƒr6td|jƒtj|jƒdS)Nzdeleting database (%s))rˆr¡r¢r£r>rf)rrrrrf•s  zSETroubleshootDatabase.removecCs|jjƒdS)N)r‹Úacquire)rrrrrªœszSETroubleshootDatabase.acquirecCs|jjƒdS)N)r‹Úrelease)rrrrr«ŸszSETroubleshootDatabase.releasecCs†d}|jj|ƒ}tdt|ƒdjdd„|Dƒƒfƒt|ƒdkrHttƒ‚t|ƒdkrxtdt|ƒdjdd„|Dƒƒfƒ|dj}|S)Nz1lookup_signature: found %d matches with scores %sú,cSsg|]}d|j‘qS)z%.2f)Úscore)r6rrrrr7¦sz;SETroubleshootDatabase.lookup_signature..rr™cSsg|]}d|j‘qS)z%.2f)r­)r6rrrrr7ªs)r€Zmatch_signaturesr>r2r8r{r}ri)rrJriZmatchesrrrry¢s $  $ z'SETroubleshootDatabase.lookup_signaturecCs2|jj|ƒ}|dkr.td|ƒttd|ƒ‚|S)Nzlookup_local_id: %s not foundzid (%s) not found)r€Úlookup_local_idr>r{ZERR_SIGNATURE_ID_NOT_FOUND)rrSrirrrr®®s   z&SETroubleshootDatabase.lookup_local_idcCs.|jj|ƒ}|jr"|jjd|jƒ|jƒ|S)NÚadd)r€rr‰Úsignatures_updatedrSr©)rrirrrrµs  z"SETroubleshootDatabase.add_siginfocCs|jS)N)rŠ)rrrrÚget_properties¼sz%SETroubleshootDatabase.get_propertiescCs8td|ƒ|dkr|jStƒ}|j|ƒ}|j|ƒ|S)Nzquery_alerts: criteria=%sr )r>r€r r®r)rZcriteriar€rirrrÚ query_alerts¿s   z#SETroubleshootDatabase.query_alertscCs†td|ƒy|j|ƒ}Wn:tk rT}z|jtkrBtdƒdS‚WYdd}~XnX|jj|ƒ|jrx|jjd|j ƒ|j |ƒdS)Nzdelete_signature: sig=%szSignature not found!Údelete) r>ryr{r|r}r€Zremove_siginfor‰r°rSr©)rrJršrirkrrrr�Ës   z'SETroubleshootDatabase.delete_signaturecCs"|jr|jjd|jƒ|jƒdS)NZmodify)r‰r°rSr©)rrirrrrzÜsz%SETroubleshootDatabase.modify_siginfocCshtd||fƒy|j|ƒ}Wn:tk rX}z|jtkrFtdƒdS‚WYdd}~XnX|j|ƒ}|S)Nz)evaluate_alert_filter: username=%s sig=%szSignature not found!Úignore)r>ryr{r|r}Zevaluate_filter_for_user)rrJÚusernamerirkÚactionrrrÚevaluate_alert_filterás  z,SETroubleshootDatabase.evaluate_alert_filtercCs‚td||||fƒy|j|ƒ}Wn:tk r\}z|jtkrJtdƒdS‚WYdd}~XnX|j|ƒ}|j||ƒ|j|ƒdS)Nz2set_user_data: username=%s item=%s data=%s sig= %szSignature not found!)r>ryr{r|r}Z get_user_dataZ update_itemrz)rrJrµÚitemÚdatarirkZ user_datarrrÚ set_user_dataðs   z$SETroubleshootDatabase.set_user_dataÚcCsxtd|||fƒy|j|ƒ}Wn:tk rZ}z|jtkrHtdƒdS‚WYdd}~XnX|j|||ƒ|j|ƒdS)Nz.set_filter: username=%s filter_type=%s sig= %szSignature not found!)r>ryr{r|r}Zupdate_user_filterrz)rrJrµZ filter_typer¹rirkrrrÚ set_filters z!SETroubleshootDatabase.set_filtercCs|jjj|ƒ|_|jƒdS)N)r€ÚusersÚadd_userÚuserr©)rrµrrrr¾szSETroubleshootDatabase.add_usercCs|jjj|ƒS)N)r€r½Úget_user)rrµrrrrÀszSETroubleshootDatabase.get_user)N)F)F)F)r»)r(r)r*r ršržrŸr”r§r©r¨rfrªr«ryr®rr±r²r�rzr·rºr¼r¾rÀrrrrr"s. !     c@s^eZdZejjdejejffejjdejejejffdœZ dd„Z dd„Z dd„Z d d „Z dS) rN)r°z async-errorcCs,tjj|ƒtj|ƒ||_|jj|ƒdS)N)r r Ú RpcManagerxrž)rrxrrrr %s  z$SETroubleshootDatabaseLocal.__init__cCs|jj|ƒdS)N)rxrž)rr‰rrrrž+sz&SETroubleshootDatabaseLocal.set_notifycGsàtd|jj|jdjdd„|Dƒƒ|fƒ|j|}t|j|jdƒ}|dkrdtt d|j|jjfƒ‚y(||Ž|_ d|_ |j dk rŠ|j g|_ Wn6tk rÂ}z|j |j g|_ d|_ WYdd}~XnX|j dk rÜtj|j|ƒdS)Nz%s emit %s(%s) id=%sr¬cSsg|] }t|ƒ‘qSr)r5)r6Úargrrrr7/sz8SETroubleshootDatabaseLocal.emit_rpc..z'method %s not found in base class of %sZ method_returnZ error_return)r>r‚r(Úmethodr8Zasync_rpc_cacheÚgetattrrxr{ZERR_METHOD_NOT_FOUNDZ return_argsZ return_typer|Ústrerrorr Úidle_addZprocess_async_return)rZrpc_idÚtypeZrpc_defÚargsZ async_rpcÚfuncrkrrrÚemit_rpc.s *    z$SETroubleshootDatabaseLocal.emit_rpccCs"td||fƒ|jd||ƒdS)Nz4signatures_updated() database local: type=%s item=%sr°)r>Úemit)rrÇr¸rrrr°Asz.SETroubleshootDatabaseLocal.signatures_updated)r(r)r*r Ú SignalFlagsÚRUN_LASTÚ TYPE_PYOBJECTZ TYPE_STRINGZTYPE_INTÚ __gsignals__r ržrÊr°rrrrrs c@sneZdZejjdejffejjdejffdœZddd„Z ddd„Z dd„Z d d „Z d d „Z d d„Zdd„ZdS)r N)Úprogressz state-changedcCsftjj|ƒtd|jj|fƒ||_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_dS)Nz%s.__init__(%s)é€)r r r>r‚r(Ú logfile_pathrUÚfilenoÚ read_sizeÚ record_readerÚrecord_receiverÚanalyzerrhÚ idle_proc_idr|rÅ)rrÒrrrr Rs zLogfileAnalyzer.__init__cCsT|dk r||_td|jj|jfƒy2tj|jƒ}|t|_t|jƒ|_ |j j ƒ|_ WnRt k r¨}z6t j t j d|jj|jfƒ|j|_|j|_|‚WYdd}~XnXd|_d|_d|_d|_d|_|jd|jƒtjj|jƒ}dtjj|ƒd|_td||jd�|_ttjƒ|_tƒ|_ t!ƒ|_"t#d d t$ƒ�sDt%|jƒ|_&n t'|jƒ|_&d S) Nz %s.open(%s)z %s.open(): %srgFrÐzfile: %s)r“ZtestrZT)(rÒr>r‚r(r¡r¤r¥Ú file_sizeÚopenrUrÓÚEnvironmentErrorrarbrÅr|Ú n_bytes_readZ line_countÚ record_countrÐÚ cancelledrËr¢ÚbasenameÚsplitextr“rrxZAuditRecordReaderZ TEXT_FORMATrÕZAuditRecordReceiverrÖrr×rÚboolrrhr)rrÒr¦rkZlogfile_basenamerrrrÚfs:     zLogfileAnalyzer.opencs6td|jj|jfƒ|jƒ‰tj‡fdd„ƒ|_dS)Nz %s.run(%s)cstˆƒS)N)Únextr)Útask_generatorrrr�sz%LogfileAnalyzer.run..T)r>r‚r(rUÚtaskr rÆrØ)rr)rãrrwŠszLogfileAnalyzer.runcCs¢|jdk r&tj|j|jƒ}d|_d|_|j|jkrdddl}d|j|j|jf}t |ƒ|j |_||_ |j dk rŒx|j j ƒD]}|j|ƒqzW|jsž|jddƒdS)NrzFfailed to read complete file, %d bytes read out of total %d bytes (%s)rÐgð?)rUr¡ÚreadrÓrÔrÜrÙr|rÒr>ZEIOrÅrÖÚcloseÚavc_event_handlerrÞrË)rÚnew_dataZErrnorÅrMrrrræ�s    zLogfileAnalyzer.closeccsx|jddƒ�xR|j�r`y8tj|j|jƒjdƒ}|dkrNtd|jƒ|jƒWn|t k rœ}z0|j |_ |j |_ |jƒ|jddƒdVWYdd}~Xn2t k rÌ}zt d|tjd �WYdd}~XnX|jt|ƒ7_|jd k�rt|jƒt|jƒ|_|jd |jƒxF|jj|ƒD]6\}}}}}|j|||||ƒd V|j�rdV�qWd VqW|jddƒdVdS) Nz state-changedZrunningzutf-8r»z EOF on %sZstoppedFr4)rUrrÐT)rËrÓr¡rårÔÚdecoder>rÒrærÛr|rÅrur^r_r`rÜr2rÙÚfloatrÐrÕÚfeedÚnew_audit_record_handlerrÞ)rrèrkÚ record_typeÚevent_idÚ body_textÚfieldsÚ line_numberrrrrä§s6    "    zLogfileAnalyzer.taskcCsHtd|ƒ|jƒrD|jƒ rD|jƒdkrDt|ƒ}|jj||jdƒdS)Nz"avc_event_handler() audit_event=%srF)r>Zis_avcZ is_grantedZ num_recordsZAVCr×rlrh)rrMrIrrrrçÆs z!LogfileAnalyzer.avc_event_handlerc CsŠtd|||fƒ|jd7_t|||||ƒ}xT|jj|ƒD]D}y|j|ƒWq>tk r€}zt|tj d�WYdd}~Xq>Xq>WdS)z"called to enter a new audit recordzBnew_audit_record_handler() record_type=%s event_id=%s body_text=%sr™)rUN) r>rÝZ AuditRecordrÖrërçrur^r_r`) rrírîrïrðrñZ audit_recordrMrkrrrrìÍsz(LogfileAnalyzer.new_audit_record_handler)N)N)r(r)r*r rÌrÍZ TYPE_FLOATrÎrÏr rÚrwrærärçrìrrrrr Js  $)+Z __future__rÚ__all__raZ gi.repositoryr r r¡rsr#rnrdr¤r_Ú functoolsr Zsetroubleshoot.configrZsetroubleshoot.avc_auditZsetroubleshoot.errcodeZsetroubleshoot.rpcZsetroubleshoot.rpc_interfacesZsetroubleshoot.signatureZsetroubleshoot.utilZsetroubleshoot.audit_dataZsetroubleshoot.xml_serializerr•Úobjectrr+rrorrrrrÁZSETroubleshootDatabaseInterfaceZ%SETroubleshootDatabaseNotifyInterfacerZ type_registerr rrrrÚsV    ()W x ) __pycache__/audit_data.cpython-36.opt-1.pyc000064400000066655152572267760014505 0ustar003 �Àn`Ç�ã@sdddlmZddlZddlmZddlZdddddd d d gZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z dd lTddljZdd lTdd lTdd lTdd lTd Zdd„ZeƒZdd„Zdd„Ze jdƒZdd„Ze jdƒZdd„Zddl Z dd„Z!Gdd„de"ƒZ#Gdd„de"ƒZ$Gdd „d e"ƒZ%Gdd „d ƒZ&Gdd „d e"ƒZ'Gdd„dƒZ(dS) é)Úabsolute_importN)ÚrangeÚderive_record_formatÚparse_audit_record_textÚ AvcContextÚAVCÚ AuditEventIDÚ AuditEventÚ AuditRecordÚAuditRecordReader)Ú*écCs||k||kS)N©)ÚxÚyrrú /usr/lib/python3.6/audit_data.pyÚ6srcCs t|ƒ\}}}}t|||ƒ}|S)N)rr )ÚtextÚparse_succeededÚ record_typeÚevent_idÚ body_textÚ audit_recordrrrÚaudit_record_from_text@s rcCs*tjd|ƒrtjStjd|ƒr$tjStjS)Nz/audispd_events$z/audit_events$)ÚreÚsearchr Ú TEXT_FORMATÚ BINARY_FORMAT)Z socket_pathrrrrHs   zL(node=(\S+)\s+)?(type=(\S+)\s+)?(msg=)?audit\(((\d+)\.(\d+):(\d+))\):\s*(.*)c Csªd}d}d}d}d}tj|ƒ}|dk ržd}|jdƒr>|jdƒ}|jdƒrR|jdƒ}|jdƒr”t|jdƒƒ}t|jdƒƒ}t|jdƒƒ} t||| |ƒ}|jd ƒ}||||fS) NFTéééééé é )Úaudit_input_rerÚgroupÚintr) ÚinputrÚhostrrrÚmatchÚsecondsÚmilliÚserialrrrras&       z%audit\(((\d+)\.(\d+):(\d+))\):\s*(.*)cCsvd}d}d}tj|ƒ}|dk rld}|jdƒrbt|jdƒƒ}t|jdƒƒ}t|jdƒƒ}t|||ƒ}|jdƒ}|||fS)NFTérr ré)Úaudit_binary_input_rerr&r'r)r(rrrr*r+r,r-rrrÚparse_audit_binary_texts    r1cCs"|rdd„|Dƒ}||krdSdS)NcSsg|]}|tjkr|‘qSr)ÚstringÚ printable)Ú.0rrrrú ™szprintable..TFr)ÚsZ filtered_pathrrrr3—s r3csZeZdZddiddiddiddidœZ‡fdd„Zdd„Zdd „Zd d „Zd d „Z‡Z S)rÚXMLFormÚ attribute)ÚuserÚroleÚtypeÚmlscsztt|ƒjƒt|tjƒrv|jdƒ}t|ƒdkrv|d|_|d|_ |d|_ t|ƒdkrpdj |dd…ƒ|_ nd|_ dS)Nú:r rr.rZs0) ÚsuperrÚ__init__Ú isinstanceÚsixZ string_typesÚsplitÚlenr9r:r;Újoinr<)ÚselfÚdataÚfields)Ú __class__rrr?§s       zAvcContext.__init__cCsd|j|j|j|jfS)Nz %s:%s:%s:%s)r9r:r;r<)rErrrÚ__str__´szAvcContext.__str__cCstjt|ƒƒ\}}|S)N)ÚselinuxZselinux_raw_to_trans_contextÚstr)rEZrcZtransrrrÚformat·szAvcContext.formatcCs |j|ƒ S)N)Ú__eq__)rEÚotherrrrÚ__ne__¼szAvcContext.__ne__cCs4x.t|jjƒƒD]}t||ƒt||ƒkrdSqWdS)NFT)ÚlistÚ _xml_infoÚkeysÚgetattr)rErNÚnamerrrrM¿szAvcContext.__eq__) Ú__name__Ú __module__Ú __qualname__rQr?rIrLrOrMÚ __classcell__rr)rHrrŸs  csveZdZdedœdedœdedœddidœZd‡fdd„ Zdd „Zd d „Zd d „Ze dd„ƒZ dd„Z dd„Z ‡Z S)rr8)r7Úimport_typecastr7)r+r,r-r)Ncs2tt|ƒjƒ||_||_||_|dk r.||_dS)N)r>rr?r+r,r-r))rEr+r,r-r))rHrrr?Ðs zAuditEventID.__init__cCsD|j|jkrdS|j|jkr dS|j|jkr0dS|j|jkr@dSdS)NFT)r)r+r,r-)rErNrrrrMØs    zAuditEventID.__eq__cCsb|j|jkr&td|jj|j|jfƒ‚|j|jkr>|j|jkS|j|jkrV|j|jkS|j|jkS)Nz?cannot compare two %s objects whose host values differ (%s!=%s))r)Ú ValueErrorrHrUr+r,r-)rErNrrrÚ__lt__ãs     zAuditEventID.__lt__cCsddl}|j|ƒS)Nr)Úcopy)rEr\rrrr\ïszAuditEventID.copycCst|jƒ|jdS)Ng@�@)ÚfloatZsecr,)rErrrrószAuditEventID.cCsd|j|j|jfS)Nzaudit(%d.%d:%d))r+r,r-)rErrrrIõszAuditEventID.__str__cCs.|jdkrdS|jdkrdS|jdkr*dSdS)NFT)r+r,r-)rErrrÚis_validøs   zAuditEventID.is_valid)N)rUrVrWr'rQr?rMr[r\ÚpropertyZtimerIr^rXrr)rHrrÈs    csØeZdZddidedœddidedœdœZdZdZej eƒZ e j dƒZ e j d ƒZe j d ƒZd(‡fd d „ Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd&d'„Z‡ZS))r r7r8Úelement)r7rY)rrrÚ line_numberrZiiiiz([^ \t]+)\s*=\s*([^ \t]+)z$avc:\s+([^\s]+)\s+{([^}]+)}\s+for\s+z^a\d+$Ncs8tt|ƒjƒ||_||_||_||_||_|jƒdS)N) r>r r?rrrrGraÚ_init_postprocess)rErrrrGra)rHrrr?szAuditRecord.__init__cCsrt|ddƒdkr|j|jƒ|jd krnd|jkrntjj|jƒ}|rn|jdƒ}||jd<|jdƒ}|j ƒ|jd <dS) NrGrÚUSER_AVCÚ1400Ú1107Úseresultr.rÚseperms)rrcrdre) rSÚset_fields_from_textrrrGr Úavc_rerr&rB)rEr*rfrgrrrrbs      zAuditRecord._init_postprocesscCs|jƒS)N)Ú to_host_text)rErrrrI+szAuditRecord.__str__cCs d|_|jjdkrtƒ|j_dS)N)rarr)Z get_hostname)rErrrÚaudispd_rectify.s zAuditRecord.audispd_rectifycCs.|jjƒsdS|jdkrdS|jdkr*dSdS)NFT)rr^rÚmessage)rErrrr^3s   zAuditRecord.is_validcCs¾ddddddddd d d d d dddg}xF|D]>}||jkr*|jdkrL|dkrLq*|j|}t|ƒ}||j|<q*W|jdkrºxBt|jjƒƒD]0\}}|jj|ƒr†|j|}t|ƒ}||j|<q†WdS)NZacctÚcmdÚcommÚcwdrFÚdirÚexeÚfiler)ÚkeyÚmsgrTÚnewZocommoldÚpathZwatchrZsaddrZEXECVE)rGrZaudit_msg_decoderPÚitemsÚ exec_arg_rer)rEZencoded_fieldsZfieldÚvalueZ decoded_valuerrrÚ decode_fields<s       zAuditRecord.decode_fieldsc Cs<y,tjddkr|jdƒStj|ƒjdƒSWn |SdS)Nrr Úhexzutf-8)ÚsysÚ version_infoÚdecodeÚ bytearrayÚfromhex)rErvrrrÚ translate_hexPs  zAuditRecord.translate_hexcCs g|_i|_�xötjj|ƒD]æ}|jdƒ}|jdƒ}|jdƒ}y˜|dkrbtjt |dƒƒ}tj |ƒ}|dkr„|jdƒj dƒs„|j |ƒ}|d kr°yt jtt |ƒƒ}Wn YnX|d krÔtjt |ƒtjƒƒ}|rÔ|}Wntk rêYnX||j|<|jj|ƒqWdS)Nr.rú"ÚarchérTrvrnrmrqroÚexitÚsyscall)rTrvrnrmrqro)Ú fields_ordrGr Úkey_value_pair_reÚfinditerr&ÚstripÚauditZaudit_elf_to_machiner'Zaudit_machine_to_nameÚ startswithr�ÚerrnoÚ errorcodeÚabsZaudit_syscall_to_nameZaudit_detect_machinerZÚappend)rErr*rsryÚiZ syscall_namerrrrh_s4      z AuditRecord.set_fields_from_textcCs |jj|ƒS)N)rGÚget)rErTrrrÚ get_field�szAuditRecord.get_fieldcCs"t|ƒ}tjtjtjtj|j|ƒS)N)rCÚstructÚpackr Úbinary_header_formatÚbinary_versionÚbinary_header_sizer)rErtÚ msg_lengthrrrÚget_binary_header„s zAuditRecord.get_binary_headercsjˆjdkrdSˆjdkr4dˆjˆjdjˆjƒf}ndˆjˆjf}|dj‡fdd„ˆjDƒƒd7}|S) NÚrz#type=%s msg=%s: avc: denied { %s } ú ztype=%s msg=%s: csg|]}d|ˆj|f‘qS)z%s=%s)rG)r4Úk)rErrr5�sz.AuditRecord.fields_to_text..Ú )rGrrrDÚaccessr‡)rEZbufr)rErÚfields_to_text‰s  "zAuditRecord.fields_to_textcCsd|j|j|jfS)Nztype=%s msg=%s: %s )rrr)rErrrÚto_text“szAuditRecord.to_textcCs2|jjdk r&d|jj|j|j|jfS|jƒSdS)Nznode=%s type=%s msg=%s: %s )rr)rrr¡)rErrrrj–s zAuditRecord.to_host_textcCsd|j|jf}|j|ƒ|S)Nz%s: %s)rrrš)rEÚrecordrrrÚ to_binary�szAuditRecord.to_binary)NN)rUrVrWrr'rQr—r–r”Úcalcsizer˜rÚcompilerˆrirxr?rbrIrkr^rzr�rhr“ršr r¡rjr£rXrr)rHrr s0      " c@s,eZdZdZdZdd„Zdd„Zdd„Zd S) r r.rcCsV||_d|_d|_|j|jkr(|j|_n*|j|jkr>|j|_ntd||j j fƒ‚dS)Nr›rz unknown record format (%s) in %s) Ú record_formatÚ _input_bufferrarÚ feed_textZfeedrÚ feed_binaryrZrHrU)rEr¦rrrr?¨s    zAuditRecordReader.__init__c csÂt|ƒdkrdS|j|7_xžt|jƒtjkr4dStjtj|jdtj…ƒ\}}}}tj|}t|jƒ|krrdS|jtj|…}t|ƒ\}} } |j|d…|_|r tj |ƒ| | ddfVq WdS)Nr) rCr§r r˜r”Úunpackr–r1r‹Zaudit_msg_type_to_name) rEÚnew_datar—r˜rr™Z total_lenrrrrrrrr©´s"  zAuditRecordReader.feed_binaryc cs®t|ƒdkrdS|j|7_d}|jjd|ƒ}xh|dkr˜|jd7_|d7}|j||…}t|ƒ\}}}}|r„|||d|jfV|}|jjd|ƒ}q2W|j|d…|_dS)Nrržr.)rCr§Úfindrar) rEr«ÚstartÚendÚlinerrrrrrrr¨Õs   zAuditRecordReader.feed_textN)rUrVrWrrr?r©r¨rrrrr ¤s  !cs¤eZdZddedœdedœdœZ‡fdd„Zdd „Zd d „Zd$d d„Z dd„Z e dd„ƒZ dd„Z dd„Zd%dd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Z‡ZS)&r r`r)r7rPrY)r7rY)Úrecordsrcs*tt|ƒjƒd|_g|_i|_d|_dS)N)r>r r?rr°Ú record_typesÚ timestamp)rE)rHrrr?÷s zAuditEvent.__init__cCs4t|ddƒdkri|_x|jD]}|j|ƒqWdS)Nr±)rSr±r°Úprocess_record)rEr¢rrrrbþs zAuditEvent._init_postprocesscCsL|j}|jƒd|j|jƒ|jƒdjdd„|Dƒƒdjdd„|jDƒƒfS)Nz2%s: is_avc=%s, is_granted=%s: line_numbers=[%s] %sú,cSsg|] }t|ƒ‘qSr)rK)r4rrrrr5 sz&AuditEvent.__str__..ržcSsg|] }d|‘qS)z %sr)r4r¢rrrr5 s)Ú line_numbersÚsortrÚis_avcÚ is_grantedrDr°)rErµrrrrIs zAuditEvent.__str__ržcCs|jdd„|jDƒƒS)NcSsg|] }t|ƒ‘qSr)rK)r4r¢rrrr5sz%AuditEvent.format..)rDr°)rEZ separatorrrrrL szAuditEvent.formatcCs t|jƒS)N)rCr°)rErrrÚ num_recordsszAuditEvent.num_recordscCsdd„|jDƒS)NcSsg|]}|jr|j‘qSr)ra)r4r¢rrrr5sz'AuditEvent...)r°)rErrrrszAuditEvent.cCs|jj|ƒ|j|ƒdS)N)r°r�r³)rEr¢rrrÚ add_records zAuditEvent.add_recordcCsp|jdkr2|jjƒ|_t|jjƒ|jjd|_n |j|jksRtd|j|jfƒ‚|jj|j gƒ}|j |ƒdS)Ng@�@zBcannot add audit record to audit event, event_id mismatch %s != %s) rr\r]r+r,r²rZr±Ú setdefaultrr�)rEr¢Z record_listrrrr³s   zAuditEvent.process_recordNcCsVg}|dkr|j}n |j|ƒ}x2|D]*}|jj|ƒ}|dkr>q$|j||jfƒq$W|S)aNReturn list of (value, record_type) tuples. In other words return the value matching name for every record_type. If record_type is not specified then all records are searched. Note: it is possible to have more than one record of a given type thus it is always possible to have multiple values returned.N)r°Úget_records_of_typerGr’r�r;)rErTrrwr°r¢ryrrrr“%s   zAuditEvent.get_fieldcCs d}|jj|ƒ}|r|d}|S)Nr)r±r’)rEr;r¢r°rrrÚget_record_of_type9s  zAuditEvent.get_record_of_typecCs|jj|gƒS)N)r±r’)rEr;rrrr¼@szAuditEvent.get_records_of_typecCs$xdD]}|j|ƒ}|r|SqWdS)Nrrcrdre)rrcrdre)r½)rErr¢rrrÚget_avc_recordCs  zAuditEvent.get_avc_recordcCs |jƒdk S)N)r¾)rErrrr·IszAuditEvent.is_avccCsH|jƒ}|dkrdS|jd}|dkr*dS|dkr6dStjjd|ƒdS)NFrfZdeniedZgrantedTz!unknown value for seresult ('%s'))r¾rGÚlogZavcÚwarn)rEÚ avc_recordrfrrrr¸Ls zAuditEvent.is_granted)rž)N)rUrVrWr rrQr?rbrIrLr¹r_rµrºr³r“r½r¼r¾r·r¸rXrr)rHrr ñs      c@s|eZdZdgZddgZdddddgZddddddgZddddddgZddd d gZd ddd dd d gZ dd ddddd d ddd d g Z ddddddgZ ddddddddd g Z dddddddd gZ dd dddd ddd d ddddd dgZddddgZddgZdgZd gZddddddgZdddddd dgZdddddd dgZdd dd dd dd d dddddddgZdgZd gZdddddgZdddddgZddd dddgZdddd dddgZdd gZdd dd dd dd dd ddg Zej dƒZ!ej dƒZ"dBdd„Z#dd„Z$dd„Z%dd „Z&d!d"„Z'd#d$„Z(d%d&„Z)d'd(„Z*d)d*„Z+d+d,„Z,d-d.„Z-d/d0„Z.d1d2„Z/d3d4„Z0d5d6„Z1d7d8„Z2d9d:„Z3d;d<„Z4d=d>„Z5d?d@„Z6dAS)CrrSZexecuteÚopenÚreadÚlockZioctlr�ÚlinkÚunlinkÚrenameZcreateÚsetattrÚwriterZadd_nameZ remove_nameZreparentÚrmdirZmountZremountZunmountz^(\w+):\[([^\]]*)\]z^(/proc/)(\d+)(.*)TcCs„||_||_i|_d|_d|_d|_d|_d|_d|_d|_ d|_ d|_ g|_ g|_ d|_d|_d|_d|_d|_g|_|jƒdS)N)Ú audit_eventÚquery_environmentÚtemplate_substitutionsÚtpathÚspathÚsourceÚ source_pkgrŸÚscontextÚtcontextÚtclassÚportÚsrc_rpmsÚtgt_rpmsr)ÚpidÚkmodr†ÚwhyÚboolsÚ derive_avc_info_from_audit_event)rErËrÌrrrr?‚s*z AVC.__init__cCs|jƒS)N)Ú format_avc)rErrrrI›sz AVC.__str__cCsNd}|d|j7}|d|j7}|d|j7}|d|j7}|d|j7}|S)Nr›z scontext=%s z tcontext=%s z access=%s z tclass=%s z tpath=%s )rÒrÓrŸrÔrÎ)rErrrrrÝžszAVC.format_avccCs.|jdkrdSx|jD]}||krdSqWdS)zMReturns true if the AVC contains _any_ of the permissions in the access list.NFT)rŸ)rEÚ access_listÚarrrÚhas_any_access_in«s   zAVC.has_any_access_incCs.|jdkrdSx|jD]}||krdSqWdS)zmReturns true if _every_ access in the AVC matches at least one of the permissions in the access list.NFT)rŸ)rErÞrßrrrÚall_accesses_are_in¶s   zAVC.all_accesses_are_inc CsÀtƒtƒ}|jƒtƒ}|jƒg}dd„dd„ttgt|jjt |j t |j iƒDƒDƒ}|}x,|D]$}||krd|j ttt|ƒƒdƒqdWx&|D]}||kr’||kr’|j|ƒq’W|jƒ|S)NcSsg|] }|t‘qSr)ZTARGET)r4rrrrr5Èsz,AVC.allowed_target_types..cSsg|]}|dr|‘qS)Zenabledr)r4rrrrr5ÈsÚtypes)Zget_all_file_typesZget_all_port_typesr¶Zget_all_attributesrÚALLOWÚSOURCErÒr;ZCLASSrÔZPERMSrŸÚextendÚnextÚinfoZ ATTRIBUTEr�)rEZ all_typesZall_attributesZ allowed_typesZwtypesrâÚtrrrÚallowed_target_typesÂs  4  zAVC.allowed_target_typesc Cs@|jdgƒr pipe socket:[1234] --> socket /proc/1234/fd --> /proc//fd ./foo --> ./foo /etc/sysconfig --> /etc/sysconfig NrTrvÚinoÚPATHZnametypeZPARENTrÔrrz%srpú/rÚdevz/dev/z /proc/mountsÚrržr.r z/dev/%srzunknown mountpointFZlocatez-bz\%sT)ÚstderrZuniversal_newlinesz \1\3úú@Z filesystemr›Z udp_socketZ tcp_socketzport %sZUnknown)"rÁr“rËr¼ÚendswithrìrvÚexistsÚlstatÚst_rdevr'rÂrÃrBrCÚstatÚst_inor�ÚOSErrorÚcloseÚ TypeErrorrŒÚ subprocessZ check_outputZSTDOUTÚproc_pid_instance_reÚsubÚpipe_instance_path_rerrÔrŠrÎÚ_rÕ)rErvrTZinodestrZavc_path_recordsZavc_path_recordrrÔZmatchesZdev_rdevrýrúÚfdr‘rr ZcommandÚoutputrrr*rrrÚ _set_tpaths¼               :        zAVC._set_tpathc Csxd|_d|_d|_d|_d|_g|_d}}}}|jjƒ|_|jj dƒ}|jj dƒ|_ t |j tƒsxt|jj dƒƒ|_ t |jtƒs–t|jj dƒƒ|_|jj dƒ|_|jj dƒdkrÄ|jj dƒ|_n|jj dƒ|_|jƒ|jj d ƒ|_|jj d ƒ|_|�r8|j d ƒ}|j d ƒ}|j d ƒ|_|j dƒdk|_|j dƒ|_|dk�rN|jj d ƒ}|dk�rd|jj d ƒ}||_|�rx||_n|�r†|j|_|j�s–|j|_|j�s¨|j j|_|jj dƒ}|�rÆ|j dƒ}nd}|jjdƒ}xR|D]J} | j dƒ} tjj| ƒ�s| �r|jj| ƒn|jjtjj|| ƒƒ�qÜWg|_g|_|jjj |_ t!j"t#|j ƒt#|jƒt#|jƒ|j ƒ\|_$} |j$t!j%k�rŒt&t'dƒ|jƒ‚|j$t!j(k�r¬t&t'dƒ|jƒ‚|j$t!j)k�rÆt&t'dƒƒ‚|j$t!j*k�ræt&t'dƒ|jƒ‚|j$t!j+k�rt&t'dƒ|jƒ‚|j$t!j,k�r&t&t'dƒ|jƒ‚|j$t!j-k�rFt&t'dƒ|jƒ‚|j$t!j.k�r`t&t'dƒƒ‚|j$t!j/k�rt| |_0dS)NFZSYSCALLrgrÒrÓrÔÚdestÚsrcrÙrØrqrnr†ÚsuccessÚyesrêZCWDrorûrTz8%s **** Recorded AVC is allowed in current policy **** zh%s **** Recorded AVC is dontaudited in current policy. 'semodule -B' will turn on dontaudit rules **** zMust call policy_init firstz.%s **** Invalid AVC: bad target context **** z.%s **** Invalid AVC: bad source context **** z*%s **** Invalid AVC: bad type class **** z*%s **** Invalid AVC: bad permission **** z&Error during access vector computation)1rÎrÏrÐrêrZ syscall_pathsrËr¾rÁr½r“rŸr@rÒrrÓrÔrÕrrÙrØr†r;r¼rìrvÚisabsr�rDrÖr×rr)Ú audit2whyZanalyzerKrÚrãrZrZ DONTAUDITZNOPOLICYZBADTCONZBADSCONZ BADTCLASSZBADPERMZ BADCOMPUTEZBOOLEANrÛ) rErqrnrƒr†Zsyscall_recordZ cwd_recordroZ path_recordsZ path_recordrvrÛrrrrÜŸs�                   *  z$AVC.derive_avc_info_from_audit_eventcCsP|jrL|jr,t|jƒ|_|jr,|jj|jƒ|jrLt|jƒ}|rL|jj|ƒdS)N)rÌrÏZget_package_nvr_by_file_pathrÑrÖr�rÎr×)rEZrpmrrrrõs  zAVC.derive_environmental_infocCs|jdkr||_dS)N)rÎ)rErvrrrÚ set_alt_path s zAVC.set_alt_pathcKs,x&t|jƒƒD]\}}|r||j|<qWdS)N)rPrwrÍ)rEÚkwdsrsryrrrÚset_template_substitutionsszAVC.set_template_substitutionscCsVt|jjƒ|jd<t|jjƒ|jd<t|jƒ|jd<t|jƒ|jd<|jrdtjddt|jƒƒ|jd<t|j ƒ|jd<|j r”tjddt|j ƒƒ|jd <|j dkrªd|jd <nJ|j d krÆt|j ƒ|jd <n.|j d krêtt j j |j ƒƒ|jd <n d|jd <t|j ƒ|jd <|jdk�rd|jd<ntdj|jƒƒ|jd<t|jƒ|jd<t|jƒ|jd<dS)NZ SOURCE_TYPEZ TARGET_TYPEräZ SOURCE_PATHrœÚ.ZFIX_SOURCE_PATHZ TARGET_PATHZFIX_TARGET_PATHZ TARGET_DIRrprrZ TARGET_CLASSZACCESSZSOURCE_PACKAGEZ PORT_NUMBER)Ú escape_htmlrÒr;rÍrÓrÐrÏrr rÎrÔrìrvÚdirnamerŸrDrÑrÕ)rErrrrös,       z)AVC.update_derived_template_substitutionscCs:x4t|jjƒƒD]"\}}|dkrtt|ƒƒ|j|<qWdS)N)rPrÍrwrZ default_text)rErsryrrrÚvalidate_template_substitutions5sz#AVC.validate_template_substitutionsN)T)7rUrVrWZstat_file_permsZ x_file_permsZ r_file_permsZ rx_file_permsZ ra_file_permsZlink_file_permsZcreate_lnk_permsZcreate_file_permsZ r_dir_permsZ rw_dir_permsZ ra_dir_permsZcreate_dir_permsZmount_fs_permsZsearch_dir_permsZgetattr_dir_permsZsetattr_dir_permsZlist_dir_permsZadd_entry_dir_permsZdel_entry_dir_permsZmanage_dir_permsZgetattr_file_permsZsetattr_file_permsZread_file_permsZappend_file_permsZwrite_file_permsZ rw_file_permsZdelete_file_permsZmanage_file_permsrr¥rr r?rIrÝràrárérîrñròrórôr÷rùrrÜrõrrrörrrrrr[sn            b ))Z __future__rrAZ six.movesrr|Ú__all__r‹r”rìr�rrJÚbase64râZselinux.audit2whyrZsetroubleshoot.utilZsetroubleshoot.html_utilZsetroubleshoot.xml_serializeZsepolicyrëZcmpZget_standard_directoriesrørrr¥r%rr0r1r2r3Z XmlSerializerrr r r rrrrrÚsV     )<!Mj__pycache__/audit_data.cpython-36.pyc000064400000066655152572267760013546 0ustar003 �Àn`Ç�ã@sdddlmZddlZddlmZddlZdddddd d d gZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z dd lTddljZdd lTdd lTdd lTdd lTd Zdd„ZeƒZdd„Zdd„Ze jdƒZdd„Ze jdƒZdd„Zddl Z dd„Z!Gdd„de"ƒZ#Gdd„de"ƒZ$Gdd „d e"ƒZ%Gdd „d ƒZ&Gdd „d e"ƒZ'Gdd„dƒZ(dS) é)Úabsolute_importN)ÚrangeÚderive_record_formatÚparse_audit_record_textÚ AvcContextÚAVCÚ AuditEventIDÚ AuditEventÚ AuditRecordÚAuditRecordReader)Ú*écCs||k||kS)N©)ÚxÚyrrú /usr/lib/python3.6/audit_data.pyÚ6srcCs t|ƒ\}}}}t|||ƒ}|S)N)rr )ÚtextÚparse_succeededÚ record_typeÚevent_idÚ body_textÚ audit_recordrrrÚaudit_record_from_text@s rcCs*tjd|ƒrtjStjd|ƒr$tjStjS)Nz/audispd_events$z/audit_events$)ÚreÚsearchr Ú TEXT_FORMATÚ BINARY_FORMAT)Z socket_pathrrrrHs   zL(node=(\S+)\s+)?(type=(\S+)\s+)?(msg=)?audit\(((\d+)\.(\d+):(\d+))\):\s*(.*)c Csªd}d}d}d}d}tj|ƒ}|dk ržd}|jdƒr>|jdƒ}|jdƒrR|jdƒ}|jdƒr”t|jdƒƒ}t|jdƒƒ}t|jdƒƒ} t||| |ƒ}|jd ƒ}||||fS) NFTéééééé é )Úaudit_input_rerÚgroupÚintr) ÚinputrÚhostrrrÚmatchÚsecondsÚmilliÚserialrrrras&       z%audit\(((\d+)\.(\d+):(\d+))\):\s*(.*)cCsvd}d}d}tj|ƒ}|dk rld}|jdƒrbt|jdƒƒ}t|jdƒƒ}t|jdƒƒ}t|||ƒ}|jdƒ}|||fS)NFTérr ré)Úaudit_binary_input_rerr&r'r)r(rrrr*r+r,r-rrrÚparse_audit_binary_texts    r1cCs"|rdd„|Dƒ}||krdSdS)NcSsg|]}|tjkr|‘qSr)ÚstringÚ printable)Ú.0rrrrú ™szprintable..TFr)ÚsZ filtered_pathrrrr3—s r3csZeZdZddiddiddiddidœZ‡fdd„Zdd„Zdd „Zd d „Zd d „Z‡Z S)rÚXMLFormÚ attribute)ÚuserÚroleÚtypeÚmlscsztt|ƒjƒt|tjƒrv|jdƒ}t|ƒdkrv|d|_|d|_ |d|_ t|ƒdkrpdj |dd…ƒ|_ nd|_ dS)Nú:r rr.rZs0) ÚsuperrÚ__init__Ú isinstanceÚsixZ string_typesÚsplitÚlenr9r:r;Újoinr<)ÚselfÚdataÚfields)Ú __class__rrr?§s       zAvcContext.__init__cCsd|j|j|j|jfS)Nz %s:%s:%s:%s)r9r:r;r<)rErrrÚ__str__´szAvcContext.__str__cCstjt|ƒƒ\}}|S)N)ÚselinuxZselinux_raw_to_trans_contextÚstr)rEZrcZtransrrrÚformat·szAvcContext.formatcCs |j|ƒ S)N)Ú__eq__)rEÚotherrrrÚ__ne__¼szAvcContext.__ne__cCs4x.t|jjƒƒD]}t||ƒt||ƒkrdSqWdS)NFT)ÚlistÚ _xml_infoÚkeysÚgetattr)rErNÚnamerrrrM¿szAvcContext.__eq__) Ú__name__Ú __module__Ú __qualname__rQr?rIrLrOrMÚ __classcell__rr)rHrrŸs  csveZdZdedœdedœdedœddidœZd‡fdd„ Zdd „Zd d „Zd d „Ze dd„ƒZ dd„Z dd„Z ‡Z S)rr8)r7Úimport_typecastr7)r+r,r-r)Ncs2tt|ƒjƒ||_||_||_|dk r.||_dS)N)r>rr?r+r,r-r))rEr+r,r-r))rHrrr?Ðs zAuditEventID.__init__cCsD|j|jkrdS|j|jkr dS|j|jkr0dS|j|jkr@dSdS)NFT)r)r+r,r-)rErNrrrrMØs    zAuditEventID.__eq__cCsb|j|jkr&td|jj|j|jfƒ‚|j|jkr>|j|jkS|j|jkrV|j|jkS|j|jkS)Nz?cannot compare two %s objects whose host values differ (%s!=%s))r)Ú ValueErrorrHrUr+r,r-)rErNrrrÚ__lt__ãs     zAuditEventID.__lt__cCsddl}|j|ƒS)Nr)Úcopy)rEr\rrrr\ïszAuditEventID.copycCst|jƒ|jdS)Ng@�@)ÚfloatZsecr,)rErrrrószAuditEventID.cCsd|j|j|jfS)Nzaudit(%d.%d:%d))r+r,r-)rErrrrIõszAuditEventID.__str__cCs.|jdkrdS|jdkrdS|jdkr*dSdS)NFT)r+r,r-)rErrrÚis_validøs   zAuditEventID.is_valid)N)rUrVrWr'rQr?rMr[r\ÚpropertyZtimerIr^rXrr)rHrrÈs    csØeZdZddidedœddidedœdœZdZdZej eƒZ e j dƒZ e j d ƒZe j d ƒZd(‡fd d „ Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd&d'„Z‡ZS))r r7r8Úelement)r7rY)rrrÚ line_numberrZiiiiz([^ \t]+)\s*=\s*([^ \t]+)z$avc:\s+([^\s]+)\s+{([^}]+)}\s+for\s+z^a\d+$Ncs8tt|ƒjƒ||_||_||_||_||_|jƒdS)N) r>r r?rrrrGraÚ_init_postprocess)rErrrrGra)rHrrr?szAuditRecord.__init__cCsrt|ddƒdkr|j|jƒ|jd krnd|jkrntjj|jƒ}|rn|jdƒ}||jd<|jdƒ}|j ƒ|jd <dS) NrGrÚUSER_AVCÚ1400Ú1107Úseresultr.rÚseperms)rrcrdre) rSÚset_fields_from_textrrrGr Úavc_rerr&rB)rEr*rfrgrrrrbs      zAuditRecord._init_postprocesscCs|jƒS)N)Ú to_host_text)rErrrrI+szAuditRecord.__str__cCs d|_|jjdkrtƒ|j_dS)N)rarr)Z get_hostname)rErrrÚaudispd_rectify.s zAuditRecord.audispd_rectifycCs.|jjƒsdS|jdkrdS|jdkr*dSdS)NFT)rr^rÚmessage)rErrrr^3s   zAuditRecord.is_validcCs¾ddddddddd d d d d dddg}xF|D]>}||jkr*|jdkrL|dkrLq*|j|}t|ƒ}||j|<q*W|jdkrºxBt|jjƒƒD]0\}}|jj|ƒr†|j|}t|ƒ}||j|<q†WdS)NZacctÚcmdÚcommÚcwdrFÚdirÚexeÚfiler)ÚkeyÚmsgrTÚnewZocommoldÚpathZwatchrZsaddrZEXECVE)rGrZaudit_msg_decoderPÚitemsÚ exec_arg_rer)rEZencoded_fieldsZfieldÚvalueZ decoded_valuerrrÚ decode_fields<s       zAuditRecord.decode_fieldsc Cs<y,tjddkr|jdƒStj|ƒjdƒSWn |SdS)Nrr Úhexzutf-8)ÚsysÚ version_infoÚdecodeÚ bytearrayÚfromhex)rErvrrrÚ translate_hexPs  zAuditRecord.translate_hexcCs g|_i|_�xötjj|ƒD]æ}|jdƒ}|jdƒ}|jdƒ}y˜|dkrbtjt |dƒƒ}tj |ƒ}|dkr„|jdƒj dƒs„|j |ƒ}|d kr°yt jtt |ƒƒ}Wn YnX|d krÔtjt |ƒtjƒƒ}|rÔ|}Wntk rêYnX||j|<|jj|ƒqWdS)Nr.rú"ÚarchérTrvrnrmrqroÚexitÚsyscall)rTrvrnrmrqro)Ú fields_ordrGr Úkey_value_pair_reÚfinditerr&ÚstripÚauditZaudit_elf_to_machiner'Zaudit_machine_to_nameÚ startswithr�ÚerrnoÚ errorcodeÚabsZaudit_syscall_to_nameZaudit_detect_machinerZÚappend)rErr*rsryÚiZ syscall_namerrrrh_s4      z AuditRecord.set_fields_from_textcCs |jj|ƒS)N)rGÚget)rErTrrrÚ get_field�szAuditRecord.get_fieldcCs"t|ƒ}tjtjtjtj|j|ƒS)N)rCÚstructÚpackr Úbinary_header_formatÚbinary_versionÚbinary_header_sizer)rErtÚ msg_lengthrrrÚget_binary_header„s zAuditRecord.get_binary_headercsjˆjdkrdSˆjdkr4dˆjˆjdjˆjƒf}ndˆjˆjf}|dj‡fdd„ˆjDƒƒd7}|S) NÚrz#type=%s msg=%s: avc: denied { %s } ú ztype=%s msg=%s: csg|]}d|ˆj|f‘qS)z%s=%s)rG)r4Úk)rErrr5�sz.AuditRecord.fields_to_text..Ú )rGrrrDÚaccessr‡)rEZbufr)rErÚfields_to_text‰s  "zAuditRecord.fields_to_textcCsd|j|j|jfS)Nztype=%s msg=%s: %s )rrr)rErrrÚto_text“szAuditRecord.to_textcCs2|jjdk r&d|jj|j|j|jfS|jƒSdS)Nznode=%s type=%s msg=%s: %s )rr)rrr¡)rErrrrj–s zAuditRecord.to_host_textcCsd|j|jf}|j|ƒ|S)Nz%s: %s)rrrš)rEÚrecordrrrÚ to_binary�szAuditRecord.to_binary)NN)rUrVrWrr'rQr—r–r”Úcalcsizer˜rÚcompilerˆrirxr?rbrIrkr^rzr�rhr“ršr r¡rjr£rXrr)rHrr s0      " c@s,eZdZdZdZdd„Zdd„Zdd„Zd S) r r.rcCsV||_d|_d|_|j|jkr(|j|_n*|j|jkr>|j|_ntd||j j fƒ‚dS)Nr›rz unknown record format (%s) in %s) Ú record_formatÚ _input_bufferrarÚ feed_textZfeedrÚ feed_binaryrZrHrU)rEr¦rrrr?¨s    zAuditRecordReader.__init__c csÂt|ƒdkrdS|j|7_xžt|jƒtjkr4dStjtj|jdtj…ƒ\}}}}tj|}t|jƒ|krrdS|jtj|…}t|ƒ\}} } |j|d…|_|r tj |ƒ| | ddfVq WdS)Nr) rCr§r r˜r”Úunpackr–r1r‹Zaudit_msg_type_to_name) rEÚnew_datar—r˜rr™Z total_lenrrrrrrrr©´s"  zAuditRecordReader.feed_binaryc cs®t|ƒdkrdS|j|7_d}|jjd|ƒ}xh|dkr˜|jd7_|d7}|j||…}t|ƒ\}}}}|r„|||d|jfV|}|jjd|ƒ}q2W|j|d…|_dS)Nrržr.)rCr§Úfindrar) rEr«ÚstartÚendÚlinerrrrrrrr¨Õs   zAuditRecordReader.feed_textN)rUrVrWrrr?r©r¨rrrrr ¤s  !cs¤eZdZddedœdedœdœZ‡fdd„Zdd „Zd d „Zd$d d„Z dd„Z e dd„ƒZ dd„Z dd„Zd%dd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Z‡ZS)&r r`r)r7rPrY)r7rY)Úrecordsrcs*tt|ƒjƒd|_g|_i|_d|_dS)N)r>r r?rr°Ú record_typesÚ timestamp)rE)rHrrr?÷s zAuditEvent.__init__cCs4t|ddƒdkri|_x|jD]}|j|ƒqWdS)Nr±)rSr±r°Úprocess_record)rEr¢rrrrbþs zAuditEvent._init_postprocesscCsL|j}|jƒd|j|jƒ|jƒdjdd„|Dƒƒdjdd„|jDƒƒfS)Nz2%s: is_avc=%s, is_granted=%s: line_numbers=[%s] %sú,cSsg|] }t|ƒ‘qSr)rK)r4rrrrr5 sz&AuditEvent.__str__..ržcSsg|] }d|‘qS)z %sr)r4r¢rrrr5 s)Ú line_numbersÚsortrÚis_avcÚ is_grantedrDr°)rErµrrrrIs zAuditEvent.__str__ržcCs|jdd„|jDƒƒS)NcSsg|] }t|ƒ‘qSr)rK)r4r¢rrrr5sz%AuditEvent.format..)rDr°)rEZ separatorrrrrL szAuditEvent.formatcCs t|jƒS)N)rCr°)rErrrÚ num_recordsszAuditEvent.num_recordscCsdd„|jDƒS)NcSsg|]}|jr|j‘qSr)ra)r4r¢rrrr5sz'AuditEvent...)r°)rErrrrszAuditEvent.cCs|jj|ƒ|j|ƒdS)N)r°r�r³)rEr¢rrrÚ add_records zAuditEvent.add_recordcCsp|jdkr2|jjƒ|_t|jjƒ|jjd|_n |j|jksRtd|j|jfƒ‚|jj|j gƒ}|j |ƒdS)Ng@�@zBcannot add audit record to audit event, event_id mismatch %s != %s) rr\r]r+r,r²rZr±Ú setdefaultrr�)rEr¢Z record_listrrrr³s   zAuditEvent.process_recordNcCsVg}|dkr|j}n |j|ƒ}x2|D]*}|jj|ƒ}|dkr>q$|j||jfƒq$W|S)aNReturn list of (value, record_type) tuples. In other words return the value matching name for every record_type. If record_type is not specified then all records are searched. Note: it is possible to have more than one record of a given type thus it is always possible to have multiple values returned.N)r°Úget_records_of_typerGr’r�r;)rErTrrwr°r¢ryrrrr“%s   zAuditEvent.get_fieldcCs d}|jj|ƒ}|r|d}|S)Nr)r±r’)rEr;r¢r°rrrÚget_record_of_type9s  zAuditEvent.get_record_of_typecCs|jj|gƒS)N)r±r’)rEr;rrrr¼@szAuditEvent.get_records_of_typecCs$xdD]}|j|ƒ}|r|SqWdS)Nrrcrdre)rrcrdre)r½)rErr¢rrrÚget_avc_recordCs  zAuditEvent.get_avc_recordcCs |jƒdk S)N)r¾)rErrrr·IszAuditEvent.is_avccCsH|jƒ}|dkrdS|jd}|dkr*dS|dkr6dStjjd|ƒdS)NFrfZdeniedZgrantedTz!unknown value for seresult ('%s'))r¾rGÚlogZavcÚwarn)rEÚ avc_recordrfrrrr¸Ls zAuditEvent.is_granted)rž)N)rUrVrWr rrQr?rbrIrLr¹r_rµrºr³r“r½r¼r¾r·r¸rXrr)rHrr ñs      c@s|eZdZdgZddgZdddddgZddddddgZddddddgZddd d gZd ddd dd d gZ dd ddddd d ddd d g Z ddddddgZ ddddddddd g Z dddddddd gZ dd dddd ddd d ddddd dgZddddgZddgZdgZd gZddddddgZdddddd dgZdddddd dgZdd dd dd dd d dddddddgZdgZd gZdddddgZdddddgZddd dddgZdddd dddgZdd gZdd dd dd dd dd ddg Zej dƒZ!ej dƒZ"dBdd„Z#dd„Z$dd„Z%dd „Z&d!d"„Z'd#d$„Z(d%d&„Z)d'd(„Z*d)d*„Z+d+d,„Z,d-d.„Z-d/d0„Z.d1d2„Z/d3d4„Z0d5d6„Z1d7d8„Z2d9d:„Z3d;d<„Z4d=d>„Z5d?d@„Z6dAS)CrrSZexecuteÚopenÚreadÚlockZioctlr�ÚlinkÚunlinkÚrenameZcreateÚsetattrÚwriterZadd_nameZ remove_nameZreparentÚrmdirZmountZremountZunmountz^(\w+):\[([^\]]*)\]z^(/proc/)(\d+)(.*)TcCs„||_||_i|_d|_d|_d|_d|_d|_d|_d|_ d|_ d|_ g|_ g|_ d|_d|_d|_d|_d|_g|_|jƒdS)N)Ú audit_eventÚquery_environmentÚtemplate_substitutionsÚtpathÚspathÚsourceÚ source_pkgrŸÚscontextÚtcontextÚtclassÚportÚsrc_rpmsÚtgt_rpmsr)ÚpidÚkmodr†ÚwhyÚboolsÚ derive_avc_info_from_audit_event)rErËrÌrrrr?‚s*z AVC.__init__cCs|jƒS)N)Ú format_avc)rErrrrI›sz AVC.__str__cCsNd}|d|j7}|d|j7}|d|j7}|d|j7}|d|j7}|S)Nr›z scontext=%s z tcontext=%s z access=%s z tclass=%s z tpath=%s )rÒrÓrŸrÔrÎ)rErrrrrÝžszAVC.format_avccCs.|jdkrdSx|jD]}||krdSqWdS)zMReturns true if the AVC contains _any_ of the permissions in the access list.NFT)rŸ)rEÚ access_listÚarrrÚhas_any_access_in«s   zAVC.has_any_access_incCs.|jdkrdSx|jD]}||krdSqWdS)zmReturns true if _every_ access in the AVC matches at least one of the permissions in the access list.NFT)rŸ)rErÞrßrrrÚall_accesses_are_in¶s   zAVC.all_accesses_are_inc CsÀtƒtƒ}|jƒtƒ}|jƒg}dd„dd„ttgt|jjt |j t |j iƒDƒDƒ}|}x,|D]$}||krd|j ttt|ƒƒdƒqdWx&|D]}||kr’||kr’|j|ƒq’W|jƒ|S)NcSsg|] }|t‘qSr)ZTARGET)r4rrrrr5Èsz,AVC.allowed_target_types..cSsg|]}|dr|‘qS)Zenabledr)r4rrrrr5ÈsÚtypes)Zget_all_file_typesZget_all_port_typesr¶Zget_all_attributesrÚALLOWÚSOURCErÒr;ZCLASSrÔZPERMSrŸÚextendÚnextÚinfoZ ATTRIBUTEr�)rEZ all_typesZall_attributesZ allowed_typesZwtypesrâÚtrrrÚallowed_target_typesÂs  4  zAVC.allowed_target_typesc Cs@|jdgƒr pipe socket:[1234] --> socket /proc/1234/fd --> /proc//fd ./foo --> ./foo /etc/sysconfig --> /etc/sysconfig NrTrvÚinoÚPATHZnametypeZPARENTrÔrrz%srpú/rÚdevz/dev/z /proc/mountsÚrržr.r z/dev/%srzunknown mountpointFZlocatez-bz\%sT)ÚstderrZuniversal_newlinesz \1\3úú@Z filesystemr›Z udp_socketZ tcp_socketzport %sZUnknown)"rÁr“rËr¼ÚendswithrìrvÚexistsÚlstatÚst_rdevr'rÂrÃrBrCÚstatÚst_inor�ÚOSErrorÚcloseÚ TypeErrorrŒÚ subprocessZ check_outputZSTDOUTÚproc_pid_instance_reÚsubÚpipe_instance_path_rerrÔrŠrÎÚ_rÕ)rErvrTZinodestrZavc_path_recordsZavc_path_recordrrÔZmatchesZdev_rdevrýrúÚfdr‘rr ZcommandÚoutputrrr*rrrÚ _set_tpaths¼               :        zAVC._set_tpathc Csxd|_d|_d|_d|_d|_g|_d}}}}|jjƒ|_|jj dƒ}|jj dƒ|_ t |j tƒsxt|jj dƒƒ|_ t |jtƒs–t|jj dƒƒ|_|jj dƒ|_|jj dƒdkrÄ|jj dƒ|_n|jj dƒ|_|jƒ|jj d ƒ|_|jj d ƒ|_|�r8|j d ƒ}|j d ƒ}|j d ƒ|_|j dƒdk|_|j dƒ|_|dk�rN|jj d ƒ}|dk�rd|jj d ƒ}||_|�rx||_n|�r†|j|_|j�s–|j|_|j�s¨|j j|_|jj dƒ}|�rÆ|j dƒ}nd}|jjdƒ}xR|D]J} | j dƒ} tjj| ƒ�s| �r|jj| ƒn|jjtjj|| ƒƒ�qÜWg|_g|_|jjj |_ t!j"t#|j ƒt#|jƒt#|jƒ|j ƒ\|_$} |j$t!j%k�rŒt&t'dƒ|jƒ‚|j$t!j(k�r¬t&t'dƒ|jƒ‚|j$t!j)k�rÆt&t'dƒƒ‚|j$t!j*k�ræt&t'dƒ|jƒ‚|j$t!j+k�rt&t'dƒ|jƒ‚|j$t!j,k�r&t&t'dƒ|jƒ‚|j$t!j-k�rFt&t'dƒ|jƒ‚|j$t!j.k�r`t&t'dƒƒ‚|j$t!j/k�rt| |_0dS)NFZSYSCALLrgrÒrÓrÔÚdestÚsrcrÙrØrqrnr†ÚsuccessÚyesrêZCWDrorûrTz8%s **** Recorded AVC is allowed in current policy **** zh%s **** Recorded AVC is dontaudited in current policy. 'semodule -B' will turn on dontaudit rules **** zMust call policy_init firstz.%s **** Invalid AVC: bad target context **** z.%s **** Invalid AVC: bad source context **** z*%s **** Invalid AVC: bad type class **** z*%s **** Invalid AVC: bad permission **** z&Error during access vector computation)1rÎrÏrÐrêrZ syscall_pathsrËr¾rÁr½r“rŸr@rÒrrÓrÔrÕrrÙrØr†r;r¼rìrvÚisabsr�rDrÖr×rr)Ú audit2whyZanalyzerKrÚrãrZrZ DONTAUDITZNOPOLICYZBADTCONZBADSCONZ BADTCLASSZBADPERMZ BADCOMPUTEZBOOLEANrÛ) rErqrnrƒr†Zsyscall_recordZ cwd_recordroZ path_recordsZ path_recordrvrÛrrrrÜŸs�                   *  z$AVC.derive_avc_info_from_audit_eventcCsP|jrL|jr,t|jƒ|_|jr,|jj|jƒ|jrLt|jƒ}|rL|jj|ƒdS)N)rÌrÏZget_package_nvr_by_file_pathrÑrÖr�rÎr×)rEZrpmrrrrõs  zAVC.derive_environmental_infocCs|jdkr||_dS)N)rÎ)rErvrrrÚ set_alt_path s zAVC.set_alt_pathcKs,x&t|jƒƒD]\}}|r||j|<qWdS)N)rPrwrÍ)rEÚkwdsrsryrrrÚset_template_substitutionsszAVC.set_template_substitutionscCsVt|jjƒ|jd<t|jjƒ|jd<t|jƒ|jd<t|jƒ|jd<|jrdtjddt|jƒƒ|jd<t|j ƒ|jd<|j r”tjddt|j ƒƒ|jd <|j dkrªd|jd <nJ|j d krÆt|j ƒ|jd <n.|j d krêtt j j |j ƒƒ|jd <n d|jd <t|j ƒ|jd <|jdk�rd|jd<ntdj|jƒƒ|jd<t|jƒ|jd<t|jƒ|jd<dS)NZ SOURCE_TYPEZ TARGET_TYPEräZ SOURCE_PATHrœÚ.ZFIX_SOURCE_PATHZ TARGET_PATHZFIX_TARGET_PATHZ TARGET_DIRrprrZ TARGET_CLASSZACCESSZSOURCE_PACKAGEZ PORT_NUMBER)Ú escape_htmlrÒr;rÍrÓrÐrÏrr rÎrÔrìrvÚdirnamerŸrDrÑrÕ)rErrrrös,       z)AVC.update_derived_template_substitutionscCs:x4t|jjƒƒD]"\}}|dkrtt|ƒƒ|j|<qWdS)N)rPrÍrwrZ default_text)rErsryrrrÚvalidate_template_substitutions5sz#AVC.validate_template_substitutionsN)T)7rUrVrWZstat_file_permsZ x_file_permsZ r_file_permsZ rx_file_permsZ ra_file_permsZlink_file_permsZcreate_lnk_permsZcreate_file_permsZ r_dir_permsZ rw_dir_permsZ ra_dir_permsZcreate_dir_permsZmount_fs_permsZsearch_dir_permsZgetattr_dir_permsZsetattr_dir_permsZlist_dir_permsZadd_entry_dir_permsZdel_entry_dir_permsZmanage_dir_permsZgetattr_file_permsZsetattr_file_permsZread_file_permsZappend_file_permsZwrite_file_permsZ rw_file_permsZdelete_file_permsZmanage_file_permsrr¥rr r?rIrÝràrárérîrñròrórôr÷rùrrÜrõrrrörrrrrr[sn            b ))Z __future__rrAZ six.movesrr|Ú__all__r‹r”rìr�rrJÚbase64râZselinux.audit2whyrZsetroubleshoot.utilZsetroubleshoot.html_utilZsetroubleshoot.xml_serializeZsepolicyrëZcmpZget_standard_directoriesrørrr¥r%rr0r1r2r3Z XmlSerializerrr r r rrrrrÚsV     )<!Mj__pycache__/avc_audit.cpython-36.opt-1.pyc000064400000030564152572267760014333 0ustar003 Úh>`—;ã @sdddgZddlmZddlmZddlZddlZddlZddlZddlZ ddl Z ddl m Z ddl Z ddlZddlmZdd lmZdd lTdd lTdd lTyeed ƒWnek rÆd e_YnXeejƒd ƒZdd„ZGdd„deƒZGdd„de jƒZdS)ÚAuditSocketReceiverThreadÚAuditRecordReceiverÚ verify_avcé)Ústr)ÚobjectN)Ú_thread)Ú cmp_to_key)Ú get_config)Ú*Ú AUDIT_EOEi(écCsp|jjdks|jjdkrdStj|jjkrltjtjdt|jfƒtjtjd|jjƒƒddl}|j dƒdS)NFzUsetroubleshoot generated AVC, exiting to avoid recursion, context=%s, AVC scontext=%szaudit event %srT) ZscontextÚtypeZtcontextÚ my_contextÚsyslogÚLOG_ERRÚ audit_eventÚformatÚsysÚexit)Úavcr©rú/usr/lib/python3.6/avc_audit.pyr7s c@sxeZdZdZdZdd„Zdd„Zdd„Zd d „Zd d „Z d d„Z dd„Z dd„Z ddd„Z ddd„Zdd„Zdd„ZdS)raO The audit system emits messages about a single event independently. Thus one single auditable event may be composed from one or more individual audit messages. Each audit message is prefixed with a unique event id, which includes a timestamp. The last audit message associated with an event is not marked in any fashion. Audit messages for a specific event may arrive interleaved with audit messages for other events. It is the job of higher level software (this code) to assemble the audit messages into events. The AuditEvent class is used for assembly. When a new event id is seen a new AuditEvent object is created, then every time an audit message arrives with that event id it is added to that object. The AuditEvent object contains the timestamp associated with the audit event as well as other data items useful for processing and handling the event. The audit system does not tell us when the last message belonging to an event has been emitted so we have no explicit way of knowing when the audit event has been fully assembled from its constituent message parts. We use the heuristic if a sufficient length of time has expired since we last saw a message for this event, then it must be complete Thus when audit events are created we place them in a cache where they will reside until their time to live has expired at which point we will assume they are complete and emit the event. Events are expired in the flush_cache() method. The events resident in the cache are sorted by their timestamps. A time threshold is established. Any events in the cache older than the time threshold are flushed from the cache as complete events. When should flushes be performed? The moment when a new message is added would seem a likely candidate moment to perform a sweep of the cache. But this is costly and does not improve how quickly events are expired. We could wait some interval of time (something much greater than how long we expect it would take for messages percolate) and this has good behavior, except for the following case. Sometimes messages are emitted by audit in rapid succession. If we swept the cache once a second then the cache may have grown quite large. Since it is very likely that any given audit event is complete by the time the next several events start arriving we can optimize by tracking how many messages have arrived since the last time we swept the cache. The the heuristic for when to sweep the cache becomes: If we've seen a sufficient number of messages then sweep -or- if a sufficient length of time has elapsed then we sweep Note that when audit messages are injected via log file scanning elapsed wall clock time has no meaning relative to when to perform the cache sweep. However, the timestamp for an event remains a critical factor when deciding if an event is complete (have we scanned far enough ahead such we're confident we won't see any more messages for this event?). Thus the threshold for when to expire an event from the cache during static log file scanning is determined not by wall clock time but rather by the oldest timestamp in the cache (e.g.there is enough spread between timestamps in the cache its reasonable to assume the event is complete). One might ask in the case of log file scanning why not fill the cache until EOF is reached and then sweep the cache? Because in log files it is not unusual to have thousands or tens of thousands of events and the cache would grown needlessly large. Because we have to deal with the real time case we already have code to keep only the most recent events in the cache so we might as well use that logic, keep the code paths the same and minimize resource usage. g{®Gázt?cCs$d|_d|_i|_g|_|jƒdS)Nér)Ú flush_sizeÚ flush_countÚcacheÚeventsÚreset_statistics)ÚselfrrrÚ__init__‘s zAuditRecordReceiver.__init__cCs t|jƒS)N)Úlenr)rrrrÚnum_cached_events˜sz%AuditRecordReceiver.num_cached_eventscCsd|_d|_dS)Nr)Úmax_cache_lengthÚ event_count)rrrrr›sz$AuditRecordReceiver.reset_statisticscCstƒ}||jt|jƒ<|S)N)Z AuditEventrrÚevent_id)rÚrecordrrrrÚinsert_new_eventŸsz$AuditRecordReceiver.insert_new_eventcCs|jjt|jƒdƒS)N)rÚgetrr$)rr%rrrÚget_event_from_record¤sz)AuditRecordReceiver.get_event_from_recordcCsZtd|jj|fƒ|j|ƒ}|jdkr:|r6|j|ƒdS|dkrL|j|ƒ}|j|ƒdS)Nz%s.add_record_to_cache(): %sÚEOE)Ú log_debugÚ __class__Ú__name__r(Ú record_typeÚ flush_eventr&Z add_record)rr%rrrrÚadd_record_to_cache§s    z'AuditRecordReceiver.add_record_to_cachecCs |jd7_|jjd|ƒdS)Nr r)r#rÚinsert)rrrrrÚ emit_event³szAuditRecordReceiver.emit_eventcCs|j|ƒ|jt|jƒ=dS)N)r1rrr$)rrrrrr.·s zAuditRecordReceiver.flush_eventNcsÐtˆjƒdkrdStˆjƒˆjkr.tˆjƒˆ_tˆjjƒƒ}|dkrjx |D]}ˆj|}ˆj|ƒqJWdS|jt‡fdd„ƒd�|dkr ˆj|djˆj }x*|D]"}ˆj|}|j|kr¦ˆj|ƒq¦WdS)alFlush events from the cache if they are older than the threshold age. If the threshold age is None then the threshold age is set to the age of the newest event in the cache minus the cache time to live, in other words anything in the cache which is older than the time to live relative to the most current event is flushed. rNcsˆj|jˆj|jkS)N)rÚ timestamp)ÚaÚb)rrrÚÔsz1AuditRecordReceiver.flush_cache..)Úkeyr éÿÿÿÿ) r rr"ÚlistÚkeysr.Úsortrr2Úcache_time_to_live)rÚ threshold_ageZ event_idsr$rr)rrÚ flush_cache»s"       zAuditRecordReceiver.flush_cacheccs8|j|ƒd|_x"t|jƒdkr2|jjƒ}|VqWdS)Nr)r=rr rÚpop)rr<rrrrÚflushÝs   zAuditRecordReceiver.flushccsx|jdƒD] }|Vq WdS)z{Emit every event in the cache irrespective of its timestamp. This means we're done, nothing should remain buffered.rN)r?)rrrrrÚcloseäszAuditRecordReceiver.closec csn|jd7_|jd kr"|j|ƒ|j|jkrFx|jƒD] }|Vq8Wx"t|jƒd krh|jjƒ}|VqHWd S) z9Accept a new audit record into the system for processing.r ÚAVCÚAVC_PATHÚSYSCALLÚCWDÚPATHr)Ú1400Ú1107rN)rArBrCrDrEr)rFrG)rr-r/rr?r rr>)rr%rrrrÚfeedës     zAuditRecordReceiver.feed)N)N)r,Ú __module__Ú __qualname__Ú__doc__r;rr!rr&r(r/r1r.r=r?r@rHrrrrrFsE  " c@s<eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd S)rcCsFtjj|ƒ||_||_tƒ|_tddtƒ|_ |j ƒd|_ d|_ dS)NÚauditÚretry_intervaléF) Ú threadingÚThreadrÚqueueÚreport_receiverrÚrecord_receiverr ÚintrMÚget_socket_pathsÚtimeout_intervalÚ has_audit_eoe)rrQrRrrrrs z"AuditSocketReceiverThread.__init__cCs6g|_tddƒ}|jj|ƒtddƒ}|jj|ƒdS)NrLZtext_protocol_socket_pathZbinary_protocol_socket_path)Úaudit_socket_pathsr Úappend)rÚaudit_socket_pathrrrrU s    z*AuditSocketReceiverThread.get_socket_pathscCs†�x~yèxÈ|jD]¾|_|jdk ryjt|jƒ}t|ƒ|_tjtjtjƒ|_ t j |j j ƒt j t j ƒ|j j|jƒ|j jƒ|_td|jƒdStjk rÊ}z$t|ƒ\}}td|j|fƒWYdd}~XqXqWtddj|jƒ|jfƒWn„tjk �r4}z(t|ƒ\}}td|j||jfƒWYdd}~Xn>tk �rp}z td|j|d|jfƒWYdd}~XnXtj|jƒqWdS)Nzaudit socket (%s) connectedz4attempt to open audit socket (%s) failed, error='%s'z:could not open any audit sockets (%s), retry in %d secondsz, z9audit socket (%s) failed, error='%s', retry in %d secondsr )rXrZZderive_record_formatZAuditRecordReaderÚ record_readerÚSocketÚsocketZAF_UNIXZ SOCK_STREAMÚ audit_socketÚfcntlÚfilenoZF_SETFDZ FD_CLOEXECÚconnectÚmakefileÚaudit_socket_fdr*ÚerrorZget_error_from_socket_exceptionÚjoinrMÚOSErrorÚtimeZsleep)rZ record_formatÚeÚerrnoÚstrerrorrrrras.     ( &,z!AuditSocketReceiverThread.connectcCs<t|||||ƒ}|jƒx|jj|ƒD]}|j|ƒq&WdS)z"called to enter a new audit recordN)Z AuditRecordZaudispd_rectifyrSrHÚnew_audit_event_handler)rr-r$Ú body_textÚfieldsÚ line_numberZ audit_recordrrrrÚnew_audit_record_handler1sz2AuditSocketReceiverThread.new_audit_record_handlercCsD|jƒr@|jƒ r@|jƒdkr@t|ƒ}t|ƒr@|jj||jfƒdS)Nr)Zis_avcZ is_grantedZ num_recordsrArrQZputrR)rrrrrrrk9sz1AuditSocketReceiverThread.new_audit_event_handlercCsâ|jƒ|j}�xÌtj|jggg|ƒ\}}}yä|j|krÐddl}|j|jjƒdƒ}|dkrltdƒ|jƒnbtd|j j ƒƒ|j sŠ|j}x‚|j j |ƒD]2\}}} } } |dkr¸d|_ d}|j||| | | ƒq˜Wn>x(|j jtjƒ|jƒD]} |j| ƒqèW|j j ƒdk�rd}Wqtk �rL} ztd|jjƒtjƒWYdd} ~ Xqtk �r†} ztd |jjƒtjƒWYdd} ~ Xqtk �rØ} z6ddl}t|jƒƒtjtjd | jjt| ƒfƒdSd} ~ XqXqWdS) NriÚzaudit socket connection droppedzcached audit event count = %dr)Tz!KeyboardInterrupt exception in %szSystemExit exception in %szexception %s: %s)rarVÚselectr^ÚosÚreadrcr`r*rSr!rWr[rHror?rgrkÚKeyboardInterruptr+r,rÚinterrupt_mainÚ SystemExitÚ ExceptionÚ tracebackZ syslog_traceÚ format_excrrr)rZtimeoutZinListZoutListZerrListrrZnew_datar-r$rlrmrnrrhrxrrrÚrun?sD   zAuditSocketReceiverThread.runN) r,rIrJrrUrarorkrzrrrrrþs   ) Ú__all__ÚbuiltinsrrrrLrqZselinuxr]r\r_Z six.movesrrOrgÚ functoolsrZsetroubleshoot.configr Zsetroubleshoot.errcodeZsetroubleshoot.utilZsetroubleshoot.audit_dataÚgetattrÚAttributeErrorr Z AvcContextZgetconrrrrPrrrrrÚs6      9__pycache__/avc_audit.cpython-36.pyc000064400000030564152572267760013374 0ustar003 Úh>`—;ã @sdddgZddlmZddlmZddlZddlZddlZddlZddlZ ddl Z ddl m Z ddl Z ddlZddlmZdd lmZdd lTdd lTdd lTyeed ƒWnek rÆd e_YnXeejƒd ƒZdd„ZGdd„deƒZGdd„de jƒZdS)ÚAuditSocketReceiverThreadÚAuditRecordReceiverÚ verify_avcé)Ústr)ÚobjectN)Ú_thread)Ú cmp_to_key)Ú get_config)Ú*Ú AUDIT_EOEi(écCsp|jjdks|jjdkrdStj|jjkrltjtjdt|jfƒtjtjd|jjƒƒddl}|j dƒdS)NFzUsetroubleshoot generated AVC, exiting to avoid recursion, context=%s, AVC scontext=%szaudit event %srT) ZscontextÚtypeZtcontextÚ my_contextÚsyslogÚLOG_ERRÚ audit_eventÚformatÚsysÚexit)Úavcr©rú/usr/lib/python3.6/avc_audit.pyr7s c@sxeZdZdZdZdd„Zdd„Zdd„Zd d „Zd d „Z d d„Z dd„Z dd„Z ddd„Z ddd„Zdd„Zdd„ZdS)raO The audit system emits messages about a single event independently. Thus one single auditable event may be composed from one or more individual audit messages. Each audit message is prefixed with a unique event id, which includes a timestamp. The last audit message associated with an event is not marked in any fashion. Audit messages for a specific event may arrive interleaved with audit messages for other events. It is the job of higher level software (this code) to assemble the audit messages into events. The AuditEvent class is used for assembly. When a new event id is seen a new AuditEvent object is created, then every time an audit message arrives with that event id it is added to that object. The AuditEvent object contains the timestamp associated with the audit event as well as other data items useful for processing and handling the event. The audit system does not tell us when the last message belonging to an event has been emitted so we have no explicit way of knowing when the audit event has been fully assembled from its constituent message parts. We use the heuristic if a sufficient length of time has expired since we last saw a message for this event, then it must be complete Thus when audit events are created we place them in a cache where they will reside until their time to live has expired at which point we will assume they are complete and emit the event. Events are expired in the flush_cache() method. The events resident in the cache are sorted by their timestamps. A time threshold is established. Any events in the cache older than the time threshold are flushed from the cache as complete events. When should flushes be performed? The moment when a new message is added would seem a likely candidate moment to perform a sweep of the cache. But this is costly and does not improve how quickly events are expired. We could wait some interval of time (something much greater than how long we expect it would take for messages percolate) and this has good behavior, except for the following case. Sometimes messages are emitted by audit in rapid succession. If we swept the cache once a second then the cache may have grown quite large. Since it is very likely that any given audit event is complete by the time the next several events start arriving we can optimize by tracking how many messages have arrived since the last time we swept the cache. The the heuristic for when to sweep the cache becomes: If we've seen a sufficient number of messages then sweep -or- if a sufficient length of time has elapsed then we sweep Note that when audit messages are injected via log file scanning elapsed wall clock time has no meaning relative to when to perform the cache sweep. However, the timestamp for an event remains a critical factor when deciding if an event is complete (have we scanned far enough ahead such we're confident we won't see any more messages for this event?). Thus the threshold for when to expire an event from the cache during static log file scanning is determined not by wall clock time but rather by the oldest timestamp in the cache (e.g.there is enough spread between timestamps in the cache its reasonable to assume the event is complete). One might ask in the case of log file scanning why not fill the cache until EOF is reached and then sweep the cache? Because in log files it is not unusual to have thousands or tens of thousands of events and the cache would grown needlessly large. Because we have to deal with the real time case we already have code to keep only the most recent events in the cache so we might as well use that logic, keep the code paths the same and minimize resource usage. g{®Gázt?cCs$d|_d|_i|_g|_|jƒdS)Nér)Ú flush_sizeÚ flush_countÚcacheÚeventsÚreset_statistics)ÚselfrrrÚ__init__‘s zAuditRecordReceiver.__init__cCs t|jƒS)N)Úlenr)rrrrÚnum_cached_events˜sz%AuditRecordReceiver.num_cached_eventscCsd|_d|_dS)Nr)Úmax_cache_lengthÚ event_count)rrrrr›sz$AuditRecordReceiver.reset_statisticscCstƒ}||jt|jƒ<|S)N)Z AuditEventrrÚevent_id)rÚrecordrrrrÚinsert_new_eventŸsz$AuditRecordReceiver.insert_new_eventcCs|jjt|jƒdƒS)N)rÚgetrr$)rr%rrrÚget_event_from_record¤sz)AuditRecordReceiver.get_event_from_recordcCsZtd|jj|fƒ|j|ƒ}|jdkr:|r6|j|ƒdS|dkrL|j|ƒ}|j|ƒdS)Nz%s.add_record_to_cache(): %sÚEOE)Ú log_debugÚ __class__Ú__name__r(Ú record_typeÚ flush_eventr&Z add_record)rr%rrrrÚadd_record_to_cache§s    z'AuditRecordReceiver.add_record_to_cachecCs |jd7_|jjd|ƒdS)Nr r)r#rÚinsert)rrrrrÚ emit_event³szAuditRecordReceiver.emit_eventcCs|j|ƒ|jt|jƒ=dS)N)r1rrr$)rrrrrr.·s zAuditRecordReceiver.flush_eventNcsÐtˆjƒdkrdStˆjƒˆjkr.tˆjƒˆ_tˆjjƒƒ}|dkrjx |D]}ˆj|}ˆj|ƒqJWdS|jt‡fdd„ƒd�|dkr ˆj|djˆj }x*|D]"}ˆj|}|j|kr¦ˆj|ƒq¦WdS)alFlush events from the cache if they are older than the threshold age. If the threshold age is None then the threshold age is set to the age of the newest event in the cache minus the cache time to live, in other words anything in the cache which is older than the time to live relative to the most current event is flushed. rNcsˆj|jˆj|jkS)N)rÚ timestamp)ÚaÚb)rrrÚÔsz1AuditRecordReceiver.flush_cache..)Úkeyr éÿÿÿÿ) r rr"ÚlistÚkeysr.Úsortrr2Úcache_time_to_live)rÚ threshold_ageZ event_idsr$rr)rrÚ flush_cache»s"       zAuditRecordReceiver.flush_cacheccs8|j|ƒd|_x"t|jƒdkr2|jjƒ}|VqWdS)Nr)r=rr rÚpop)rr<rrrrÚflushÝs   zAuditRecordReceiver.flushccsx|jdƒD] }|Vq WdS)z{Emit every event in the cache irrespective of its timestamp. This means we're done, nothing should remain buffered.rN)r?)rrrrrÚcloseäszAuditRecordReceiver.closec csn|jd7_|jd kr"|j|ƒ|j|jkrFx|jƒD] }|Vq8Wx"t|jƒd krh|jjƒ}|VqHWd S) z9Accept a new audit record into the system for processing.r ÚAVCÚAVC_PATHÚSYSCALLÚCWDÚPATHr)Ú1400Ú1107rN)rArBrCrDrEr)rFrG)rr-r/rr?r rr>)rr%rrrrÚfeedës     zAuditRecordReceiver.feed)N)N)r,Ú __module__Ú __qualname__Ú__doc__r;rr!rr&r(r/r1r.r=r?r@rHrrrrrFsE  " c@s<eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd S)rcCsFtjj|ƒ||_||_tƒ|_tddtƒ|_ |j ƒd|_ d|_ dS)NÚauditÚretry_intervaléF) Ú threadingÚThreadrÚqueueÚreport_receiverrÚrecord_receiverr ÚintrMÚget_socket_pathsÚtimeout_intervalÚ has_audit_eoe)rrQrRrrrrs z"AuditSocketReceiverThread.__init__cCs6g|_tddƒ}|jj|ƒtddƒ}|jj|ƒdS)NrLZtext_protocol_socket_pathZbinary_protocol_socket_path)Úaudit_socket_pathsr Úappend)rÚaudit_socket_pathrrrrU s    z*AuditSocketReceiverThread.get_socket_pathscCs†�x~yèxÈ|jD]¾|_|jdk ryjt|jƒ}t|ƒ|_tjtjtjƒ|_ t j |j j ƒt j t j ƒ|j j|jƒ|j jƒ|_td|jƒdStjk rÊ}z$t|ƒ\}}td|j|fƒWYdd}~XqXqWtddj|jƒ|jfƒWn„tjk �r4}z(t|ƒ\}}td|j||jfƒWYdd}~Xn>tk �rp}z td|j|d|jfƒWYdd}~XnXtj|jƒqWdS)Nzaudit socket (%s) connectedz4attempt to open audit socket (%s) failed, error='%s'z:could not open any audit sockets (%s), retry in %d secondsz, z9audit socket (%s) failed, error='%s', retry in %d secondsr )rXrZZderive_record_formatZAuditRecordReaderÚ record_readerÚSocketÚsocketZAF_UNIXZ SOCK_STREAMÚ audit_socketÚfcntlÚfilenoZF_SETFDZ FD_CLOEXECÚconnectÚmakefileÚaudit_socket_fdr*ÚerrorZget_error_from_socket_exceptionÚjoinrMÚOSErrorÚtimeZsleep)rZ record_formatÚeÚerrnoÚstrerrorrrrras.     ( &,z!AuditSocketReceiverThread.connectcCs<t|||||ƒ}|jƒx|jj|ƒD]}|j|ƒq&WdS)z"called to enter a new audit recordN)Z AuditRecordZaudispd_rectifyrSrHÚnew_audit_event_handler)rr-r$Ú body_textÚfieldsÚ line_numberZ audit_recordrrrrÚnew_audit_record_handler1sz2AuditSocketReceiverThread.new_audit_record_handlercCsD|jƒr@|jƒ r@|jƒdkr@t|ƒ}t|ƒr@|jj||jfƒdS)Nr)Zis_avcZ is_grantedZ num_recordsrArrQZputrR)rrrrrrrk9sz1AuditSocketReceiverThread.new_audit_event_handlercCsâ|jƒ|j}�xÌtj|jggg|ƒ\}}}yä|j|krÐddl}|j|jjƒdƒ}|dkrltdƒ|jƒnbtd|j j ƒƒ|j sŠ|j}x‚|j j |ƒD]2\}}} } } |dkr¸d|_ d}|j||| | | ƒq˜Wn>x(|j jtjƒ|jƒD]} |j| ƒqèW|j j ƒdk�rd}Wqtk �rL} ztd|jjƒtjƒWYdd} ~ Xqtk �r†} ztd |jjƒtjƒWYdd} ~ Xqtk �rØ} z6ddl}t|jƒƒtjtjd | jjt| ƒfƒdSd} ~ XqXqWdS) NriÚzaudit socket connection droppedzcached audit event count = %dr)Tz!KeyboardInterrupt exception in %szSystemExit exception in %szexception %s: %s)rarVÚselectr^ÚosÚreadrcr`r*rSr!rWr[rHror?rgrkÚKeyboardInterruptr+r,rÚinterrupt_mainÚ SystemExitÚ ExceptionÚ tracebackZ syslog_traceÚ format_excrrr)rZtimeoutZinListZoutListZerrListrrZnew_datar-r$rlrmrnrrhrxrrrÚrun?sD   zAuditSocketReceiverThread.runN) r,rIrJrrUrarorkrzrrrrrþs   ) Ú__all__ÚbuiltinsrrrrLrqZselinuxr]r\r_Z six.movesrrOrgÚ functoolsrZsetroubleshoot.configr Zsetroubleshoot.errcodeZsetroubleshoot.utilZsetroubleshoot.audit_dataÚgetattrÚAttributeErrorr Z AvcContextZgetconrrrrPrrrrrÚs6      9__pycache__/config.cpython-36.opt-1.pyc000064400000026761152572267760013645 0ustar003 ¹Qf.Sã#@sÆddlmZyddlmZejƒWn YnXddddddgZdd lZdd lZdd lZydd l m Z Wn e k rŠdd l m Z YnXdd l Z d aejjd d d ƒZddddœd dddœddddœdddœddddœd dddœddddœddddœddddœd dddœddddœdœ d d!d"dœid#d$dœd%d&dœd'd(dœd)œd*d+ddœid,dddœd-dddœd.dddœd/œd,dddœd-dddœd.dddœd/œd0ddœd ddœd1d2dœdd3dœd4œd5d6ddœiejjd7d8ƒdddœd9d:dœd;œejjd7d8ƒdddœddddœd?œd@dAdœdBdCdœdDœdEd@dFdœidGdHdœdIdJdœdKœdLdMdœdNdOdœdPdQdœdRdSdœejjd0dTƒdUdœdVœdWdXdœdYdZdœd[œd\d]d^ddœid_œZd`d„Zdadb„Zd{dcdd„Zd|ded„Zd}dfd„Zdgd„Ze jdhƒZdid„Zdjd„Zd~dkdl„Zdmdn„Zedok�r¼dpdq„Z y$ejej!drd …dsdtdugƒ\Z"Z#Wn(ej$k �rle ƒej%dvƒYnXdZ&x8e"D]0\Z'Z(e'dk�rŽdZ&e'd€k�rxe ƒej%ƒ�qxWe&�rÂeeƒneƒd S)�é)Úprint_function)Ústandard_libraryÚ config_initÚ get_configÚ get_optionÚ set_configÚparse_config_settingÚconfig_has_sectionN)ÚSafeConfigParserz/etc/setroubleshootz%s.confZsetroubleshootz/var/run/setroubleshootd.pidÚF)ÚvalueÚ descriptionÚreadOnlyTz3.3.26z https://pagure.io/setroubleshootzURL of project website)r r z1.1z/internationalization (i18n) translation catalogz/usr/share/localez9internationalization (i18n) translation catalog directoryzutf-8z.internationalization (i18n) encoding (codeset)z/usr/share/setroubleshootZsetroubleshoot_icon) Zpid_fileZpkg_nameZ pkg_versionZ project_urlZ rpc_versionZi18n_text_domainZi18n_locale_dirZ i18n_encodingZdata_dirZ config_dirZ icon_nameZweb_browser_launcherz/usr/bin/xdg-openz1Helper application to launch web browser on a URLz/var/run/audit_eventszLunix domain socket used to listen for audit messages (binary audit protocol)z/var/run/audispd_eventszNunix domain socket used to listen for audit messages (textural audit protocol)Z60zgnumber of seconds to wait before trying to connect to audit socket again in the event of socket failure)Zbinary_protocol_socket_pathZtext_protocol_socket_pathZretry_intervalZ plugin_dirz!/usr/share/setroubleshoot/pluginsz!org.fedoraproject.Setroubleshootdz"/org/fedoraproject/Setroubleshootdz&org.fedoraproject.SetroubleshootdIface)Zbus_nameZ object_pathZ interfacez/var/lib/setroubleshootZ50z’ Keep no more than this many alerts in the database. Oldest alerts based on the alert's last seen date will be purged first. Zero implies no limita; Purge any alerts whose age based on its last seen date exceeds this threshold. Age may be specified as a sequence of integer unit pairs. Units may be one of year,month,week,day,hour,minute,second and may optionally be plural. Example: '2 weeks 1 day' sets the threshold at 15 days. An empty string implies no limit)Z database_dirÚfilenameZ max_alertsZ max_alert_ageZ default_portZ69783z/var/run/setroubleshootZsetroubleshoot_serverz{unix}%(path)sa_ List of socket addresses server should listen on for client connections. Addresses should not contain any whitespace. Each address is of the form "[{family}]address[:port]" where [] indicates the value is optional. Valid values for family are inet or unix, if the family is absent it defaults to inet. If the family is unix the address is interpreted as a file path. If the family is inet the address is interpreted as either a host name or IP address. As a special case if the inet address is "hostname" the current hostname will be substituted. If the family is inet the address may optionally be followed by a colon (:) and a port number. If the port number is absent in the address it defaults to the port specified in this config section. Example, to listen on the local unix domain socket and provide remote connections use this "{unix}%(path)s, hostname" )ÚpathZ address_listz{unix}%(path)s hostnameZ2048Ú5)Zbuf_sizeZtimeoutZwarningz¾ setroubleshootd logging level. Levels are the same as in the python logging module, but are case insenstive. The defined levels in severity order are:[CRITICAL, ERROR, WARNING, INFO, DEBUG]ÚTruez/True|False, log full report analysis to journal)ÚlevelZlog_full_reportrz· sealert logging level. Levels are the same as in the python logging module, but are case insenstive. The defined levels in severity order are: [CRITICAL, ERROR, WARNING, INFO, DEBUG]Ú*z² Comma-separated list of users allowed to run the client and connect to the local fault server and therefore see security denials. Also accepts '*' to allow all users to connect.Úroota| Comma-separated list of users allowed to run the fix commands with root privileges. Members of this list can execute the fix commands specified in any alert. The command is executed with root privileges so you should be very caeful who you add to this list as you are granting them significant power to alter the security settings of this system. The wildcard '*' is NOT allowed.)Z client_usersZ fix_cmd_usersZ localhostzThe SMTP server addressZ25zThe SMTP server portZSELinux_TroubleshootzThe From: email headerzSELinux AVC AlertzThe Subject: email headerZemail_alert_recipientsz{Path name of file with email recipients. One address per line, optionally followed by enable flag. Comment character is #. )Z smtp_hostZ smtp_portZ from_addressZsubjectZrecipients_filepathz&https://pagure.io/docs/setroubleshoot/zURL to user help informationz1http://bugzilla.redhat.com/bugzilla/enter_bug.cgizURL used to report bugs)Zhelp_urlZbug_report_urlZanalyzeÚFalsezPrint plugin report)ZgeneralZ helper_appsZauditZpluginsZ session_dbusZ system_dbusZdatabaseZ connectionZlisten_for_clientZclient_connect_toZsocketZsetroubleshootd_logZ sealert_logÚaccessZemailÚhelpZtestcCs ttƒadS)N)Úread_configurationÚdefaultsÚ_cfg©rrú/usr/lib/python3.6/config.pyrZsc Csôtƒ}y|jtƒWn6tk rJ}ztdt|ftjd�dSd}~XnXt|jƒƒ}x–|D]Ž}|j |ƒsv|j |ƒxtt||j ƒƒD]`\}}|d}|j ddƒ}|j ||ƒsÀ|j|||ƒqˆ|rˆtd||ftjd�|j|||ƒqˆWq^W|S)Nz"error parsing config file (%s): %s)Úfiler rFz*error [%s] %s cannot be set in config file)r ÚreadÚCFG_FILEÚ ExceptionÚprintÚsysÚstderrÚlistÚkeysÚ has_sectionÚ add_sectionÚitemsÚgetZ has_optionÚset) rÚcfgÚeZdefault_sectionsZdefault_sectionZdefault_optionÚ propertiesr rrrrr_s&      rcCs\�yä|dks|tkr|S|tkr(t|ƒS|tkr~t|tƒr>|St|tƒrPt|ƒS|jƒdkr`dS|jƒdkrpd Std |ƒ‚nf|tkrŽt|ƒS|dkrš|Syddlm}|j d||ƒWn*t k rât d||ft j d�YnXWnptk �rV}zRyddlm}|j d||ƒWn,t k �rDt d||ft j d�YnXWYdd}~XnXdS)NÚtrueÚtÚyesÚyÚonTÚfalseÚfÚnoÚnÚoffFzcannot convert %s to booleanÚrawr)Úlog_cfgzunknown type %s for option %sz#error unknown type %s for option %s)r)r/r0r1r2r3)r4r5r6r7r8)ÚstrÚintÚboolÚ isinstanceÚlowerÚ ValueErrorÚfloatÚsetroubleshoot.logr:ÚerrorÚ ImportErrorr"r#r$r!)r Úcfg_typer:r-rrrÚconvert_cfg_typezs<       rFcCsFd}|dk r"||kr"t||ƒ}nt|ƒr6t|||ƒ}|dkrB|}|S)N)rFr r)ÚsectionÚnameZ default_valueÚkwdsZ option_typer rrrr s cCsFtdkr dSyÂ|dks|tkr*tj||ƒS|tkr>tj||ƒS|tkrRtj||ƒS|tkrftj||ƒS|dkr~tj||dd�Sy ddl m }|j d|||ƒWn,t k rÊt d|||ftjd�YnXWnrtk �r@}zTy ddl m }|j d |||ƒWn.t k �r0t d |||ftjd�YnXdSd}~XnXdS) Nr9T)r9r)r:z5unknown type = %s getting %s option in %s section: %sz;error unknown type = %s getting %s option in %s section: %s)rz&cannot get %s option in %s section: %sz,error cannot get %s option in %s section: %s)rr;r*r<Zgetintr=Z getbooleanrAZgetfloatrBr:rCrDr"r#r$r!)rGÚoptionrEr:r-rrrr­s2     " cCshy2tdkrdStj|ƒs"tj|ƒtj|||ƒWn0tk rb}ztjd|||ƒdSd}~XnXdS)NFz6Cannot set config: section='%s' option='%s' value='%s'T)rr'r(r+r!Z log_programZ exception)rGrJr r-rrrrÏs  z%([^.=]+?)\s*\.\s*([^.=]+?)\s*=\s*(.*)cCsÔtj|ƒ}|r.|jdƒ}|jdƒ}|jdƒ}nHyddlm}|jd|ƒWn&tk rptd|tj d�YnXd Sy ddlm}|j d |||ƒWn,tk rÂtd |||ftj d�YnXt |||ƒd S) Nééér)r:z4could not parse '%s', must be 'section.option=value'z;error: could not parse '%s', must be 'section.option=value')rFz3setting config: section='%s' option='%s' value='%s'T) Úconfig_setting_reÚsearchÚgrouprBr:rCrDr"r#r$Údebugr)Z cfg_settingÚmatchrGrJr r:rrrrÞs$       cCs†tdkr dSy tj|ƒStk r€}zNyddlm}|jd||ƒWn*tk rptd||ftj d�YnXdSd}~XnXdS)Nr)r:zconfig_has_section(%s): %sz!error: config_has_section(%s): %s)rF) rr'r!rBr:rCrDr"r#r$)rGr-r:rrrr ús  c Cs$ddl}|jdddd�}t|jƒƒ}|jƒxò|D]ê}d}x:t||jƒƒD]&\}}|jddƒ} |sj| rL|d7}qLW|dkr2td|ƒx�t||jƒƒD]|\}}|d } |jddƒ} |jd d ƒ} | rÐ| rÐqœ| sØd } t|jd || ƒƒ| �rtd| ƒntd|| fƒtƒqœWq2WdS)NréNz# )ÚwidthZinitial_indentZsubsequent_indentrFrKz[%s]r r r zNo Description Availablez%s: z# READ ONLY, default = "%s"z%s = %s) ÚtextwrapZ TextWrapperr%r&Úsortr)r*r"Zfill) rZ showReadOnlyrUZwrapÚsectionsrGZvisibleOptionsrJr.rr r rrrÚ dump_defaults s4          rXcCsd|jƒ}|jƒxN|D]F}|j|ƒ}|jƒx(|D] }t||ƒ}td|||fƒq2WtƒqWdS)Nz [%s] %s = %s)rWrVÚoptionsrr")r,rWrGrYrJr rrrÚdump_configuration+s    rZÚ__main__cCs tdƒdS)Nz5 -d generate default config file -h help )r"rrrrÚusage;sr\rKZdhrrrLú-dú --defaultsú-hú--help)N)NNN)N)F)r]r^)r_r`))Z __future__rZfuturerZinstall_aliasesÚ__all__Zgetoptr#ÚosZ configparserr rDZ ConfigParserÚrerrÚjoinr rrrrFrrrÚcompilerNrr rXrZÚ__name__r\ÚargvZoptsÚargsZ GetoptErrorÚexitZdo_dump_defaultsÚoÚarrrrÚsN                   & "  ! $   __pycache__/config.cpython-36.pyc000064400000026761152572267760012706 0ustar003 ¹Qf.Sã#@sÆddlmZyddlmZejƒWn YnXddddddgZdd lZdd lZdd lZydd l m Z Wn e k rŠdd l m Z YnXdd l Z d aejjd d d ƒZddddœd dddœddddœdddœddddœd dddœddddœddddœddddœd dddœddddœdœ d d!d"dœid#d$dœd%d&dœd'd(dœd)œd*d+ddœid,dddœd-dddœd.dddœd/œd,dddœd-dddœd.dddœd/œd0ddœd ddœd1d2dœdd3dœd4œd5d6ddœiejjd7d8ƒdddœd9d:dœd;œejjd7d8ƒdddœddddœd?œd@dAdœdBdCdœdDœdEd@dFdœidGdHdœdIdJdœdKœdLdMdœdNdOdœdPdQdœdRdSdœejjd0dTƒdUdœdVœdWdXdœdYdZdœd[œd\d]d^ddœid_œZd`d„Zdadb„Zd{dcdd„Zd|ded„Zd}dfd„Zdgd„Ze jdhƒZdid„Zdjd„Zd~dkdl„Zdmdn„Zedok�r¼dpdq„Z y$ejej!drd …dsdtdugƒ\Z"Z#Wn(ej$k �rle ƒej%dvƒYnXdZ&x8e"D]0\Z'Z(e'dk�rŽdZ&e'd€k�rxe ƒej%ƒ�qxWe&�rÂeeƒneƒd S)�é)Úprint_function)Ústandard_libraryÚ config_initÚ get_configÚ get_optionÚ set_configÚparse_config_settingÚconfig_has_sectionN)ÚSafeConfigParserz/etc/setroubleshootz%s.confZsetroubleshootz/var/run/setroubleshootd.pidÚF)ÚvalueÚ descriptionÚreadOnlyTz3.3.26z https://pagure.io/setroubleshootzURL of project website)r r z1.1z/internationalization (i18n) translation catalogz/usr/share/localez9internationalization (i18n) translation catalog directoryzutf-8z.internationalization (i18n) encoding (codeset)z/usr/share/setroubleshootZsetroubleshoot_icon) Zpid_fileZpkg_nameZ pkg_versionZ project_urlZ rpc_versionZi18n_text_domainZi18n_locale_dirZ i18n_encodingZdata_dirZ config_dirZ icon_nameZweb_browser_launcherz/usr/bin/xdg-openz1Helper application to launch web browser on a URLz/var/run/audit_eventszLunix domain socket used to listen for audit messages (binary audit protocol)z/var/run/audispd_eventszNunix domain socket used to listen for audit messages (textural audit protocol)Z60zgnumber of seconds to wait before trying to connect to audit socket again in the event of socket failure)Zbinary_protocol_socket_pathZtext_protocol_socket_pathZretry_intervalZ plugin_dirz!/usr/share/setroubleshoot/pluginsz!org.fedoraproject.Setroubleshootdz"/org/fedoraproject/Setroubleshootdz&org.fedoraproject.SetroubleshootdIface)Zbus_nameZ object_pathZ interfacez/var/lib/setroubleshootZ50z’ Keep no more than this many alerts in the database. Oldest alerts based on the alert's last seen date will be purged first. Zero implies no limita; Purge any alerts whose age based on its last seen date exceeds this threshold. Age may be specified as a sequence of integer unit pairs. Units may be one of year,month,week,day,hour,minute,second and may optionally be plural. Example: '2 weeks 1 day' sets the threshold at 15 days. An empty string implies no limit)Z database_dirÚfilenameZ max_alertsZ max_alert_ageZ default_portZ69783z/var/run/setroubleshootZsetroubleshoot_serverz{unix}%(path)sa_ List of socket addresses server should listen on for client connections. Addresses should not contain any whitespace. Each address is of the form "[{family}]address[:port]" where [] indicates the value is optional. Valid values for family are inet or unix, if the family is absent it defaults to inet. If the family is unix the address is interpreted as a file path. If the family is inet the address is interpreted as either a host name or IP address. As a special case if the inet address is "hostname" the current hostname will be substituted. If the family is inet the address may optionally be followed by a colon (:) and a port number. If the port number is absent in the address it defaults to the port specified in this config section. Example, to listen on the local unix domain socket and provide remote connections use this "{unix}%(path)s, hostname" )ÚpathZ address_listz{unix}%(path)s hostnameZ2048Ú5)Zbuf_sizeZtimeoutZwarningz¾ setroubleshootd logging level. Levels are the same as in the python logging module, but are case insenstive. The defined levels in severity order are:[CRITICAL, ERROR, WARNING, INFO, DEBUG]ÚTruez/True|False, log full report analysis to journal)ÚlevelZlog_full_reportrz· sealert logging level. Levels are the same as in the python logging module, but are case insenstive. The defined levels in severity order are: [CRITICAL, ERROR, WARNING, INFO, DEBUG]Ú*z² Comma-separated list of users allowed to run the client and connect to the local fault server and therefore see security denials. Also accepts '*' to allow all users to connect.Úroota| Comma-separated list of users allowed to run the fix commands with root privileges. Members of this list can execute the fix commands specified in any alert. The command is executed with root privileges so you should be very caeful who you add to this list as you are granting them significant power to alter the security settings of this system. The wildcard '*' is NOT allowed.)Z client_usersZ fix_cmd_usersZ localhostzThe SMTP server addressZ25zThe SMTP server portZSELinux_TroubleshootzThe From: email headerzSELinux AVC AlertzThe Subject: email headerZemail_alert_recipientsz{Path name of file with email recipients. One address per line, optionally followed by enable flag. Comment character is #. )Z smtp_hostZ smtp_portZ from_addressZsubjectZrecipients_filepathz&https://pagure.io/docs/setroubleshoot/zURL to user help informationz1http://bugzilla.redhat.com/bugzilla/enter_bug.cgizURL used to report bugs)Zhelp_urlZbug_report_urlZanalyzeÚFalsezPrint plugin report)ZgeneralZ helper_appsZauditZpluginsZ session_dbusZ system_dbusZdatabaseZ connectionZlisten_for_clientZclient_connect_toZsocketZsetroubleshootd_logZ sealert_logÚaccessZemailÚhelpZtestcCs ttƒadS)N)Úread_configurationÚdefaultsÚ_cfg©rrú/usr/lib/python3.6/config.pyrZsc Csôtƒ}y|jtƒWn6tk rJ}ztdt|ftjd�dSd}~XnXt|jƒƒ}x–|D]Ž}|j |ƒsv|j |ƒxtt||j ƒƒD]`\}}|d}|j ddƒ}|j ||ƒsÀ|j|||ƒqˆ|rˆtd||ftjd�|j|||ƒqˆWq^W|S)Nz"error parsing config file (%s): %s)Úfiler rFz*error [%s] %s cannot be set in config file)r ÚreadÚCFG_FILEÚ ExceptionÚprintÚsysÚstderrÚlistÚkeysÚ has_sectionÚ add_sectionÚitemsÚgetZ has_optionÚset) rÚcfgÚeZdefault_sectionsZdefault_sectionZdefault_optionÚ propertiesr rrrrr_s&      rcCs\�yä|dks|tkr|S|tkr(t|ƒS|tkr~t|tƒr>|St|tƒrPt|ƒS|jƒdkr`dS|jƒdkrpd Std |ƒ‚nf|tkrŽt|ƒS|dkrš|Syddlm}|j d||ƒWn*t k rât d||ft j d�YnXWnptk �rV}zRyddlm}|j d||ƒWn,t k �rDt d||ft j d�YnXWYdd}~XnXdS)NÚtrueÚtÚyesÚyÚonTÚfalseÚfÚnoÚnÚoffFzcannot convert %s to booleanÚrawr)Úlog_cfgzunknown type %s for option %sz#error unknown type %s for option %s)r)r/r0r1r2r3)r4r5r6r7r8)ÚstrÚintÚboolÚ isinstanceÚlowerÚ ValueErrorÚfloatÚsetroubleshoot.logr:ÚerrorÚ ImportErrorr"r#r$r!)r Úcfg_typer:r-rrrÚconvert_cfg_typezs<       rFcCsFd}|dk r"||kr"t||ƒ}nt|ƒr6t|||ƒ}|dkrB|}|S)N)rFr r)ÚsectionÚnameZ default_valueÚkwdsZ option_typer rrrr s cCsFtdkr dSyÂ|dks|tkr*tj||ƒS|tkr>tj||ƒS|tkrRtj||ƒS|tkrftj||ƒS|dkr~tj||dd�Sy ddl m }|j d|||ƒWn,t k rÊt d|||ftjd�YnXWnrtk �r@}zTy ddl m }|j d |||ƒWn.t k �r0t d |||ftjd�YnXdSd}~XnXdS) Nr9T)r9r)r:z5unknown type = %s getting %s option in %s section: %sz;error unknown type = %s getting %s option in %s section: %s)rz&cannot get %s option in %s section: %sz,error cannot get %s option in %s section: %s)rr;r*r<Zgetintr=Z getbooleanrAZgetfloatrBr:rCrDr"r#r$r!)rGÚoptionrEr:r-rrrr­s2     " cCshy2tdkrdStj|ƒs"tj|ƒtj|||ƒWn0tk rb}ztjd|||ƒdSd}~XnXdS)NFz6Cannot set config: section='%s' option='%s' value='%s'T)rr'r(r+r!Z log_programZ exception)rGrJr r-rrrrÏs  z%([^.=]+?)\s*\.\s*([^.=]+?)\s*=\s*(.*)cCsÔtj|ƒ}|r.|jdƒ}|jdƒ}|jdƒ}nHyddlm}|jd|ƒWn&tk rptd|tj d�YnXd Sy ddlm}|j d |||ƒWn,tk rÂtd |||ftj d�YnXt |||ƒd S) Nééér)r:z4could not parse '%s', must be 'section.option=value'z;error: could not parse '%s', must be 'section.option=value')rFz3setting config: section='%s' option='%s' value='%s'T) Úconfig_setting_reÚsearchÚgrouprBr:rCrDr"r#r$Údebugr)Z cfg_settingÚmatchrGrJr r:rrrrÞs$       cCs†tdkr dSy tj|ƒStk r€}zNyddlm}|jd||ƒWn*tk rptd||ftj d�YnXdSd}~XnXdS)Nr)r:zconfig_has_section(%s): %sz!error: config_has_section(%s): %s)rF) rr'r!rBr:rCrDr"r#r$)rGr-r:rrrr ús  c Cs$ddl}|jdddd�}t|jƒƒ}|jƒxò|D]ê}d}x:t||jƒƒD]&\}}|jddƒ} |sj| rL|d7}qLW|dkr2td|ƒx�t||jƒƒD]|\}}|d } |jddƒ} |jd d ƒ} | rÐ| rÐqœ| sØd } t|jd || ƒƒ| �rtd| ƒntd|| fƒtƒqœWq2WdS)NréNz# )ÚwidthZinitial_indentZsubsequent_indentrFrKz[%s]r r r zNo Description Availablez%s: z# READ ONLY, default = "%s"z%s = %s) ÚtextwrapZ TextWrapperr%r&Úsortr)r*r"Zfill) rZ showReadOnlyrUZwrapÚsectionsrGZvisibleOptionsrJr.rr r rrrÚ dump_defaults s4          rXcCsd|jƒ}|jƒxN|D]F}|j|ƒ}|jƒx(|D] }t||ƒ}td|||fƒq2WtƒqWdS)Nz [%s] %s = %s)rWrVÚoptionsrr")r,rWrGrYrJr rrrÚdump_configuration+s    rZÚ__main__cCs tdƒdS)Nz5 -d generate default config file -h help )r"rrrrÚusage;sr\rKZdhrrrLú-dú --defaultsú-hú--help)N)NNN)N)F)r]r^)r_r`))Z __future__rZfuturerZinstall_aliasesÚ__all__Zgetoptr#ÚosZ configparserr rDZ ConfigParserÚrerrÚjoinr rrrrFrrrÚcompilerNrr rXrZÚ__name__r\ÚargvZoptsÚargsZ GetoptErrorÚexitZdo_dump_defaultsÚoÚarrrrÚsN                   & "  ! $   __pycache__/email_alert.cpython-36.opt-1.pyc000064400000003430152572267760014642 0ustar003 Úh>`ã ã@sŠddlmZdgZddlZddlZddlmZddlmZddl m Z ddl m Z ddl Tejd ƒZd d „Zd d„Zed kr†eddƒdS)é)Úabsolute_importÚ email_alertN)ÚMIMEText)Ú MIMEMultipart)Ú formatdate)Ú get_config)Ú*z ^\s*([^@ \t]+)(@([^@ \t]+))?\s*$cCs2tj|ƒ}d}d}|r*|jdƒ}|jdƒ}||fS)Néé)Ú email_addr_reÚsearchÚgroup)ZaddrÚmatchÚuserZdomain©rú!/usr/lib/python3.6/email_alert.pyÚparse_email_addr$s   rcCsPtddƒ}tddtƒ}tddƒ}t|ƒ\}}|dkr8d}|dkrFtƒ}d||f}td||dj|ƒfƒ|jƒ|j|jƒƒ}d tdd ƒ|f}|j ƒ|j ƒ} t d ƒ} || d <|| d <dj|ƒ| d<t ƒ| d<| j t| ƒƒddl} y*| j||ƒ} | j||| jƒƒ| jƒWn8| jk �rJ} ztjtjd| ƒWYdd} ~ XnXdS)NZemailÚ smtp_hostÚ smtp_portÚ from_addressZSELinuxTroubleshootz%s@%szalert smtp=%s:%d -> %sú,z[%s] %sÚsubjectÚ alternativeZSubjectZFromz, ZToZDaterzemail failed: %s)rÚintrZ get_hostnameZ log_debugÚjoinZ%update_derived_template_substitutionsZ substituteÚsummaryZ format_textZformat_detailsrrZattachrÚsmtplibZSMTPZsendmailZ as_stringÚquitZ SMTPExceptionÚsyslogZLOG_ERR)ZsiginfoZto_addrsrrrZ from_userZ from_domainrrÚtextZ email_msgrZsmtpÚerrrr.s6        Ú__main__zThis is the sigzThis is the solution)Z __future__rÚ__all__rÚreZemail.mime.textrZemail.mime.multipartrZ email.utilsrZsetroubleshoot.configrZsetroubleshoot.utilÚcompiler rrÚ__name__rrrrÚs       %__pycache__/email_alert.cpython-36.pyc000064400000003430152572267760013703 0ustar003 Úh>`ã ã@sŠddlmZdgZddlZddlZddlmZddlmZddl m Z ddl m Z ddl Tejd ƒZd d „Zd d„Zed kr†eddƒdS)é)Úabsolute_importÚ email_alertN)ÚMIMEText)Ú MIMEMultipart)Ú formatdate)Ú get_config)Ú*z ^\s*([^@ \t]+)(@([^@ \t]+))?\s*$cCs2tj|ƒ}d}d}|r*|jdƒ}|jdƒ}||fS)Néé)Ú email_addr_reÚsearchÚgroup)ZaddrÚmatchÚuserZdomain©rú!/usr/lib/python3.6/email_alert.pyÚparse_email_addr$s   rcCsPtddƒ}tddtƒ}tddƒ}t|ƒ\}}|dkr8d}|dkrFtƒ}d||f}td||dj|ƒfƒ|jƒ|j|jƒƒ}d tdd ƒ|f}|j ƒ|j ƒ} t d ƒ} || d <|| d <dj|ƒ| d<t ƒ| d<| j t| ƒƒddl} y*| j||ƒ} | j||| jƒƒ| jƒWn8| jk �rJ} ztjtjd| ƒWYdd} ~ XnXdS)NZemailÚ smtp_hostÚ smtp_portÚ from_addressZSELinuxTroubleshootz%s@%szalert smtp=%s:%d -> %sú,z[%s] %sÚsubjectÚ alternativeZSubjectZFromz, ZToZDaterzemail failed: %s)rÚintrZ get_hostnameZ log_debugÚjoinZ%update_derived_template_substitutionsZ substituteÚsummaryZ format_textZformat_detailsrrZattachrÚsmtplibZSMTPZsendmailZ as_stringÚquitZ SMTPExceptionÚsyslogZLOG_ERR)ZsiginfoZto_addrsrrrZ from_userZ from_domainrrÚtextZ email_msgrZsmtpÚerrrr.s6        Ú__main__zThis is the sigzThis is the solution)Z __future__rÚ__all__rÚreZemail.mime.textrZemail.mime.multipartrZ email.utilsrZsetroubleshoot.configrZsetroubleshoot.utilÚcompiler rrÚ__name__rrrrÚs       %__pycache__/errcode.cpython-36.opt-1.pyc000064400000005204152572267760014010 0ustar003 Úh>`à ã @sÂddlZddlmZmZejeddƒeddƒdd�Zy ejZWnek rXejZYnXdd gZia ia d Z d d „Z d d „Z Gdd„deƒZe ddedƒƒe ddedƒƒe ddedƒƒe ddedƒƒe ddedƒƒe dded ƒƒe d!d"ed#ƒƒe d$d%ed&ƒƒe d'd(ed)ƒƒe d*d+ed,ƒƒe d-d.ed/ƒƒe d0d1ed2ƒƒe d3d4ed5ƒƒe d6d7ed8ƒƒe d9d:ed;ƒƒe dƒƒe d?d@edAƒƒe dBdCedDƒƒe dEdFedGƒƒdS)HéN)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_dirT)ZdomainZ localedirZfallbackÚ ProgramErrorÚ get_strerroriècCs*tj|dƒ}|dkr&ddl}|j|ƒ}|S)Nr)ÚstrerrorÚgetÚos)ÚerrnoÚstrr©r ú/usr/lib/python3.6/errcode.pyr.s   cCs0t|}|tƒ|<|t|<tj|ƒ|t|<dS)N)Ú ERROR_BASEÚglobalsÚerrcodeÚ__all__Úappendr)ZnumÚnamer r r r r Úerr6s   rc@seZdZddd„Zdd„ZdS)rNcCs>||_|dkrt|ƒ|_n||_|dk r:|jd|7_dS)Nú )r rr)Úselfr rZdetailr r r Ú__init__Ds  zProgramError.__init__cCsd|j|jfS)Nz [Errno %d] %s)r r)rr r r Ú__str__MszProgramError.__str__)NN)Ú__name__Ú __module__Ú __qualname__rrr r r r rBs éZERR_NO_SIGNATURE_MATCHzsignature not foundéZERR_MULTIPLE_SIGNATURE_MATCHzmultiple signatures matchedéZERR_SIGNATURE_ID_NOT_FOUNDz id not foundéZERR_DATABASE_NOT_FOUNDzdatabase not foundéZERR_NOT_MEMBERzitem is not a memberéZERR_ILLEGAL_USER_CHANGEzillegal to change useréZERR_METHOD_NOT_FOUNDzmethod not foundéZERR_CANNOT_CREATE_GUIzcannot create GUIé ZERR_UNKNOWN_VALUEz value unknowné Z ERR_FILE_OPENzcannot open fileé ZERR_INVALID_EMAIL_ADDRzinvalid email addressé ZERR_SOCKET_ERRORz socket erroré ZERR_SOCKET_HUPzconnection has been brokenéZERR_IO_INVALIDz0Invalid request. The file descriptor is not openéZERR_USER_PERMISSIONz&insufficient permission to modify useréZERR_AUTHENTICATION_FAILEDzauthentication failedéZERR_USER_PROHIBITEDzuser prohibitedéZERR_NOT_AUTHENTICATEDznot authenticatedéZERR_USER_LOOKUPzuser lookup failed)ÚgettextZsetroubleshoot.configrrZ translationZugettextÚ_ÚAttributeErrorrrrr rrÚ Exceptionrr r r r ÚsF    __pycache__/errcode.cpython-36.pyc000064400000005204152572267760013051 0ustar003 Úh>`à ã @sÂddlZddlmZmZejeddƒeddƒdd�Zy ejZWnek rXejZYnXdd gZia ia d Z d d „Z d d „Z Gdd„deƒZe ddedƒƒe ddedƒƒe ddedƒƒe ddedƒƒe ddedƒƒe dded ƒƒe d!d"ed#ƒƒe d$d%ed&ƒƒe d'd(ed)ƒƒe d*d+ed,ƒƒe d-d.ed/ƒƒe d0d1ed2ƒƒe d3d4ed5ƒƒe d6d7ed8ƒƒe d9d:ed;ƒƒe dƒƒe d?d@edAƒƒe dBdCedDƒƒe dEdFedGƒƒdS)HéN)Úparse_config_settingÚ get_configZgeneralZi18n_text_domainZi18n_locale_dirT)ZdomainZ localedirZfallbackÚ ProgramErrorÚ get_strerroriècCs*tj|dƒ}|dkr&ddl}|j|ƒ}|S)Nr)ÚstrerrorÚgetÚos)ÚerrnoÚstrr©r ú/usr/lib/python3.6/errcode.pyr.s   cCs0t|}|tƒ|<|t|<tj|ƒ|t|<dS)N)Ú ERROR_BASEÚglobalsÚerrcodeÚ__all__Úappendr)ZnumÚnamer r r r r Úerr6s   rc@seZdZddd„Zdd„ZdS)rNcCs>||_|dkrt|ƒ|_n||_|dk r:|jd|7_dS)Nú )r rr)Úselfr rZdetailr r r Ú__init__Ds  zProgramError.__init__cCsd|j|jfS)Nz [Errno %d] %s)r r)rr r r Ú__str__MszProgramError.__str__)NN)Ú__name__Ú __module__Ú __qualname__rrr r r r rBs éZERR_NO_SIGNATURE_MATCHzsignature not foundéZERR_MULTIPLE_SIGNATURE_MATCHzmultiple signatures matchedéZERR_SIGNATURE_ID_NOT_FOUNDz id not foundéZERR_DATABASE_NOT_FOUNDzdatabase not foundéZERR_NOT_MEMBERzitem is not a memberéZERR_ILLEGAL_USER_CHANGEzillegal to change useréZERR_METHOD_NOT_FOUNDzmethod not foundéZERR_CANNOT_CREATE_GUIzcannot create GUIé ZERR_UNKNOWN_VALUEz value unknowné Z ERR_FILE_OPENzcannot open fileé ZERR_INVALID_EMAIL_ADDRzinvalid email addressé ZERR_SOCKET_ERRORz socket erroré ZERR_SOCKET_HUPzconnection has been brokenéZERR_IO_INVALIDz0Invalid request. The file descriptor is not openéZERR_USER_PERMISSIONz&insufficient permission to modify useréZERR_AUTHENTICATION_FAILEDzauthentication failedéZERR_USER_PROHIBITEDzuser prohibitedéZERR_NOT_AUTHENTICATEDznot authenticatedéZERR_USER_LOOKUPzuser lookup failed)ÚgettextZsetroubleshoot.configrrZ translationZugettextÚ_ÚAttributeErrorrrrr rrÚ Exceptionrr r r r ÚsF    __pycache__/html_util.cpython-36.opt-1.pyc000064400000012375152572267760014375 0ustar003 Úh>`Cã@sâddddgZddlZddlZejdkrLddlZddlZddlZddlmZnddl Z ddlmZddl Z ddl Z ddl TGd d „d e jƒZejdkrªGd d „d ejjƒZnGd d „d e jƒZdd„Zdd„Zddd„Zdd„ZdS)Ú escape_htmlÚ unescape_htmlÚ html_to_textÚ html_documentéNé)ÚStringIO)Ú*c@s6eZdZddd„Zdd„Zdd „Zd d „Zd d „ZdS)Ú TextWriterNéPécCs(tjj|||ƒd|_||_|jƒdS)Nr)Ú FormatterÚ DumbWriterÚ__init__Ú indent_levelÚ indent_widthÚ _set_indent)ÚselfÚfileÚmaxcolr©rú/usr/lib/python3.6/html_util.pyr0szTextWriter.__init__cCs|j|j|_d|j|_dS)Nú )rrÚ indent_colÚindent)rrrrr6szTextWriter._set_indentcCs||_|jƒdS)N)rr)rZmarginÚlevelrrrÚ new_margin:szTextWriter.new_margincCsF|d}t|ƒ|jkr"|j|ƒn |jt|ƒ}|jd||ƒdS)Nr)ÚlenrZsend_literal_data)rÚdataÚoffsetrrrÚsend_label_data>s  zTextWriter.send_label_datacCsÌ|sdS|jp|dtjk}|j}|j}|jj}|j}|dkrN||jƒ|j}xb|j ƒD]V}|r–|t |ƒ|kr†|d|jƒ|j}n|dƒ|d}||ƒ|t |ƒ}d}qXW||_|dtjk|_dS)NrÚ rééÿÿÿÿ) ÚatbreakÚstringZ whitespaceÚcolrrÚwriterrÚsplitr)rrr#r%rr&ZwordrrrÚsend_flowing_dataFs,  zTextWriter.send_flowing_data)Nr r )Ú__name__Ú __module__Ú __qualname__rrrrr(rrrrr .s  r cs6eZdZd ‡fdd„ Zdd„Zdd„Zdd „Z‡ZS) ÚHTMLParserAnchorFcstt|ƒjƒ||_d|_dS)N)Úsuperr,rÚ formatterÚ anchor_href)rr.ÚstrictZconvert_charrefs)Ú __class__rrrbszHTMLParserAnchor.__init__cCs,|dkr(x|D]\}}|dkr||_qWdS)NÚaÚhref)r/)rÚtagZattrsÚkeyÚvaluerrrÚhandle_starttaggsz HTMLParserAnchor.handle_starttagcCs4|dkr0|jdkr*|jjjd|jdƒd|_dS)Nr2ú(ú))r/r.Úwriterr()rr4rrrÚ handle_endtagms zHTMLParserAnchor.handle_endtagcCs|jjj|ƒdS)N)r.r:r()rrrrrÚ handle_datasszHTMLParserAnchor.handle_data)FF)r)r*r+rr7r;r<Ú __classcell__rr)r1rr,`sr,c@s&eZdZd dd„Zdd„Zdd„ZdS) r,rcCstjj|||ƒdS)N)ÚhtmllibÚ HTMLParserr)rr.ÚverboserrrryszHTMLParserAnchor.__init__cCs ||_dS)N)Úanchor)rr3ÚnameÚtyperrrÚ anchor_bgn|szHTMLParserAnchor.anchor_bgncCs |jr|jd|jƒd|_dS)Nz (%s) )rAr<)rrrrÚ anchor_endszHTMLParserAnchor.anchor_endN)r)r)r*r+rrDrErrrrr,ws c Cs^|dkr dSy@|jddƒ}|jddƒ}|jddƒ}|jddƒ}|jd d ƒ}Wn YnX|S) Nú&z&úz>ú'z'ú"z")Úreplace)Úsrrrr‡s    cCsX|dkr dSd|kr|S|jddƒ}|jddƒ}|jddƒ}|jdd ƒ}|jd dƒ}|S) NrFz<rGz>rHz'rIz"rJz&)rK)rLrrrr•s     r cCs|yDtƒ}tjt||ƒƒ}t|ƒ}|j|ƒ|jƒ|jƒ}|jƒ|Stk rv}zt j t j d|ƒdSd}~XnXdS)Nzcannot convert html to text: %s) rr ZAbstractFormatterr r,ZfeedÚcloseÚgetvalueÚ ExceptionÚsyslogZLOG_ERR)ÚhtmlrÚbufferr.ÚparserÚtextÚerrrr¢s cGs¨d}d}|}xŽ|D]†}t|tjƒr,||7}qt|ttfƒrRx\|D] }||7}q@Wqt|ƒr�|ƒ}t|ttfƒr†x|D] }||7}qtWq˜||7}q||7}qW||7}|S)a&Wrap the body components in a HTML document structure with a valid header. Accepts a variable number of arguments of of which canb be: * string * a sequences of strings (tuple or list). * a callable object taking no parameters and returning a string or sequence of strings. zl z )Ú isinstanceZsixZ string_typesÚtupleÚlistÚcallable)Zbody_componentsÚheadÚtailÚdocZbody_componentÚitemÚresultrrrr±s$       )r)r)r )Ú__all__rPÚsysÚ version_inforQZ html.parserZ html.entitiesÚiorr>r.r r$Útypesr r rSr?r,rrrrrrrrÚs.  1  __pycache__/html_util.cpython-36.pyc000064400000012375152572267760013436 0ustar003 Úh>`Cã@sâddddgZddlZddlZejdkrLddlZddlZddlZddlmZnddl Z ddlmZddl Z ddl Z ddl TGd d „d e jƒZejdkrªGd d „d ejjƒZnGd d „d e jƒZdd„Zdd„Zddd„Zdd„ZdS)Ú escape_htmlÚ unescape_htmlÚ html_to_textÚ html_documentéNé)ÚStringIO)Ú*c@s6eZdZddd„Zdd„Zdd „Zd d „Zd d „ZdS)Ú TextWriterNéPécCs(tjj|||ƒd|_||_|jƒdS)Nr)Ú FormatterÚ DumbWriterÚ__init__Ú indent_levelÚ indent_widthÚ _set_indent)ÚselfÚfileÚmaxcolr©rú/usr/lib/python3.6/html_util.pyr0szTextWriter.__init__cCs|j|j|_d|j|_dS)Nú )rrÚ indent_colÚindent)rrrrr6szTextWriter._set_indentcCs||_|jƒdS)N)rr)rZmarginÚlevelrrrÚ new_margin:szTextWriter.new_margincCsF|d}t|ƒ|jkr"|j|ƒn |jt|ƒ}|jd||ƒdS)Nr)ÚlenrZsend_literal_data)rÚdataÚoffsetrrrÚsend_label_data>s  zTextWriter.send_label_datacCsÌ|sdS|jp|dtjk}|j}|j}|jj}|j}|dkrN||jƒ|j}xb|j ƒD]V}|r–|t |ƒ|kr†|d|jƒ|j}n|dƒ|d}||ƒ|t |ƒ}d}qXW||_|dtjk|_dS)NrÚ rééÿÿÿÿ) ÚatbreakÚstringZ whitespaceÚcolrrÚwriterrÚsplitr)rrr#r%rr&ZwordrrrÚsend_flowing_dataFs,  zTextWriter.send_flowing_data)Nr r )Ú__name__Ú __module__Ú __qualname__rrrrr(rrrrr .s  r cs6eZdZd ‡fdd„ Zdd„Zdd„Zdd „Z‡ZS) ÚHTMLParserAnchorFcstt|ƒjƒ||_d|_dS)N)Úsuperr,rÚ formatterÚ anchor_href)rr.ÚstrictZconvert_charrefs)Ú __class__rrrbszHTMLParserAnchor.__init__cCs,|dkr(x|D]\}}|dkr||_qWdS)NÚaÚhref)r/)rÚtagZattrsÚkeyÚvaluerrrÚhandle_starttaggsz HTMLParserAnchor.handle_starttagcCs4|dkr0|jdkr*|jjjd|jdƒd|_dS)Nr2ú(ú))r/r.Úwriterr()rr4rrrÚ handle_endtagms zHTMLParserAnchor.handle_endtagcCs|jjj|ƒdS)N)r.r:r()rrrrrÚ handle_datasszHTMLParserAnchor.handle_data)FF)r)r*r+rr7r;r<Ú __classcell__rr)r1rr,`sr,c@s&eZdZd dd„Zdd„Zdd„ZdS) r,rcCstjj|||ƒdS)N)ÚhtmllibÚ HTMLParserr)rr.ÚverboserrrryszHTMLParserAnchor.__init__cCs ||_dS)N)Úanchor)rr3ÚnameÚtyperrrÚ anchor_bgn|szHTMLParserAnchor.anchor_bgncCs |jr|jd|jƒd|_dS)Nz (%s) )rAr<)rrrrÚ anchor_endszHTMLParserAnchor.anchor_endN)r)r)r*r+rrDrErrrrr,ws c Cs^|dkr dSy@|jddƒ}|jddƒ}|jddƒ}|jddƒ}|jd d ƒ}Wn YnX|S) Nú&z&úz>ú'z'ú"z")Úreplace)Úsrrrr‡s    cCsX|dkr dSd|kr|S|jddƒ}|jddƒ}|jddƒ}|jdd ƒ}|jd dƒ}|S) NrFz<rGz>rHz'rIz"rJz&)rK)rLrrrr•s     r cCs|yDtƒ}tjt||ƒƒ}t|ƒ}|j|ƒ|jƒ|jƒ}|jƒ|Stk rv}zt j t j d|ƒdSd}~XnXdS)Nzcannot convert html to text: %s) rr ZAbstractFormatterr r,ZfeedÚcloseÚgetvalueÚ ExceptionÚsyslogZLOG_ERR)ÚhtmlrÚbufferr.ÚparserÚtextÚerrrr¢s cGs¨d}d}|}xŽ|D]†}t|tjƒr,||7}qt|ttfƒrRx\|D] }||7}q@Wqt|ƒr�|ƒ}t|ttfƒr†x|D] }||7}qtWq˜||7}q||7}qW||7}|S)a&Wrap the body components in a HTML document structure with a valid header. Accepts a variable number of arguments of of which canb be: * string * a sequences of strings (tuple or list). * a callable object taking no parameters and returning a string or sequence of strings. zl z )Ú isinstanceZsixZ string_typesÚtupleÚlistÚcallable)Zbody_componentsÚheadÚtailÚdocZbody_componentÚitemÚresultrrrr±s$       )r)r)r )Ú__all__rPÚsysÚ version_inforQZ html.parserZ html.entitiesÚiorr>r.r r$Útypesr r rSr?r,rrrrrrrrÚs.  1  Plugin.py000064400000012270152572267760006401 0ustar00# Authors: John Dennis # Thomas Liu # Dan Walsh # # Copyright (C) 2006-2010 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # import gettext from setroubleshoot.config import parse_config_setting, get_config translation = gettext.translation(domain=get_config('general', 'i18n_text_domain'), localedir=get_config('general', 'i18n_locale_dir'), fallback=True) try: _ = translation.ugettext # Unicode version of gettext for Py2 except AttributeError: _ = translation.gettext # Python3 (uses unicode by default) from setroubleshoot.signature import * from setroubleshoot.util import * #import sys import os.path import re #------------------------------------------------------------------------------ class Plugin(object): """ Each plugin object recognizes one or more access denials and presents a description of the denial to the user. Optionally, the plugin can provide a suggestion for allowing the access to the user. There are four user visible strings that are part of each Plugin subclass (some or all of these can be changed by the plugin author): * summary: summary of the denial * problem_description: detailed description of the denial * fix_description: description of how to allow the denied access * fix_cmd: command that can be used to allow the access All of the strings will have a standard set of substitutions performed. Each keyword (proceeded by a '$' will be replace by a string) - see http://docs.python.org/lib/node109.html for more information. The keywords are: * $SOURCE_TYPE - type for the source of the avc (usually the process performing the operation). * $TARGET_TYPE - type for the target of the avc (the type of the object). * $SOURCE_PATH - source of the executable (from the exe or comm field of the exe). A full path is not always available. * $TARGET_PATH - path for the target object. A full path is not always available. * $TARGET_DIR - path of the containing directory for TARGET_PATH. Essentially os.path.dirname($TARGET_PATH) * $TARGET_CLASS - the object class for the target. * $PERMS - the permissions denied. * $SOURCE_PACKAGE - name of the package which contains the executable (from $SOURCE_PATH). * $PORT_NUMBER - the port number for the connection denied. Additional subtitutions can be added with set_template_substitutions. You can also optional pass the name for a single boolean which will be used to set the $BOOLEAN subtitution into Plugin.__init__. o You can also set the level, of the alert, if the plugin believes discovers a signature of an attack, the level should be set to red * level: Defines the level of the alert ** yellow default ** red Indicates troubleshooter believes machine is being attacked ** green Indicates a configuration issue. Browser will not display Report Bug button ** white Tells the troubleshooter to ignore the AVC """ summary = "" problem_description = "" if_text = _('If you want to allow $SOURCE_BASE_PATH to have $ACCESS access on the $TARGET_BASE_PATH $TARGET_CLASS') then_text = "No default" do_text = "No default" def __init__(self, name): self.analysis_id = re.sub(r'^plugins\.', '', name) self.priority = 10 self.level = "yellow" self.fixable = False self.button_text = "" self.report_bug = False def init_args(self, args): pass def get_problem_description(self, avc, args): return self.problem_description def get_if_text(self, avc, args): return self.if_text def get_then_text(self, avc, args): return self.then_text def get_do_text(self, avc, args): return self.do_text def get_fix_cmd(self, avc, args): return self.fix_cmd def get_if_text(self, avc, args): return self.if_text def report(self, args=()): """ Report a denial and solution to the fault server. """ return SEPlugin(self.analysis_id, args) def analyze(self, avc): return False def set_priority(self, priority): self.priority = priority def get_priority(self): return self.priority def check_for_man(self, name): man_page = name.split("_")[0] + "_selinux" if os.path.isfile("/usr/share/man/man8/%s.8.gz" % man_page): return man_page return "" __init__.py000064400000001345152572267760006703 0ustar00# # Copyright (C) 2006,2007,2008, 2009 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # access_control.py000064400000013554152572267760010152 0ustar00# Authors: Karl MacMillan # # Copyright (C) 2006,2007,2008 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # """Access control for setroubleshoot. For now this is only used for determining which users are allowed to connect to the server: see UserServerAccess for more information.""" import struct import socket as Socket import syslog from setroubleshoot.config import get_config from setroubleshoot.util import syslog_trace __all__ = [ 'ServerAccess', ] # SO_PEERCRED is not defined by the socket class unless patched # SO_PEERCRED's value is architecture dependent # alpha, mips: 18 # parisc: 0x4011 # powerpc: 21 # sparc, sparc64: 0x0040 # default: 17 try: SO_PEERCRED = Socket.SO_PEERCRED except AttributeError: import os import re machine = os.uname()[4] if re.search(r'^i\d86', machine): SO_PEERCRED = 17 # i386,i486,i586,i686, etc. elif re.search(r'^x86_64', machine): SO_PEERCRED = 17 # x86_64 elif re.search(r'^(ppc|powerpc)', machine): SO_PEERCRED = 21 # ppc elif re.search(r'^(alpha|mips)', machine): SO_PEERCRED = 18 # alpha, mips elif re.search(r'^sparc', machine): SO_PEERCRED = 0x0040 # sparc elif re.search(r'^parisc', machine): SO_PEERCRED = 0x4011 # parisc else: SO_PEERCRED = 17 #print "hardcoding SO_PEERCRED=%s" % SO_PEERCRED class ServerAccess: """ Determine if a user should be given access to the server based on the configuration file. """ privileges = {'client': {'wildcard': True}, 'fix_cmd': {'wildcard': False}, } def __init__(self): # No attempt is made to validate the user name is valid. This # makes the configuration file more relaxed. Additionally, the # server (which we assume is the only user of this class) will # be getting uids from the kernel, so there shouldn't be access # requested from invalid uids self.privileges = {} for privilege in list(ServerAccess.privileges.keys()): self.privileges[privilege] = self.init_privilege(privilege) def init_privilege(self, privilege): cfg_names = [name.strip() for name in get_config('access', '%s_users' % privilege).split(',')] return cfg_names def valid_privilege(self, privilege): valid = privilege in ServerAccess.privileges if valid: return True syslog.syslog(syslog.LOG_ERR, "unknown access privilege (%s)" % privilege) return False def unrestricted_privilege(self, privilege): if not self.valid_privilege(privilege): return False if not ServerAccess.privileges[privilege]['wildcard']: return False return '*' in self.privileges[privilege] def user_allowed(self, privilege, user): """ Determine if the given user name is allowed access. Returns True if access should be given, False if not. """ if not self.valid_privilege(privilege): return False if self.unrestricted_privilege(privilege): return True if user in self.privileges[privilege]: return True else: return False def uid_allowed(self, privilege, uid): """ Determine if the given uid is allowed access. No error is returned if the uid is invalid (False is returned). Returns True if access should be given, False if not. """ if not self.valid_privilege(privilege): return False if self.unrestricted_privilege(privilege): return True try: import pwd pwd_entry = pwd.getpwuid(uid) except KeyError: # Not a valid uid - so they don't get access. This # is not an error. return False return self.user_allowed(privilege, pwd_entry[0]) def get_credentials(self, sock): """Obtain the effective user and group IDs of the process on the other end of a socket. SO_PEERCRED is used so the information returned is generally trustworthy (though root processes can impersonate any uid/gid).""" pid = uid = gid = None try: # socket attributes family,type,proto,timeout available only in Python >= 2.5 family = sock.family if family != Socket.AF_UNIX: return uid, gid except AttributeError: # rely on pid,uid,gid being -1 if family is not AF_UNIX pass format_ucred = 'III' # pid_t, uid_t, gid_t sizeof_ucred = struct.calcsize(format_ucred) try: ucred = sock.getsockopt(Socket.SOL_SOCKET, SO_PEERCRED, sizeof_ucred) pid, uid, gid = struct.unpack(format_ucred, ucred) if pid == -1: pid = None if uid == -1: uid = None if gid == -1: gid = None except Exception as e: pid = uid = gid = None import traceback syslog_trace(traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, "get_credentials(): %s" % e) return uid, gid analyze.py000064400000064234152572267760006615 0ustar00# Authors: John Dennis # # Copyright (C) 2006-2010 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # from __future__ import print_function __all__ = ['AnalyzeThread', 'Analyze', 'PluginReportReceiver', 'TestPluginReportReceiver', 'SETroubleshootDatabase', 'SETroubleshootDatabaseLocal', 'LogfileAnalyzer', ] import syslog from gi.repository import GObject, GLib import os import signal import time import threading import traceback from stat import * import sys from functools import cmp_to_key from setroubleshoot.config import get_config from setroubleshoot.avc_audit import * from setroubleshoot.errcode import * from setroubleshoot.rpc import * from setroubleshoot.rpc_interfaces import * from setroubleshoot.signature import * from setroubleshoot.util import * from setroubleshoot.audit_data import * from setroubleshoot.xml_serialize import validate_database_doc cmp = lambda x, y: (x > y) - (x < y) #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ class PluginStatistics(object): def __init__(self, plugin): self.name = plugin.analysis_id self.analyze_start_time = None self.analyze_end_time = None self.analyze_elapsed_time = None self.report_start_time = None self.report_end_time = None self.report_elapsed_time = None def __str__(self): analyze_elapsed_time = format_elapsed_time(self.analyze_elapsed_time) if self.report_elapsed_time is None: return "%s: %s elapsed" % (self.name, analyze_elapsed_time) else: total_elapsed_time = format_elapsed_time(self.report_end_time - self.analyze_start_time) report_elapsed_time = format_elapsed_time(self.report_elapsed_time) return "%s: %s elapsed, %s analyze elapsed, %s report elapsed" % \ (self.name, total_elapsed_time, analyze_elapsed_time, report_elapsed_time) def analyze_start(self): self.analyze_start_time = time.time() def analyze_end(self): self.analyze_end_time = time.time() self.analyze_elapsed_time = self.analyze_end_time - self.analyze_start_time def report_start(self): self.report_start_time = time.time() def report_end(self): self.report_end_time = time.time() self.report_elapsed_time = self.report_end_time - self.report_start_time #------------------------------------------------------------------------------ class AnalyzeStatistics(object): def __init__(self, num_plugins): self.num_plugins = num_plugins self.cur_plugin = None self.called_plugins = [] self.start_time = None self.end_time = None self.elapsed_time = None def __str__(self): elapsed_time = None avg_plugin_time = None n_called = len(self.called_plugins) if self.elapsed_time is not None: elapsed_time = format_elapsed_time(self.elapsed_time) if n_called: avg_plugin_time = format_elapsed_time(self.elapsed_time / n_called) return "%d/%d plugins in %s elapsed, avg plugin %s elapsed, plugins=[\n%s\n]" % \ (n_called, self.num_plugins, elapsed_time, avg_plugin_time, self.called_plugins_to_string()) def called_plugins_to_string(self): return '\n'.join([str(x) for x in self.called_plugins]) def start(self): self.start_time = time.time() def end(self): self.end_time = time.time() self.elapsed_time = self.end_time - self.start_time def new_plugin(self, plugin): self.cur_plugin = PluginStatistics(plugin) self.called_plugins.append(self.cur_plugin) self.cur_plugin.analyze_start() #------------------------------------------------------------------------------ class Analyze(object): def __init__(self): self.plugins = load_plugins() log_debug("Number of Plugins = %d" % len(self.plugins)) def get_environment(self, query_environment): environment = SEEnvironment() if query_environment: environment.update() return environment def get_signature(self, avc, environment): sig = SEFaultSignature( host=avc.host, access=avc.access, scontext=avc.scontext, tcontext=avc.tcontext, tclass=avc.tclass, tpath=avc.tpath) return sig def analyze_avc(self, avc, report_receiver, query_environment=True): log_debug("analyze_avc() avc=%s" % avc) avc.update() environment = self.get_environment(avc.query_environment) from string import Template if avc.audit_event.line_numbers is not None: avc.audit_event.line_numbers.sort() siginfo = SEFaultSignatureInfo( audit_event=avc.audit_event, source=avc.source, spath=avc.spath, tpath=avc.tpath, src_rpm_list=avc.src_rpms, tgt_rpm_list=avc.tgt_rpms, scontext=avc.scontext, tcontext=avc.tcontext, tclass=avc.tclass, port=avc.port, host=avc.host, sig=self.get_signature(avc, environment), environment=environment, line_numbers=avc.audit_event.line_numbers, last_seen_date=TimeStamp(avc.audit_event.timestamp), local_id=report_receiver.generate_id(), level="yellow" ) for plugin in self.plugins: try: report = plugin.analyze(avc) if report is not None: if plugin.level == "white": log_debug("plugin level white, not reporting") return # "yellow" is default # "green" overrides "yellow" # "red" overrides everything if plugin.level is not None and siginfo.level != "red": if plugin.level == "red" or plugin.level == "green": siginfo.level = plugin.level if isinstance(report, list): for r in report: siginfo.plugin_list.append(r) else: siginfo.plugin_list.append(report) except Exception as e: print(e, file=sys.stderr) syslog.syslog(syslog.LOG_ERR, "Plugin Exception %s " % plugin.analysis_id) (v1, v2, v3) = sys.exc_info() log_debug('\n'.join(traceback.format_tb(v3))) self.plugins.remove(plugin) report_receiver.report_problem(siginfo) #------------------------------------------------------------------------------ class AnalyzeThread(Analyze, threading.Thread): def __init__(self, queue, timeout=10): # parent class constructors threading.Thread.__init__(self) Analyze.__init__(self) self.queue = queue self.timeout = timeout def run(self): while True: try: avc, report_receiver = self.queue.get() syslog.syslog(syslog.LOG_DEBUG, "AnalyzeThread.run(): Cancel pending alarm") signal.alarm(0) self.analyze_avc(avc, report_receiver) except Exception as e: syslog.syslog(syslog.LOG_ERR, "Exception during AVC analysis: %s" % e) except ValueError as e: syslog.syslog(syslog.LOG_ERR, "Exception during AVC analysis: %s" % e) syslog.syslog(syslog.LOG_DEBUG, "AnalyzeThread.run(): Set alarm timeout to {}".format(self.timeout)) signal.alarm(self.timeout) #------------------------------------------------------------------------------ class PluginReportReceiver(object): def __init__(self, database): self.database = database def report_problem(self, siginfo): try: database_siginfo = self.database.lookup_signature(siginfo.sig) database_siginfo.update_merge(siginfo) self.database.modify_siginfo(database_siginfo) log_debug("signature found in database") except ProgramError as e: if e.errno == ERR_NO_SIGNATURE_MATCH: log_debug("not in database yet") siginfo.first_seen_date = siginfo.last_seen_date database_siginfo = self.database.add_siginfo(siginfo) else: raise return database_siginfo def generate_id(self): return self.database.sigs.generate_local_id() class TestPluginReportReceiver(object): def __init__(self, database): super(TestPluginReportReceiver, self).__init__(database) def report_problem(self, siginfo): print("Analysis Result: %s" % (siginfo.sig.analysis_id)) #------------------------------------------------------------------------------ class SETroubleshootDatabase(object): def __init__(self, filepath, name, friendly_name=None): self.filepath = filepath self.notify = None self.properties = SEDatabaseProperties(name, friendly_name, self.filepath) self.lock = threading.Lock() self.file_exists = False self.modified_count = 0 self.auto_save_interval = 5 # auto save after this many seconds self.auto_save_threshold = 200 # auto save after this many changes self.auto_save_timer = None self.max_alerts = get_config('database', 'max_alerts', int) self.max_alert_age = None max_alert_age = get_config('database', 'max_alert_age') if max_alert_age is not None: max_alert_age = max_alert_age.strip() if max_alert_age: self.max_alert_age = parse_datetime_offset(max_alert_age) log_debug("created new database: name=%s, friendly_name=%s, filepath=%s" % (self.properties.name, self.properties.friendly_name, self.properties.filepath)) self.load() def prune(self): if not (self.max_alerts or self.max_alert_age): return False # Sort oldest to youngest by last_seen_date self.sigs.signature_list.sort(key=cmp_to_key(lambda a, b: cmp(a.last_seen_date, b.last_seen_date))) if self.max_alert_age: # Find the first alert younger than the age threshold, prune everything before that min_time_to_survive = TimeStamp() # current time min_time_to_survive -= self.max_alert_age keep = 0 for siginfo in self.sigs.signature_list: if siginfo.last_seen_date > min_time_to_survive: break keep += 1 if keep > 0: log_debug("prune by age: max_alert_age=%s min_time_to_survive=%s" % (self.max_alert_age, min_time_to_survive.format())) log_debug("prune by age: pruning [%s - %s]" % (self.sigs.signature_list[0].last_seen_date.format(), self.sigs.signature_list[keep - 1].last_seen_date.format())) log_debug("prune by age: keeping [%s - %s]" % (self.sigs.signature_list[keep].last_seen_date.format(), self.sigs.signature_list[-1].last_seen_date.format())) sigs = [siginfo.sig for siginfo in self.sigs.signature_list[:keep]] for sig in sigs: self.delete_signature(sig, prune=True) if self.max_alerts: keep = len(self.sigs.signature_list) - self.max_alerts if keep > 0: sigs = [siginfo.sig for siginfo in self.sigs.signature_list[:keep]] log_debug("prune first %d alerts, len(sigs=%d sigs=%s" % (keep, len(sigs), sigs)) for sig in sigs: self.delete_signature(sig, prune=True) def set_notify(self, notify): self.notify = notify def validate(self): for siginfo in self.sigs.signature_list: # Assure first_seen_date is before last_seen_data, if not swap if siginfo.last_seen_date < siginfo.first_seen_date: tmp = siginfo.last_seen_date siginfo.last_seen_date = siginfo.first_seen_date siginfo.first_seen_date = tmp def load(self): self.sigs = SEFaultSignatureSet() if self.filepath is None: return if os.path.exists(self.filepath): stat_info = os.stat(self.filepath) if stat_info[ST_SIZE] > 0: if self.sigs.read_xml_file(self.filepath, 'sigs', validate_database_doc): self.file_exists = True self.validate() self.prune() def save(self, prune=False): if self.filepath is None: return log_debug("writing database (%s) modified_count=%s" % (self.filepath, self.modified_count)) if not prune: self.prune() self.sigs.write_xml('sigs', self.filepath) self.file_exists = True self.modified_count = 0 if self.auto_save_timer is not None: GLib.source_remove(self.auto_save_timer) self.auto_save_timer = None def mark_modified(self, prune=False): self.modified_count += 1 if self.filepath is None: return if self.modified_count > self.auto_save_threshold or not self.file_exists: self.save(prune) elif self.auto_save_timer is None: self.auto_save_timer = \ GLib.timeout_add(self.auto_save_interval * 1000, self.auto_save_callback) def auto_save_callback(self): log_debug("auto_save database (%s) modified_count=%s" % (self.filepath, self.modified_count)) self.save() return False def remove(self): if self.filepath is None: return if os.path.exists(self.filepath): log_debug("deleting database (%s)" % self.filepath) os.remove(self.filepath) def acquire(self): self.lock.acquire() def release(self): self.lock.release() def lookup_signature(self, sig): siginfo = None matches = self.sigs.match_signatures(sig) log_debug("lookup_signature: found %d matches with scores %s" % (len(matches), ",".join(["%.2f" % x.score for x in matches]))) if len(matches) == 0: raise ProgramError(ERR_NO_SIGNATURE_MATCH) if len(matches) > 1: log_debug("lookup_signature: found %d matches with scores %s" % (len(matches), ",".join(["%.2f" % x.score for x in matches]))) siginfo = matches[0].siginfo return siginfo def lookup_local_id(self, local_id): siginfo = self.sigs.lookup_local_id(local_id) if siginfo is None: log_debug("lookup_local_id: %s not found" % local_id) raise ProgramError(ERR_SIGNATURE_ID_NOT_FOUND, "id (%s) not found" % local_id) return siginfo def add_siginfo(self, siginfo): siginfo = self.sigs.add_siginfo(siginfo) if self.notify: self.notify.signatures_updated('add', siginfo.local_id) self.mark_modified() return siginfo def get_properties(self): return self.properties def query_alerts(self, criteria): log_debug("query_alerts: criteria=%s" % criteria) if criteria == '*': return self.sigs # FIXME: we assume if criteria is not wildcard its a local_id, need a more general/robust mechanism sigs = SEFaultSignatureSet() siginfo = self.lookup_local_id(criteria) sigs.add_siginfo(siginfo) return sigs def delete_signature(self, sig, prune=False): log_debug("delete_signature: sig=%s" % sig) try: siginfo = self.lookup_signature(sig) except ProgramError as e: if e.errno == ERR_NO_SIGNATURE_MATCH: log_debug("Signature not found!") return else: raise self.sigs.remove_siginfo(siginfo) if self.notify: self.notify.signatures_updated('delete', siginfo.local_id) self.mark_modified(prune) def modify_siginfo(self, siginfo): if self.notify: self.notify.signatures_updated('modify', siginfo.local_id) self.mark_modified() def evaluate_alert_filter(self, sig, username): log_debug("evaluate_alert_filter: username=%s sig=%s" % (username, sig)) try: siginfo = self.lookup_signature(sig) except ProgramError as e: if e.errno == ERR_NO_SIGNATURE_MATCH: log_debug("Signature not found!") return "ignore" else: raise action = siginfo.evaluate_filter_for_user(username) return action def set_user_data(self, sig, username, item, data): log_debug("set_user_data: username=%s item=%s data=%s sig=\n%s" % (username, item, data, sig)) try: siginfo = self.lookup_signature(sig) except ProgramError as e: if e.errno == ERR_NO_SIGNATURE_MATCH: log_debug("Signature not found!") return else: raise user_data = siginfo.get_user_data(username) user_data.update_item(item, data) self.modify_siginfo(siginfo) def set_filter(self, sig, username, filter_type, data=""): log_debug("set_filter: username=%s filter_type=%s sig=\n%s" % (username, filter_type, sig)) try: siginfo = self.lookup_signature(sig) except ProgramError as e: if e.errno == ERR_NO_SIGNATURE_MATCH: log_debug("Signature not found!") return else: raise siginfo.update_user_filter(username, filter_type, data) self.modify_siginfo(siginfo) def add_user(self, username): self.user = self.sigs.users.add_user(username) self.mark_modified() def get_user(self, username): return self.sigs.users.get_user(username) #------------------------------------------------------------------------------ class SETroubleshootDatabaseLocal(RpcManage, SETroubleshootDatabaseInterface, SETroubleshootDatabaseNotifyInterface, GObject.GObject): __gsignals__ = { 'signatures_updated': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT)), 'async-error': # callback(method, errno, strerror) (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_STRING)), } def __init__(self, database): GObject.GObject.__init__(self) RpcManage.__init__(self) self.database = database self.database.set_notify(self) def set_notify(self, notify): self.database.set_notify(notify) def emit_rpc(self, rpc_id, type, rpc_def, *args): log_debug("%s emit %s(%s) id=%s" % (self.__class__.__name__, rpc_def.method, ','.join([str(arg) for arg in args]), rpc_id)) async_rpc = self.async_rpc_cache[rpc_id] func = getattr(self.database, rpc_def.method, None) if func is None: raise ProgramError(ERR_METHOD_NOT_FOUND, "method %s not found in base class of %s" % (rpc_def.method, self.__class__.__name__)) try: async_rpc.return_args = func(*args) async_rpc.return_type = 'method_return' if async_rpc.return_args is not None: async_rpc.return_args = [async_rpc.return_args] except ProgramError as e: async_rpc.return_args = [e.errno, e.strerror] async_rpc.return_type = 'error_return' if async_rpc.return_args is not None: GObject.idle_add(self.process_async_return, async_rpc) def signatures_updated(self, type, item): log_debug('signatures_updated() database local: type=%s item=%s' % (type, item)) self.emit('signatures_updated', type, item) GObject.type_register(SETroubleshootDatabaseLocal) #------------------------------------------------------------------------------ class LogfileAnalyzer(GObject.GObject): __gsignals__ = { 'progress': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_FLOAT,)), 'state-changed': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,)), } def __init__(self, logfile_path=None): GObject.GObject.__init__(self) log_debug("%s.__init__(%s)" % (self.__class__.__name__, logfile_path)) self.logfile_path = logfile_path self.file = None self.fileno = None self.read_size = 128 self.record_reader = None self.record_receiver = None self.analyzer = None self.report_receiver = None self.idle_proc_id = None self.errno = None self.strerror = None def open(self, logfile_path=None): if logfile_path is not None: self.logfile_path = logfile_path log_debug('%s.open(%s)' % (self.__class__.__name__, self.logfile_path)) try: stat_info = os.stat(self.logfile_path) self.file_size = stat_info[ST_SIZE] self.file = open(self.logfile_path) self.fileno = self.file.fileno() except EnvironmentError as e: syslog.syslog(syslog.LOG_ERR, '%s.open(): %s' % (self.__class__.__name__, e.strerror)) self.errno = e.errno self.strerror = e.strerror raise e self.n_bytes_read = 0 self.line_count = 0 self.record_count = 0 self.progress = 0.0 self.cancelled = False self.emit('progress', self.progress) logfile_basename = os.path.basename(self.logfile_path) self.friendly_name = "file: %s" % (os.path.splitext(logfile_basename)[0]) self.database = SETroubleshootDatabase(None, logfile_basename, friendly_name=self.friendly_name) self.record_reader = AuditRecordReader(AuditRecordReader.TEXT_FORMAT) self.record_receiver = AuditRecordReceiver() self.analyzer = Analyze() if not get_config('test', 'analyze', bool): self.report_receiver = PluginReportReceiver(self.database) else: self.report_receiver = TestPluginReportReceiver(self.database) return True def run(self): log_debug('%s.run(%s)' % (self.__class__.__name__, self.file)) task_generator = self.task() self.idle_proc_id = GLib.idle_add(lambda: next(task_generator)) return True def close(self): if self.file is not None: new_data = os.read(self.fileno, self.read_size) self.file = None self.fileno = None if self.n_bytes_read < self.file_size: # ok to read more (meanwhile, new messages got appended) import errno as Errno strerror = "failed to read complete file, %d bytes read out of total %d bytes (%s)" % \ (self.n_bytes_read, self.file_size, self.logfile_path) log_debug(strerror) self.errno = Errno.EIO self.strerror = strerror if self.record_receiver is not None: # All done, flush all buffered events out for audit_event in self.record_receiver.close(): self.avc_event_handler(audit_event) if not self.cancelled: self.emit('progress', 1.0) def task(self): self.emit('state-changed', 'running') while self.fileno: try: new_data = os.read(self.fileno, self.read_size).decode('utf-8') if new_data == '': log_debug("EOF on %s" % self.logfile_path) self.close() except EnvironmentError as e: self.errno = e.errno self.strerror = e.strerror self.close() self.emit('state-changed', 'stopped') yield False except ValueError as e: print("\n", e, file=sys.stderr) self.n_bytes_read += len(new_data) if self.file_size > 0: self.progress = float(self.n_bytes_read) / float(self.file_size) self.emit('progress', self.progress) for (record_type, event_id, body_text, fields, line_number) in self.record_reader.feed(new_data): self.new_audit_record_handler(record_type, event_id, body_text, fields, line_number) yield True if self.cancelled: yield False yield True self.emit('state-changed', 'stopped') yield False def avc_event_handler(self, audit_event): log_debug('avc_event_handler() audit_event=%s' % audit_event) if audit_event.is_avc() and not audit_event.is_granted() and audit_event.num_records() > 0: avc = AVC(audit_event) self.analyzer.analyze_avc(avc, self.report_receiver, False) def new_audit_record_handler(self, record_type, event_id, body_text, fields, line_number): 'called to enter a new audit record' log_debug('new_audit_record_handler() record_type=%s event_id=%s body_text=%s' % (record_type, event_id, body_text)) self.record_count += 1 audit_record = AuditRecord(record_type, event_id, body_text, fields, line_number) for audit_event in self.record_receiver.feed(audit_record): try: self.avc_event_handler(audit_event) except ValueError as e: print(e, file=sys.stderr) GObject.type_register(LogfileAnalyzer) audit_data.py000064400000116707152572267760007254 0ustar00from __future__ import absolute_import import six from six.moves import range import sys # Authors: John Dennis # Thomas Liu y) - (x < y) #----------------------------------------------------------------------------- standard_directories = get_standard_directories() #----------------------------------------------------------------------------- def audit_record_from_text(text): parse_succeeded, record_type, event_id, body_text = parse_audit_record_text(text) audit_record = AuditRecord(record_type, event_id, body_text) return audit_record #----------------------------------------------------------------------------- def derive_record_format(socket_path): if re.search('/audispd_events$', socket_path): return AuditRecordReader.TEXT_FORMAT if re.search('/audit_events$', socket_path): return AuditRecordReader.BINARY_FORMAT return AuditRecordReader.TEXT_FORMAT # assume new format # regular expression to find message like this: # msg=audit(1152828325.857:123085): avc: denied { append } for pid=14205 ... # Note, messages arriving directly from the audit system omit # 'msg=', but messages in log files prepend 'msg=' # group 1 is the optional "node=XXX " # group 2 is the node if node=XXX is present # group 3 is the optional "type=XXX " # group 4 is the type if type=XXX is present # group 5 is the optional 'msg=' # group 6 is the complete event id # group 7 is the seconds component of the timestamp # group 8 is the millisconds component of the timestamp # group 9 is the timestamp unique number # group 10 is the body of the message appearing after the event id audit_input_re = re.compile(r'(node=(\S+)\s+)?(type=(\S+)\s+)?(msg=)?audit\(((\d+)\.(\d+):(\d+))\):\s*(.*)') def parse_audit_record_text(input): parse_succeeded = False host = None record_type = None event_id = None body_text = None match = audit_input_re.search(input) if match is not None: parse_succeeded = True if match.group(2): host = match.group(2) if match.group(4): record_type = match.group(4) if match.group(6): seconds = int(match.group(7)) milli = int(match.group(8)) serial = int(match.group(9)) event_id = AuditEventID(seconds, milli, serial, host) body_text = match.group(10) return (parse_succeeded, record_type, event_id, body_text) audit_binary_input_re = re.compile(r'audit\(((\d+)\.(\d+):(\d+))\):\s*(.*)') def parse_audit_binary_text(input): parse_succeeded = False event_id = None body_text = None match = audit_binary_input_re.search(input) if match is not None: parse_succeeded = True if match.group(1): seconds = int(match.group(2)) milli = int(match.group(3)) serial = int(match.group(4)) event_id = AuditEventID(seconds, milli, serial) body_text = match.group(5) return (parse_succeeded, event_id, body_text) #------------------------------------------------------------------------ import string def printable(s): if s: filtered_path = [x for x in s if x in string.printable] if filtered_path == s: return True return False class AvcContext(XmlSerialize): _xml_info = { 'user': {'XMLForm': 'attribute'}, 'role': {'XMLForm': 'attribute'}, 'type': {'XMLForm': 'attribute'}, 'mls': {'XMLForm': 'attribute'}, } def __init__(self, data): super(AvcContext, self).__init__() if isinstance(data, six.string_types): fields = data.split(':') if len(fields) >= 3: self.user = fields[0] self.role = fields[1] self.type = fields[2] if len(fields) > 3: self.mls = ':'.join(fields[3:]) else: self.mls = 's0' def __str__(self): return '%s:%s:%s:%s' % (self.user, self.role, self.type, self.mls) def format(self): # FIXME, what does selinux_raw_to_trans_context() do and why do we need it? (rc, trans) = selinux.selinux_raw_to_trans_context(str(self)) return trans def __ne__(self, other): return not self.__eq__(other) def __eq__(self, other): for name in list(self._xml_info.keys()): if getattr(self, name) != getattr(other, name): return False return True #----------------------------------------------------------------------------- class AuditEventID(XmlSerialize): _xml_info = { 'seconds': {'XMLForm': 'attribute', 'import_typecast': int}, 'milli': {'XMLForm': 'attribute', 'import_typecast': int}, 'serial': {'XMLForm': 'attribute', 'import_typecast': int}, 'host': {'XMLForm': 'attribute'}, } def __init__(self, seconds, milli, serial, host=None): super(AuditEventID, self).__init__() self.seconds = seconds self.milli = milli self.serial = serial if host is not None: self.host = host def __eq__(self, other): if self.host != other.host: return False if self.seconds != other.seconds: return False if self.milli != other.milli: return False if self.serial != other.serial: return False return True def __lt__(self, other): if self.host != other.host: raise ValueError("cannot compare two %s objects whose host values differ (%s!=%s)" % (self.__class__.__name__, self.host, other.host)) if self.seconds != other.seconds: return self.seconds < other.seconds if self.milli != other.milli: return self.milli < other.milli return self.serial < other.serial def copy(self): import copy return copy.copy(self) time = property(lambda self: float(self.sec) + self.milli / 1000.0) def __str__(self): return "audit(%d.%d:%d)" % (self.seconds, self.milli, self.serial) def is_valid(self): if self.seconds is None: return False if self.milli is None: return False if self.serial is None: return False return True #----------------------------------------------------------------------------- class AuditRecord(XmlSerialize): _xml_info = { 'record_type': {'XMLForm': 'attribute', }, 'event_id': {'XMLForm': 'element', 'import_typecast': AuditEventID}, 'body_text': {'XMLForm': 'element'}, 'line_number': {'XMLForm': 'attribute', 'import_typecast': int}, } binary_version = 0 binary_header_format = "iiii" binary_header_size = struct.calcsize(binary_header_format) key_value_pair_re = re.compile(r"([^ \t]+)\s*=\s*([^ \t]+)") avc_re = re.compile(r"avc:\s+([^\s]+)\s+{([^}]+)}\s+for\s+") exec_arg_re = re.compile(r'^a\d+$') def __init__(self, record_type, event_id, body_text, fields=None, line_number=None): super(AuditRecord, self).__init__() # Header self.record_type = record_type self.event_id = event_id self.body_text = body_text self.fields = fields self.line_number = line_number self._init_postprocess() def _init_postprocess(self): if getattr(self, 'fields', None) is None: self.set_fields_from_text(self.body_text) if self.record_type in ['AVC', 'USER_AVC', "1400", "1107"]: if 'seresult' not in self.fields: match = AuditRecord.avc_re.search(self.body_text) if match: seresult = match.group(1) self.fields['seresult'] = seresult seperms = match.group(2) self.fields['seperms'] = seperms.split() def __str__(self): return self.to_host_text() def audispd_rectify(self): self.line_number = None if self.event_id.host is None: self.event_id.host = get_hostname() def is_valid(self): if not self.event_id.is_valid(): return False if self.record_type is None: return False if self.message is None: return False return True def decode_fields(self): encoded_fields = ['acct', 'cmd', 'comm', 'cwd', 'data', 'dir', 'exe', 'file', 'host', 'key', 'msg', 'name', 'new', 'ocomm' 'old', 'path', 'watch'] for field in encoded_fields: if field in self.fields: if self.record_type == 'AVC' and field == 'saddr': continue value = self.fields[field] decoded_value = audit_msg_decode(value) self.fields[field] = decoded_value if self.record_type == 'EXECVE': for field, value in list(self.fields.items()): if self.exec_arg_re.search(field): value = self.fields[field] decoded_value = audit_msg_decode(value) self.fields[field] = decoded_value def translate_hex(self, path): try: if sys.version_info[0] < 3: # Produces normal string instead of unicode string which is not # accepted by libselinux functions. # This means that len(path) will return inaccurate results when # the string contains special characters. Also individual bytes # of path may not be printable. return path.decode('hex') else: # produces str in python 3 and unicode string in python 2 return bytearray.fromhex(path).decode('utf-8') except: return path def set_fields_from_text(self, body_text): self.fields_ord = [] self.fields = {} for match in AuditRecord.key_value_pair_re.finditer(body_text): key = match.group(1) value = match.group(2) value = value.strip('"') try: if key == "arch": i = audit.audit_elf_to_machine(int(value, 16)) value = audit.audit_machine_to_name(i) if key in ["name", "path", "comm", "cmd", "exe", "cwd"]: # audit uses " to distinguish plain text from hex in listed keys if not match.group(2).startswith('"'): value = self.translate_hex(value) if key == "exit": try: value = errno.errorcode[abs(int(value))] except: pass if key == "syscall": syscall_name = audit.audit_syscall_to_name(int(value), audit.audit_detect_machine()) if syscall_name: value = syscall_name except ValueError: pass self.fields[key] = value self.fields_ord.append(key) def get_field(self, name): return self.fields.get(name) def get_binary_header(self, msg): msg_length = len(msg) return struct.pack(AuditRecord.binary_header_format, AuditRecord.binary_version, AuditRecord.binary_header_size, self.record_type, msg_length) def fields_to_text(self): if self.fields is None: return '' if self.record_type == 'AVC': buf = "type=%s msg=%s: avc: denied { %s } " % (self.record_type, self.event_id, ' '.join(self.access)) else: buf = "type=%s msg=%s: " % (self.record_type, self.event_id) buf += ' '.join(["%s=%s" % (k, self.fields[k]) for k in self.fields_ord]) + "\n" return buf def to_text(self): return "type=%s msg=%s: %s\n" % (self.record_type, self.event_id, self.body_text) def to_host_text(self): if self.event_id.host is not None: return "node=%s type=%s msg=%s: %s\n" % \ (self.event_id.host, self.record_type, self.event_id, self.body_text) else: return self.to_text() def to_binary(self): record = "%s: %s" % (self.event_id, self.body_text) return self.get_binary_header(record) + record #----------------------------------------------------------------------------- class AuditRecordReader: BINARY_FORMAT = 1 TEXT_FORMAT = 2 def __init__(self, record_format): self.record_format = record_format self._input_buffer = '' self.line_number = 0 if self.record_format == self.TEXT_FORMAT: self.feed = self.feed_text elif self.record_format == self.BINARY_FORMAT: self.feed = self.feed_binary else: raise ValueError("unknown record format (%s) in %s" % (record_format, self.__class__.__name__)) def feed_binary(self, new_data): if len(new_data) <= 0: return self._input_buffer += new_data # Now process as much of the buffer as we can, iterating over complete # messages. while True: # To read a complete message there must be a complete header and # all the data the header specified via the header.length if len(self._input_buffer) < AuditRecord.binary_header_size: return binary_version, binary_header_size, record_type, msg_length = \ struct.unpack(AuditRecord.binary_header_format, self._input_buffer[0:AuditRecord.binary_header_size]) total_len = AuditRecord.binary_header_size + msg_length if len(self._input_buffer) < total_len: return text = self._input_buffer[AuditRecord.binary_header_size:total_len] parse_succeeded, event_id, body_text = parse_audit_binary_text(text) self._input_buffer = self._input_buffer[total_len:] if parse_succeeded: yield (audit.audit_msg_type_to_name(record_type), event_id, body_text, None, 0) return def feed_text(self, new_data): if len(new_data) <= 0: return self._input_buffer += new_data # Now process as much of the buffer as we can, iterating over complete # messages. # To read a complete message we must see a line ending start = 0 end = self._input_buffer.find('\n', start) while end >= 0: self.line_number += 1 end += 1 # include newline line = self._input_buffer[start:end] parse_succeeded, record_type, event_id, body_text = parse_audit_record_text(line) if parse_succeeded: yield (record_type, event_id, body_text, None, self.line_number) start = end end = self._input_buffer.find('\n', start) self._input_buffer = self._input_buffer[start:] return #----------------------------------------------------------------------------- class AuditEvent(XmlSerialize): _xml_info = { 'records': {'XMLForm': 'element', 'list': 'audit_record', 'import_typecast': AuditRecord, }, 'event_id': {'XMLForm': 'element', 'import_typecast': AuditEventID}, } def __init__(self): super(AuditEvent, self).__init__() self.event_id = None self.records = [] self.record_types = {} self.timestamp = None def _init_postprocess(self): if getattr(self, 'record_types', None) is None: self.record_types = {} for record in self.records: self.process_record(record) def __str__(self): line_numbers = self.line_numbers line_numbers.sort() return "%s: is_avc=%s, is_granted=%s: line_numbers=[%s]\n%s" % \ (self.event_id, self.is_avc(), self.is_granted(), ",".join([str(x) for x in line_numbers]), "\n".join([" %s" % record for record in self.records])) def format(self, separator='\n'): return separator.join([str(record) for record in self.records]) def num_records(self): return len(self.records) line_numbers = property(lambda self: [record.line_number for record in self.records if record.line_number]) def add_record(self, record): self.records.append(record) self.process_record(record) def process_record(self, record): if self.event_id is None: self.event_id = record.event_id.copy() self.timestamp = float(self.event_id.seconds) + (self.event_id.milli / 1000.0) else: if not self.event_id == record.event_id: raise ValueError("cannot add audit record to audit event, event_id mismatch %s != %s" % (self.event_id, record.event_id)) record_list = self.record_types.setdefault(record.record_type, []) record_list.append(record) def get_field(self, name, record_type=None): '''Return list of (value, record_type) tuples. In other words return the value matching name for every record_type. If record_type is not specified then all records are searched. Note: it is possible to have more than one record of a given type thus it is always possible to have multiple values returned.''' items = [] if record_type is None: records = self.records else: records = self.get_records_of_type(record_type) for record in records: value = record.fields.get(name) if value is None: continue items.append((value, record.type)) return items def get_record_of_type(self, type): record = None records = self.record_types.get(type) if records: record = records[0] return record def get_records_of_type(self, type): return self.record_types.get(type, []) def get_avc_record(self): for record_type in ['AVC', 'USER_AVC', "1400", "1107"]: record = self.get_record_of_type(record_type) if (record): return record def is_avc(self): return self.get_avc_record() is not None def is_granted(self): avc_record = self.get_avc_record() if avc_record is None: return False seresult = avc_record.fields['seresult'] if seresult == 'denied': return False if seresult == 'granted': return True log.avc.warn("unknown value for seresult ('%s')", seresult) return False #------------------------------------------------------------------------------ class AVC: # These are the perm sets from the reference policy for file, dirs, and filesystems. # They are here to be used below in the access matching functions. stat_file_perms = ['getattr'] x_file_perms = ['getattr', 'execute'] r_file_perms = ['open', 'read', 'getattr', 'lock', 'ioctl'] rx_file_perms = ['open', 'read', 'getattr', 'lock', 'execute', 'ioctl'] ra_file_perms = ['open', 'ioctl', 'read', 'getattr', 'lock', 'append'] link_file_perms = ['getattr', 'link', 'unlink', 'rename'] create_lnk_perms = ['create', 'read', 'getattr', 'setattr', 'link', 'unlink', 'rename'] create_file_perms = ['open', 'create', 'ioctl', 'read', 'getattr', 'lock', 'write', 'setattr', 'append', 'link', 'unlink', 'rename'] r_dir_perms = ['open', 'read', 'getattr', 'lock', 'search', 'ioctl'] rw_dir_perms = ['open', 'read', 'getattr', 'lock', 'search', 'ioctl', 'add_name', 'remove_name', 'write'] ra_dir_perms = ['open', 'read', 'getattr', 'lock', 'search', 'ioctl', 'add_name', 'write'] create_dir_perms = ['open', 'create', 'read', 'getattr', 'lock', 'setattr', 'ioctl', 'link', 'unlink', 'rename', 'search', 'add_name', 'remove_name', 'reparent', 'write', 'rmdir'] mount_fs_perms = ['mount', 'remount', 'unmount', 'getattr'] search_dir_perms = ['getattr', 'search'] getattr_dir_perms = ['getattr'] setattr_dir_perms = ['setattr'] list_dir_perms = ['open', 'getattr', 'search', 'read', 'lock', 'ioctl'] add_entry_dir_perms = ['open', 'getattr', 'search', 'lock', 'ioctl', 'write', 'add_name'] del_entry_dir_perms = ['open', 'getattr', 'search', 'lock', 'ioctl', 'write', 'remove_name'] manage_dir_perms = ['open', 'create', 'getattr', 'setattr', 'read', 'write', 'link', 'unlink', 'rename', 'search', 'add_name', 'remove_name', 'reparent', 'rmdir', 'lock', 'ioctl'] getattr_file_perms = ['getattr'] setattr_file_perms = ['setattr'] read_file_perms = ['open', 'getattr', 'read', 'lock', 'ioctl'] append_file_perms = ['open', 'getattr', 'append', 'lock', 'ioctl'] write_file_perms = ['open', 'getattr', 'write', 'append', 'lock', 'ioctl'] rw_file_perms = ['open', 'getattr', 'read', 'write', 'append', 'ioctl', 'lock'] delete_file_perms = ['getattr', 'unlink'] manage_file_perms = ['open', 'create', 'getattr', 'setattr', 'read', 'write', 'append', 'rename', 'link', 'unlink', 'ioctl', 'lock'] pipe_instance_path_re = re.compile(r'^(\w+):\[([^\]]*)\]') proc_pid_instance_re = re.compile(r'^(/proc/)(\d+)(.*)') def __init__(self, audit_event, query_environment=True): self.audit_event = audit_event self.query_environment = query_environment # if audit_event.timestamp is None: # self.audit_event.timestamp = TimeStamp() self.template_substitutions = {} self.tpath = None self.spath = None self.source = None self.source_pkg = None self.access = None self.scontext = None self.tcontext = None self.tclass = None self.port = None self.src_rpms = [] self.tgt_rpms = [] self.host = None self.pid = None self.kmod = None self.syscall = None self.why = None self.bools = [] self.derive_avc_info_from_audit_event() def __str__(self): return self.format_avc() def format_avc(self): text = '' text += 'scontext=%s ' % self.scontext text += 'tcontext=%s ' % self.tcontext text += 'access=%s ' % self.access text += 'tclass=%s ' % self.tclass text += 'tpath=%s ' % self.tpath return text # Below are helper functions to get values that might be # stored in one or more fields in an AVC. def has_any_access_in(self, access_list): 'Returns true if the AVC contains _any_ of the permissions in the access list.' if self.access is None: return False for a in self.access: if a in access_list: return True return False def all_accesses_are_in(self, access_list): """Returns true if _every_ access in the AVC matches at least one of the permissions in the access list.""" if self.access is None: return False for a in self.access: if a not in access_list: return False return True def allowed_target_types(self): all_types = get_all_file_types() + get_all_port_types() all_types.sort() all_attributes = get_all_attributes() all_attributes.sort() allowed_types = [] wtypes = [x[TARGET] for x in [y for y in search([ALLOW], {SOURCE: self.scontext.type, CLASS: self.tclass, PERMS: self.access}) if y["enabled"]]] types = wtypes for t in types: if t in all_attributes: wtypes.extend(next(info(ATTRIBUTE, t))["types"]) for t in wtypes: if t in all_types: if t not in allowed_types: allowed_types.append(t) allowed_types.sort() return allowed_types def open_with_write(self): if self.has_any_access_in(['open']): try: if self.a1 and (int(self.a1) & O_ACCMODE) != os.O_RDONLY: return True except: pass return False def __typeMatch(self, context, type_list): for type in type_list: if re.match(type, context.type): return True return False def matches_source_types(self, type_list): """Returns true if the type in the source context of the avc regular expression matches any of the types in the type list.""" if self.scontext is None: return False return self.__typeMatch(self.scontext, type_list) def matches_target_types(self, type_list): """Returns true if the type in the target context of the avc regular expression matches any of the types in the type list.""" if self.tcontext is None: return False return self.__typeMatch(self.tcontext, type_list) def has_tclass_in(self, tclass_list): if self.tclass is None: return False return self.tclass in tclass_list def update(self): self.derive_environmental_info() self.update_derived_template_substitutions() def path_is_not_standard_directory(self): if self.tpath is None: return True return self.tpath not in standard_directories def _set_tpath(self): '''Derive the target path. If path information is available the avc record will have a path field and no name field because the path field is more specific and supercedes name. The name field is typically the directory entry. For some special files the kernel embeds instance information into the file name. For example 'pipe:[1234]' or 'socket:[1234]' where the number inside the brackets is the inode number. The proc pseudo file system has the process pid embedded in the name, for example '/proc/1234/mem'. These numbers are ephemeral and do not contribute meaningful information for our reports. Plus we may use the path information to decide if an alert is identical to a previous alert, we coalesce them if they are. The presence of an instance specific number in the path confuses this comparison. For these reasons we strip any instance information out of the path, Example input and output: pipe:[1234] --> pipe socket:[1234] --> socket /proc/1234/fd --> /proc//fd ./foo --> ./foo /etc/sysconfig --> /etc/sysconfig ''' path = None name = self.avc_record.get_field('name') # First try to get the path from the AVC record, new kernel # versions put it there rather than in AVC_PATH path = self.avc_record.get_field('path') inodestr = self.avc_record.get_field("ino") if path is None: # No path field in AVC record, try to get path from PATH records avc_path_records = self.audit_event.get_records_of_type('PATH') for avc_path_record in avc_path_records: record_type = avc_path_record.get_field('nametype') #Avoid PARENT records if possible if path and record_type == "PARENT": continue path = avc_path_record.get_field('name') # If there is more non-PARENT PATH records, use the one matching # the name from AVC record... otherwise use the last one if path and name and record_type != "PARENT" and path.endswith(name): break if path is None: # No path field, so try and use the name field instead name = self.avc_record.get_field('name') if name is not None: # Use the class to be smart about formatting the name tclass = self.avc_record.get_field('tclass') if tclass == 'file': # file name is not a full path so make it appear relative path = '%s' % name elif tclass == 'dir': # directory component is not a full path so make it appear # relative, but only if it's not the root if name == '/': path = name else: path = '%s' % name else: # just use the bare name path = name if path is not None: if path == "/" and inodestr: matches = [] try: dev_rdev = 0 dev = self.avc_record.get_field('dev') if os.path.exists("/dev/" + dev): dev_rdev = os.lstat("/dev/" + dev).st_rdev ino = int(inodestr) fd = open("/proc/mounts", "r") for i in fd.read().split("\n"): x = i.split() if len(x) and x[1][0] == '/': try: if (dev_rdev == 0 or os.stat(x[0]).st_rdev == dev_rdev) and int(os.lstat(x[1]).st_ino) == ino: matches.append(x[:3]) except OSError: continue fd.close() if len(matches) == 1: path = matches[0][1] elif len(matches) > 1: for i in matches: if i[0] == ("/dev/%s" % dev) or i[2] == dev: path = i[1] break else: try: if dev_rdev != 0 and os.lstat(i[0]).st_rdev == dev_rdev: path = i[1] break except OSError: pass except TypeError: path = "unknown mountpoint" pass except OSError: path = "unknown mountpoint" pass else: if path.startswith("/") == False and inodestr: import subprocess command = ["locate", "-b", r"\%s" % path] try: output = subprocess.check_output(command, stderr=subprocess.STDOUT, universal_newlines=True) ino = int(inodestr) for file in output.split("\n"): try: if int(os.lstat(file).st_ino) == ino: path = file break except: pass except: pass if path is not None: if path.startswith('/'): # Fully qualified path # map /proc/1234/ to /proc/, replacing numeric pid with path = self.proc_pid_instance_re.sub(r'\1\3', path) else: # map pipe:[1234] to pipe, stripping out inode instance (e.g. [1234]) # applies to socket as well match = self.pipe_instance_path_re.search(path) if match: path = self.tclass # abstract socket paths start with '\0' if path[0] == '\0': path = "@" + path.strip('\0') self.tpath = path if self.tpath is None: if self.tclass == "filesystem": self.tpath = "" elif self.tclass == "udp_socket" or self.tclass == "tcp_socket": self.tpath = _("port %s") % self.port else: self.tpath = _("Unknown") 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') 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') 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**** Recorded AVC is allowed in current policy ****\n") % self.avc_record) if self.why == audit2why.DONTAUDIT: raise ValueError(_("%s \n**** Recorded AVC is 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.BADTCLASS: 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 derive_environmental_info(self): if self.query_environment: if self.spath: self.source_pkg = get_package_nvr_by_file_path(self.spath) if self.source_pkg: self.src_rpms.append(self.source_pkg) if self.tpath: rpm = get_package_nvr_by_file_path(self.tpath) if rpm: self.tgt_rpms.append(rpm) def set_alt_path(self, path): if self.tpath is None: self.tpath = path def set_template_substitutions(self, **kwds): for key, value in list(kwds.items()): if value: self.template_substitutions[key] = value def update_derived_template_substitutions(self): self.template_substitutions["SOURCE_TYPE"] = escape_html(self.scontext.type) self.template_substitutions["TARGET_TYPE"] = escape_html(self.tcontext.type) self.template_substitutions["SOURCE"] = escape_html(self.source) self.template_substitutions["SOURCE_PATH"] = escape_html(self.spath) if self.spath: self.template_substitutions["FIX_SOURCE_PATH"] = re.sub(" ", ".", escape_html(self.spath)) self.template_substitutions["TARGET_PATH"] = escape_html(self.tpath) if self.tpath: self.template_substitutions["FIX_TARGET_PATH"] = re.sub(" ", ".", escape_html(self.tpath)) if self.tpath is None: self.template_substitutions["TARGET_DIR"] = None else: if self.tclass == 'dir': self.template_substitutions["TARGET_DIR"] = escape_html(self.tpath) elif self.tclass == 'file': self.template_substitutions["TARGET_DIR"] = escape_html(os.path.dirname(self.tpath)) else: self.template_substitutions["TARGET_DIR"] = None self.template_substitutions["TARGET_CLASS"] = escape_html(self.tclass) if self.access is None: self.template_substitutions["ACCESS"] = None else: self.template_substitutions["ACCESS"] = escape_html(' '.join(self.access)) self.template_substitutions["SOURCE_PACKAGE"] = escape_html(self.source_pkg) self.template_substitutions["PORT_NUMBER"] = escape_html(self.port) def validate_template_substitutions(self): # validate, replace any None values with friendly string for key, value in list(self.template_substitutions.items()): if value is None: self.template_substitutions[key] = escape_html(default_text(value)) avc_audit.py000064400000035627152572267760007115 0ustar00# Authors: John Dennis # # Copyright (C) 2006,2007,2008 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # __all__ = [ 'AuditSocketReceiverThread', 'AuditRecordReceiver', # FIXME, do we really want to export this? 'verify_avc', ] from builtins import str from builtins import object import syslog import audit import select import selinux import socket as Socket import fcntl from six.moves import _thread import threading import time from functools import cmp_to_key from setroubleshoot.config import get_config from setroubleshoot.errcode import * from setroubleshoot.util import * from setroubleshoot.audit_data import * try: getattr(audit, 'AUDIT_EOE') except AttributeError: audit.AUDIT_EOE = 1320 #------------------------------------------------------------------------------ my_context = AvcContext(selinux.getcon()[1]) def verify_avc(avc): if avc.scontext.type == None or avc.tcontext.type == None: return False if my_context.type == avc.scontext.type: syslog.syslog(syslog.LOG_ERR, "setroubleshoot generated AVC, exiting to avoid recursion, context=%s, AVC scontext=%s" % (my_context, avc.scontext)) syslog.syslog(syslog.LOG_ERR, "audit event\n%s" % (avc.audit_event.format())) import sys sys.exit(0) return True #------------------------------------------------------------------------------ class AuditRecordReceiver(object): """ The audit system emits messages about a single event independently. Thus one single auditable event may be composed from one or more individual audit messages. Each audit message is prefixed with a unique event id, which includes a timestamp. The last audit message associated with an event is not marked in any fashion. Audit messages for a specific event may arrive interleaved with audit messages for other events. It is the job of higher level software (this code) to assemble the audit messages into events. The AuditEvent class is used for assembly. When a new event id is seen a new AuditEvent object is created, then every time an audit message arrives with that event id it is added to that object. The AuditEvent object contains the timestamp associated with the audit event as well as other data items useful for processing and handling the event. The audit system does not tell us when the last message belonging to an event has been emitted so we have no explicit way of knowing when the audit event has been fully assembled from its constituent message parts. We use the heuristic if a sufficient length of time has expired since we last saw a message for this event, then it must be complete Thus when audit events are created we place them in a cache where they will reside until their time to live has expired at which point we will assume they are complete and emit the event. Events are expired in the flush_cache() method. The events resident in the cache are sorted by their timestamps. A time threshold is established. Any events in the cache older than the time threshold are flushed from the cache as complete events. When should flushes be performed? The moment when a new message is added would seem a likely candidate moment to perform a sweep of the cache. But this is costly and does not improve how quickly events are expired. We could wait some interval of time (something much greater than how long we expect it would take for messages percolate) and this has good behavior, except for the following case. Sometimes messages are emitted by audit in rapid succession. If we swept the cache once a second then the cache may have grown quite large. Since it is very likely that any given audit event is complete by the time the next several events start arriving we can optimize by tracking how many messages have arrived since the last time we swept the cache. The the heuristic for when to sweep the cache becomes: If we've seen a sufficient number of messages then sweep -or- if a sufficient length of time has elapsed then we sweep Note that when audit messages are injected via log file scanning elapsed wall clock time has no meaning relative to when to perform the cache sweep. However, the timestamp for an event remains a critical factor when deciding if an event is complete (have we scanned far enough ahead such we're confident we won't see any more messages for this event?). Thus the threshold for when to expire an event from the cache during static log file scanning is determined not by wall clock time but rather by the oldest timestamp in the cache (e.g.there is enough spread between timestamps in the cache its reasonable to assume the event is complete). One might ask in the case of log file scanning why not fill the cache until EOF is reached and then sweep the cache? Because in log files it is not unusual to have thousands or tens of thousands of events and the cache would grown needlessly large. Because we have to deal with the real time case we already have code to keep only the most recent events in the cache so we might as well use that logic, keep the code paths the same and minimize resource usage. """ # number of seconds an event must reside in the cache until its # considered complete cache_time_to_live = 0.005 def __init__(self): self.flush_size = 30 self.flush_count = 0 self.cache = {} self.events = [] self.reset_statistics() def num_cached_events(self): return len(self.cache) def reset_statistics(self): self.max_cache_length = 0 self.event_count = 0 def insert_new_event(self, record): audit_event = AuditEvent() self.cache[str(record.event_id)] = audit_event return audit_event def get_event_from_record(self, record): return self.cache.get(str(record.event_id), None) def add_record_to_cache(self, record): log_debug("%s.add_record_to_cache(): %s" % (self.__class__.__name__, record)) audit_event = self.get_event_from_record(record) if record.record_type == 'EOE': if audit_event: self.flush_event(audit_event) return if audit_event is None: audit_event = self.insert_new_event(record) audit_event.add_record(record) def emit_event(self, audit_event): self.event_count += 1 self.events.insert(0, audit_event) def flush_event(self, audit_event): self.emit_event(audit_event) del(self.cache[str(audit_event.event_id)]) def flush_cache(self, threshold_age=None): '''Flush events from the cache if they are older than the threshold age. If the threshold age is None then the threshold age is set to the age of the newest event in the cache minus the cache time to live, in other words anything in the cache which is older than the time to live relative to the most current event is flushed. ''' # no events, nothing to do if len(self.cache) == 0: return if len(self.cache) > self.max_cache_length: self.max_cache_length = len(self.cache) event_ids = list(self.cache.keys()) # flush everything if threshold_age == 0: for event_id in event_ids: audit_event = self.cache[event_id] self.flush_event(audit_event) return # flush old events event_ids.sort(key=cmp_to_key(lambda a, b: self.cache[a].timestamp < self.cache[b].timestamp)) if threshold_age is None: threshold_age = self.cache[event_ids[-1]].timestamp - self.cache_time_to_live for event_id in event_ids: audit_event = self.cache[event_id] if audit_event.timestamp < threshold_age: self.flush_event(audit_event) def flush(self, threshold_age=None): self.flush_cache(threshold_age) self.flush_count = 0 while len(self.events) > 0: audit_event = self.events.pop() yield audit_event def close(self): """Emit every event in the cache irrespective of its timestamp. This means we're done, nothing should remain buffered.""" for audit_event in self.flush(0): yield audit_event def feed(self, record): 'Accept a new audit record into the system for processing.' self.flush_count += 1 if record.record_type in ('AVC', 'AVC_PATH', 'SYSCALL', 'CWD', 'PATH', 'EOE', "1400", "1107"): self.add_record_to_cache(record) # If we've seen enough messages then sweep the event cache and flush what we can if self.flush_count > self.flush_size: for audit_event in self.flush(): yield audit_event while len(self.events) > 0: audit_event = self.events.pop() yield audit_event #------------------------------------------------------------------------------ class AuditSocketReceiverThread(threading.Thread): def __init__(self, queue, report_receiver): # parent class constructor threading.Thread.__init__(self) self.queue = queue self.report_receiver = report_receiver self.record_receiver = AuditRecordReceiver() self.retry_interval = get_config('audit', 'retry_interval', int) self.get_socket_paths() self.timeout_interval = 2 self.has_audit_eoe = False def get_socket_paths(self): self.audit_socket_paths = [] audit_socket_path = get_config('audit', 'text_protocol_socket_path') self.audit_socket_paths.append(audit_socket_path) audit_socket_path = get_config('audit', 'binary_protocol_socket_path') self.audit_socket_paths.append(audit_socket_path) def connect(self): while True: try: for self.audit_socket_path in self.audit_socket_paths: if self.audit_socket_path is not None: try: record_format = derive_record_format(self.audit_socket_path) self.record_reader = AuditRecordReader(record_format) self.audit_socket = Socket.socket(Socket.AF_UNIX, Socket.SOCK_STREAM) fcntl.fcntl(self.audit_socket.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC) self.audit_socket.connect(self.audit_socket_path) self.audit_socket_fd = self.audit_socket.makefile() log_debug("audit socket (%s) connected" % self.audit_socket_path) return except Socket.error as e: errno, strerror = get_error_from_socket_exception(e) log_debug("attempt to open audit socket (%s) failed, error='%s'" % (self.audit_socket_path, strerror)) log_debug("could not open any audit sockets (%s), retry in %d seconds" % (', '.join(self.audit_socket_paths), self.retry_interval)) except Socket.error as e: errno, strerror = get_error_from_socket_exception(e) log_debug("audit socket (%s) failed, error='%s', retry in %d seconds" % (self.audit_socket_path, strerror, self.retry_interval)) except OSError as e: log_debug("audit socket (%s) failed, error='%s', retry in %d seconds" % (self.audit_socket_path, e[1], self.retry_interval)) time.sleep(self.retry_interval) def new_audit_record_handler(self, record_type, event_id, body_text, fields, line_number): 'called to enter a new audit record' audit_record = AuditRecord(record_type, event_id, body_text, fields, line_number) audit_record.audispd_rectify() for audit_event in self.record_receiver.feed(audit_record): self.new_audit_event_handler(audit_event) def new_audit_event_handler(self, audit_event): if audit_event.is_avc() and not audit_event.is_granted() and audit_event.num_records() > 0: avc = AVC(audit_event) if verify_avc(avc): self.queue.put((avc, self.report_receiver)) def run(self): self.connect() timeout = self.timeout_interval while True: inList, outList, errList = select.select([self.audit_socket], [], [], timeout) try: if self.audit_socket in inList: import os new_data = os.read(self.audit_socket_fd.fileno(), 1024) if new_data == '': log_debug("audit socket connection dropped") self.connect() else: log_debug("cached audit event count = %d" % (self.record_receiver.num_cached_events())) if not self.has_audit_eoe: timeout = self.timeout_interval for (record_type, event_id, body_text, fields, line_number) in self.record_reader.feed(new_data): if record_type == 'EOE': self.has_audit_eoe = True timeout = None self.new_audit_record_handler(record_type, event_id, body_text, fields, line_number) else: # timeout, anything waiting in our event cache? for audit_event in self.record_receiver.flush(time.time() - self.timeout_interval): self.new_audit_event_handler(audit_event) if self.record_receiver.num_cached_events() == 0: timeout = None except KeyboardInterrupt as e: log_debug("KeyboardInterrupt exception in %s" % self.__class__.__name__) _thread.interrupt_main() except SystemExit as e: log_debug("SystemExit exception in %s" % self.__class__.__name__) _thread.interrupt_main() except Exception as e: import traceback syslog_trace(traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, "exception %s: %s" % (e.__class__.__name__, str(e))) return config.py000064400000051456152572267760006421 0ustar00from __future__ import print_function try: # Python 2 from future import standard_library standard_library.install_aliases() except: # On Python 3 the code above throws an exception pass # /usr/bin/python3 -E # -*- mode: Python; -*- # # Copyright (C) 2006 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # __all__ = ['config_init', 'get_config', 'get_option', 'set_config', 'parse_config_setting', 'config_has_section', ] import getopt import sys import os try: from configparser import SafeConfigParser except ImportError: from ConfigParser import SafeConfigParser import re _cfg = None CFG_FILE = os.path.join('/etc/setroubleshoot', "%s.conf" % 'setroubleshoot') defaults = { 'general': { 'pid_file': { 'value': '/var/run/setroubleshootd.pid', 'description': '', 'readOnly': False, }, 'pkg_name': { 'value': 'setroubleshoot', 'description': '', 'readOnly': True, }, 'pkg_version': { 'value': '3.3.26', 'description': '', 'readOnly': True, }, 'project_url': { 'value': 'https://pagure.io/setroubleshoot', 'description': 'URL of project website', }, 'rpc_version': { 'value': '1.1', 'description': '', 'readOnly': True, }, 'i18n_text_domain': { 'value': 'setroubleshoot', 'description': 'internationalization (i18n) translation catalog', 'readOnly': True, }, 'i18n_locale_dir': { 'value': '/usr/share/locale', 'description': 'internationalization (i18n) translation catalog directory', 'readOnly': True, }, 'i18n_encoding': { 'value': 'utf-8', 'description': 'internationalization (i18n) encoding (codeset)', 'readOnly': True, }, 'data_dir': { 'value': '/usr/share/setroubleshoot', 'description': '', 'readOnly': True, }, 'config_dir': { 'value': '/etc/setroubleshoot', 'description': '', 'readOnly': True, }, 'icon_name': { 'value': 'setroubleshoot_icon', 'description': '', 'readOnly': True, }, }, 'helper_apps': { 'web_browser_launcher': { 'value': '/usr/bin/xdg-open', 'description': 'Helper application to launch web browser on a URL', }, }, 'audit': { 'binary_protocol_socket_path': { 'value': '/var/run/audit_events', 'description': 'unix domain socket used to listen for audit messages (binary audit protocol)', }, 'text_protocol_socket_path': { 'value': '/var/run/audispd_events', 'description': 'unix domain socket used to listen for audit messages (textural audit protocol)', }, 'retry_interval': { 'value': '60', 'description': 'number of seconds to wait before trying to connect to audit socket again in the event of socket failure', }, }, 'plugins': { 'plugin_dir': { 'value': '/usr/share/setroubleshoot/plugins', 'description': '', }, }, 'session_dbus': { 'bus_name': { 'value': 'org.fedoraproject.Setroubleshootd', 'description': '', 'readOnly': True, }, 'object_path': { 'value': '/org/fedoraproject/Setroubleshootd', 'description': '', 'readOnly': True, }, 'interface': { 'value': 'org.fedoraproject.SetroubleshootdIface', 'description': '', 'readOnly': True, }, }, 'system_dbus': { 'bus_name': { 'value': 'org.fedoraproject.Setroubleshootd', 'description': '', 'readOnly': True, }, 'object_path': { 'value': '/org/fedoraproject/Setroubleshootd', 'description': '', 'readOnly': True, }, 'interface': { 'value': 'org.fedoraproject.SetroubleshootdIface', 'description': '', 'readOnly': True, }, }, 'database': { 'database_dir': { 'value': '/var/lib/setroubleshoot', 'description': '', }, 'filename': { 'value': 'setroubleshoot', 'description': '', }, 'max_alerts': { 'value': '50', 'description' : ''' Keep no more than this many alerts in the database. Oldest alerts based on the alert's last seen date will be purged first. Zero implies no limit''', }, 'max_alert_age': { 'value': '', 'description' : ''' Purge any alerts whose age based on its last seen date exceeds this threshold. Age may be specified as a sequence of integer unit pairs. Units may be one of year,month,week,day,hour,minute,second and may optionally be plural. Example: '2 weeks 1 day' sets the threshold at 15 days. An empty string implies no limit''', }, }, 'connection': { 'default_port': { 'value': '69783', # FIXME: figure out defined port, 'description': '', }, }, 'listen_for_client': { 'path': { 'value': os.path.join('/var/run/setroubleshoot', 'setroubleshoot_server'), 'description': '', 'readOnly': False, }, 'address_list': { 'value': '{unix}%(path)s', 'description' : ''' List of socket addresses server should listen on for client connections. Addresses should not contain any whitespace. Each address is of the form "[{family}]address[:port]" where [] indicates the value is optional. Valid values for family are inet or unix, if the family is absent it defaults to inet. If the family is unix the address is interpreted as a file path. If the family is inet the address is interpreted as either a host name or IP address. As a special case if the inet address is "hostname" the current hostname will be substituted. If the family is inet the address may optionally be followed by a colon (:) and a port number. If the port number is absent in the address it defaults to the port specified in this config section. Example, to listen on the local unix domain socket and provide remote connections use this "{unix}%(path)s, hostname" ''' }, }, 'client_connect_to': { 'path': { 'value': os.path.join('/var/run/setroubleshoot', 'setroubleshoot_server'), 'description': '', 'readOnly': False, }, 'address_list': { 'value': '{unix}%(path)s hostname', 'description' : ''' List of socket addresses server should listen on for client connections. Addresses should not contain any whitespace. Each address is of the form "[{family}]address[:port]" where [] indicates the value is optional. Valid values for family are inet or unix, if the family is absent it defaults to inet. If the family is unix the address is interpreted as a file path. If the family is inet the address is interpreted as either a host name or IP address. As a special case if the inet address is "hostname" the current hostname will be substituted. If the family is inet the address may optionally be followed by a colon (:) and a port number. If the port number is absent in the address it defaults to the port specified in this config section. Example, to listen on the local unix domain socket and provide remote connections use this "{unix}%(path)s, hostname" ''' }, }, 'socket': { 'buf_size': { 'value': '2048', 'description': '', 'readOnly': True, }, 'timeout': { 'value': '5', 'description': '', 'readOnly': True, }, }, 'setroubleshootd_log': { 'level': { 'value': 'warning', 'description' : ''' setroubleshootd logging level. Levels are the same as in the python logging module, but are case insenstive. The defined levels in severity order are:[CRITICAL, ERROR, WARNING, INFO, DEBUG]''', }, 'log_full_report': { 'value': 'True', 'description': 'True|False, log full report analysis to journal', }, }, 'sealert_log': { 'level': { 'value': 'warning', 'description' : ''' sealert logging level. Levels are the same as in the python logging module, but are case insenstive. The defined levels in severity order are: [CRITICAL, ERROR, WARNING, INFO, DEBUG]''', }, }, 'access': { 'client_users': { 'value': '*', 'description' : ''' Comma-separated list of users allowed to run the client and connect to the local fault server and therefore see security denials. Also accepts '*' to allow all users to connect.''' }, 'fix_cmd_users': { 'value': 'root', 'description' : ''' Comma-separated list of users allowed to run the fix commands with root privileges. Members of this list can execute the fix commands specified in any alert. The command is executed with root privileges so you should be very caeful who you add to this list as you are granting them significant power to alter the security settings of this system. The wildcard '*' is NOT allowed.''' }, }, 'email': { 'smtp_host': { 'value': 'localhost', 'description': 'The SMTP server address', }, 'smtp_port': { 'value': '25', 'description': 'The SMTP server port', }, 'from_address': { 'value': 'SELinux_Troubleshoot', 'description': 'The From: email header', }, 'subject': { 'value': 'SELinux AVC Alert', 'description': 'The Subject: email header', }, 'recipients_filepath': { 'value': os.path.join('/var/lib/setroubleshoot', 'email_alert_recipients'), 'description': 'Path name of file with email recipients. One address per line, optionally followed by enable flag. Comment character is #. ' }, }, 'help': { 'help_url': { 'value': 'https://pagure.io/docs/setroubleshoot/', 'description': 'URL to user help information', }, 'bug_report_url': { 'value': 'http://bugzilla.redhat.com/bugzilla/enter_bug.cgi', 'description': 'URL used to report bugs', }, }, 'test': { 'analyze': { 'value': 'False', 'description': 'Print plugin report', 'readOnly': True, }, }, } def config_init(): global _cfg _cfg = read_configuration(defaults) def read_configuration(defaults): cfg = SafeConfigParser() try: cfg.read(CFG_FILE) except Exception as e: # loggers have not been initialized yet, can't use log_cfg, use stderr instead print("error parsing config file (%s): %s" % (CFG_FILE, e), file=sys.stderr) return None default_sections = list(defaults.keys()) for default_section in default_sections: if not cfg.has_section(default_section): cfg.add_section(default_section) for default_option, properties in list(defaults[default_section].items()): value = properties['value'] readOnly = properties.get('readOnly', False) if not cfg.has_option(default_section, default_option): cfg.set(default_section, default_option, value) else: if readOnly: # loggers have not been initialized yet, can't use log_cfg, use stderr instead print("error [%s] %s cannot be set in config file" % (default_section, default_option), file=sys.stderr) cfg.set(default_section, default_option, value) return cfg def convert_cfg_type(value, cfg_type=None): try: if cfg_type is None or cfg_type is str: return value elif cfg_type is int: return int(value) elif cfg_type is bool: if isinstance(value, bool): return value if isinstance(value, int): return bool(value) if value.lower() in ['true', 't', 'yes', 'y', 'on']: return True if value.lower() in ['false', 'f', 'no', 'n', 'off']: return False raise ValueError("cannot convert %s to boolean" % value) elif cfg_type is float: return float(value) elif cfg_type == 'raw': return value else: try: # We can't import log in this modules scope because log imports us, thus loggers will not # have been created yet, Therefore we must import the logger in our function local scope from setroubleshoot.log import log_cfg log_cfg.error("unknown type %s for option %s", cfg_type, value) except ImportError: print("error unknown type %s for option %s" % (cfg_type, value), file=sys.stderr) except Exception as e: try: # We can't import log in this modules scope because log imports us, thus loggers will not # have been created yet, Therefore we must import the logger in our function local scope from setroubleshoot.log import log_cfg log_cfg.error("unknown type %s for option %s", cfg_type, value) except ImportError: print("error unknown type %s for option %s" % (cfg_type, value), file=sys.stderr) def get_option(section, name, default_value=None, kwds=None, option_type=None): value = None if kwds is not None and name in kwds: value = convert_cfg_type(kwds[name]) elif config_has_section(section): value = get_config(section, name, option_type) if value is None: value = default_value return value def get_config(section, option, cfg_type=None): if _cfg is None: return None try: if cfg_type is None or cfg_type is str: return _cfg.get(section, option) elif cfg_type is int: return _cfg.getint(section, option) elif cfg_type is bool: return _cfg.getboolean(section, option) elif cfg_type is float: return _cfg.getfloat(section, option) elif cfg_type == 'raw': return _cfg.get(section, option, raw=True) else: try: # We can't import log in this modules scope because log imports us, thus loggers will not # have been created yet, Therefore we must import the logger in our function local scope from setroubleshoot.log import log_cfg log_cfg.error("unknown type = %s getting %s option in %s section: %s", cfg_type, option, section) except ImportError: print("error unknown type = %s getting %s option in %s section: %s" % (cfg_type, option, section), file=sys.stderr) except Exception as e: try: # We can't import log in this modules scope because log imports us, thus loggers will not # have been created yet, Therefore we must import the logger in our function local scope from setroubleshoot.log import log_cfg log_cfg.error("cannot get %s option in %s section: %s", option, section, e) except ImportError: print("error cannot get %s option in %s section: %s" % (option, section, e), file=sys.stderr) return None def set_config(section, option, value): try: if _cfg is None: return False if not _cfg.has_section(section): _cfg.add_section(section) _cfg.set(section, option, value) except Exception as e: log_program.exception("Cannot set config: section='%s' option='%s' value='%s'", section, option, value) return False return True config_setting_re = re.compile("([^.=]+?)\s*\.\s*([^.=]+?)\s*=\s*(.*)") def parse_config_setting(cfg_setting): match = config_setting_re.search(cfg_setting) if match: section = match.group(1) option = match.group(2) value = match.group(3) else: try: # We can't import log in this modules scope because log imports us, thus loggers will not # have been created yet, Therefore we must import the logger in our function local scope from setroubleshoot.log import log_cfg log_cfg.error("could not parse '%s', must be 'section.option=value'", cfg_setting) except ImportError: print("error: could not parse '%s', must be 'section.option=value'" % (cfg_setting), file=sys.stderr) return False try: # We can't import log in this modules scope because log imports us, thus loggers will not # have been created yet, Therefore we must import the logger in our function local scope from setroubleshoot.log import log_cfg log_cfg.debug("setting config: section='%s' option='%s' value='%s'", section, option, value) except ImportError: print("setting config: section='%s' option='%s' value='%s'" % (section, option, value), file=sys.stderr) set_config(section, option, value) return True def config_has_section(section): if _cfg is None: return None try: return _cfg.has_section(section) except Exception as e: try: # We can't import log in this modules scope because log imports us, thus loggers will not # have been created yet, Therefore we must import the logger in our function local scope from setroubleshoot.log import log_cfg log_cfg.error("config_has_section(%s): %s", section, e) except ImportError: print("error: config_has_section(%s): %s" % (section, e), file=sys.stderr) return False def dump_defaults(defaults, showReadOnly=False): import textwrap wrap = textwrap.TextWrapper(width=78, initial_indent='# ', subsequent_indent='# ') sections = list(defaults.keys()) sections.sort() for section in sections: visibleOptions = 0 for option, properties in list(defaults[section].items()): readOnly = properties.get('readOnly', False) if showReadOnly or not readOnly: visibleOptions += 1 if visibleOptions > 0: print("[%s]" % section) for option, properties in list(defaults[section].items()): value = properties['value'] readOnly = properties.get('readOnly', False) description = properties.get('description', '') if readOnly and not showReadOnly: continue if not description: description = 'No Description Available' print(wrap.fill('%s: ' % option + description)) if readOnly: print('# READ ONLY, default = "%s"' % (value)) else: print("%s = %s" % (option, value)) print() def dump_configuration(cfg): sections = cfg.sections() sections.sort() for section in sections: options = cfg.options(section) options.sort() for option in options: value = get_config(section, option) print("[%s] %s = %s" % (section, option, value)) print() # ----------------------------------------------------------------------------- if __name__ == '__main__': def usage(): print(''' -d generate default config file -h help ''') try: opts, args = getopt.getopt(sys.argv[1:], "dh", ["defaults", "help"]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) do_dump_defaults = False for o, a in opts: if o in ("-d", "--defaults"): do_dump_defaults = True if o in ("-h", "--help"): usage() sys.exit() if do_dump_defaults: dump_defaults(defaults) else: config_init() email_alert.py000064400000005343152572267760007424 0ustar00from __future__ import absolute_import # Authors: John Dennis # # Copyright (C) 2006,2007,2008 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # __all__ = ['email_alert', ] import syslog import re from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.utils import formatdate from setroubleshoot.config import get_config from setroubleshoot.util import * email_addr_re = re.compile(r'^\s*([^@ \t]+)(@([^@ \t]+))?\s*$') def parse_email_addr(addr): match = email_addr_re.search(addr) user = None domain = None if match: user = match.group(1) domain = match.group(3) return (user, domain) def email_alert(siginfo, to_addrs): smtp_host = get_config('email', 'smtp_host') smtp_port = get_config('email', 'smtp_port', int) from_address = get_config('email', 'from_address') from_user, from_domain = parse_email_addr(from_address) if from_user is None: from_user = "SELinuxTroubleshoot" if from_domain is None: from_domain = get_hostname() from_address = '%s@%s' % (from_user, from_domain) log_debug("alert smtp=%s:%d -> %s" % (smtp_host, smtp_port, ','.join(to_addrs))) siginfo.update_derived_template_substitutions() summary = siginfo.substitute(siginfo.summary()) subject = '[%s] %s' % (get_config('email', 'subject'), summary) text = siginfo.format_text() + siginfo.format_details() email_msg = MIMEMultipart('alternative') email_msg['Subject'] = subject email_msg['From'] = from_address email_msg['To'] = ', '.join(to_addrs) email_msg['Date'] = formatdate() email_msg.attach(MIMEText(text)) import smtplib try: smtp = smtplib.SMTP(smtp_host, smtp_port) smtp.sendmail(from_address, to_addrs, email_msg.as_string()) smtp.quit() except smtplib.SMTPException as e: syslog.syslog(syslog.LOG_ERR, "email failed: %s" % e) #----------------------------------------------------------------------------- if __name__ == "__main__": email_alert('This is the sig', 'This is the solution') errcode.py000064400000006740152572267760006573 0ustar00# Authors: John Dennis # # Copyright (C) 2006,2007,2008 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # import gettext from setroubleshoot.config import parse_config_setting, get_config translation = gettext.translation(domain=get_config('general', 'i18n_text_domain'), localedir=get_config('general', 'i18n_locale_dir'), fallback=True) try: _ = translation.ugettext # Unicode version of gettext for Py2 except AttributeError: _ = translation.gettext # Python3 (uses unicode by default) __all__ = [ 'ProgramError', 'get_strerror' ] #----------------------------------------------------------------------------- errcode = {} strerror = {} ERROR_BASE = 1000 #----------------------------------------------------------------------------- def get_strerror(errno): str = strerror.get(errno, None) if str is None: import os str = os.strerror(errno) return str def err(num, name, str): global errcode, strerror errno = ERROR_BASE + num globals()[name] = errno errcode[name] = errno __all__.append(name) strerror[errno] = str #----------------------------------------------------------------------------- class ProgramError(Exception): def __init__(self, errno, strerror=None, detail=None): self.errno = errno if strerror is None: self.strerror = get_strerror(errno) else: self.strerror = strerror if detail is not None: self.strerror += ' ' + detail def __str__(self): return "[Errno %d] %s" % (self.errno, self.strerror) #----------------------------------------------------------------------------- err(1, 'ERR_NO_SIGNATURE_MATCH', _('signature not found')) err(2, 'ERR_MULTIPLE_SIGNATURE_MATCH', _('multiple signatures matched')) err(3, 'ERR_SIGNATURE_ID_NOT_FOUND', _('id not found')) err(4, 'ERR_DATABASE_NOT_FOUND', _('database not found')) err(5, 'ERR_NOT_MEMBER', _('item is not a member')) err(6, 'ERR_ILLEGAL_USER_CHANGE', _('illegal to change user')) err(7, 'ERR_METHOD_NOT_FOUND', _('method not found')) err(8, 'ERR_CANNOT_CREATE_GUI', _('cannot create GUI')) err(9, 'ERR_UNKNOWN_VALUE', _('value unknown')) err(10, 'ERR_FILE_OPEN', _('cannot open file')) err(11, 'ERR_INVALID_EMAIL_ADDR', _('invalid email address')) # gobject IO Errors err(12, 'ERR_SOCKET_ERROR', _('socket error')) err(13, 'ERR_SOCKET_HUP', _('connection has been broken')) err(14, 'ERR_IO_INVALID', _('Invalid request. The file descriptor is not open')) err(15, 'ERR_USER_PERMISSION', _('insufficient permission to modify user')) err(16, 'ERR_AUTHENTICATION_FAILED', _('authentication failed')) err(17, 'ERR_USER_PROHIBITED', _('user prohibited')) err(18, 'ERR_NOT_AUTHENTICATED', _('not authenticated')) err(19, 'ERR_USER_LOOKUP', _('user lookup failed')) html_util.py000064400000014103152572267760007141 0ustar00# Authors: John Dennis # # Copyright (C) 2007 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # __all__ = [ 'escape_html', 'unescape_html', 'html_to_text', 'html_document', ] import syslog import sys if sys.version_info > (3,): import html import html.parser import html.entities from io import StringIO else: import htmllib from StringIO import StringIO import formatter as Formatter import string from types import * #------------------------------------------------------------------------------ class TextWriter(Formatter.DumbWriter): def __init__(self, file=None, maxcol=80, indent_width=4): Formatter.DumbWriter.__init__(self, file, maxcol) self.indent_level = 0 self.indent_width = indent_width self._set_indent() def _set_indent(self): self.indent_col = self.indent_level * self.indent_width self.indent = ' ' * self.indent_col def new_margin(self, margin, level): self.indent_level = level self._set_indent() def send_label_data(self, data): data = data + ' ' if len(data) > self.indent_col: self.send_literal_data(data) else: offset = self.indent_col - len(data) self.send_literal_data(' ' * offset + data) def send_flowing_data(self, data): if not data: return atbreak = self.atbreak or data[0] in string.whitespace col = self.col maxcol = self.maxcol write = self.file.write col = self.col if col == 0: write(self.indent) col = self.indent_col for word in data.split(): if atbreak: if col + len(word) >= maxcol: write('\n' + self.indent) col = self.indent_col else: write(' ') col = col + 1 write(word) col = col + len(word) atbreak = 1 self.col = col self.atbreak = data[-1] in string.whitespace if sys.version_info > (3,): class HTMLParserAnchor(html.parser.HTMLParser): def __init__(self, formatter, strict=False, convert_charrefs=False): super(HTMLParserAnchor, self).__init__() self.formatter = formatter self.anchor_href = None def handle_starttag(self, tag, attrs): if tag == 'a': for key, value in attrs: if key == 'href': self.anchor_href = value def handle_endtag(self, tag): if tag == 'a': if self.anchor_href != None: self.formatter.writer.send_flowing_data('(' + self.anchor_href + ')') self.anchor_href = None def handle_data(self, data): self.formatter.writer.send_flowing_data(data) else: class HTMLParserAnchor(htmllib.HTMLParser): def __init__(self, formatter, verbose=0): htmllib.HTMLParser.__init__(self, formatter, verbose) def anchor_bgn(self, href, name, type): self.anchor = href def anchor_end(self): if self.anchor: self.handle_data(' (%s) ' % self.anchor) self.anchor = None #------------------------------------------------------------------------------ def escape_html(s): if s is None: return None try: s = s.replace("&", "&") # Must be done first! s = s.replace("<", "<") s = s.replace(">", ">") s = s.replace("'", "'") s = s.replace('"', """) except: pass return s def unescape_html(s): if s is None: return None if '&' not in s: return s s = s.replace("<", "<") s = s.replace(">", ">") s = s.replace("'", "'") s = s.replace(""", '"') s = s.replace("&", "&") # Must be last return s def html_to_text(html, maxcol=80): try: buffer = StringIO() formatter = Formatter.AbstractFormatter(TextWriter(buffer, maxcol)) parser = HTMLParserAnchor(formatter) parser.feed(html) parser.close() text = buffer.getvalue() buffer.close() return text except Exception as e: syslog.syslog(syslog.LOG_ERR, 'cannot convert html to text: %s' % e) return None def html_document(*body_components): '''Wrap the body components in a HTML document structure with a valid header. Accepts a variable number of arguments of of which canb be: * string * a sequences of strings (tuple or list). * a callable object taking no parameters and returning a string or sequence of strings. ''' head = '\n \n \n \n \n' tail = '\n \n' doc = head for body_component in body_components: if isinstance(body_component, six.string_types): doc += body_component elif isinstance(body_component, (tuple, list)): for item in body_component: doc += item elif callable(body_component): result = body_component() if isinstance(result, (tuple, list)): for item in result: doc += item else: doc += result else: doc += body_component doc += tail return doc rpc.py000064400000111773152572267760005737 0ustar00from __future__ import absolute_import from __future__ import print_function # Authors: John Dennis # # Copyright (C) 2006,2007,2008 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # import six import libxml2 import re import syslog import errno as Errno from gi.repository import GObject, GLib import os import socket as Socket import fcntl import threading from types import * from setroubleshoot.config import get_config from setroubleshoot.errcode import * from setroubleshoot.xml_serialize import xml_child_elements, xml_get_child_elements_by_name from setroubleshoot.util import * __all__ = [ 'rpc_method', 'rpc_arg_type', 'rpc_callback', 'rpc_signal', 'interface_registry', 'parse_socket_address_list', 'get_default_port', 'get_socket_list_from_config', 'get_local_server_socket_address', 'ConnectionState', 'RpcManage', 'RpcChannel', 'ListeningServer', 'SocketAddress', ] #--------------------------------- Variables --------------------------------- content_length_re = re.compile(r"content-length:(\d+)") header_end_re = re.compile("\r\n\r\n") header_field_re = re.compile("([a-zA-Z0-9_-]+):(.*)\r\n") i18n_encoding = get_config('general', 'i18n_encoding') #------------------------------ Utility Functions ----------------------------- def parse_socket_address_list(addr_string, default_port=None): socket_addresses = [] family_re = re.compile(r'\s*{(unix|inet)}(.+)') log_debug("parse_socket_address_list: input='%s'" % addr_string) if not addr_string: return socket_addresses addrs = re.split(r'[\s,]+', addr_string) for cfg_addr in addrs: if not cfg_addr: continue match = family_re.search(cfg_addr) if match: family_tag = match.group(1).lower() address = match.group(2) family = SocketAddress.map_family(family_tag) if family is None: log_debug("unknown socket family - %s in address %s" % (family_tag, cfg_addr)) continue else: family = Socket.AF_INET address = cfg_addr socket_address = SocketAddress(family, address, default_port) socket_addresses.append(socket_address) log_debug("parse_socket_address_list: %s --> %s" % (cfg_addr, socket_address)) return socket_addresses def get_default_port(): default_port = get_config('connection', 'default_port', int) return default_port def get_socket_list_from_config(cfg_section): addr_string = get_config(cfg_section, 'address_list') socket_addresses = parse_socket_address_list(addr_string) return socket_addresses def get_local_server_socket_address(): addr_list = get_socket_list_from_config('client_connect_to') if len(addr_list) == 0: return None return addr_list[0] def io_condition_to_string(io_condition): names = [] if io_condition & GObject.IO_IN: names.append('IN') if io_condition & GObject.IO_OUT: names.append('OUT') if io_condition & GObject.IO_PRI: names.append('PRI') if io_condition & GObject.IO_ERR: names.append('ERR') if io_condition & GObject.IO_HUP: names.append('HUP') if io_condition & GObject.IO_NVAL: names.append('NVAL') return '(%d)[%s]' % (io_condition, ','.join(names)) def rpc_header(body, **kwds): hdr = "content-length: %d\r\n" % len(body) for key, value in list(kwds.items()): hdr += "%s: %s\r\n" % (key, value) hdr += "\r\n" return hdr def rpc_message(rpc_id, type, body): hdr = rpc_header(body, rpc_id=rpc_id, type=type) return hdr + body def convert_rpc_xml_to_args(cmd): interface = method = args = doc = None try: doc = libxml2.parseDoc(cmd) cmd = doc.getRootElement() interface = cmd.prop('interface') method = cmd.prop('method') # FIXME: If the interface.method is not known you get back a dummy # rpc_def with zero parameters defined, but if the incoming call has # parameters we'll try to iterate through them generating an IndexError # exception when this code executes: rpc_def.positional_args[arg_position] # # We either need to detect and report the failed rpc_def lookup earlier # and/or we need to not iterate on unknown parameters. rpc_def = interface_registry.get_rpc_def(interface, method) arg_nodes = xml_get_child_elements_by_name(cmd, 'arg') args = preextend_list(len(arg_nodes)) for arg_node in arg_nodes: arg_name = arg_node.prop('name') arg_type = arg_node.prop('type') arg_position = int(arg_node.prop('position')) rpc_arg = rpc_def.positional_args[arg_position] if rpc_arg.obj_type is not None: if arg_type == 'xml': arg_value = rpc_arg.obj_type(arg_node, obj_name=arg_name) else: arg_value = rpc_arg.obj_type(arg_node.content) else: arg_value = arg_node.content args[arg_position] = arg_value finally: if doc is not None: doc.freeDoc() return interface, method, args def convert_rpc_to_xml(rpc_id, rpc_def, *args): text_doc = doc = None try: interface = rpc_def.interface method = rpc_def.method doc = libxml2.newDoc('1.0') root = libxml2.newNode('cmd') root.setProp('interface', interface) root.setProp('method', method) doc.setRootElement(root) position = 0 for rpc_arg in rpc_def.positional_args: arg_name = rpc_arg.name arg_value = args[position] arg_node = libxml2.newNode('arg') root.addChild(arg_node) arg_node.setProp('name', arg_name) arg_node.setProp('position', str(position)) if isinstance(arg_value, libxml2.xmlNode): arg_node.setProp('type', 'xml') arg_node.addChild(arg_value) elif hasattr(arg_value, 'get_xml_nodes'): arg_node.setProp('type', 'xml') arg_node.addChild(arg_value.get_xml_nodes(doc, arg_name)) else: arg_node.setProp('type', 'string') arg_node.addContent(str(arg_value)) position += 1 root.setProp('arg_count', str(position)) text_doc = doc.serialize(encoding=i18n_encoding, format=1) finally: if doc is not None: doc.freeDoc() return text_doc #----------------------------------------------------------------------------- class ConnectionState(GObject.GObject): CONNECTING = (1 << 1) OPEN = (1 << 2) AUTHENTICATED = (1 << 3) HUP = (1 << 4) ERROR = (1 << 5) TIMEOUT = (1 << 6) RETRY = (1 << 7) ALL_FLAGS = CONNECTING | OPEN | AUTHENTICATED | HUP | ERROR | TIMEOUT | RETRY GOOD_FLAGS = OPEN | AUTHENTICATED PROBLEM_FLAGS = HUP | ERROR | TIMEOUT | RETRY map_connection_enum_to_string = { CONNECTING: 'CONNECTING', OPEN: 'OPEN', AUTHENTICATED: 'AUTHENTICATED', HUP: 'HUP', ERROR: 'ERROR', TIMEOUT: 'TIMEOUT', RETRY: 'RETRY', } connection_states = [CONNECTING, OPEN, AUTHENTICATED, HUP, ERROR, TIMEOUT, RETRY] __gsignals__ = { 'changed': # callback(connection_state, flags, flags_added, flags_removed): (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_INT, GObject.TYPE_INT, GObject.TYPE_INT)), } def __init__(self): GObject.GObject.__init__(self) self.flags = 0 self.result_code = None self.result_msg = None self.clear_result() def __str__(self): return "flags=%s, result_code=%d, result_msg=%s" % \ (self.flags_to_string(self.flags), self.result_code, self.result_msg) def clear(self): self.update(0, self.ALL_FLAGS) def flags_to_string(self, val): if val is None: val = 0 names = [] for state in ConnectionState.connection_states: if val & state: names.append(ConnectionState.map_connection_enum_to_string[state]) return ','.join(names) def clear_result(self): self.result_code = 0 self.result_msg = '' def set_result(self, result_code, result_msg): self.result_code = result_code self.result_msg = result_msg def get_result(self): return(self.result_code, self.result_msg) def update(self, add_flags=0, remove_flags=0, result_code=0, result_msg=''): previous_flags = self.flags self.flags |= add_flags self.flags &= ~remove_flags self.result_code = result_code self.result_msg = result_msg difference = previous_flags ^ self.flags flags_added = self.flags & difference flags_removed = previous_flags & difference # Send signal if anything changed if difference: self.emit('changed', self.flags, flags_added, flags_removed) GObject.type_register(ConnectionState) #----------------------------------------------------------------------------- class RpcArg(object): def __init__(self, name=None, obj_type=None): self.name = name self.obj_type = obj_type def __str__(self): if self.name is None: name = 'name_undefined' else: name = self.name if self.obj_type is None: return name else: return "%s:%s" % (name, self.obj_type) error_positional_args = [RpcArg('method', str), RpcArg('err_code', int), RpcArg('err_msg', str)] #----------------------------------------------------------------------------- class RpcDefinition(object): def __init__(self, type, interface, method, rpc_args): self.type = type self.interface = interface self.method = method self.callback = None if rpc_args is None: self.positional_args = [] else: self.positional_args = rpc_args def __str__(self): args = [] if self.positional_args is not None: for rpc_arg in self.positional_args: if rpc_arg.obj_type is not None: args.append("%s:%s" % (rpc_arg.name, rpc_arg.obj_type)) else: args.append(rpc_arg.name) text = "[%s] %s:%s (%s)" % (self.type, self.interface, self.method, ','.join(args)) if self.type == 'method': text += ' callback=%s' % (self.callback) return text def set_type(self, type): self.type = type def set_callback(self, callback): if self.callback is not None: interface_dict = interface_registry.get_interface(self.interface) del(interface_dict[self.callback]) self.callback = callback def get_callback_def(self): if self.type != 'method': raise ValueError("%s rpc types do not have callbacks" % self.type) if self.callback is None: callback_name = '%s_default_callback' % self.method callback_def = RpcDefinition('method_return', self.interface, callback_name, None) interface_registry.register_rpc_def(self.interface, callback_name, callback_def) self.callback = callback_name return callback_def return interface_registry.get_rpc_def(self.interface, self.callback) def set_positional_args(self, arg_names): if arg_names is not None: self.positional_args = preextend_list(len(arg_names), self.positional_args, RpcArg) position = 0 for arg_name in arg_names: rpc_arg = self.positional_args[position] rpc_arg.name = arg_name position += 1 def set_arg_obj_types(self, *obj_types): if obj_types is not None: self.positional_args = preextend_list(len(obj_types), self.positional_args, RpcArg) position = 0 for obj_type in obj_types: rpc_arg = self.positional_args[position] rpc_arg.obj_type = obj_type position += 1 def get_positional_arg_names(self): return [rpc_arg.name for rpc_arg in self.positional_args] #----------------------------------------------------------------------------- class InterfaceRegistry(object): def __init__(self): self.interfaces = {} def new_interface(self, interface): error_return_def = RpcDefinition('error_return', interface, '_error_return', error_positional_args) return {'_error_return': error_return_def} def get_interface(self, interface_name): interface = self.interfaces.get(interface_name) if interface is None: interface = self.new_interface(interface_name) self.interfaces[interface_name] = interface return interface def set_rpc_def(self, type, interface, method_ptr): import inspect method = method_ptr.__name__ positional_args = inspect.getargspec(method_ptr)[0] if positional_args[0] == 'self': del(positional_args[0]) rpc_def = self.get_rpc_def(interface, method) rpc_def.set_type(type) rpc_def.set_positional_args(positional_args) return rpc_def def get_rpc_def(self, interface, method): interface_dict = self.get_interface(interface) if isinstance(method, MethodType): method = method.__name__ rpc_def = interface_dict.get(method) if rpc_def is None: rpc_def = RpcDefinition(None, interface, method, None) self.register_rpc_def(interface, method, rpc_def) return rpc_def def register_rpc_def(self, interface, method, rpc_def): interface_dict = self.get_interface(interface) if isinstance(method, MethodType): method = method.__name__ interface_dict[method] = rpc_def def get_error_rpc_def(self, interface): interface_dict = self.get_interface(interface) return interface_dict['_error_return'] def dump_interfaces(self): interface_names = list(self.interfaces.keys()) interface_names.sort() for interface_name in interface_names: interface = self.interfaces[interface_name] print(("Interface: %s" % interface_name)) method_names = list(interface.keys()) method_names.sort() for method_name in method_names: method = interface[method_name] print((" %s" % str(method))) interface_registry = InterfaceRegistry() #-------------------------------- Decorators --------------------------------- def rpc_method(interface): def decorator(method_ptr): rpc_def = interface_registry.set_rpc_def('method', interface, method_ptr) method = method_ptr.__name__ def rpc_func(self, *args): rpc_id = self.new_rpc_id() rpc_def = interface_registry.get_rpc_def(interface, method) async_rpc = AsyncRpc(rpc_def, rpc_id) self.async_rpc_cache[rpc_id] = async_rpc self.emit_rpc(rpc_id, 'method', rpc_def, *args) return async_rpc method_ptr._rpc_definition = True return rpc_func return decorator def rpc_arg_type(interface, *arg_types): def decorator(method_ptr): method = method_ptr.__name__ rpc_def = interface_registry.get_rpc_def(interface, method) rpc_def.set_arg_obj_types(*arg_types) return method_ptr return decorator def rpc_callback(interface, method): def decorator(method_ptr): rpc_callback_def = interface_registry.set_rpc_def('method_return', interface, method_ptr) rpc_def = interface_registry.get_rpc_def(interface, method) rpc_def.set_callback(rpc_callback_def.method) method_ptr._rpc_definition = True return method_ptr return decorator def rpc_signal(interface): def decorator(method_ptr): rpc_def = interface_registry.set_rpc_def('signal', interface, method_ptr) method = method_ptr.__name__ def rpc_func(self, *args): rpc_id = self.new_rpc_id() rpc_def = interface_registry.get_rpc_def(interface, method) self.emit_rpc(rpc_id, 'signal', rpc_def, *args) method_ptr._rpc_definition = True return rpc_func return decorator #------------------------------------------------------------------------------ class SocketAddress(object): def __init__(self, family=None, address=None, default_port=get_default_port(), friendly_name=None): self.family = SocketAddress.map_family(family) self.address = address self.port = default_port self.default_port = default_port self.type = Socket.SOCK_STREAM self.socket = None self.friendly_name = friendly_name if address is not None: self.parse(self.family, address) def __str__(self): socket_repr = re.sub('^.+ at (0x[0-9A-Fa-f]+)>$', '\\1', repr(self.socket)) if self.family is None: return "None" elif self.family is Socket.AF_UNIX: return "{unix}%s socket=%s" % (self.address, socket_repr) elif self.family is Socket.AF_INET: return "{inet}%s:%s socket=%s" % (self.address, self.port, socket_repr) else: return "unknown" def _get_default_friendly_name(self): if self.family is None: return "None" elif self.family is Socket.AF_UNIX: return "%s" % (self.address) elif self.family is Socket.AF_INET: return "%s:%s" % (self.address, self.port) else: return _("Unknown") def get_friendly_name(self): if self.friendly_name is None: return self._get_default_friendly_name() return self.friendly_name def copy(self): import copy return copy.copy(self) def get_py_address(self): if self.family is Socket.AF_UNIX: return self.address elif self.family is Socket.AF_INET: return (self.address, self.port) else: return None @staticmethod def map_family(family): if isinstance(family, six.string_types): family = family.lower() family = {'unix': Socket.AF_UNIX, 'inet': Socket.AF_INET}.get(family) return family return family def parse(self, family, addr): self.family = family if family is Socket.AF_UNIX: self.address = addr self.port = None elif family is Socket.AF_INET: self.parse_inet_addr(addr) def parse_inet_addr(self, addr): match = re.search(r'^\s*([^:\s]+)\s*(:\s*([^\s]+))?', addr) if match: addr = match.group(1) port = match.group(3) if port is None: port = self.default_port if addr == 'hostname': addr = get_hostname() self.address = addr self.port = port else: self.address = None self.port = None #----------------------------------------------------------------------------- class ConnectionIO(object): io_input_conditions = GLib.IO_IN | GLib.IO_HUP | GLib.IO_ERR | GLib.IO_NVAL def __init__(self, channel_type=None, channel_name=None, socket_address=SocketAddress()): self.connection_state = ConnectionState() self.socket_address = socket_address self.channel_type = channel_type self.channel_name = channel_name self.io_watch_id = None def io_watch_add(self, callback): '''callback signature: (io_object, io_condition)''' self.io_watch_remove() self.io_watch_id = GLib.io_add_watch(self.socket_address.socket, GLib.PRIORITY_DEFAULT, self.io_input_conditions, callback) def io_watch_remove(self): if self.io_watch_id is not None: GLib.source_remove(self.io_watch_id) self.io_watch_id = None def valid_io_condition(self, io_condition): if io_condition & (GLib.IO_HUP | GLib.IO_ERR | GLib.IO_NVAL): if io_condition & GLib.IO_HUP: errno = ERR_SOCKET_HUP strerror = get_strerror(errno) self.close_connection(ConnectionState.HUP, 0, errno, strerror) if io_condition & GLib.IO_ERR: errno = ERR_SOCKET_ERROR strerror = get_strerror(errno) self.close_connection(ConnectionState.ERROR, 0, errno, strerror) if io_condition & GLib.IO_NVAL: errno = ERR_IO_INVALID strerror = get_strerror(errno) self.close_connection(ConnectionState.ERROR, 0, errno, strerror) return False else: return True #----------------------------------------------------------------------------- class ListeningServer(ConnectionIO): allow_reuse_address = False request_queue_size = 5 def __init__(self, socket_address, client_connection_handler_class): ConnectionIO.__init__(self, channel_type='listening', channel_name='server_listening', socket_address=socket_address) self.client_connection_handler_class = client_connection_handler_class def new_listening_socket(self, socket_address): self.socket_address = socket_address if self.socket_address.family == Socket.AF_UNIX: # Unix domain socket, delete the socket if left from before if os.path.exists(self.socket_address.address): os.remove(self.socket_address.address) else: path = os.path.dirname(socket_address.address) if not os.path.exists(path): os.makedirs(path) self.socket_address.socket = Socket.socket(self.socket_address.family, self.socket_address.type) fcntl.fcntl(self.socket_address.socket.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC) if self.allow_reuse_address: self.socket_address.socket.setsockopt(Socket.SOL_SOCKET, Socket.SO_REUSEADDR, 1) self.socket_address.socket.bind(self.socket_address.get_py_address()) if self.socket_address.family == Socket.AF_UNIX: os.chmod(self.socket_address.address, 0o666) self.socket_address.socket.listen(self.request_queue_size) return self.socket_address.socket def open(self): try: self.socket_address.socket = self.new_listening_socket(self.socket_address) self.io_watch_add(self.handle_client_connect) except Exception as e: self.connection_state.update(ConnectionState.ERROR, ConnectionState.OPEN, -1, str(e)) return False return True def handle_client_connect(self, socket, io_condition): try: if not self.valid_io_condition(io_condition): return False if io_condition & GLib.IO_IN: try: client_socket, client_address = socket.accept() fcntl.fcntl(client_socket.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC) client_handler = self.client_connection_handler_class(self.socket_address) client_handler.open(client_socket, client_address) self.connection_state.update(0, ConnectionState.PROBLEM_FLAGS) except Socket.error as e: errno, strerror = get_error_from_socket_exception(e) syslog.syslog(syslog.LOG_ERR, "closing client connection due to socket error(%s): %s" % (self.socket_address, strerror)) if errno == Errno.EPIPE: add_flags = ConnectionState.HUP else: add_flags = ConnectionState.ERROR self.connection_state.update(add_flags, 0, errno, strerror) except Exception as e: syslog.syslog(syslog.LOG_ERR, "exception %s: %s" % (e.__class__.__name__, str(e))) import traceback syslog_trace(traceback.format_exc()) self.connection_state.update(ConnectionState.ERROR, 0, -1, str(e)) return True #----------------------------------------------------------------------------- class RequestReceiver: def __init__(self, dispatchFunc): self.dispatchFunc = dispatchFunc self.reset() def reset(self): self.headerLen = -1 self.bodyLen = 0 self.header = None self.body = '' self.feed_buf = '' def process(self): if len(self.feed_buf) == 0: # No data, nothing to process return while True: if self.headerLen < 0: # Have not seen the end of the header yet, is it there now? match = header_end_re.search(self.feed_buf) if match: # Yes, header is complete, convert to dict, mark header end self.headerLen = match.end() self.parse_header() continue else: # Can't read header till more data arrives break if len(self.feed_buf) >= self.headerLen + self.bodyLen: # Read entire request, dispatch request, reset for next request bodyBegin = self.headerLen bodyEnd = self.headerLen + self.bodyLen self.body = self.feed_buf[bodyBegin:bodyEnd] self.feed_buf = self.feed_buf[bodyEnd:] self.headerLen = -1 self.bodyLen = -1 self.dispatchFunc(self.header, self.body) continue # Have neither a full header nor a full body. # Exit till more data is available. break def feed(self, data): self.feed_buf += data self.process() def parse_header(self): self.header = {} begin = 0 while 1: match = header_field_re.search(self.feed_buf, begin, self.headerLen + 1) if match: key = match.group(1) value = match.group(2).strip() self.header[key] = value begin = match.end() else: break self.bodyLen = int(self.header['content-length']) #----------------------------------------------------------------------------- class RpcManage(object): def __init__(self): self.async_rpc_cache = {} self.rpc_handlers = {} self.rpc_id = 0 def new_rpc_id(self): self.rpc_id += 1 return str(self.rpc_id) def dump_async_rpc_cache(self): log_debug("async_rpc_cache: %d entries, cur rpc_id=%s" % (len(self.async_rpc_cache), self.rpc_id)) rpc_ids = list(self.async_rpc_cache.keys()) rpc_ids.sort() for rpc_id in rpc_ids: log_debug("%s: %s" % (rpc_id, self.async_rpc_cache[rpc_id])) def flush_async_rpc_cache(self): self.async_rpc_cache.clear() def default_errback(self, method, err_code, err_msg): syslog.syslog(syslog.LOG_ERR, "[%s] %d %s" % (method, err_code, err_msg)) def process_async_return(self, async_rpc): if async_rpc is None: syslog.syslog(syslog.LOG_ERR, "process_async_return(): rpc_id=%s not in async_rpc_cache" % rpc_id) return if async_rpc.return_type == 'method_return': for callback in async_rpc.callbacks: callback(*async_rpc.return_args) elif async_rpc.return_type == 'error_return': if len(async_rpc.errbacks) > 0: for callback in async_rpc.errbacks: callback(*async_rpc.return_args) else: self.default_errback(*async_rpc.return_args) def connect_rpc_interface(self, interface, handler): self.rpc_handlers[interface] = handler #----------------------------------------------------------------------------- class RpcChannel(ConnectionIO, RpcManage): socket_buf_size = get_config('socket', 'buf_size', int) socket_timeout = get_config('socket', 'timeout', int) def __init__(self, channel_type=None, channel_name=None): ConnectionIO.__init__(self, channel_type=channel_type, channel_name=channel_name, socket_address=None) RpcManage.__init__(self) self.write_lock = threading.Lock() self.receiver = RequestReceiver(self.default_request_handler) def __str__(self): return "channel: name=%s addr=%s type=%s" % (self.channel_name, self.socket_address, self.channel_type) def acquire_write_lock(self): self.write_lock.acquire() def release_write_lock(self): self.write_lock.release() def set_channel_type(self, channel_type): self.channel_type = channel_type def get_channel_type(self): return self.channel_type def close_connection(self, add_flags=0, remove_flags=0, result_code=0, result_msg=''): log_debug("close_connection: %s" % (self.socket_address)) self.flush_async_rpc_cache() if self.socket_address.socket is None: return if self.socket_address.socket is not None: try: self.socket_address.socket.shutdown(Socket.SHUT_RDWR) self.socket_address.socket.close() self.socket_address.socket = None except Socket.error as e: self.socket_address.socket = None self.connection_state.update(add_flags, remove_flags | ConnectionState.GOOD_FLAGS, result_code, result_msg) self.io_watch_remove() def get_method_implementation(self, interface, method): handler_obj = self.rpc_handlers.get(interface, None) if handler_obj is None: return None method_ptr = getattr(handler_obj, method, None) return method_ptr def emit_rpc(self, rpc_id, type, rpc_def, *args): if len(rpc_def.positional_args) != len(args): syslog.syslog(syslog.LOG_ERR, "emit_rpc() arg length=%s does not match rpc_def(%s)" % (len(args), rpc_def)) return rpc_xml = convert_rpc_to_xml(rpc_id, rpc_def, *args) rpc_data = rpc_message(rpc_id, type, rpc_xml) self.send_data(rpc_data) def send_data(self, data): if not (self.connection_state.flags & ConnectionState.OPEN): return self.acquire_write_lock() try: totalSent = 0 while totalSent < len(data): sent = self.socket_address.socket.send(bytes(data[totalSent:], 'UTF-8')) if sent == 0: self.close_connection(ConnectionState.HUP) raise ProgramError(ERR_SOCKET_HUP, detail=self.connection_state) totalSent = totalSent + sent except Socket.timeout as e: syslog.syslog(syslog.LOG_ERR, "socket timeout: (%s)" % (self.socket_address)) self.release_write_lock() self.connection_state.update(ConnectionState.TIMEOUT) return except Socket.error as e: errno, strerror = get_error_from_socket_exception(e) syslog.syslog(syslog.LOG_ERR, "could not send data on socket (%s): %s" % (self.socket_address, strerror)) self.release_write_lock() if errno == Errno.EPIPE: add_flags = ConnectionState.HUP else: add_flags = ConnectionState.ERROR self.close_connection(add_flags, 0, errno, strerror) return self.connection_state.update(0, ConnectionState.PROBLEM_FLAGS) self.release_write_lock() def handle_client_io(self, socket, io_condition): try: if not self.valid_io_condition(io_condition): return False if io_condition & GLib.IO_IN: try: data = socket.recv(self.socket_buf_size) data = data.decode("utf-8") if len(data) == 0: self.close_connection(ConnectionState.HUP) return False except Socket.error as e: errno, strerror = get_error_from_socket_exception(e) syslog.syslog(syslog.LOG_ERR, "socket error (%s): %s" % (self.socket_address, strerror)) if errno == Errno.EPIPE: add_flags = ConnectionState.HUP else: add_flags = ConnectionState.ERROR self.close_connection(add_flags, 0, errno, strerror) return False self.connection_state.update(0, ConnectionState.PROBLEM_FLAGS) self.receiver.feed(data) except Exception as e: syslog.syslog(syslog.LOG_ERR, "exception %s: %s" % (e.__class__.__name__, str(e))) import traceback syslog_trace(traceback.format_exc()) self.close_connection(ConnectionState.ERROR, 0, -1, str(e)) return False return True def handle_return(self, type, rpc_id, body): async_rpc = self.async_rpc_cache.pop(rpc_id, None) if async_rpc is None: syslog.syslog(syslog.LOG_ERR, "handle_return(): rpc_id=%s not in async_rpc_cache" % rpc_id) return log_debug("%s.handle_return: rpc_id=%s type=%s %s.%s, {%s}" % (self.__class__.__name__, rpc_id, type, async_rpc.rpc_def.interface, async_rpc.rpc_def.method, body)) interface, method, args = convert_rpc_xml_to_args(body) async_rpc.return_type = type async_rpc.return_args = args self.process_async_return(async_rpc) def default_request_handler(self, header, body): rpc_id = header.get('rpc_id', 0) type = header.get('type', None) log_debug("%s.default_request_handler: rpc_id=%s type=%s {%s}" % (self.__class__.__name__, rpc_id, type, body)) if type == 'error_return' or type == 'method_return': self.handle_return(type, rpc_id, body) elif type == 'method': interface, method, args = convert_rpc_xml_to_args(body) method_ptr = self.get_method_implementation(interface, method) if method_ptr: try: return_args = method_ptr(*args) if return_args is None: return_args = [] rpc_method_def = interface_registry.get_rpc_def(interface, method) rpc_callback_def = rpc_method_def.get_callback_def() self.emit_rpc(rpc_id, 'method_return', rpc_callback_def, *return_args) except ProgramError as e: rpc_error_def = interface_registry.get_error_rpc_def(interface) self.emit_rpc(rpc_id, 'error_return', rpc_error_def, method, e.errno, e.strerror) else: err_code = Errno.ENOSYS err_msg = "method '%s' is not implemented in class '%s'" % (method, self.__class__.__name__) rpc_error_def = interface_registry.get_error_rpc_def(interface) self.emit_rpc(rpc_id, 'error_return', rpc_error_def, method, err_code, err_msg) elif type == 'signal': interface, method, args = convert_rpc_xml_to_args(body) method_ptr = self.get_method_implementation(interface, method) if method_ptr: try: method_ptr(*args) except ProgramError as e: rpc_error_def = interface_registry.get_error_rpc_def(interface) else: err_code = Errno.ENOSYS err_msg = "method '%s' is not implemented in class '%s'" % (method, self.__class__.__name__) rpc_error_def = interface_registry.get_error_rpc_def(interface) self.emit_rpc(rpc_id, 'error_return', rpc_error_def, method, err_code, err_msg) else: raise ValueError("unknown type(%s) for %s:%s" % (type, interface, method)) #----------------------------------------------------------------------------- class AsyncRpc(object): def __init__(self, rpc_def, rpc_id): self.rpc_def = rpc_def self.rpc_id = rpc_id self.return_args = None self.return_type = None self.callbacks = [] self.errbacks = [] def add_callback(self, callback): self.callbacks.append(callback) def add_errback(self, errback): self.errbacks.append(errback) #----------------------------------------------------------------------------- rpc_interfaces.py000064400000011270152572267760010131 0ustar00# Authors: John Dennis # # Copyright (C) 2006,2007,2008 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # from setroubleshoot.rpc import rpc_method, rpc_arg_type, rpc_callback, rpc_signal from setroubleshoot.signature import * __all__ = [ 'SETroubleshootServerInterface', 'SETroubleshootDatabaseInterface', 'SETroubleshootDatabaseNotifyInterface', 'SEAlertInterface', ] #----------------------------------------------------------------------------- class SETroubleshootServerInterface: # # database_bind # @rpc_method('SETroubleshootServer') def database_bind(self, database_name): pass @rpc_callback('SETroubleshootServer', 'database_bind') @rpc_arg_type('SETroubleshootServer', SEDatabaseProperties) def database_bind_callback(self, properties): pass # # logon # @rpc_method('SETroubleshootServer') def logon(self, type, username, password): pass @rpc_callback('SETroubleshootServer', 'logon') def logon_callback(pkg_version, rpc_version): pass # # email_recipients # @rpc_method('SETroubleshootServer') def query_email_recipients(self): pass @rpc_callback('SETroubleshootServer', 'query_email_recipients') @rpc_arg_type('SETroubleshootServer', SEEmailRecipientSet) def query_email_recipients_callback(self, recipients): pass @rpc_method('SETroubleshootServer') @rpc_arg_type('SETroubleshootServer', SEEmailRecipientSet) def set_email_recipients(self, recipients): pass #----------------------------------------------------------------------------- class SETroubleshootDatabaseInterface: # # delete_signature # @rpc_method('SETroubleshootDatabase') @rpc_arg_type('SETroubleshootDatabase', SEFaultSignature) def delete_signature(self, sig): pass # # evaluate_alert_filter # @rpc_method('SETroubleshootDatabase') @rpc_arg_type('SETroubleshootDatabase', SEFaultSignature, str) def evaluate_alert_filter(self, sig, username): pass @rpc_callback('SETroubleshootDatabase', 'evaluate_alert_filter') def evaluate_alert_filter_callback(self, result): pass # # get_properties # @rpc_method('SETroubleshootDatabase') def get_properties(self): pass @rpc_callback('SETroubleshootDatabase', 'get_properties') @rpc_arg_type('SETroubleshootDatabase', SEDatabaseProperties) def get_properties_callback(self, properties): pass # # lookup_local_id # @rpc_method('SETroubleshootDatabase') def lookup_local_id(self, local_id): pass @rpc_callback('SETroubleshootDatabase', 'lookup_local_id') @rpc_arg_type('SETroubleshootDatabase', SEFaultSignatureInfo) def lookup_local_id_callback(self, siginfo): pass # # query_alerts # @rpc_method('SETroubleshootDatabase') def query_alerts(self, criteria): pass @rpc_callback('SETroubleshootDatabase', 'query_alerts') @rpc_arg_type('SETroubleshootDatabase', SEFaultSignatureSet) def query_alerts_callback(self, sigs): pass # # set_filter # @rpc_method('SETroubleshootDatabase') @rpc_arg_type('SETroubleshootDatabase', SEFaultSignature, str, int, str) def set_filter(self, sig, username, filter_type, data): pass # # set_user_data # @rpc_method('SETroubleshootDatabase') @rpc_arg_type('SETroubleshootDatabase', SEFaultSignature, str, str, str) def set_user_data(self, sig, username, key, value): pass #----------------------------------------------------------------------------- class SETroubleshootDatabaseNotifyInterface: # # signatures_updated # @rpc_signal('SETroubleshootDatabaseNotify') def signatures_updated(type, item): pass #----------------------------------------------------------------------------- class SEAlertInterface: # # alert # @rpc_signal('SEAlert') @rpc_arg_type('SEAlert', SEFaultSignatureInfo) def alert(siginfo): pass server.py000064400000102064152572267760006452 0ustar00from __future__ import absolute_import # Authors: John Dennis # Thomas Liu # Dan Walsh # # Copyright (C) 2006-2010 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # __all__ = ['RunFaultServer', 'ClientConnectionHandler', 'get_host_database', 'send_alert_notification', 'ConnectionPool', ] from gi.repository import GObject, GLib import dbus import dbus.service import dbus.glib import gettext #import errno as Errno import os #import pwd import signal import atexit #from stat import * import sys import syslog import systemd.journal #import threading #from types import * from setroubleshoot.config import parse_config_setting, get_config domain = get_config('general', 'i18n_text_domain') localedir = get_config('general', 'i18n_locale_dir') kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(domain=domain, localedir=localedir, **kwargs) translation = gettext.translation(domain=domain, localedir=localedir, fallback=True) try: _ = translation.ugettext # This raises exception in Python3, succ. in Py2 except AttributeError: _ = translation.gettext # Python3 from setroubleshoot.access_control import ServerAccess from setroubleshoot.analyze import (PluginReportReceiver, SETroubleshootDatabase, TestPluginReportReceiver, AnalyzeThread, ) from setroubleshoot.avc_audit import * from setroubleshoot.config import get_config from setroubleshoot.avc_audit import AuditRecordReceiver from setroubleshoot.errcode import (ProgramError, ERR_NOT_AUTHENTICATED, ERR_USER_LOOKUP, ERR_USER_PROHIBITED, ERR_USER_PERMISSION, ERR_FILE_OPEN, ERR_DATABASE_NOT_FOUND, ) from setroubleshoot.rpc import (RpcChannel, ConnectionState, get_socket_list_from_config, ListeningServer, ) from setroubleshoot.rpc_interfaces import (SETroubleshootServerInterface, SETroubleshootDatabaseNotifyInterface, SEAlertInterface, ) from setroubleshoot.util import (get_hostname, make_database_filepath, assure_file_ownership_permissions, get_identity, log_init, log_debug, syslog_trace ) log_init('setroubleshootd_log') #------------------------------ Utility Functions ----------------------------- def sighandler(signum, frame): log_debug("received signal=%s" % signum) import setroubleshoot.config as config if signum == signal.SIGHUP: log_debug("reloading configuration file") config.config_init() return def polling_failed_handler(signum, frame): log_debug("received signal=%s" % signum) syslog.syslog(syslog.LOG_ERR, "/sys/fs/selinux/policy is in use by another process. Exiting!") os._exit(1) # TODO: change to sys.exit(1) when the bug in audti2why is fixed def make_instance_id(): import time hostname = get_hostname() pid = os.getpid() stamp = str(time.time()) return '%s:%s:%s' % (hostname, pid, stamp) def get_host_database(): return host_database dbus_system_bus_name = get_config('system_dbus', 'bus_name') dbus_system_object_path = get_config('system_dbus', 'object_path') dbus_system_interface = get_config('system_dbus', 'interface') system_bus = dbus.SystemBus() system_bus.request_name(dbus_system_bus_name) # FIXME: this should be part of ClientNotifier def send_alert_notification(siginfo): alert = dbus.lowlevel.SignalMessage(dbus_system_object_path, dbus_system_interface, "alert") alert.append(siginfo.level) alert.append(siginfo.local_id) system_bus.send_message(alert) for client in connection_pool.clients('sealert'): client.alert(siginfo) #------------------------------ Variables ------------------------------- host_database = None analysis_queue = None email_recipients = None email_recipients_filepath = get_config('email', 'recipients_filepath') pkg_name = get_config('general', 'pkg_name') pkg_version = get_config('general', 'pkg_version') rpc_version = get_config('general', 'rpc_version') instance_id = make_instance_id() #----------------------------------------------------------------------------- class ConnectionPool(object): def __init__(self): self.client_pool = {} def add_client(self, handler): if handler in self.client_pool: log_debug("add_client: client (%s) already in client pool" % handler) return self.client_pool[handler] = None def remove_client(self, handler): if handler not in self.client_pool: log_debug("remove_client: client (%s) not in client pool" % handler) return del(self.client_pool[handler]) def clients(self, channel_type=None): for client in self.client_pool: if channel_type is None: yield client elif client.channel_type == channel_type: yield client def close_all(self, channel_type=None): for client in self.client_pool: if client.channel_type == channel_type: client.close_connection() connection_pool = ConnectionPool() #------------------------------------------------------------------------------ class AlertPluginReportReceiver(PluginReportReceiver): def __init__(self, database): super(AlertPluginReportReceiver, self).__init__(database) def report_problem(self, siginfo): siginfo = super(AlertPluginReportReceiver, self).report_problem(siginfo) if email_recipients is not None: to_addrs = [] for recipient in email_recipients.recipient_list: username = "email:%s" % recipient.address action = siginfo.evaluate_filter_for_user(username, recipient.filter_type) if action != "ignore": log_debug("Email: siginfo.sig=%s" % siginfo.sig) to_addrs.append(recipient.address) if len(to_addrs): from setroubleshoot.email_alert import email_alert email_alert(siginfo, to_addrs) self.database.mark_modified() log_debug("sending alert to all clients") from setroubleshoot.html_util import html_to_text syslog.syslog(syslog.LOG_ERR, siginfo.summary() + _(" For complete SELinux messages run: sealert -l %s") % siginfo.local_id) for audit_record in siginfo.audit_event.records: if audit_record.record_type == 'AVC': pid = audit_record.fields["pid"] break if get_config('setroubleshootd_log', 'log_full_report', bool): global pkg_name systemd.journal.send(siginfo.format_text(), OBJECT_PID=pid, SYSLOG_IDENTIFIER=pkg_name) for u in siginfo.users: if u.username[0:6] == "email:": # skip email users - they were evaluated before continue action = siginfo.evaluate_filter_for_user(u.username) if action == "ignore": return siginfo send_alert_notification(siginfo) return siginfo #----------------------------------------------------------------------------- class ClientConnectionHandler(RpcChannel): def __init__(self, socket_address): RpcChannel.__init__(self, 'sealert') self.socket_address = socket_address.copy() self.connection_state.connect('changed', self.on_connection_state_change) def on_connection_state_change(self, connection_state, flags, flags_added, flags_removed): log_debug("%s.on_connection_state_change: connection_state=%s flags_added=%s flags_removed=%s address=%s" % (self.__class__.__name__, connection_state, connection_state.flags_to_string(flags_added), connection_state.flags_to_string(flags_removed), self.socket_address)) if flags_removed & ConnectionState.OPEN: connection_pool.remove_client(self) if flags_added & ConnectionState.OPEN: connection_pool.add_client(self) def open(self, socket, socket_address): if self.connection_state.flags & ConnectionState.OPEN: return True self.socket_address.socket = socket self.connection_state.update(ConnectionState.OPEN) self.io_watch_add(self.handle_client_io) #----------------------------------------------------------------------------- class SetroubleshootdClientConnectionHandler(ClientConnectionHandler, SETroubleshootServerInterface, SETroubleshootDatabaseNotifyInterface, SEAlertInterface, ): def __init__(self, socket_address): ClientConnectionHandler.__init__(self, socket_address) self.database = get_host_database() self.connect_rpc_interface('SETroubleshootServer', self) self.connect_rpc_interface('SETroubleshootDatabase', self) self.access = ServerAccess() self.username = None self.uid = None self.gid = None def on_connection_state_change(self, connection_state, flags, flags_added, flags_removed): log_debug("%s.on_connection_state_change: connection_state=%s flags_added=%s flags_removed=%s address=%s" % (self.__class__.__name__, connection_state, connection_state.flags_to_string(flags_added), connection_state.flags_to_string(flags_removed), self.socket_address)) if flags_removed & ConnectionState.OPEN: connection_pool.remove_client(self) if flags_added & ConnectionState.OPEN: self.uid, self.gid = self.access.get_credentials(self.socket_address.socket) log_debug("%s.on_connection_state_change: open, socket credentials: uid=%s gid=%s" % (self.__class__.__name__, self.uid, self.gid)) connection_pool.add_client(self) def open(self, socket, socket_address): if self.connection_state.flags & ConnectionState.OPEN: return True self.socket_address.socket = socket self.connection_state.update(ConnectionState.OPEN) self.io_watch_add(self.handle_client_io) # ---- SETroubleshootServerInterface Methods ---- def database_bind(self, database_name): if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) host_database = get_host_database() if host_database.properties.name == database_name: return [host_database.properties] raise ProgramError(ERR_DATABASE_NOT_FOUND, "database (%s) not found" % database_name) def logon(self, type, username, password): log_debug("logon(%s) type=%s username=%s" % (self, type, username)) if username != get_identity(self.uid): raise ProgramError(ERR_USER_LOOKUP, detail="uid=%s does not match logon username (%s)" % (self.uid, username)) if type == 'sealert': privilege = 'client' else: privilege = None if not self.access.user_allowed(privilege, username): raise ProgramError(ERR_USER_PROHIBITED) self.channel_type = type self.channel_name = username self.username = username self.user = self.database.get_user(username) if self.user is None: self.database.add_user(username) self.connection_state.update(ConnectionState.AUTHENTICATED) return [pkg_version, rpc_version] def query_email_recipients(self): if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) return [email_recipients] def set_email_recipients(self, recipients): global email_recipients log_debug("set_email_recipients: %s" % recipients) if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) email_recipients = recipients email_recipients.write_recipient_file(email_recipients_filepath) # ---- SETroubleshootDatabaseInterface Methods ---- def delete_signature(self, sig): log_debug("delete_signature: sig=%s" % sig) if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) siginfo = self.database.delete_signature(sig) return None def get_properties(self): log_debug("get_properties") if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) properties = self.database.get_properties() return [properties] def evaluate_alert_filter(self, sig, username): log_debug("evaluate_alert_filter: username=%s sig=%s" % (username, sig)) if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) action = self.database.evaluate_alert_filter(sig, username) return [action] def lookup_local_id(self, local_id): log_debug("lookup_local_id: %s" % local_id) if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) siginfo = self.database.lookup_local_id(local_id) return [siginfo] def query_alerts(self, criteria): log_debug("query_alerts: criteria=%s" % criteria) if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) sigs = self.database.query_alerts(criteria) return [sigs] def set_filter(self, sig, username, filter_type, data=""): log_debug("set_filter: username=%s filter_type=%s sig=\n%s" % (username, filter_type, sig)) if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) if username != self.username: raise ProgramError(ERR_USER_PERMISSION, detail=_("The user (%s) cannot modify data for (%s)") % (self.username, username)) self.database.set_filter(sig, username, filter_type, data) return None def set_user_data(self, sig, username, item, data): log_debug("set_user_data: username=%s item=%s data=%s sig=\n%s" % (username, item, data, sig)) if not (self.connection_state.flags & ConnectionState.AUTHENTICATED): raise ProgramError(ERR_NOT_AUTHENTICATED) self.database.set_user_data(sig, username, item, data) return None #------------------------------------------------------------------------------ class ClientNotifier(object): def __init__(self, connection_pool): self.connection_pool = connection_pool # ---- SETroubleshootDatabaseNotifyInterface Methods ---- def signatures_updated(self, type, item): for client in self.connection_pool.clients('sealert'): client.signatures_updated(type, item) #------------------------------------------------------------------------------ from setroubleshoot.audit_data import * import setroubleshoot.util class SetroubleshootdDBusObject(dbus.service.Object): def __init__(self, object_path, analysis_queue, alert_receiver, timeout=10): dbus.service.Object.__init__(self, dbus.SystemBus(), object_path) self.conn_ctr = 0 self.timeout = timeout self.alarm(self.timeout) log_debug('dbus __init__ %s called' % object_path) self.queue = analysis_queue self.receiver = alert_receiver self.record_reader = AuditRecordReader(AuditRecordReader.TEXT_FORMAT) self.record_receiver = AuditRecordReceiver() def add(self, avc): try: # FIXME: do not hardcode /var/lib/selinux/ store_path policy_type = selinux.selinux_getpolicytype()[1] for store_path in [ "%s%s/modules/active/disable_dontaudit" % (selinux.selinux_path(), policy_type), "/var/lib/selinux/%s/active/disable_dontaudit" % policy_type ]: if os.path.exists(store_path): raise ValueError("Setroubleshoot can not analyze AVCs while dontaudit rules are disabled, 'semodule -B' will turn on dontaudit rules.") if verify_avc(avc): self.queue.put((avc, self.receiver)) except ValueError as e: syslog.syslog(syslog.LOG_ERR, str(e)) @dbus.service.signal(dbus_system_interface) def restart(self, reason): pass @dbus.service.signal(dbus_system_interface, signature='ss') def alert(self, level, local_id): pass @dbus.service.method(dbus_system_interface) def start(self): self.alarm(0) self.conn_ctr += 1 log_debug('dbus iface start() called: %d Connections' % self.conn_ctr) return _("Started") @dbus.service.method(dbus_system_interface, sender_keyword="sender", in_signature='s', out_signature='ii') def check_for_new(self, last_seen_id, sender): username = get_identity(self.connection.get_unix_user(sender)) database = get_host_database() s = "" signatures = [] for sig in database.query_alerts("*").siginfos(): action = sig.evaluate_filter_for_user(username) if action != "ignore": signatures.append(sig) signatures.sort(key=compare_sig) count = 0 red = 0 for sig in signatures: count += 1 if sig.level == "red": red += 1 if sig.local_id == last_seen_id: red = 0 count = 0 return count, red def _get_all_alerts_since(self, since, sender, alert_action="display"): username = get_identity(self.connection.get_unix_user(sender)) database = get_host_database() since_alerts = setroubleshoot.util.TimeStamp(float(since / 1000000)) database_alerts = database.query_alerts("*").signature_list alerts = [] for alert in database_alerts: if alert.last_seen_date < since_alerts: continue if alert.evaluate_filter_for_user(username) == alert_action: alerts.append((alert.local_id, alert.summary(), alert.report_count)) return alerts @dbus.service.method(dbus_system_interface, sender_keyword="sender", in_signature='t', out_signature='a(ssi)') def get_all_alerts_since(self, since, sender): return self._get_all_alerts_since(since, sender) @dbus.service.method(dbus_system_interface, sender_keyword="sender", in_signature='', out_signature='a(ssi)') def get_all_alerts(self, sender): """ Return array of *local_id*'s, *summary*'s, and *report_count*'s of all current alerts in a setroubleshoot database returns list of: * `local_id(s)`: a report id in a setroubleshoot database * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert """ return self._get_all_alerts_since(0, sender) @dbus.service.method(dbus_system_interface, sender_keyword="sender", in_signature='', out_signature='a(ssi)') def get_all_alerts_ignored(self, sender): """ Return array of *local_id*'s, *summary*'s, and *report_count*'s of all alerts which a user set to be ignored by a user returns list of: * `local_id(s)`: a report id in a setroubleshoot database * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert """ return self._get_all_alerts_since(0, sender, alert_action="ignore") def _get_alert(self, local_id, database): try: database_alerts = database.query_alerts(local_id) except ProgramError as e: raise e alert = database_alerts.siginfos().__next__() return alert @dbus.service.method(dbus_system_interface, sender_keyword="sender", in_signature='s', out_signature='ssiasa(ssssbbi)tts') def get_alert(self, local_id, sender): """ Return an alert with summary, audit events, fix suggestions ##### arguments * `local_id(s)`: an alert id ##### return values * `local_id(s)`: an alert id * `summary(s)`: a brief description of an alert. E.g. `"SELinux is preventing /usr/bin/bash from ioctl access on the unix_stream_socket unix_stream_socket."` * `report_count(i)`: count of reports of this alert * `audit_event(as)`: an array of audit events (AVC, SYSCALL) connected to the alert * `plugin_analysis(a(ssssbb)`: an array of plugin analysis structure * `if_text(s)`: * `then_text(s)` * `do_text(s)` * `analysis_id(s)`: plugin id. It can be used in `org.fedoraproject.SetroubleshootFixit.run_fix()` * `fixable(b)`: True when an alert is fixable by a plugin * `report_bug(b)`: True when an alert should be reported to bugzilla * `priority(i)`: An analysis priority. Typically the value is between 1 - 100. * `first_seen_date(t)`: when the alert was seen for the first time, number of microseconds since the Epoch * `last_seen_date(t)`: when the alert was seen for the last time, number of microseconds since the Epoch * `level(s)`: "green", "yellow" or "red" """ username = get_identity(self.connection.get_unix_user(sender)) database = get_host_database() alert = self._get_alert(local_id, database) alert.update_derived_template_substitutions() avc = alert.audit_event.records audit_events = [event.to_text() for event in avc] total_priority, alert_plugins = alert.get_plugins() plugins = [] for plugin, args in alert_plugins: plugins.append(( alert.substitute(plugin.get_if_text(avc, args)), alert.substitute(plugin.get_then_text(avc, args)), alert.substitute(plugin.get_do_text(avc, args)), plugin.analysis_id, plugin.fixable, plugin.report_bug, plugin.priority) ) return (alert.local_id, alert.summary(), alert.report_count, audit_events, plugins, int(alert.first_seen_date.format("%s")) * 1000000, int(alert.last_seen_date.format("%s")) * 1000000, alert.level or '' ) @dbus.service.method(dbus_system_interface, sender_keyword="sender", in_signature='ss', out_signature='b') def set_filter(self, local_id, filter_type, sender): """ Sets a filter on an alert. The alert can be "always" filtered, "never" filtered or "after_first" filtered. ##### arguments * `local_id(s)`: an alert id * `filter_type(s)`: "always", "never", "after_first" ##### return values * `success(b)`: """ try: username = get_identity(self.connection.get_unix_user(sender)) database = get_host_database() alert = self._get_alert(local_id, database) from setroubleshoot.signature import map_filter_name_to_value database.set_filter(alert.sig, username, map_filter_name_to_value[filter_type], None) return True except: return False @dbus.service.method(dbus_system_interface, sender_keyword="sender", in_signature='s', out_signature='b') def delete_alert(self, local_id, sender): """ Deletes an alert from the database. ##### arguments * `local_id(s)`: an alert id ##### return values * `success(b)`: """ try: database = get_host_database() alert = self._get_alert(local_id, database) database.delete_signature(alert.sig) return True except: return False @dbus.service.method(dbus_system_interface, in_signature='s', out_signature='s') def avc(self, data): data = str(data) self.alarm(0) self.conn_ctr += 1 log_debug('dbus avc(%s) called: %d Connections' % (data, self.conn_ctr)) for (record_type, event_id, body_text, fields, line_number) in self.record_reader.feed(str(data)): audit_record = AuditRecord(record_type, event_id, body_text, fields, line_number) audit_record.audispd_rectify() for audit_event in self.record_receiver.feed(audit_record): self.add(AVC(audit_event)) for audit_event in self.record_receiver.flush(0): try: self.add(AVC(audit_event)) except ValueError as e: syslog.syslog(syslog.LOG_ERR, "Unable to add audit event: %s" % e) self.conn_ctr -= 1 self.alarm(self.timeout) return _("AVC") @dbus.service.method(dbus_system_interface) def finish(self): self.conn_ctr -= 1 log_debug('dbus iface finish() called: %d Connections' % self.conn_ctr) self.alarm(self.timeout) return "" def alarm(self, timeout=10): if self.conn_ctr == 0: signal.alarm(timeout) def compare_sig(a): return a.last_seen_date class SetroubleshootdDBus: def __init__(self, analysis_queue, alert_receiver, timeout): try: log_debug("creating system dbus: bus_name=%s object_path=%s interface=%s" % (dbus_system_bus_name, dbus_system_object_path, dbus_system_interface)) self.dbus_obj = SetroubleshootdDBusObject(dbus_system_object_path, analysis_queue, alert_receiver, timeout) except Exception as e: syslog.syslog(syslog.LOG_ERR, "cannot start system DBus service: %s" % e) raise e def do_restart(self): self.dbus_obj.restart("daemon request") return True #------------------------------------------------------------------------------ import selinux import selinux.audit2why as audit2why def goodbye(database): database.save() audit2why.finish() main_loop = GLib.MainLoop() def alarm_handler(signum, frame): log_debug("SIGALRM raised in RunFaultServer") main_loop.quit() def RunFaultServer(timeout=10): signal.alarm(timeout) 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, alarm_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 its id global 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, timeout) 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.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))) if __name__ == '__main__': RunFaultServer() serverconnection.py000064400000014217152572267760010534 0ustar00from __future__ import absolute_import import syslog import sys if sys.version_info < (3,): import setroubleshoot.default_encoding_utf8 from gi.repository import GObject import errno as Errno import gettext import os import six.moves.queue import re import signal import selinux import socket as Socket import fcntl from setroubleshoot.config import parse_config_setting, get_config from setroubleshoot.rpc import RpcChannel, ConnectionState from setroubleshoot.rpc_interfaces import SETroubleshootServerInterface from setroubleshoot.rpc_interfaces import SETroubleshootDatabaseInterface from setroubleshoot.util import Retry, get_error_from_socket_exception __all__ = [ "ServerConnectionHandler" ] class ServerConnectionHandler(RpcChannel, SETroubleshootServerInterface, SETroubleshootDatabaseInterface, GObject.GObject): __gsignals__ = { 'alert': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,)), 'connection_state_changed': # callback(connection_state, flags, flags_added, flags_removed): (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_INT, GObject.TYPE_INT, GObject.TYPE_INT)), 'signatures_updated': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT)), 'database_bind': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT)), 'async-error': # callback(method, errno, strerror) (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_STRING)), } def __init__(self, username): RpcChannel.__init__(self, channel_type='sealert') GObject.GObject.__init__(self) self.connection_state.connect('changed', self.on_connection_state_change) self.connect_rpc_interface('SEAlert', self) self.connect_rpc_interface('SETroubleshootDatabaseNotify', self) self.pkg_version = get_config('general', 'pkg_version') self.rpc_version = get_config('general', 'rpc_version') self.username = username self.retry_connection_if_closed = False self.connection_retry = Retry(self.retry_connection, self.get_connection_retry_interval, notify_interval=1.0) self.report_connect_failure = True self.database_name = 'audit_listener' def on_connection_state_change(self, connection_state, flags, flags_added, flags_removed): self.emit('connection_state_changed', connection_state, flags, flags_added, flags_removed) if (flags_removed & ConnectionState.OPEN) or (flags_added & (ConnectionState.HUP | ConnectionState.ERROR)): if self.retry_connection_if_closed and not (flags & ConnectionState.RETRY): self.connection_state.update(ConnectionState.RETRY) self.connection_retry.start() # Retry Behavior: # # Started when: # Connection lost is detected, however must not start if deliberate close is requested # Stopped when: # 1) successful open # 2) deliberate close def open(self, socket_address=None): if socket_address is not None: self.socket_address = socket_address if self.connection_state.flags & ConnectionState.OPEN: return True try: self.connection_state.update(ConnectionState.CONNECTING, ConnectionState.OPEN | ConnectionState.ERROR) self.socket_address.socket = Socket.socket(self.socket_address.family, self.socket_address.type) fcntl.fcntl(self.socket_address.socket.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC) self.socket_address.socket.connect(self.socket_address.get_py_address()) self.io_watch_add(self.handle_client_io) self.connection_state.update(ConnectionState.OPEN, ConnectionState.CONNECTING | ConnectionState.RETRY) self.connection_retry.stop() self.report_connect_failure = True self.do_logon() except Socket.error as e: errno, strerror = get_error_from_socket_exception(e) if self.report_connect_failure == True: syslog.syslog(syslog.LOG_ERR, "attempt to open server connection failed: %s" % strerror) self.report_connect_failure = False if errno == Errno.EPIPE: add_flags = ConnectionState.HUP else: add_flags = ConnectionState.ERROR self.close_connection(add_flags, ConnectionState.CONNECTING, errno, strerror) return False return True def retry_connection(self, retry, user_data): if self.open(self.socket_address): return True else: return False def get_connection_retry_interval(self, retry, user_data): if retry.failed_attempts < 5: return 10 else: return 60 def async_error_callback(self, method, errno, strerror): syslog.syslog(syslog.LOG_ERR, "async_error: method=%s errno=%s: %s" % (method, errno, strerror)) self.emit('async-error', method, errno, strerror) def bind(self): def database_bind_callback(properties): self.emit('database_bind', self, properties) async_rpc = self.database_bind(self.database_name) async_rpc.add_callback(database_bind_callback) async_rpc.add_errback(self.async_error_callback) def do_logon(self): def logon_callback(pkg_version, rpc_version): self.connection_state.update(ConnectionState.AUTHENTICATED) self.channel_name = self.username async_rpc = self.logon(self.channel_type, self.username, 'passwd') async_rpc.add_callback(logon_callback) async_rpc.add_errback(self.async_error_callback) def set_filter(self, sig, user, filter_type, data): async_rpc = SETroubleshootDatabaseInterface.set_filter(self, sig, user, filter_type, data) async_rpc.add_errback(self.async_error_callback) # ------ def alert(self, siginfo): self.emit('alert', siginfo) def signatures_updated(self, type, item): self.emit('signatures_updated', type, item) signature.py000064400000102342152572267760007144 0ustar00from __future__ import absolute_import from __future__ import print_function # Authors: John Dennis # Thomas Liu # Dan Walsh # # Copyright (C) 2006-2010 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # import six import syslog from subprocess import * from six.moves import range from functools import cmp_to_key import gettext from setroubleshoot.config import parse_config_setting, get_config translation = gettext.translation(domain=get_config('general', 'i18n_text_domain'), localedir=get_config('general', 'i18n_locale_dir'), fallback=True) try: _ = translation.ugettext # Unicode version of gettext for Py2 except AttributeError: _ = translation.gettext # Python3 (uses unicode by default) __all__ = [ 'SignatureMatch', 'SEFilter', 'SEFaultSignature', 'SEFaultSignatureInfo', 'SEFaultSignatureSet', 'SEFaultSignatureUser', 'SEEnvironment', 'SEDatabaseProperties', 'SEFaultUserInfo', 'SEFaultUserSet', 'SEPlugin', 'SEEmailRecipient', 'SEEmailRecipientSet', 'FILTER_NEVER', 'FILTER_ALWAYS', 'FILTER_AFTER_FIRST', 'filter_text' ] if __name__ == "__main__": gettext.install(domain=get_config('general', 'i18n_text_domain'), localedir=get_config('general', 'i18n_locale_dir')) from gettext import ngettext as P_ from setroubleshoot.config import get_config from setroubleshoot.errcode import * from setroubleshoot.util import * from setroubleshoot.xml_serialize import * from setroubleshoot.html_util import * import setroubleshoot.uuid as uuid from setroubleshoot.audit_data import * import hashlib from types import * from string import Template import re import os cmp = lambda x, y: (x > y) - (x < y) # Don't reuse the numeric values! FILTER_NEVER = 0 FILTER_ALWAYS = 4 FILTER_AFTER_FIRST = 8 filter_text = { FILTER_NEVER: _("Never Ignore"), FILTER_ALWAYS: _("Ignore Always"), FILTER_AFTER_FIRST: _("Ignore After First Alert"), } map_filter_value_to_name = { FILTER_NEVER: 'never', FILTER_ALWAYS: 'always', FILTER_AFTER_FIRST: 'after_first', } map_filter_name_to_value = { 'never': FILTER_NEVER, 'always': FILTER_ALWAYS, 'after_first': FILTER_AFTER_FIRST, } #------------------------------------------------------------------------ class SignatureMatch(object): def __init__(self, siginfo, score): self.siginfo = siginfo self.score = score class SEEnvironment(XmlSerialize): _xml_info = { 'version': {'XMLForm': 'attribute', 'default': lambda: '1.0'}, 'platform': {'XMLForm': 'element'}, 'kernel': {'XMLForm': 'element'}, 'policy_type': {'XMLForm': 'element'}, 'policy_rpm': {'XMLForm': 'element'}, 'local_policy_rpm': {'XMLForm': 'element'}, 'enforce': {'XMLForm': 'element'}, 'selinux_enabled': {'XMLForm': 'element', 'import_typecast': boolean, }, 'selinux_mls_enabled': {'XMLForm': 'element', 'import_typecast': boolean, }, 'policyvers': {'XMLForm': 'element'}, 'hostname': {'XMLForm': 'element'}, 'uname': {'XMLForm': 'element'}, } def __init__(self): super(SEEnvironment, self).__init__() self.update() def update(self): import platform import selinux # security_getenforce is the same as the getenforce command. # selinux_getenforcemode tells you what is set in /etc/selinux/config self.platform, self.kernel = get_os_environment() self.policy_type = selinux.selinux_getpolicytype()[1] self.policy_rpm = get_package_nvr_by_file_path("/etc/selinux/%s" % self.policy_type) self.local_policy_rpm = self.policy_rpm self.policyvers = str(selinux.security_policyvers()) enforce = selinux.security_getenforce() if enforce == 0: self.enforce = "Permissive" else: self.enforce = "Enforcing" self.selinux_enabled = bool(selinux.is_selinux_enabled()) self.selinux_mls_enabled = bool(selinux.is_selinux_mls_enabled()) self.hostname = platform.node() self.uname = " ".join(platform.uname()) def __ne__(self, other): return not self.__eq__(other) def __eq__(self, other): for name in list(self._xml_info.keys()): if getattr(self, name) != getattr(other, name): return False return True class SEFilter(XmlSerialize): _xml_info = { 'filter_type': {'XMLForm': 'element', 'import_typecast': int, 'default': lambda: FILTER_NEVER}, 'count': {'XMLForm': 'element', 'import_typecast': int, 'default': lambda: 0}, } def __init__(self, filter_type=FILTER_NEVER): super(SEFilter, self).__init__() self.filter_type = filter_type class SEFaultSignatureUser(XmlSerialize): _xml_info = { 'username': {'XMLForm': 'attribute'}, 'seen_flag': {'XMLForm': 'attribute', 'import_typecast': boolean, 'default': lambda: False}, 'delete_flag': {'XMLForm': 'attribute', 'import_typecast': boolean, 'default': lambda: False}, 'filter': {'XMLForm': 'element', 'import_typecast': SEFilter, 'default': lambda: SEFilter()}, } def __init__(self, username): super(SEFaultSignatureUser, self).__init__() self.username = username def update_item(self, item, data): if not item in self._names: raise ProgramError(ERR_NOT_MEMBER, 'item (%s) is not a defined member' % item) if item == 'username': raise ProgramError(ERR_ILLEGAL_USER_CHANGE, 'changing the username is illegal') setattr(self, item, data) def update_filter(self, filter_type, data=None): log_debug("update_filter: filter_type=%s data=%s" % (map_filter_value_to_name.get(filter_type, 'unknown'), data)) if filter_type == FILTER_NEVER or \ filter_type == FILTER_AFTER_FIRST or \ filter_type == FILTER_ALWAYS: log_debug("update_filter: !!!") self.filter = SEFilter(filter_type=filter_type) return True else: raise ValueError("Bad filter_type (%s)" % filter_type) class_dict = {} class_dict['dir'] = _("directory") class_dict['sem'] = _("semaphore") class_dict['shm'] = _("shared memory") class_dict['msgq'] = _("message queue") class_dict['msg'] = _("message") class_dict['file'] = _("file") class_dict['socket'] = _("socket") class_dict['process'] = _("process") class_dict['process2'] = _("process2") class_dict['filesystem'] = _("filesystem") class_dict['node'] = _("node") class_dict['capability'] = _("capability") class_dict['capability2'] = _("capability2") def translate_class(tclass): if tclass in list(class_dict.keys()): return class_dict[tclass] return tclass # -- class AttributeValueDictionary(XmlSerialize): _xml_info = 'unstructured' def __init__(self): super(AttributeValueDictionary, self).__init__() class SEFaultSignature(XmlSerialize): _xml_info = { 'version': {'XMLForm': 'attribute', 'default': lambda: '4.0', }, 'host': {'XMLForm': 'element', }, 'access': {'XMLForm': 'element', 'list': 'operation', }, 'scontext': {'XMLForm': 'element', 'import_typecast': AvcContext}, 'tcontext': {'XMLForm': 'element', 'import_typecast': AvcContext}, 'tclass': {'XMLForm': 'element', }, 'port': {'XMLForm': 'element', 'import_typecast': int, }, } def __init__(self, **kwds): super(SEFaultSignature, self).__init__() for k, v in list(kwds.items()): setattr(self, k, v) class SEPlugin(XmlSerialize): _xml_info = { 'analysis_id': {'XMLForm': 'element'}, 'args': {'XMLForm': 'element', 'list': 'arg', }, } def __init__(self, analysis_id, args): super(SEPlugin, self).__init__() self.analysis_id = analysis_id self.args = args def __str__(self): return str((self.analysis_id, self.args)) class SEFaultSignatureInfo(XmlSerialize): _xml_info = { 'plugin_list': {'XMLForm': 'element', 'list': 'plugin', 'import_typecast': SEPlugin}, 'audit_event': {'XMLForm': 'element', 'import_typecast': AuditEvent}, 'source': {'XMLForm': 'element'}, 'spath': {'XMLForm': 'element'}, 'tpath': {'XMLForm': 'element'}, 'src_rpm_list': {'XMLForm': 'element', 'list': 'rpm', }, 'tgt_rpm_list': {'XMLForm': 'element', 'list': 'rpm', }, 'scontext': {'XMLForm': 'element', 'import_typecast': AvcContext}, 'tcontext': {'XMLForm': 'element', 'import_typecast': AvcContext}, 'tclass': {'XMLForm': 'element', }, 'port': {'XMLForm': 'element', 'import_typecast': int, }, 'sig': {'XMLForm': 'element', 'import_typecast': SEFaultSignature}, 'if_text': {'XMLForm': 'element'}, 'then_text': {'XMLForm': 'element'}, 'do_text': {'XMLForm': 'element'}, 'environment': {'XMLForm': 'element', 'import_typecast': SEEnvironment}, 'first_seen_date': {'XMLForm': 'element', 'import_typecast': TimeStamp}, 'last_seen_date': {'XMLForm': 'element', 'import_typecast': TimeStamp}, 'report_count': {'XMLForm': 'element', 'import_typecast': int, 'default': lambda: 0}, 'local_id': {'XMLForm': 'element'}, 'users': {'XMLForm': 'element', 'list': 'user', 'import_typecast': SEFaultSignatureUser, }, 'level': {'XMLForm': 'element'}, 'fixable': {'XMLForm': 'element'}, 'button_text': {'XMLForm': 'element'}, } merge_include = ['audit_event', 'tpath', 'src_rpm_list', 'tgt_rpm_list', 'scontext', 'tcontext', 'tclass', 'port', 'environment', 'last_seen_date' ] def __init__(self, **kwds): super(SEFaultSignatureInfo, self).__init__() for k, v in list(kwds.items()): setattr(self, k, v) self.report_count = 1 self.plugin_list = [] use_dbus=True if os.getuid() == 0: # root doesn't need to use dbus use_dbus=False try: self.environment.local_policy_rpm = get_rpm_nvr_by_scontext(self.scontext, use_dbus=use_dbus) except: # leave it as it is pass def update_merge(self, siginfo): if siginfo.last_seen_date != self.last_seen_date: self.last_seen_date = siginfo.last_seen_date self.report_count += 1 for name in self.merge_include: setattr(self, name, getattr(siginfo, name)) # older databases can have an uninitialized level if self.level is None: self.level = siginfo.level def get_policy_rpm(self): return self.environment.policy_rpm def get_hash_str(self): return "%s,%s,%s,%s,%s" % (self.source, self.scontext.type, self.tcontext.type, self.tclass, ",".join(self.sig.access)) def get_hash(self): hash = hashlib.sha256(self.get_hash_str().encode('utf-8')) return hash.hexdigest() def get_user_data(self, username): for user in self.users: if user.username == username: return user log_debug("new SEFaultSignatureUser for %s" % username) user = SEFaultSignatureUser(username) self.users.append(user) return user def find_filter_by_username(self, username): log_debug("find_filter_by_username %s" % username) filter = None user_data = self.get_user_data(username) if user_data is not None: filter = user_data.filter return filter def update_user_filter(self, username, filter_type, data=None): user_data = self.get_user_data(username) user_data.update_filter(filter_type, data) def evaluate_filter_for_user(self, username, filter_type=None): action = 'display' f = self.find_filter_by_username(username) log_debug("evaluate_filter_for_user: found %s user's filter = %s" % (username, f)) if f is not None: if filter_type is not None: f.filter_type = filter_type action = self.evaluate_filter(f) log_debug("evaluate_filter_for_user: found filter for %s: %s\n%s" % (username, action, f)) return action def evaluate_filter(self, filter): filter_type = filter.filter_type action = 'display' if filter_type == FILTER_NEVER: action = 'display' elif filter_type == FILTER_AFTER_FIRST: if filter.count == 0: action = 'display' else: action = 'ignore' elif filter_type == FILTER_ALWAYS: action = 'ignore' else: raise ValueError("unknown filter_type (%s)" % (filter_type)) filter.count += 1 return action def format_rpm_list(self, rpm_list): if isinstance(rpm_list, list): if len(rpm_list) > 0: return " ".join(rpm_list) else: return "" else: return default_text(None) def format_target_object(self): return "%s [ %s ]" % (self.tpath, self.tclass) def description_adjusted_for_permissive(self): permissive_msg = None syscall_record = self.audit_event.get_record_of_type('SYSCALL') if syscall_record != None and syscall_record.get_field('success') == 'yes': permissive_msg = _("%s has a permissive type (%s). This access was not denied.") % (self.source, self.scontext.type) if self.environment.enforce == "Permissive": permissive_msg = _("SELinux is in permissive mode. This access was not denied.") def update_derived_template_substitutions(self): self.template_substitutions = {} self.template_substitutions["SOURCE_TYPE"] = self.scontext.type self.template_substitutions["TARGET_TYPE"] = self.tcontext.type self.template_substitutions["SOURCE"] = self.source self.template_substitutions["SOURCE_PATH"] = self.spath self.template_substitutions["SOURCE_BASE_PATH"] = os.path.basename(self.spath) self.template_substitutions["MODULE_NAME"] = re.sub('[^a-zA-Z0-9]', '', self.source) if self.spath: self.template_substitutions["FIX_SOURCE_PATH"] = re.sub(" ", ".", self.spath) else: self.spath = _("N/A") self.template_substitutions["TARGET_PATH"] = self.tpath self.template_substitutions["TARGET_BASE_PATH"] = os.path.basename(self.tpath) if self.tpath: self.template_substitutions["FIX_TARGET_PATH"] = re.sub(" ", ".", self.tpath) if self.tpath is None: self.template_substitutions["TARGET_DIR"] = None else: if self.tclass == 'dir': self.template_substitutions["TARGET_DIR"] = self.tpath elif self.tclass == 'file': self.template_substitutions["TARGET_DIR"] = os.path.dirname(self.tpath) else: self.template_substitutions["TARGET_DIR"] = None if self.tclass == "dir": self.template_substitutions["TARGET_CLASS"] = "directory" else: self.template_substitutions["TARGET_CLASS"] = self.tclass if self.sig.access is None: self.template_substitutions["ACCESS"] = None else: self.template_substitutions["ACCESS"] = ' '.join(self.sig.access) if len(self.src_rpm_list) > 0: self.template_substitutions["SOURCE_PACKAGE"] = self.src_rpm_list[0] self.template_substitutions["PORT_NUMBER"] = self.port # validate, replace any None values with friendly string for key, value in list(self.template_substitutions.items()): if value is None: self.template_substitutions[key] = default_text(value) def priority_sort(self, x, y): return cmp(y[0].priority, x[0].priority) def summary(self): if self.tclass in ["process", "process2"]: return P_(_("SELinux is preventing %s from using the %s access on a process."), _("SELinux is preventing %s from using the '%s' accesses on a process."), len(self.sig.access)) % (self.spath, ", ".join(self.sig.access)) if self.tclass in ["capability", "capability2"]: return P_(_("SELinux is preventing %s from using the %s capability."), _("SELinux is preventing %s from using the '%s' capabilities."), len(self.sig.access)) % (self.spath, ", ".join(self.sig.access)) if self.tpath in ["(null)", "Unknown"] : return P_(_("SELinux is preventing %s from %s access on the %s labeled %s."), _("SELinux is preventing %s from '%s' accesses on the %s labeled %s."), len(self.sig.access)) % (self.spath, ", ".join(self.sig.access), translate_class(self.tclass), self.tcontext.type) return P_(_("SELinux is preventing %s from %s access on the %s %s."), _("SELinux is preventing %s from '%s' accesses on the %s %s."), len(self.sig.access)) % (self.spath, ", ".join(self.sig.access), translate_class(self.tclass), self.tpath) def get_plugins(self, all=False): self.plugins = load_plugins() plugins = [] total_priority = 0 if all: for p in self.plugins: total_priority += p.priority plugins.append((p, ("allow_ypbind", "1"))) else: for solution in self.plugin_list: for p in self.plugins: if solution.analysis_id == p.analysis_id: total_priority += p.priority p.init_args(tuple(solution.args)) plugins.append((p, tuple(solution.args))) break plugins.sort(key=cmp_to_key(self.priority_sort)) # do not show "report bug" button if switching one of the following booleans was suggested noreport_booleans = ["mozilla_read_content", "mozilla_plugin_can_network_connect", "mozilla_plugin_use_bluejeans", "unconfined_mozilla_plugin_transition"] # suggested commands (from all plugins) do_texts = " ".join([p.get_do_text(self.audit_event.records, a) for p, a in plugins]) for b in noreport_booleans: if b in do_texts: # remove "report bug" button from all plugins for p, a in plugins: p.report_bug = False break return total_priority, plugins def substitute(self, txt): return Template(txt).safe_substitute(self.template_substitutions) def substitute_array(self, args): return [self.substitute(txt) for txt in args] def format_details(self, replace=False): env = self.environment text = _("Additional Information:\n") text += format_2_column_name_value(_("Source Context"), self.scontext.format()) text += format_2_column_name_value(_("Target Context"), self.tcontext.format()) text += format_2_column_name_value(_("Target Objects"), self.format_target_object()) text += format_2_column_name_value(_("Source"), default_text(self.source)) text += format_2_column_name_value(_("Source Path"), default_text(self.spath)) text += format_2_column_name_value(_("Port"), default_text(self.port)) if (replace): text += format_2_column_name_value(_("Host"), "(removed)") else: text += format_2_column_name_value(_("Host"), default_text(self.sig.host)) text += format_2_column_name_value(_("Source RPM Packages"), default_text(self.format_rpm_list(self.src_rpm_list))) text += format_2_column_name_value(_("Target RPM Packages"), default_text(self.format_rpm_list(self.tgt_rpm_list))) text += format_2_column_name_value(_("SELinux Policy RPM"), default_text(env.policy_rpm)) text += format_2_column_name_value(_("Local Policy RPM"), default_text(env.local_policy_rpm)) text += format_2_column_name_value(_("Selinux Enabled"), default_text(env.selinux_enabled)) text += format_2_column_name_value(_("Policy Type"), default_text(env.policy_type)) text += format_2_column_name_value(_("Enforcing Mode"), default_text(env.enforce)) if replace: text += format_2_column_name_value(_("Host Name"), "(removed)") else: text += format_2_column_name_value(_("Host Name"), default_text(env.hostname)) if replace: uname = env.uname.split() uname[1] = "(removed)" text += format_2_column_name_value(_("Platform"), default_text(" ".join(uname))) else: text += format_2_column_name_value(_("Platform"), default_text(env.uname)) text += format_2_column_name_value(_("Alert Count"), default_text(self.report_count)) date_format = "%Y-%m-%d %H:%M:%S %Z" text += format_2_column_name_value(_("First Seen"), self.first_seen_date.format(date_format)) text += format_2_column_name_value(_("Last Seen"), self.last_seen_date.format(date_format)) text += format_2_column_name_value(_("Local ID"), default_text(self.local_id)) text += '\n' + _("Raw Audit Messages") avcbuf = "" for audit_record in self.audit_event.records: if audit_record.record_type == 'AVC': avcbuf += "\n" + audit_record.to_text() + "\n" else: avcbuf += "\ntype=%s msg=%s: " % (audit_record.record_type, audit_record.event_id) avcbuf += ' '.join(["%s=%s" % (k, audit_record.fields[k]) for k in audit_record.fields_ord]) + "\n" avcbuf += "\nHash: " + self.get_hash_str() try: audit2allow = "/usr/bin/audit2allow" if os.path.exist(audit2allow): newbuf = "\n\naudit2allow" p = Popen([audit2allow], stdin=PIPE, stdout=PIPE) newbuf += p.communicate(avcbuf)[0] if os.path.exists("/var/lib/sepolgen/interface_info"): newbuf += "\naudit2allow -R" p = Popen([audit2allow, "-R"], stdin=PIPE, stdout=PIPE) newbuf += p.communicate(avcbuf)[0] avcbuf += newbuf except: pass text += avcbuf + '\n' return text def untranslated(self, func, *args, **kwargs): r'define.*untranslated\(.*\n' # Call the parameter function with the translations turned off # This function is not thread safe, since it manipulates globals global P_, _ saved_translateP_ = P_ saved_translate_ = _ try: P_ = lambda x, y, z: x if z > 1 else y _ = lambda x: x return func(*args, **kwargs) finally: P_ = saved_translateP_ _ = saved_translate_ def format_text(self, all=False, replace=False): self.update_derived_template_substitutions() text = self.summary() total_priority, plugins = self.get_plugins(all) for p, args in plugins: title = _("\n\n***** Plugin %s (%.4s confidence) suggests ") % (p.analysis_id, ((float(p.priority) / float(total_priority)) * 100 + .5)) text += title for i in range(len(title), 80): text += _("*") text += _("\n") txt = self.substitute(p.get_if_text(self.audit_event.records, args)) text += _("\n") + txt txt = self.substitute(p.get_then_text(self.audit_event.records, args)) text += _("\nThen ") + txt[0].lower() + txt[1:] txt = self.substitute(p.get_do_text(self.audit_event.records, args)) text += _("\nDo\n") + txt[0].lower() + txt[1:] text += _('\n\n') return text class SEFaultUserInfo(XmlSerialize): _xml_info = { 'version': {'XMLForm': 'attribute', 'default': lambda: '1.0'}, 'username': {'XMLForm': 'attribute'}, 'email_alert': {'XMLForm': 'element', 'import_typecast': boolean, 'default': lambda: False}, 'email_address_list': {'XMLForm': 'element', 'list': 'email_address', }, } def __init__(self, username): super(SEFaultUserInfo, self).__init__() self.username = username def add_email_address(self, email_address): if not email_address in self.email_address_list: self.email_address_list.append(email_address) class SEFaultUserSet(XmlSerialize): _xml_info = { 'version': {'XMLForm': 'attribute', 'default': lambda: '1.0'}, 'user_list': {'XMLForm': 'element', 'list': 'user', 'import_typecast': SEFaultUserInfo, }, } def __init__(self): super(SEFaultUserSet, self).__init__() def get_user(self, username): for user in self.user_list: if username == user.username: return user return None def add_user(self, username): if self.get_user(username) is not None: return user = SEFaultUserInfo(username) self.user_list.append(user) return user class SEFaultSignatureSet(XmlSerialize): _xml_info = { 'version': {'XMLForm': 'attribute', 'default': lambda: '%d.%d' % (DATABASE_MAJOR_VERSION, DATABASE_MINOR_VERSION)}, 'users': {'XMLForm': 'element', 'import_typecast': SEFaultUserSet, 'default': lambda: SEFaultUserSet()}, 'signature_list': {'XMLForm': 'element', 'list': 'siginfo', 'import_typecast': SEFaultSignatureInfo, }, } def __init__(self): super(SEFaultSignatureSet, self).__init__() def siginfos(self): for siginfo in self.signature_list: yield siginfo def add_siginfo(self, siginfo): self.signature_list.append(siginfo) return siginfo def remove_siginfo(self, siginfo): self.signature_list.remove(siginfo) def clear(self): self.signature_list = [] def generate_local_id(self): return str(uuid.uuid4()) def lookup_local_id(self, local_id): if local_id is None: return None for siginfo in self.signature_list: if siginfo.local_id == local_id: return siginfo return None def match_signatures(self, pat, criteria='exact', xml_info=SEFaultSignature._xml_info): match_targets = list(xml_info.keys()) exact = False if criteria == 'exact': exact = True elif isinstance(criteria, float): num_match_targets = len(match_targets) score_per_match_target = 1.0 / num_match_targets else: raise ValueError("unknown criteria = %s" % criteria) matches = [] for siginfo in self.signature_list: score = 0.0 sig = siginfo.sig for name in match_targets: if getattr(pat, name) == getattr(sig, name): if exact: score = 1.0 else: score += score_per_match_target else: if exact: score = 0.0 break if exact: if score == 1.0: matches.append(SignatureMatch(siginfo, score)) else: if score >= criteria: matches.append(SignatureMatch(siginfo, score)) matches.sort(key=cmp_to_key(lambda a, b: cmp(b.score, a.score))) return matches class SEDatabaseProperties(XmlSerialize): _xml_info = { 'name': {'XMLForm': 'element'}, 'friendly_name': {'XMLForm': 'element'}, 'filepath': {'XMLForm': 'element'}, } def __init__(self, name=None, friendly_name=None, filepath=None): super(SEDatabaseProperties, self).__init__() if name is not None: self.name = name if friendly_name is not None: self.friendly_name = friendly_name if filepath is not None: self.filepath = filepath class SEEmailRecipient(XmlSerialize): _xml_info = { 'address': {'XMLForm': 'element'}, 'filter_type': {'XMLForm': 'element', 'import_typecast': int, 'default': lambda: FILTER_AFTER_FIRST}, } def __init__(self, address, filter_type=None): super(SEEmailRecipient, self).__init__() self.address = address if filter_type is not None: self.filter_type = filter_type def __str__(self): return "%s:%s" % (self.address, map_filter_value_to_name.get(self.filter_type, 'unknown')) class SEEmailRecipientSet(XmlSerialize): _xml_info = { 'version': {'XMLForm': 'attribute', 'default': lambda: '1'}, 'recipient_list': {'XMLForm': 'element', 'list': 'recipient', 'import_typecast': SEEmailRecipient, }, } def __init__(self, recipient_list=None): super(SEEmailRecipientSet, self).__init__() if recipient_list is not None: self.recipient_list = recipient_list def __str__(self): return ','.join([str(x) for x in self.recipient_list]) def find_address(self, address): address = address.strip() for recipient in self.recipient_list: if address == recipient.address: return recipient return None def add_address(self, address, filter_type=FILTER_AFTER_FIRST): address = address.strip() if not valid_email_address(address): raise ProgramError(ERR_INVALID_EMAIL_ADDR, detail="address='%s'" % address) return recipient = self.find_address(address) if recipient is not None: return self.recipient_list.append(SEEmailRecipient(address, filter_type)) def clear_recipient_list(self): self.recipient_list = [] def parse_recipient_file(self, filepath): import re comment_re = re.compile('#.*') entry_re = re.compile(r'(\S+)(\s+(.+))?') key_value_re = re.compile(r"(\w+)\s*=\s*(\S+)") map_boolean = {'enabled': True, 'true': True, 'yes': True, 'on': True, 'disabled': False, 'false': False, 'no': False, 'off': False, } try: f = open(filepath) except IOError as e: raise ProgramError(ERR_FILE_OPEN, detail="%s, %s" % (filepath, e.strerror)) self.clear_recipient_list() for line in f.readlines(): line = comment_re.sub('', line) line = line.strip() if line: match = entry_re.search(line) if match: address = match.group(1) options = match.group(3) filter_type = None if options: for match in key_value_re.finditer(options): option = match.group(1) value = match.group(2) if option == 'filter_type': filter_type = map_filter_name_to_value.get(value.lower(), None) if filter_type is None: log_debug("unknown email filter (%s) for address %s" % (option, address)) else: log_debug("unknown email option (%s) for address %s" % (option, address)) try: self.add_address(address, filter_type) except ProgramError as e: if e.errno == ERR_INVALID_EMAIL_ADDR: log_debug(e.strerror) else: raise e f.close() def write_recipient_file(self, filepath): try: f = open(filepath, 'w') except IOError as e: raise ProgramError(ERR_FILE_OPEN, detail="%s, %s" % (filepath, e.strerror)) for recipient in self.recipient_list: filter_type = map_filter_value_to_name[recipient.filter_type] f.write("%-40s filter_type=%s\n" % (recipient.address, filter_type)) f.close() #------------------------------------------------------------------------ if __name__ == '__main__': import libxml2 #memory debug specific libxml2.debugMemory(1) xml_file = 'audit_listener_database.xml' sigs = SEFaultSignatureSet() sigs.read_xml_file(xml_file, 'sigs') siginfo = sigs.signature_list[0] record = siginfo.audit_event.records[0] print((record.record_type)) print(("siginfo.audit_event=%s" % siginfo.audit_event)) print(sigs) #memory debug specific libxml2.cleanupParser() if libxml2.debugMemory(1) == 0: print("Memory OK") else: print(("Memory leak %d bytes" % (libxml2.debugMemory(1)))) libxml2.dumpMemory() util.py000064400000076713152572267760006134 0ustar00from __future__ import absolute_import from six.moves import range # Authors: John Dennis # # Copyright (C) 2006,2007,2008 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # __all__ = [ 'audit_msg_decode', 'merge_lists', 'preextend_list', 'fmt_obj', 'format_elapsed_time', 'format_2_column_name_value', 'wrap_text', 'format_msg', 'remove_linebreaks', 'default_text', 'default_date_text', 'get_standard_directories', 'get_rpm_nvr_from_header', 'get_package_nvr_by_name', 'get_package_nvr_by_file_path', 'get_rpm_nvr_by_type', 'get_rpm_nvr_by_scontext', 'get_rpm_source_package', 'is_hex', 'split_rpm_nvr', 'file_types', 'get_user_home_dir', 'get_plugin_names', 'load_plugins', 'get_os_environment', 'find_program', 'get_identity', 'get_hostname', 'make_database_filepath', 'valid_email_address', 'launch_web_browser_on_url', 'abstract', 'log_debug', 'get_error_from_socket_exception', 'assure_file_ownership_permissions', 'parse_datetime_offset', 'DATABASE_MAJOR_VERSION', 'DATABASE_MINOR_VERSION', 'database_version_compatible', 'syslog_trace', 'TimeStamp', 'Retry', 'PACKAGE_MANAGER', ] import bz2 import six import datetime from pydbus import SystemBus import glob from gi.repository import GObject import os import pwd import re import shutil import selinux import subprocess import sys import textwrap import time from types import * import syslog from functools import cmp_to_key from types import FunctionType, MethodType from setroubleshoot.config import get_config from setroubleshoot.errcode import * cmp = lambda x, y: (x > y) - (x < y) def is_type(obj): try: return isinstance(obj, TypeType) except NameError: return isinstance(obj, type) DATABASE_MAJOR_VERSION = 3 DATABASE_MINOR_VERSION = 0 PACKAGE_MANAGER = None if shutil.which('rpm'): PACKAGE_MANAGER = 'rpm' elif shutil.which('dpkg'): PACKAGE_MANAGER = 'deb' redhat_release_path = '/etc/redhat-release' text_wrapper = textwrap.TextWrapper() fix_newline_re = re.compile(r"\s*\n+\s*") hex_re = re.compile('^[A-Fa-f0-9]+$') href_re = re.compile(r'') name_at_domain_re = re.compile(r'^([^\s@]+)@([^\s@]+)$') audit_decode_re = re.compile(r'^\s*"([^"]+)"\s*$') # regexp matching lines containing type definitions, eg. (type lib_t) # contains only 1 group that matches the type name typedef_regexp = re.compile(r"\s*\(\s*type\s+([\w-]+)\s*\)\s*") #Dictionary with all types defined in the module store as keys #and corresponding module paths as values. Used by get_package_nvr_by_name module_type_cache = None log_level = syslog.LOG_WARNING log_levels = { 'CRITICAL': syslog.LOG_CRIT, 'ERROR': syslog.LOG_ERR, 'WARNING': syslog.LOG_WARNING, 'INFO': syslog.LOG_INFO, 'DEBUG': syslog.LOG_DEBUG, } def log_init(section): global log_level log_level = log_levels.get(get_config(section, 'level').upper()) if log_level is None: log_level = syslog.LOG_WARNING def log_debug(msg): global log_level if log_level >= syslog.LOG_DEBUG: syslog.syslog(syslog.LOG_DEBUG, msg) def syslog_trace(trace): log_lines = trace.split('\n') for line in log_lines: if len(line): syslog.syslog(line) def database_version_compatible(version): major = minor = None components = version.split('.') if len(components) >= 1: major = int(components[0]) if len(components) >= 2: minor = int(components[1]) if major < DATABASE_MAJOR_VERSION: log_debug("database version %s not compatible with current %d.%d version" % (version, DATABASE_MAJOR_VERSION, DATABASE_MINOR_VERSION)) return False else: log_debug("database version %s compatible with current %d.%d version" % (version, DATABASE_MAJOR_VERSION, DATABASE_MINOR_VERSION)) return True def format_elapsed_time(elapsed_time): if elapsed_time is None: return None import math fraction, whole = math.modf(elapsed_time) whole = int(whole) days = whole / 86400 whole = whole - days * 86400 hours = whole / 3600 whole = whole - hours * 3600 minutes = whole / 60 seconds = whole - minutes * 60 if days: return "%dd:%dh:%dm:%.3fs" % (days, hours, minutes, seconds + fraction) if hours: return "%dh:%dm:%.3fs" % (hours, minutes, seconds + fraction) if minutes: return "%dm:%.3fs" % (minutes, seconds + fraction) return "%.3fs" % (seconds + fraction) def is_hex(str): if hex_re.match(str): return True else: return False def audit_msg_decode(msg): if msg is None: return None match = audit_decode_re.search(msg) if match: decoded = match.group(1) else: try: if sys.version_info[0] < 3: # Produces normal string instead of unicode string which is not # accepted by libselinux functions. # This means that len(path) will return inaccurate results when # the string contains special characters. Also individual bytes # of path may not be printable. decoded = msg.decode('hex') else: # produces str in python 3 and unicode string in python 2 decoded = bytearray.fromhex(msg).decode('utf-8') except: decoded = msg return decoded def merge_lists(a, b): 'return a list containing the unique members of a+b' if not b: return a if not a: return b d = {} for i in a: d[i] = None for i in b: d[i] = None m = list(d.keys()) return m def preextend_list(requested_length, _list=None, default=None): if _list is None: _list = [] cur_length = len(_list) delta = requested_length - cur_length if delta > 0: if is_type(default): _list.extend([default() for x in range(delta)]) else: _list.extend([default] * delta) return _list def fmt_obj(obj): if isinstance(obj, six.string_types): return obj elif isinstance(obj, (list, tuple)): return "[" + " ".join(["%s" % fmt_obj(x) for x in obj]) + "]" elif isinstance(obj, dict): keys = list(obj.keys()) keys.sort() return "{" + " ".join(["%s=%s" % (fmt_obj(key), fmt_obj(obj[key])) for key in keys]) + "}" else: return str(obj) def format_2_column_name_value(name, value, value_indent=30, page_width=80): if len(name) >= value_indent: initial_indent = name[0:value_indent - 1] + ' ' else: initial_indent = name + ' ' * (value_indent - len(name)) if not value or value.isspace(): return initial_indent + value + '\n' else: text_wrapper.initial_indent = initial_indent text_wrapper.subsequent_indent = ' ' * value_indent text_wrapper.width = page_width return text_wrapper.fill(value) + '\n' def wrap_text(s, width=80, indent=0): prefix = ' ' * indent text_wrapper.initial_indent = prefix text_wrapper.subsequent_indent = prefix text_wrapper.width = width return text_wrapper.fill(s) + '\n' def format_msg(title, msg, indent=4): if msg is None: msg = '' msg = msg.strip() indentString = " " * indent text_wrapper.initial_indent = indentString text_wrapper.subsequent_indent = indentString text_wrapper.width = 80 return title + "\n" + text_wrapper.fill(msg) + "\n\n" def remove_linebreaks(str): new_str = fix_newline_re.sub(" ", str).strip() if new_str is None: return "" else: return new_str def default_text(val): if val is None: val = '<' + _('Unknown') + '>' return str(val) def default_date_text(date): if date is None: return default_text(date) return date.format() def get_standard_directories(): """ >>> get_standard_directories() [...'/bin'...] """ lst = [] try: if PACKAGE_MANAGER == "rpm": lst = subprocess.check_output(["rpm", "-ql", "filesystem"], universal_newlines=True).rstrip().split("\n") if PACKAGE_MANAGER == "deb": lst = subprocess.check_output(["dpkg", "-L", "base-files"], universal_newlines=True).rstrip().split("\n") except: syslog.syslog(syslog.LOG_ERR, "failed to get list from {}".format(PACKAGE_MANAGER)) return lst def get_rpm_nvr_from_header(hdr): 'Given an RPM header return the package NVR as a string' name = hdr['name'] version = hdr['version'] release = hdr['release'] return "%s-%s-%s" % (name, version, release) def get_package_nvr_by_name(name): """ >>> get_package_nvr_by_name("coreutils") 'coreutils-8.30-3+b1:amd64' """ if name is None: return None nvr = None try: if PACKAGE_MANAGER == 'rpm': nvr = subprocess.check_output(["rpm", "-q", name], universal_newlines=True).rstrip() if PACKAGE_MANAGER == 'deb': # dpkg-query -f='${Package}_${Version}:${Architecture}\n' -W nvr = subprocess.check_output( ["dpkg-query", "-f=${Package}-${Version}:${Architecture}", "-W", name], universal_newlines=True ).rstrip() except: syslog.syslog(syslog.LOG_ERR, "failed to retrieve rpm info for %s" % name) return nvr def get_package_nvr_by_file_path(name): """ >>> get_package_nvr_by_file_path("/bin/ls") 'coreutils-8.30-3+b1:amd64' """ if name is None: return None name = os.path.abspath(name) if not os.path.exists(name): return None nvr = None try: if PACKAGE_MANAGER == 'rpm': nvr = subprocess.check_output(["rpm", "-qf", name], universal_newlines=True).rstrip() if PACKAGE_MANAGER == 'deb': # dpkg -S foo |cut -d: -1f # dpkg-query -f='${Package}_${Version}:${Architecture}\n' -W package_name = subprocess.check_output(["dpkg", "-S", name]).decode().split(": ")[0] nvr = subprocess.check_output( ["dpkg-query", "-f=${Package}-${Version}:${Architecture}", "-W", package_name], universal_newlines=True ).rstrip() except: syslog.syslog(syslog.LOG_ERR, "failed to retrieve rpm info for %s" % name) return nvr ### try: from sepolicy import get_all_file_types file_types = get_all_file_types() except: file_types = [] def split_rpm_nvr(nvr): components = nvr.split('-') release = components[-1] version = components[-2] name = '-'.join(components[:-2]) return (name, version, release) def get_rpm_nvr_by_type(selinux_type): """ Finds an SELinux module which defines given SELinux type ##### arguments * `selinux_type(s)`: an SELinux type ##### return values * `nvr(s)`: nvr of rpm which ships module where `selinux_type` is defined ##### usage >>> get_rpm_nvr_by_type("sshd_t") 'selinux-policy-... >>> get_rpm_nvr_by_type("mysqld_log_t") 'mysql-selinux-... """ if module_type_cache is None: build_module_type_cache() if module_type_cache is None: return None path = module_type_cache.get(selinux_type, None) return get_package_nvr_by_file_path(path) # check if given string represents an integer def __str_is_int(str): try: int(str) return True except: return False def build_module_type_cache(): """ Creates a dictionary with all types defined in the module store as keys and corresponding module paths as values. The dictionary is stored in "module_type_cache" to be used by "get_rpm_nvr_by_type" """ retval, policytype = selinux.selinux_getpolicytype() if retval != 0: return module_type_dict = dict() priorities = [] # get list of module priorities, present in the module store, sorted by integer value with os.scandir("/var/lib/selinux/{}/active/modules".format(policytype)) as module_store: priorities = sorted([x.name for x in module_store if x.is_dir() and __str_is_int(x.name)], key = lambda x: int(x)) for dir in priorities: # find individual modules in each priority and identify type definitions for (dirpath, dirnames, filenames) in os.walk("/var/lib/selinux/{}/active/modules/{}".format(policytype,dir)): if "cil" in filenames: try: try: # cil files are bzip2'ed by default f = bz2.open("{}/cil".format(dirpath), mode = 'rt') except: # maybe cil file is not bzip2'ed, try plain text f = open("{}/cil".format(dirpath)) for line in f: result = typedef_regexp.match(line) if result: module_type_dict[result.group(1)] = dirpath f.close() except: # something's wrong, move on # FIXME: log a problem? pass global module_type_cache module_type_cache = module_type_dict def get_rpm_nvr_by_scontext(scontext, use_dbus=False): """ Finds an SELinux module which defines given SELinux context ##### arguments * `scontext(s)`: an SELinux context ##### return values * `nvr(s)`: nvr of rpm which ships module where SELinux type used in `scontext` is defined ##### usage >>> get_rpm_nvr_by_scontext("system_u:system_r:syslogd_t:s0") 'selinux-policy-... >>> get_rpm_nvr_by_scontext("system_u:system_r:mysqld_log_t:s0") 'mysql-selinux-... >>> get_rpm_nvr_by_scontext("system_u:system_r:timedatex_t:s0", use_dbus=True) 'selinux-policy-... """ if use_dbus: bus = SystemBus() remote_object = bus.get("org.fedoraproject.SetroubleshootPrivileged") return str(remote_object.get_rpm_nvr_by_scontext(str(scontext))) else: context = selinux.context_new(str(scontext)) return get_rpm_nvr_by_type(str(selinux.context_type_get(context))) def get_rpm_source_package(name): """ Find a source package for `name` rpm >>> get_rpm_source_package("policycoreutils-python-utils") 'policycoreutils' >>> get_rpm_source_package("selinux-policy-targeted") 'selinux-policy' """ if name is None: return None src = None try: import subprocess src = subprocess.check_output(["rpm", "-q", "--qf", "%{SOURCERPM}", name], universal_newlines=True).rsplit('-',2)[0] except: syslog.syslog(syslog.LOG_ERR, "failed to retrieve rpm info for %s" % name) return src def get_user_home_dir(): uid = os.getuid() try: pw = pwd.getpwuid(uid) except KeyError: return None home_dir = pw.pw_dir return home_dir def valid_email_address(address): match = name_at_domain_re.search(address) if match: return True else: return False def launch_web_browser_on_url(url): web_browser_launcher = get_config('helper_apps', 'web_browser_launcher') os.spawnl(os.P_NOWAIT, web_browser_launcher, web_browser_launcher, url) def get_error_from_socket_exception(e): args = getattr(e, 'args', None) if args: errno = args[0] strerror = args[1] else: errno = ERR_SOCKET_ERROR strerror = get_strerror(errno) return errno, strerror def assure_file_ownership_permissions(filepath, mode, owner, group=None): result = True if not os.path.exists(filepath): try: f = open(filepath, "w") f.close() except Exception as e: result = False syslog.syslog(syslog.LOG_ERR, "cannot create file %s [%s]" % (filepath, e.strerror)) try: os.chmod(filepath, mode) except OSError as e: result = False syslog.syslog(syslog.LOG_ERR, "cannot chmod %s to %o [%s]" % (filepath, mode, e.strerror)) try: if isinstance(owner, int): uid = owner else: uid = pwd.getpwnam(owner)[2] if group is None: group = owner if isinstance(group, int): gid = group else: import grp gid = grp.getgrnam(group)[2] os.chown(filepath, uid, gid) except OSError as e: result = False import grp syslog.syslog(syslog.LOG_ERR, "cannot chown %s to %s:%s [%s]" % (filepath, pwd.getpwuid(uid)[0], grp.getgrgid(gid)[0], e.strerror)) return result def abstract(obj): import inspect method = inspect.getouterframes(inspect.currentframe())[1][3] subclass = obj.__class__.__name__ raise NotImplementedError('%s must be implemented in subclass %s or ancestor class of %s' % (method, subclass, subclass)) #----------------------------------------------------------------------------- def get_plugin_names(filter_glob=None): if filter_glob is None: filter_glob = '*' else: filter_glob = re.sub('.py$', '', filter_glob) plugin_dir = get_config('plugins', 'plugin_dir') plugin_names = [] for p in glob.glob(os.path.join(plugin_dir, filter_glob + ".py")): p = os.path.basename(p) if p in ['__init__.py']: continue plugin_name = os.path.splitext(os.path.basename(p))[0] plugin_names.append(plugin_name) return plugin_names def sort_plugins(x, y): return x.get_priority() - y.get_priority() def load_plugins(filter_glob=None): plugin_dir = get_config('plugins', 'plugin_dir') plugin_base = os.path.basename(plugin_dir) plugins = [] plugin_names = get_plugin_names(filter_glob) log_debug("load_plugins() names=%s" % plugin_names) # load the parent (e.g. the package containing the submodules), required for python 2.5 and above module_name = plugin_base plugin_name = '__init__' if module_name not in sys.modules: try: import imp mod_fp, mod_path, mod_description = imp.find_module(plugin_name, [plugin_dir]) mod = imp.load_module(module_name, mod_fp, mod_path, mod_description) except Exception: syslog.syslog(syslog.LOG_ERR, "failed to initialize plugins in %s" % plugin_dir) return [] if mod_fp: mod_fp.close() for plugin_name in plugin_names: module_name = "%s.%s" % (plugin_base, plugin_name) mod = sys.modules.get(module_name) if mod is not None: log_debug("load_plugins() %s previously imported" % module_name) plugins.append(mod.plugin()) continue try: import imp mod_fp, mod_path, mod_description = imp.find_module(plugin_name, [plugin_dir]) mod = imp.load_module(module_name, mod_fp, mod_path, mod_description) plugins.append(mod.plugin()) except Exception: syslog.syslog(syslog.LOG_ERR, "failed to load %s plugin" % plugin_name) if mod_fp: mod_fp.close() plugins.sort(key=cmp_to_key(sort_plugins)) return plugins def get_os_environment(): try: myplatform = open(redhat_release_path).readlines()[0].strip() except: try: import distro myplatform = ' '.join(distro.linux_distribution()) except: myplatform = "unknown" # uname returns (sysname, nodename, release, version, machine) uname = os.uname() kernel_release = uname[2] cpu = uname[4] os_desc = "%s %s" % (kernel_release, cpu) return (myplatform, os_desc) def get_identity(uid=None): if uid is None: uid = os.getuid() try: pwd_entry = pwd.getpwuid(uid) except KeyError: return None username = pwd_entry[0] return username def get_hostname(): try: import socket as Socket hostname = Socket.gethostname() return hostname except Exception as e: syslog.syslog(syslog.LOG_ERR, "cannot lookup hostname: %s" % e) return None def find_program(prog): if os.path.isabs(prog): return prog basename = os.path.basename(prog) search_path = get_config('fix_command', 'prog_search_path').split(':') for d in search_path: path = os.path.join(d, basename) if os.path.exists(path): return path return None def make_database_filepath(name): database_dir = get_config('database', 'database_dir') # strip off extension if one was provided name = re.sub('\\.xml$', '', name) filename = name + '_database.xml' filepath = os.path.join(database_dir, filename) return filepath def parse_datetime_offset(text): '''The time offset may be specified as a sequence of integer unit pairs. Units may be one of year,month,week,day,hour,minute,second and may optionally be plural. Example: '2 weeks 1 day' sets the threshold at 15 days. ''' # Note, this regexp anything to follow the unit except an integer # thus plural 's', commas, whitespace datetime_offset_re = re.compile(r'(\d+)\s*(year|month|week|day|hour|minute|second)') found = False days = 0 hours = 0 minutes = 0 seconds = 0 text = text.lower() for match in datetime_offset_re.finditer(text): if match: found = True quantity = int(match.group(1)) unit = match.group(2) if unit is not None: if unit == 'year': days += quantity * 365 if unit == 'month': days += quantity * 31 if unit == 'week': days += quantity * 7 if unit == 'day': days += quantity if unit == 'hour': hours += quantity if unit == 'minute': minutes += quantity if unit == 'second': seconds += quantity if found: td = datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) log_debug("parse_datetime_offset(%s) = time delta %s" % (text, td)) return td else: syslog.syslog(syslog.LOG_ERR, "could not parse datetime offset (%s)" % text) return None #------------------------------------------------------------------------------ STDOFFSET = datetime.timedelta(seconds=-time.timezone) if time.daylight: DSTOFFSET = datetime.timedelta(seconds=-time.altzone) else: DSTOFFSET = STDOFFSET DSTDIFF = DSTOFFSET - STDOFFSET ZERO = datetime.timedelta(0) HOUR = datetime.timedelta(hours=1) # A class capturing the platform's idea of local time. class LocalTimezone(datetime.tzinfo): def utcoffset(self, dt): if self._isdst(dt): return DSTOFFSET else: return STDOFFSET def dst(self, dt): if self._isdst(dt): return DSTDIFF else: return ZERO def tzname(self, dt): return time.tzname[self._isdst(dt)] def _isdst(self, dt): tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1) stamp = time.mktime(tt) tt = time.localtime(stamp) return tt.tm_isdst > 0 class UTC(datetime.tzinfo): """UTC""" def utcoffset(self, dt): return datetime.timedelta(0) def tzname(self, dt): return "UTC" def dst(self, dt): return datetime.timedelta(0) class TimeStamp: # class variables utc_tz = UTC() local_tz = LocalTimezone() iso8601_fmt = '%Y-%m-%dT%H:%M:%SZ' locale_fmt = '%c' def __init__(self, t=None): if t is None: self._dt = self.now(local=False) elif isinstance(t, six.string_types): self.parse(t) elif isinstance(t, float): self._dt = datetime.datetime.fromtimestamp(t, self.utc_tz) elif isinstance(t, datetime.datetime): self._dt = t elif isinstance(t, TimeStamp): self._dt = t._dt else: raise TypeError("must be string, float, datetime, or TimeStamp") def __lt__(self, other): if isinstance(other, TimeStamp): return self._dt < other._dt else: return self._dt < other def __add__(self, other): if isinstance(other, TimeStamp): return self._dt + other._dt else: return self._dt + other def __iadd__(self, other): if isinstance(other, TimeStamp): self._dt += other._dt else: self._dt += other return self def __sub__(self, other): if isinstance(other, TimeStamp): return self._dt - other._dt else: return self._dt - other def __isub__(self, other): if isinstance(other, TimeStamp): self._dt -= other._dt else: self._dt -= other return self def now(self, local=False): if local: return datetime.datetime.now(self.local_tz) else: return datetime.datetime.now(self.utc_tz) def local(self): return self._dt.astimezone(self.local_tz) def __str__(self): return self.format(self.iso8601_fmt, local=False) def parse(self, str): (year, month, day, hour, minute, second, weekday, yearday, dst) = \ time.strptime(str, self.iso8601_fmt) self._dt = datetime.datetime(year, month, day, hour, minute, second, 0, self.utc_tz) return self._dt def add(self, days=0, hours=0, minutes=0, seconds=0): self._dt += datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) def in_future(self): now = self.now() if now < self._dt: return True else: return False def in_past(self): now = self.now() if now >= self._dt: return True else: return False def format(self, fmt=None, local=True): if fmt is None: fmt = self.locale_fmt if local: return self.local().strftime(fmt) else: return self._dt.strftime(fmt) #------------------------------------------------------------------------------ class Retry(GObject.GObject): ''' A class which schedules attempts until one succeeds. Intervals are expressed as floating point seconds. The retry attempt will be scheduled in the future based on the retry_interval which may be either a number of seconds or a callable object returning the number of seconds. The callable form of the retry_interval is useful when the interval should be adjusted based on prior history or other external factors, e.g. backing off the frequency of the retry attempts if initial attempts fail. The retry callback should return False if the attempt fails, in which case it will be scheduled again in the future based on the current value obtained from the retry_interval. If the retry callback returns True it indicates the retry attempt succeeded and no more attempts will be made. Retry's are started with the start() method and continues until the retry callback returns True or the stop() method is called. It is always safe to call stop() even if a retry is not pending. The retry callback, user_data and notify_interval may be specified in either the class init() or in the start() method for convenience. If notify_interval is set a 'pending_retry' signal will be emitted every time the notification interval elapses, this provides a countdown till the next retry attempt. The signature of the retry callback is: callback(retry_obj, user_data) The signature of the pending_retry signal handler is: callback(retry_obj, seconds_pending, user_data) The signature of the retry interval function is: interval(retry_obj, user_data) ''' __gsignals__ = { 'pending_retry': # callback(retry_object, seconds_pending, user_data) (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_FLOAT, GObject.TYPE_PYOBJECT,)), } def __init__(self, callback, retry_interval, user_data=None, notify_interval=None): GObject.GObject.__init__(self) self.callback = callback self.retry_interval = retry_interval self.user_data = user_data self.failed_attempts = 0 # how many times retry has been attempted but failed self.notify_interval = notify_interval # how often pending_retry signal is emitted self.trigger_time = None # time in future when retry is attempted self.timeout_id = None # alarm timeout id def stop(self): if self.timeout_id is not None: GLib.source_remove(self.timeout_id) self.timeout_id = None def start(self, retry_interval=None, user_data=None, notify_interval=None): if retry_interval is not None: self.retry_interval = retry_interval if user_data is not None: self.user_data = user_data if notify_interval is not None: self.notify_interval = notify_interval self.stop() self.failed_attempts = 0 self._schedule_alarm(True) def _schedule_alarm(self, new_retry=False): now = time.time() if new_retry: self.trigger_time = now + self._get_retry_interval() seconds_pending = self.trigger_time - now if self.notify_interval: self.emit('pending_retry', seconds_pending, self.user_data) alarm_time = min(self.notify_interval, seconds_pending) else: alarm_time = seconds_pending self.timeout_id = GObject.timeout_add(int(alarm_time * 1000), self._alarm_callback) def _alarm_callback(self): self.timeout_id = None now = time.time() seconds_pending = self.trigger_time - now # If seconds_pending is less than 0 we've gone past the # trigger point so attempt a retry because its overdue. If # seconds_pending is 0 we've exactly hit the trigger point # (not likely). If seconds_pending is positive the trigger # point is in the future, however, due to (minor) scheduling # inaccuracies if seconds_pending is a small positive number # we assume this alarm is triggering the retry attempt even # though it is slightly in the future. if seconds_pending <= 0.005: self._attempt_retry() else: self._schedule_alarm() return False def _attempt_retry(self): if self.callback(self, self.user_data): self.stop() else: self.failed_attempts += 1 self._schedule_alarm(True) def _get_retry_interval(self): if isinstance(interval_type, (MethodType, FunctionType)): return self.retry_interval(self, self.user_data) return self.retry_interval GObject.type_register(Retry) #----------------------------------------------------------------------------- uuid.py000064400000041030152572267760006105 0ustar00r"""UUID objects (universally unique identifiers) according to RFC 4122. This module provides immutable UUID objects (class UUID) and the functions uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 UUIDs as specified in RFC 4122. If all you want is a unique ID, you should probably call uuid1() or uuid4(). Note that uuid1() may compromise privacy since it creates a UUID containing the computer's network address. uuid4() creates a random UUID. Typical usage: >>> import uuid # make a UUID based on the host ID and current time >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') # make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') # make a random UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') # make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') # make a UUID from a string of hex digits (braces and hyphens ignored) >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') # convert a UUID to a string of hex digits in standard form >>> str(x) '00010203-0405-0607-0809-0a0b0c0d0e0f' # get the raw 16 bytes of the UUID >>> x.bytes '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' # make a UUID from a 16-byte string >>> uuid.UUID(bytes=x.bytes) UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') This module works with Python 2.3 or higher.""" __author__ = 'Ka-Ping Yee ' __date__ = '$Date: 2006/08/24 19:08:53 $'.split()[1].replace('/', '-') __version__ = '$Revision: 1.2 $'.split()[1] RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ 'reserved for NCS compatibility', 'specified in RFC 4122', 'reserved for Microsoft compatibility', 'reserved for future definition'] import sys if sys.version_info > (3,): long = int # Python 2 compatibility cmp = lambda x, y: (x > y) - (x < y) class UUID(object): """Instances of the UUID class represent UUIDs as specified in RFC 4122. UUID objects are immutable, hashable, and usable as dictionary keys. Converting a UUID to a string with str() yields something in the form '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts four possible forms: a similar string of hexadecimal digits, or a string of 16 raw bytes as an argument named 'bytes', or a tuple of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 48-bit values respectively) as an argument named 'fields', or a single 128-bit integer as an argument named 'int'. UUIDs have these read-only attributes: bytes the UUID as a 16-byte string fields a tuple of the six integer fields of the UUID, which are also available as six individual attributes and two derived attributes: time_low the first 32 bits of the UUID time_mid the next 16 bits of the UUID time_hi_version the next 16 bits of the UUID clock_seq_hi_variant the next 8 bits of the UUID clock_seq_low the next 8 bits of the UUID node the last 48 bits of the UUID time the 60-bit timestamp clock_seq the 14-bit sequence number hex the UUID as a 32-character hexadecimal string int the UUID as a 128-bit integer urn the UUID as a URN as specified in RFC 4122 variant the UUID variant (one of the constants RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) version the UUID version number (1 through 5, meaningful only when the variant is RFC_4122) """ def __init__(self, hex=None, bytes=None, fields=None, int=None, version=None): r"""Create a UUID from either a string of 32 hexadecimal digits, a string of 16 bytes as the 'bytes' argument, a tuple of six integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as the 'fields' argument, or a single 128-bit integer as the 'int' argument. When a string of hex digits is given, curly braces, hyphens, and a URN prefix are all optional. For example, these expressions all yield the same UUID: UUID('{12345678-1234-5678-1234-567812345678}') UUID('12345678123456781234567812345678') UUID('urn:uuid:12345678-1234-5678-1234-567812345678') UUID(bytes='\x12\x34\x56\x78'*4) UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) UUID(int=0x12345678123456781234567812345678) Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given. The 'version' argument is optional; if given, the resulting UUID will have its variant and version number set according to RFC 4122, overriding bits in the given 'hex', 'bytes', 'fields', or 'int'. """ if [hex, bytes, fields, int].count(None) != 3: raise TypeError('need just one of hex, bytes, fields, or int') if hex is not None: hex = hex.replace('urn:', '').replace('uuid:', '') hex = hex.strip('{}').replace('-', '') if len(hex) != 32: raise ValueError('badly formed hexadecimal UUID string') int = long(hex, 16) if bytes is not None: if len(bytes) != 16: raise ValueError('bytes is not a 16-char string') int = long(('%02x' * 16) % tuple(map(ord, bytes)), 16) if fields is not None: if len(fields) != 6: raise ValueError('fields is not a 6-tuple') (time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node) = fields if not 0 <= time_low < long(1 << 32): raise ValueError('field 1 out of range (need a 32-bit value)') if not 0 <= time_mid < long(1 << 16): raise ValueError('field 2 out of range (need a 16-bit value)') if not 0 <= time_hi_version < long(1 << 16): raise ValueError('field 3 out of range (need a 16-bit value)') if not 0 <= clock_seq_hi_variant < long(1 << 8): raise ValueError('field 4 out of range (need an 8-bit value)') if not 0 <= clock_seq_low < long(1 << 8): raise ValueError('field 5 out of range (need an 8-bit value)') if not 0 <= node < long(1 << 48): raise ValueError('field 6 out of range (need a 48-bit value)') clock_seq = (clock_seq_hi_variant << long(8)) | clock_seq_low int = ((time_low << long(96)) | (time_mid << long(80)) | (time_hi_version << long(64)) | (clock_seq << long(48)) | node) if int is not None: if not 0 <= int < 1 << long(128): raise ValueError('int is out of range (need a 128-bit value)') if version is not None: if not 1 <= version <= 5: raise ValueError('illegal version number') # Set the variant to RFC 4122. int &= ~(0xc000 << long(48)) int |= 0x8000 << long(48) # Set the version number. int &= ~(0xf000 << long(64)) int |= version << long(76) self.__dict__['int'] = int def __lt__(self, other): if isinstance(other, UUID): return self.int < other.int return NotImplemented def __hash__(self): return hash(self.int) def __int__(self): return self.int def __repr__(self): return 'UUID(%r)' % str(self) def __setattr__(self, name, value): raise TypeError('UUID objects are immutable') def __str__(self): hex = '%032x' % self.int return '%s-%s-%s-%s-%s' % ( hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) def get_bytes(self): bytes = '' for shift in range(0, 128, 8): bytes = chr((self.int >> shift) & 0xff) + bytes return bytes bytes = property(get_bytes) def get_fields(self): return (self.time_low, self.time_mid, self.time_hi_version, self.clock_seq_hi_variant, self.clock_seq_low, self.node) fields = property(get_fields) def get_time_low(self): return self.int >> long(96) time_low = property(get_time_low) def get_time_mid(self): return (self.int >> long(80)) & 0xffff time_mid = property(get_time_mid) def get_time_hi_version(self): return (self.int >> long(64)) & 0xffff time_hi_version = property(get_time_hi_version) def get_clock_seq_hi_variant(self): return (self.int >> long(56)) & 0xff clock_seq_hi_variant = property(get_clock_seq_hi_variant) def get_clock_seq_low(self): return (self.int >> long(48)) & 0xff clock_seq_low = property(get_clock_seq_low) def get_time(self): return (((self.time_hi_version & 0x0fff) << long(48)) | (self.time_mid << long(32)) | self.time_low) time = property(get_time) def get_clock_seq(self): return (((self.clock_seq_hi_variant & long(0x3f)) << long(8)) | self.clock_seq_low) clock_seq = property(get_clock_seq) def get_node(self): return self.int & 0xffffffffffff node = property(get_node) def get_hex(self): return '%032x' % self.int hex = property(get_hex) def get_urn(self): return 'urn:uuid:' + str(self) urn = property(get_urn) def get_variant(self): if not self.int & (0x8000 << long(48)): return RESERVED_NCS elif not self.int & (0x4000 << long(48)): return RFC_4122 elif not self.int & (0x2000 << long(48)): return RESERVED_MICROSOFT else: return RESERVED_FUTURE variant = property(get_variant) def get_version(self): # The version bits are only meaningful for RFC 4122 UUIDs. if self.variant == RFC_4122: return int((self.int >> long(76)) & 0xf) version = property(get_version) def _ifconfig_getnode(): """Get the hardware address on Unix by running ifconfig.""" import os for d in ['', '/sbin/', '/usr/sbin']: try: pipe = os.popen(os.path.join(d, 'ifconfig')) except IOError: continue for line in pipe: words = line.lower().split() for i in range(len(words)): if words[i] in ['hwaddr', 'ether']: return int(words[i + 1].replace(':', ''), 16) def _ipconfig_getnode(): """Get the hardware address on Windows by running ipconfig.exe.""" import os import re dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] try: import ctypes buffer = ctypes.create_string_buffer(300) ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300) dirs.insert(0, buffer.value.decode('mbcs')) except: pass for d in dirs: try: pipe = os.popen(os.path.join(d, 'ipconfig') + ' /all') except IOError: continue for line in pipe: value = line.split(':')[-1].strip().lower() if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): return int(value.replace('-', ''), 16) def _netbios_getnode(): """Get the hardware address on Windows using NetBIOS calls. See http://support.microsoft.com/kb/118623 for details.""" import win32wnet import netbios ncb = netbios.NCB() ncb.Command = netbios.NCBENUM ncb.Buffer = adapters = netbios.LANA_ENUM() adapters._pack() if win32wnet.Netbios(ncb) != 0: return adapters._unpack() for i in range(adapters.length): ncb.Reset() ncb.Command = netbios.NCBRESET ncb.Lana_num = ord(adapters.lana[i]) if win32wnet.Netbios(ncb) != 0: continue ncb.Reset() ncb.Command = netbios.NCBASTAT ncb.Lana_num = ord(adapters.lana[i]) ncb.Callname = '*'.ljust(16) ncb.Buffer = status = netbios.ADAPTER_STATUS() if win32wnet.Netbios(ncb) != 0: continue status._unpack() bytes = map(ord, status.adapter_address) return ((bytes[0] << long(40)) + (bytes[1] << long(32)) + (bytes[2] << long(24)) + (bytes[3] << long(16)) + (bytes[4] << long(8)) + bytes[5]) _uuid_generate_random = _uuid_generate_time = _UuidCreate = None def _unixdll_getnode(): """Get the hardware address on Unix using ctypes.""" _uuid_generate_time(_buffer) return UUID(bytes=_buffer.raw).node def _windll_getnode(): """Get the hardware address on Windows using ctypes.""" if _UuidCreate(_buffer) == 0: return UUID(bytes=_buffer.raw).node def _random_getnode(): """Get a random node ID, with eighth bit set as suggested by RFC 4122.""" import random return random.randrange(0, 1 << long(48)) | long(0x010000000000) _node = None def getnode(): """Get the hardware address as a 48-bit integer. The first time this runs, it may launch a separate program, which could be quite slow. If all attempts to obtain the hardware address fail, we choose a random 48-bit number with its eighth bit set to 1 as recommended in RFC 4122.""" global _node if _node is not None: return _node import sys if sys.platform == 'win32': getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] else: getters = [_unixdll_getnode, _ifconfig_getnode] for getter in getters + [_random_getnode]: try: _node = getter() except: continue if _node is not None: return _node def uuid1(node=None, clock_seq=None): """Generate a UUID from a host ID, sequence number, and the current time. If 'node' is not given, getnode() is used to obtain the hardware address. If 'clock_seq' is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen.""" # When the system provides a version-1 UUID generator, use it (but don't # use UuidCreate here because its UUIDs don't conform to RFC 4122). if _uuid_generate_time and node is clock_seq is None: _uuid_generate_time(_buffer) return UUID(bytes=_buffer.raw) import time nanoseconds = int(time.time() * 1e9) # 0x01b21dd213814000 is the number of 100-ns intervals between the # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. timestamp = int(nanoseconds / 100) + long(0x01b21dd213814000) if clock_seq is None: import random clock_seq = random.randrange(1 << long(14)) # instead of stable storage time_low = timestamp & long(0xffffffff) time_mid = (timestamp >> long(32)) & long(0xffff) time_hi_version = (timestamp >> long(48)) & long(0x0fff) clock_seq_low = clock_seq & long(0xff) clock_seq_hi_variant = (clock_seq >> long(8)) & long(0x3f) if node is None: node = getnode() return UUID(fields=(time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node), version=1) def uuid3(namespace, name): """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" import md5 my_hash = md5.md5(namespace.bytes + name).digest() return UUID(bytes=my_hash[:16], version=3) def uuid4(): """Generate a random UUID.""" if _uuid_generate_random: _uuid_generate_random(_buffer) return UUID(bytes=_buffer.raw) # Otherwise, get randomness from urandom or the 'random' module. try: import os return UUID(bytes=os.urandom(16), version=4) except: import random bytes = [chr(random.randrange(256)) for i in range(16)] return UUID(bytes=bytes, version=4) def uuid5(namespace, name): """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" import sha my_hash = sha.sha(namespace.bytes + name).digest() return UUID(bytes=my_hash[:16], version=5) # The following standard UUIDs are for use with uuid3() or uuid5(). NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') xml_serialize.py000064400000037520152572267760010017 0ustar00from __future__ import absolute_import # Authors: John Dennis # # Copyright (C) 2007 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Escaping # xmlEncodeEntitiesReentrant(), encodeEntitiesReentrant() # xmlNewTextChild() # stringDecodeEntities __all__ = [ 'string_to_xmlnode', 'string_to_cdata_xmlnode', 'validate_database_doc', 'boolean', 'xml_attributes', 'xml_attribute_dict', 'xml_child_elements_iter', 'xml_child_elements', 'xml_get_child_element_by_name', 'xml_get_child_elements_by_name', 'xml_child_element_names', 'xml_has_child_elements', 'XmlSerialize', ] import sys from types import * import libxml2 import syslog from setroubleshoot.config import get_config from setroubleshoot.errcode import * from setroubleshoot.util import * from six import add_metaclass, string_types #------------------------------------------------------------------------ i18n_encoding = get_config('general', 'i18n_encoding') #------------------------------------------------------------------------ def validate_database_doc(doc): if doc is None: log_debug("validate_database_doc: doc is empty, validate fails") return False root_node = doc.getRootElement() if root_node is None: log_debug("validate_database_doc: root is empty, validate fails") return False version = root_node.prop('version') if version is None: log_debug("validate_database_doc: version is empty, validate fails") return False else: return database_version_compatible(version) def boolean(value): 'convert value to bool' if isinstance(value, bool): return value elif isinstance(value, string_types): value = value.lower() if value in ('t', 'true', '1'): return True elif value in ('f', 'false', '0'): return False else: raise ValueError("cannot convert (%s) to boolean" % value) elif isinstance(value, int): return bool(value) else: raise ValueError("cannot convert (%s) to boolean" % value) def string_to_xmlnode(doc, value): return libxml2.newText(str(value)) def string_to_cdata_xmlnode(doc, value): return doc.newCDataBlock(value, len(value)) # newChild() content is a string, which will be added as children # addChild() adds xmlNode # newChild(None, name, stringGetNodeList(value)) # newTextChild --> newDocRawNode --> newDocNode;newDocText --> newText --> strdup(content) # newChild --> newDocNode --> newNode;stringGetNodeList(content) # note: this inserts entity nodes if content contains &; # xmlEncodeEntitiesReentrant called from xmlNodeListGetString # xmlEncodeSpecialChars called from xmlNodeListGetRawString #------------------------------------------------------------------------ def xml_attributes(node): prop = node.get_properties() while prop: yield prop.get_name(), prop.get_content() prop = prop.get_next() def xml_attribute_dict(node): props = {} for name, value in xml_attributes(node): props[name] = value return props def xml_child_elements_iter(node): child = node.get_children() while child: if child.get_type() == 'element': yield child child = child.get_next() def xml_get_child_element_by_name(node, name): child = node.get_children() while child: if child.get_type() == 'element': if child.get_name() == name: return child child = child.get_next() return None def xml_get_child_elements_by_name(node, name): elements = [] child = node.get_children() while child: if child.get_type() == 'element': if child.get_name() == name: elements.append(child) child = child.get_next() return elements def xml_child_elements(node): return list(xml_child_elements_iter(node)) def xml_child_element_names(node): return [e.get_name() for e in xml_child_elements_iter(node)] def xml_has_child_elements(node): child = node.get_children() while child: if child.get_type() == 'element': return True child = child.get_next() return False #------------------------------------------------------------------------ class XmlSerializeMetaData(type): def __new__(cls, classname, bases, classdict): #print "new: cls=%s, name=%s bases=%s dict=%s" % (cls, classname, bases, classdict) if classname == 'XmlSerialize': return type.__new__(cls, classname, bases, classdict) normal_init = classdict.get('__init__') xml_init = classdict.get('init_from_xml_node', None) _init_postprocess = classdict.get('_init_postprocess', None) if xml_init is None: for base_cls in bases: #print "searching %s" % base_cls xml_init = base_cls.__dict__.get('init_from_xml_node', None) if xml_init is not None: #print "found in %s" % base_cls break else: pass #print "found in class %s" % classname def wrapped_init(*args, **kwds): if len(args) == 2 and isinstance(args[1], libxml2.xmlNode): xml_init(*args, **kwds) if _init_postprocess is not None: _init_postprocess(args[0]) else: normal_init(*args, **kwds) classdict['__init__'] = wrapped_init return type.__new__(cls, classname, bases, classdict) def __init__(cls, classname, bases, classdict): #print "init: cls=%s, name=%s bases=%s dict=%s" % (cls, classname, bases, classdict) super(XmlSerializeMetaData, cls).__init__(classname, bases, classdict) xml_info = classdict.get('_xml_info') if not xml_info: return if xml_info == 'unstructured': cls._unstructured = True else: cls._unstructured = False cls._elements = [x for x in list(xml_info.keys()) if xml_info[x]['XMLForm'] == 'element'] cls._attributes = [x for x in list(xml_info.keys()) if xml_info[x]['XMLForm'] == 'attribute'] cls._names = cls._elements + cls._attributes cls._elements.sort() cls._attributes.sort() cls._names.sort() @add_metaclass(XmlSerializeMetaData) class XmlSerialize(object): def __init__(self): self._init_defaults() def __str__(self): return self.get_xml_text_doc() def _init_defaults(self): # Initialize each known class variable to avoid KeyError on access if self._xml_info == 'unstructured': return for name in self._names: name_info = self._xml_info[name] default = name_info.get('default', None) if default is not None: setattr(self, name, default()) else: if name_info.get('list'): setattr(self, name, []) else: setattr(self, name, None) def get_elements_and_attributes(self): if self._unstructured: elements = [x for x in list(self.__dict__.keys()) if not x.startswith('_')] attributes = [] else: elements = self._elements attributes = self._attributes return(elements, attributes) def get_xml_doc(self, obj_name=None): doc = libxml2.newDoc("1.0") root = self.get_xml_nodes(doc, obj_name) doc.setRootElement(root) return doc def get_xml_text_doc(self, obj_name=None): doc = text_doc = None try: doc = self.get_xml_doc(obj_name) text_doc = doc.serialize(encoding=i18n_encoding, format=1) finally: if doc is not None: doc.freeDoc() return text_doc def read_xml(self, buf, obj_name=None): doc = None try: try: doc = libxml2.parseDoc(buf.strip()) root_node = doc.getRootElement() self.init_from_xml_node(doc, obj_name) except libxml2.parserError as e: syslog.syslog(syslog.LOG_ERR, "read_xml() libxml2.parserError: %s" % e) return finally: if doc is not None: doc.freeDoc() def read_xml_file(self, xmlfile, obj_name=None, validate_doc=None): doc = None try: try: doc = libxml2.parseFile(xmlfile) if validate_doc: if not validate_doc(doc): return False self.init_from_xml_node(doc, obj_name) except libxml2.parserError as e: syslog.syslog(syslog.LOG_ERR, "read_xml_file() libxml2.parserError: %s" % e) return False except Exception as e: syslog.syslog(syslog.LOG_ERR, "read_xml_file() error: %s" % e) return False finally: if doc is not None: doc.freeDoc() return True def write_xml(self, obj_name=None, f=None): try: need_to_close = False if f is None: f = sys.stdout elif isinstance(f, string_types): f = open(f, "w") need_to_close = True elif isinstance(f, FileType): pass else: raise ValueError("bad file parameter %s" % f) f.write(self.get_xml_text_doc(obj_name)) if need_to_close: f.close() except Exception as e: syslog.syslog(syslog.LOG_ERR, "could not write %s: %s" % (f, e)) def get_xml_nodes(self, doc, obj_name=None): elements, attributes = self.get_elements_and_attributes() if obj_name is None: obj_name = self.__class__.__name__ root = libxml2.newNode(obj_name) for name in attributes: name_info = self._xml_info[name] typecast = name_info.get('export_typecast', str) value = getattr(self, name) if value is not None: root.setProp(name, typecast(value)) for name in elements: try: if self._xml_info == 'unstructured': typecast = string_to_xmlnode list_item_name = None else: name_info = self._xml_info[name] typecast = name_info.get('export_typecast', string_to_xmlnode) list_item_name = name_info.get('list') value = getattr(self, name) if value is None or isinstance(value, list) and len(value) == 0: continue if list_item_name: # Element is list container, iterate over list items element_node = libxml2.newNode(name) root.addChild(element_node) for item in value: if isinstance(item, XmlSerialize): child = item.get_xml_nodes(doc, list_item_name) element_node.addChild(child) else: list_item_node = libxml2.newNode(list_item_name) element_node.addChild(list_item_node) child = typecast(doc, item) list_item_node.addChild(child) else: # Element is scalar if isinstance(value, XmlSerialize): child = value.get_xml_nodes(doc, name) root.addChild(child) else: element_node = libxml2.newNode(name) root.addChild(element_node) child = typecast(doc, value) element_node.addChild(child) except Exception as e: syslog.syslog(syslog.LOG_ERR, "%s.%s value=%s" % (self.__class__.__name__, name, value)) return root def init_from_xml_node(self, xml_node, obj_name=None): elements, attributes = self.get_elements_and_attributes() self._init_defaults() if obj_name is None: root = xml_node else: root = xml_get_child_element_by_name(xml_node, obj_name) if root is None: raise KeyError("xml child element (%s) not found in node %s" % (obj_name, xml_node.get_name())) # Read the attributes in the xml node Cast the attribute value # to a Python type and store coerced value in the Python # object (self) which can then be accessed by "name" for name, value in xml_attributes(root): if name not in attributes: log_debug("unknown attribute (%s) found in xml element (%s)" % (name, root.get_name())) continue name_info = self._xml_info[name] typecast = name_info.get('import_typecast', str) if isinstance(typecast, type) and issubclass(typecast, XmlSerialize): raise ValueError("Illegal use of substructure in attribute (%s)" % name) else: self.__setattr__(name, typecast(value)) for element_node in xml_child_elements_iter(root): name = element_node.get_name() if self._unstructured: # Unstructured data, store the string content of each # element in the Python object (self) which can then # be accessed by "name" value = element_node.getContent() self.__setattr__(name, value) else: # Recursively read the contents of each element. Casting to a # Python types along the recursion path and store the final # Python value in the Python object (self) which can then be # accessed by "name" if name not in elements: log_debug("unknown element (%s) found in xml element (%s)" % (name, root.get_name())) continue name_info = self._xml_info[name] typecast = name_info.get('import_typecast', str) # Does this node have substructure? list_item_name = name_info.get('list') if list_item_name: # Element is a list, recursively iterate over the elements children, e.g. list elements attr = getattr(self, name, []) list_nodes = xml_get_child_elements_by_name(element_node, list_item_name) if isinstance(typecast, type) and issubclass(typecast, XmlSerialize): for list_node in list_nodes: attr.append(typecast(list_node)) else: for list_node in list_nodes: attr.append(typecast(list_node.getContent())) else: if isinstance(typecast, type) and issubclass(typecast, XmlSerialize): self.__setattr__(name, typecast(element_node)) else: value = element_node.getContent() self.__setattr__(name, typecast(value))