o ;s*b0@sdZdZdZddlZddlZddlZddlZddlZddlZddl m Z ddl Z ddl m Z mZmZzddlmZWn eyEeZYnwejd krPddlZnddlZe eZd d iZed d ejDZGdddZdS)z2Serg G. Brester (sebres) and Fail2Ban ContributorszYCopyright (c) 2004 Cyril Jaquier, 2011-2012 Yaroslav Halchenko, 2012-2015 Serg G. BresterGPLN)Lock) getLogger _merge_dicts uni_decode) OrderedDictr am"Command not found". Make sure that all commands in %(realCmd)r are in the PATH of fail2ban-server process (grep -a PATH= /proc/`pidof -x fail2ban-server`/environ). You may want to start "fail2ban-server -f" separately, initiate it with "fail2ban-client reload" in another shell session and observe if additional informative error messages appear in the terminals.ccs&|]\}}|dr||fVqdS)SIGN) startswith).0namenumr7/usr/lib/python3/dist-packages/fail2ban/server/utils.py ;src@seZdZdZdZdZdZedZGdddeZ e dd Z e d d Z e dddZ e dddZejdkr@e ddZne ddZe ddZdS)UtilszPUtilities provide diverse static methods like executes OS shell commands, etc. rg?gMbP?dc@sLeZdZdZddZdddZdd Zdd d Zd dZddZ ddZ d S)z Utils.Cachez.A simple cache with a TTL and limit on size cOs$|j|i|t|_t|_dSN) setOptionsr_cacher _Cache__lock)selfargskwargsrrr__init__Ls zUtils.Cache.__init__<cCs||_||_dSr)maxCountmaxTime)rr r!rrrrQs zUtils.Cache.setOptionscCs t|jSr)lenrrrrr__len__Us zUtils.Cache.__len__NcCs6|j|}|r|dtkr|dS|||S)Nr)rgettimeunset)rkdefvvrrrr&Xs  zUtils.Cache.getcCst}|j}|jpt||jkrittur1|r0|jdd\}}|d|kr.t||jkr.n|sn8g}|D]\}}|d|krF| |q7|D] }|j |dqI|rit||jkri||rit||jks\|||j f||<WddS1s}wYdS)NF)lastr%) r'rrr"r rdictpopitemitemsappendpopr!)rr)r+tcacheckcvremlstrrrset`s.  "zUtils.Cache.setcCs:|j|j|dWddS1swYdSr)rrr1)rr)rrrr(|s"zUtils.Cache.unsetcCs6|j|jWddS1swYdSr)rrclearr#rrrr8s "zUtils.Cache.clear)rrr) __name__ __module__ __qualname____doc__rrr$r&r7r(r8rrrrCacheHs   r=cCs>t|tj}|s|tjO}n|tjM}t|tj||Sr)fcntlF_GETFLos O_NONBLOCKF_SETFL)fhandlevalueflagsrrr setFBlockModes   zUtils.setFBlockModecCsld}t|ts |g}t|d}|D]\}}|d||f7}|||d7}q|d|d|d<|S)aGenerates new shell command as array, contains map as variables to arguments statement (varsStat), the command (realCmd) used this variables and the list of the arguments, mapped from varsDict Example: buildShellCmd('echo "V2: $v2, V1: $v1"', {"v1": "val 1", "v2": "val 2", "vUnused": "unused var"}) returns: ['v1=$0 v2=$1 vUnused=$2 echo "V2: $v2, V1: $v1"', 'val 1', 'val 2', 'unused var'] r%z%s=$%s  r) isinstancelistr"r/r0)realCmdvarsDictvarsStatir)r+rrr buildShellCmds    zUtils.buildShellCmdrTFrNc sd}}d} d} |r|rt|nttj|} tfdd} ztjtjtj|| tj d } | durQfdd} t | |tj } | rQ| d} | dur| r^| t jd} td|ftj} t| tjttj } | dus|rt| tjttj| dur } | durt| stj} Wn8ty}z,| r| t jd} d |f}t|s|sd nd ||| fWYd}~SWYd}~nd}~ww| |vrt jnt j}|tkr| r| |t jkr|dnt jd} |s |tkrjrfz| dus| d kr#tjd j }Wnt!yB}z td |WYd}~nd}~ww|durf|d krf|tkrf|"D] }t#|dt$|qXj%rz| dusu| d kr|tj%d j% }Wnt!y}z td|WYd}~nd}~ww|dur|d kr|tkr|"D] }t#|dt$|qjrȈj&j%rшj%&d }| |vrt'd| d}nM| durtdjn?| d ks| dkr| d kr| n| d}tdt()|d|| nt*)| d}td| |r/t+d| |t,|r8|||| fSt-|dkrA|S|| fS)aExecutes a command. Parameters ---------- realCmd : str The command to execute. timeout : int The time out in seconds for the command. shell : bool If shell is True (default), the specified command (may be a string) will be executed through the shell. output : bool If output is True, the function returns tuple (success, stdoutdata, stderrdata, returncode). If False, just indication of success is returned varsDict: dict variables supplied to the command (or to the shell script) Returns ------- bool or (bool, str, str, int) True if the command succeeded and with stdout, stderr, returncode if output was set to True Raises ------ OSError If command fails to be executed. RuntimeError If command execution times out. Ncst|dS)Nz%x -- exec: %s)logSyslog)level)rK realCmdIdrrsz"Utils.executeCmd..)stdoutstderrshellenv preexec_fncs}|dur d|fSdS)NT)poll)retcode)popenrr_popen_wait_endsz)Utils.executeCmd.._popen_wait_endr%z!%x -- timed out after %s seconds.z%s -- failed with %sFrz ... -- failed to read stdout %srGz%x -- stdout: %rz ... -- failed to read stderr %sz%x -- stderr: %rz%x -- returned successfully %iTz%x -- unable to kill PID %iz&%x -- killed with %s (return code: %s)z signal %iz%x -- returned %izHINT on %i: %s).rrOrr@environid subprocessPopenPIPEsetsidr[wait_forDEFAULT_SHORTEST_INTERVALloggingERRORrQerrorgetpgidpidkillpgsignalSIGTERMr'sleepDEFAULT_SLEEP_INTERVALSIGKILL pid_existsOSErrorDEBUGgetEffectiveLevelrVrFreadIOError splitlinesrRrrWclosedebugsignamer&_RETCODE_HINTSinfolocalsr")rKtimeoutrXoutputtout_kill_tree success_codesrLrVrWr\rYlogCmdr^pgide std_levellsuccesssigcodemsgr)r]rKrTr executeCmds           &" "     zUtils.executeCmdcsxd} |}|r |S|r(d}}t|s!t|fdd}n|}|s(tj}|r. |St||tj}t|q)a5Wait until condition expression `cond` is True, up to `timeout` sec Parameters ---------- cond : callable The expression to check condition (should return equivalent to bool True if wait successful). timeout : float or callable The time out for end of wait (in seconds or callable that returns True if timeout occurred). interval : float (optional) Polling start interval for wait cycle in seconds. Returns ------- variable The return value of the last call of `cond`, logical False (or None, 0, etc) if timeout occurred. r%Trcs tkSr)r'rtime0rrrULs z Utils.wait_for..)callabler'rrqminDEFAULT_SLEEP_TIMErp)condrintervaliniretstm timeout_exprrrrrf-s&  zUtils.wait_forposixc CsXddl}|dkr dSz t|dWdSty+}z |j|jkWYd}~Sd}~ww)z6Check whether pid exists in the current process table.rNFT)errnor@killrtEPERM)rlrrrrrrsZszUtils.pid_existscCs<ddl}|jj}d}||d|}|dkr||dSdS)NriTF)ctypeswindllkernel32 OpenProcess CloseHandle)rlrr SYNCHRONIZEprocessrrrrsgs cCsHtjtj|d}tjdkrtj|| }|St ||}|S)Nrr ) r@pathsplitextbasenamesys version_info importlib machinerySourceFileLoader load_moduleimp load_source) pythonModulepythonModuleNamemodrrrload_python_modulets   zUtils.load_python_module)rTFTrPNr)r9r:r;r<rrqDEFAULT_SHORT_INTERVALrgobjectr= staticmethodrFrOrrfr@rrsrrrrrr>s2=     +   r) __author__ __copyright__ __license__r>rhr@rnrbr threadingrr'helpersrrr collectionsr ImportErrorr-rimportlib.machineryrrr9rQr}__dict__r/r|rrrrrs6