o ;s*b\`@sdZdZdZddlZddlZddlZddlZzddlmZWne y-ddl mZYnwzddl m Z Wn e yAe Z Ynwddl mZmZdd lmZdd lmZdd lmZmZmZdd lmZdd lmZddlmZddlmZee Z!GdddeeZ"dS)z Cyril Jaquierz Copyright (c) 2004 Cyril JaquierGPLN)Mapping) OrderedDict) BanManager BanTicket)IPAddr) JailThread) ActionBase CommandAction CallingMap)MyTime) Observers)Utils) getLoggerc@seZdZdZddZeddZd?dd Zd@d d Zd dZ ddZ ddZ ddZ ddZ ddZddZddZddZdAdd Zd!d"ZdBd#d$ZdCd%d&Zd'd(ZGd)d*d*eZd+d,ZdDd.d/ZdCd0d1ZdEd2d3Zd4d5ZdCd6d7ZdFd8d9ZdEd:d;Z dGd=d>Z!dS)HActionsaHandles jail actions. This class handles the actions of the jail. Creation, deletion or to actions must be done through this class. This class is based on the Mapping type, and the `add` method must be used to add new actions. This class also starts and stops the actions, and fetches bans from the jail executing these bans via the actions. Parameters ---------- jail: Jail The jail of which the actions belongs to. Attributes ---------- daemon ident name status active : bool Control the state of the thread. idle : bool Control the idle state of the thread. sleeptime : int The time the thread sleeps for in the loop. cCsLtj|d|jd||_t|_t|_d|_d|_ d|_ |j d|_ dS)Nzf2b/a.)namer r) r __init__r_jailr_actionsr_Actions__banManagerbanEpoch _Actions__lastConsistencyCheckTM banPrecedence unbanMaxCount)selfjailr9/usr/lib/python3/dist-packages/fail2ban/server/actions.pyrQszActions.__init__cCsDt|}t|dstd|t|jts td||jjf|S)NActionz&%s module does not have 'Action' classz0%s module %s does not implement required methods)rload_python_modulehasattr RuntimeError issubclassr!r __name__) pythonModulemodrrr _load_python_module_s   zActions._load_python_moduleNFcCs||jvr'|s td||j|}t|dr't|dr%|||j|<dS|dur2t|j|}n||}|j|j|fi|}||j|<dS)aAdds a new action. Add a new action if not already present, defaulting to standard `CommandAction`, or specified Python module. Parameters ---------- name : str The name of the action. pythonModule : str, optional Path to Python file which must contain `Action` class. Default None, which means `CommandAction` is used. initOpts : dict, optional Options for Python Action, used as keyword arguments for initialisation. Default None. Raises ------ ValueError If action name already exists. RuntimeError If external Python module does not have `Action` class or does not implement necessary methods as per `ActionBase` abstract class. zAction %s already existsreloadclearAllParamsN) r ValueErrorr#r+_reload_actionsr rr)r!)rrr'initOptsr*actioncustomActionModulerrr addls       z Actions.addTcs|rt_dStdrRjD]\}}|jvr*j|jd i|r&|niqtfddjD}t|rKjd|ddj |dt ddSdS) z@ Begin or end of reloading resp. refreshing of all parameters r-c3s&|]\}}|jvr||fVqdSN)r-.0rr/rrr s  z!Actions.reload..FT)dbactionsstopr8Nr) dictr-r#itemsrr*rlen_Actions__flushBan stopActionsdelattr)rbeginrr.delactsrr5r r*s    zActions.reloadcCs(z|j|WStytd|wNzInvalid Action name: %srKeyErrorrrrrr __getitem__s    zActions.__getitem__cCs*z|j|=WdStytd|wrCrDrFrrr __delitem__s   zActions.__delitem__cC t|jSr2)iterrr5rrr __iter__ zActions.__iter__cCrIr2)r=rr5rrr __len__rLzActions.__len__cCdSNFr)rotherrrr __eq__szActions.__eq__cCst|Sr2)idr5rrr __hash__szActions.__hash__cCs(t|}|j|td|dS)Nz banTime: %s)r str2secondsr setBanTimelogSysinfo)rvaluerrr rUs  zActions.setBanTimecC |jSr2)r getBanTimer5rrr rZrLzActions.getBanTimecsD|j|s St|dkr|dvrdSdSfdd|DS)Nrrcsg|] }|vr dndqS)rrrr4iplstrr sz%Actions.getBanned..)r getBanListr=)ridsrr]r getBanneds  zActions.getBannedcCs|jjd|dS)zkReturns the list of banned IP addresses. Returns ------- list The list of banned IP addresses. T)orderedwithTime)rr`)rrdrrr r`szActions.getBanListcs<tt|trfdd|D}nt|f}||S)zBan an IP or list of IPs.c3s|]}t|VqdSr2)rr[unixTimerr r6sz&Actions.addBannedIP..)r time isinstancelistr_Actions__checkBan)rr\ticketsrrer addBannedIPs    zActions.addBannedIPc Cs&|dur ||St|ttfr>g}d}|D]}z |||||7}Wqty3|s1||Yqw|rrhritupleremoveBannedIPr,appendrdatabasedelBanr getTicketByID_Actions__unBanrisSinglefiltercontainsr`rVlogloggingMSG) rr\r7ifexistsmissedcntiticketipaipsmsgrrr rnsB       zActions.removeBannedIPc Cs|dur|j}t|}||D];\}}z|Wn#ty@}ztjd|jj ||t t j kdWYd}~nd}~ww|j|=t d|jj |qdS)z>Stops the actions in reverse sequence (optionally filtered) Nz(Failed to stop jail '%s' action '%s': %sexc_infoz%s: action %s terminated)rrir<reverser9 ExceptionrVerrorrrgetEffectiveLevelrxDEBUGdebug)rr8 revactionsrr/errr r?2s"     zActions.stopActionsc sd}jD]-\}}z|Wqty4}ztjdjj||tt j kdWYd}~qd}~wwj rz{j rVt dtfddddjt d Wq5d}tjjjt}td d |jtfd d|r}||7}|r|jkrj r|d 9}td d|r|jkr|nj|j|r|jkr|njd}Wn"ty}ztjdjj|tt j kdWYd}~nd}~wwj s8jdddS)zMain loop for Threading. This function is the main loop of the thread. It checks the jail queue and executes commands when an IP address is banned. Returns ------- bool True when the thread exits nicely. rz)Failed to start jail '%s' action '%s': %srNzActions: enter idle modecsj pj Sr2)activeidlerr5rr [zActions.run..cSrNrOrrrrr r\szActions: leave idle modez1Actions: wait for pending tickets %s (default %s)csj pjjSr2)rrhasFailTicketsrr5rr rcrrz+Actions: check-unban %s, bancnt %s, max: %sz*[%s] unhandled error in actions thread: %sT)r9)rr<startrrVrrrrrxrrrrrwait_for sleeptimeminr_nextUnbanTimer rgrwrjrr_Actions__checkUnBanr>r?)rr|rr/rbancntwtrr5r runDsX       (  z Actions.runc@seZdZdZidddddddddd d dd d dd ddddddddddddddddddd1ddddddddd d!dd"d#dd$d%dZejd&Zdd'efd(d)Zd*d+Zd,d-Z d2d/d0Z dS)3zActions.ActionInfo)fid raw-ticketr\cCrYr2)_ActionInfo__ticketgetIPr5rrr r| zActions.ActionInfo.familycCs |djSNr\) familyStrr5rrr r}rzip-revcCs|ddS)Nr\)getPTRr5rrr r~zip-hostcCs |dSr)getHostr5rrr r rcCrYr2)rgetIDr5rrr rrfailurescCrYr2)r getAttemptr5rrr rrrgcCrYr2)rgetTimer5rrr rrbantimecCs|Sr2) _getBanTimer5rrr rsbancountcCrYr2)r getBanCountr5rrr rrmatchescCsd|jSN )joinr getMatchesr5rrr rrrestoredcCs|jjrdSdS)Nrr)rrr5rrr rrzF-*NcCs |j|Sr2)rgetData)rtagrrr rr ipmatchescCsd|dS)NrTr_mi4iprr5rrr rs ipjailmatchescCsd|Srrr5rrr rs ipfailurescCs|dSNTrrr5rrr rripjailfailurescCs |Sr2rr5rrr rrrcCrIr2)reprrr5rrr rr)__ticket__jail__mi4ipTcCs$||_||_t|_||_||_dSr2)r_ActionInfo__jailr;storage immutabledata)rr~rrrrrr rs  zActions.ActionInfo.__init__cCs||j|j|j|jSr2) __class__rrrrcopyr5rrr rszActions.ActionInfo.copycCs&|j}|dur|jj}t|Sr2)rrZrr8int)rbtimerrr rs zActions.ActionInfo._getBanTimeFc Cst|dsi|_|j}|rdnd}||vr"||dur||S|jSz*|j}|d}d||<|js5|jWS|rA|jj|d||<n |jj||d||<Wn"tyn}ztjd||j |t t j kd WYd}~nd}~ww||dury||S|jS) aGets bans merged once, a helper for lambda(s), prevents stop of executing action by any exception inside. This function never returns None for ainfo lambdas - always a ticket (merged or single one) and prevents any errors through merging (to guarantee ban actions will be executed). [TODO] move merging to observer - here we could wait for merge and read already merged info from a database Parameters ---------- overalljails : bool switch to get a merged bans : False - (default) bans merged for current jail only True - bans merged for all jails of current ip address Returns ------- BanTicket merged or self ticket only rallrNr\)r\)r\rz+Failed to get %s bans merged, jail '%s': %sr) r#_ActionInfo__mi4iprrrp getBansMergedrrVrrrrxr)r overalljailsmiidxrr\rrrr rs2   zActions.ActionInfo._mi4ipr2F) r& __module__ __qualname__ CM_REPR_ITEMSAI_DICTr __slots__rrrrrrrr ActionInfowsT     rcCs$|s tdt}t||j}|S)Nr)rr rgrrr)rr~aInforrr _getActionInfoszActions._getActionInfodccs>d}||kr|j}|sdS|V|d7}||ksdSdS)zAGenerator to get maximal count failure tickets from fail-manager.rrN)r getFailTicket)rcountr|r~rrr __getFailTicketss zActions.__getFailTicketsc sd}|s ||j}d}|D]*}t|||j}}|}i}|jj|dr|d7}t j durGj sGt j d|j |td|j jj sRdnd||jD]A\} } zj rkt| d d rkWq[|jsr|| |Wq[ty} ztjd |j j| || ttjkd WYd} ~ q[d} ~ wwd _|jr|j_q|ddrtd|j j|q|djr2| } | dkrtjn | dkrtj!ntj"} t#| d|j j|j|jkr| dkr|st$%|j&dkr|j'D]} | (qt$%|_&j|jkr1|s(t)fdd|jD}||j*|d7}q||*7}q|rNt+d||j,|j-|j j|S)aCheck for IP address to ban. If tickets are not specified look in the jail queue for FailTicket. If a ticket is available, it executes the "ban" command and adds a ticket to the BanManager. Returns ------- bool True if an IP address get banned. rN)reasonrbanFoundz [%s] %sBan %srzRestore norestoredF9Failed to execute ban jail '%s' action '%s' info '%r': %srTexpiredz[%s] Ignore %s, expired bantimer~<z[%s] %s already bannedc3s(|]\}}|jjkr||fVqdSr2)rr3bTicketrr r6&s z%Actions.__checkBan..r:z"Banned %s / %s, %s ticket(s) in %r)._Actions__getFailTicketsrrwraprZrrr addBanTicketrMainrr1rrVnoticerrr<getattrrresetbanrrrrxrbannedrgetrWrNOTICEWARNINGrwr rgrvaluesconsistencyCheckr;_Actions__reBanr getBanTotalsize)rrkr| rebanactsr~rr\rrrr/rdiftmllrrr __checkBansz           zActions.__checkBanc Cs|p|j}|}||}|r,td|jj|dt|dkr)dt| dnd| D]B\}}zt d|jj|||j sF| ||Wq0tyr}ztjd|jj|||ttjkd WYd }~dSd }~wwd |_|jr}|j|_dS) zRepeat bans for the ticket. Executes the actions in order to reban the host given in the ticket. Parameters ---------- ticket : Ticket Ticket to reban z[%s] Reban %s%sr\rz , action %rrrz[%s] action %r: reban %sz;Failed to execute reban jail '%s' action '%s' info '%r': %srNT)rrrrVrrrr=rikeysr<rrrrebanrrrrxrrr) rr~r8rwr\rrr/rrrr __reBan3s.  8  zActions.__reBanc Cs|j|sdSd}|jD]O\}}z'|jrt|ddrWq|js$Wq|dur-||}|js4| | |Wqt y^}zt j d|jj|||t tjkdWYd}~qd}~wwdS)NrFrr)r _inBanListrr<rr _prolongablerrrprolongrrVrrrrrxr)rr~rrr/rrrr _prolongBanUs*   zActions._prolongBancCsP|jt|}|D]}||q t|}|r&td||j|j j |S)zKCheck for IP address to unban. Unban IP addresses which are outdated. zUnbanned %s, %s ticket(s) in %r) r unBanListr rgrsr=rVrrrr)rmaxCountr^r~r|rrr __checkUnBanls zActions.__checkUnBanc sd}|durtdj}nd}tj}d}i}|dur"|njD]l\}ztdrHtt r9j rHt dj j |rHWq'Wn@ty} z4tjdj j || ttjkd td td rfd d } | WYd} ~ q'WYd} ~ nd} ~ wwtd||<q'|}|rj jdurtdj jj |D]} j| ||d|d7}qtd|jj j |S)zFlush the ban list. Unban all IP address which are still in the banning list. If actions specified, don't flush list - just execute unban for given actions (reload, obsolete resp. removed actions). TNz Flush ban listFrflushz[%s] Flush ticket(s) with %sz1Failed to flush bans in jail '%s' action '%s': %srz'No flush occurred, do consistency checkrcs$rtddsjddSdS)Nactionrepair_on_unbanz,Invariant check failed. Flush is impossible.FT)r_logSysrrr/rr9rr _beforeRepairs z)Actions.__flushBan.._beforeRepairz Unban tickets each individualyz Flush jail in database)r8rwrz! Unbanned %s, %s ticket(s) in %r)rVrr flushBanListrJrr<r#rhr actionflushrrrrrrrrxrrWrrprqrsr) rr7r8r9rwr^r| unbactionsrrr r~rr r __flushBanzsR              zActions.__flushBanc Cs|dur|j}n|}|}||}|r td|jj|d|D]@\}}ztd|jj|||j s:| | |Wq$t yd} ztj d|jj||| ttjkdWYd} ~ q$d} ~ wwdS)zUnbans host corresponding to the ticket. Executes the actions in order to unban the host given in the ticket. Parameters ---------- ticket : FailTicket Ticket of failures of which to unban Nz [%s] Unban %sr\z[%s] action %r: unban %sz;Failed to execute unban jail '%s' action '%s' info '%r': %sr)rrrrVrrrr<rrrunbanrrrrxr) rr~r8rwrr\rrr/rrrr __unBans*    zActions.__unBanbasiccCsgd}|dus ||vrtd||f|dkr#|j}t|}n|j}d|fd|jfg}|dkr>|d|fg7}|dkr`|j}|d |j|fd |j |fd |j |fg7}|S) zEStatus of current and total ban counts and current banned IP list. )shortrcymruNz9Unsupported extended jail status flavor %r. Supported: %srzCurrently bannedz Total bannedzBanned IP listrzBanned ASN listzBanned Country listzBanned RIR list) rVwarningrr`r=rrgetBanListExtendedCymruInfogeBanListExtendedASNgeBanListExtendedCountrygeBanListExtendedRIR)rflavorsupported_flavorsrr|ret cymru_inforrr statuss*     zActions.status)NNF)Tr)NTFr2)rr)FNF)r)"r&rr__doc__r staticmethodr)r1r*rGrHrKrMrQrSrUrZrbr`rlrnr?rr rrrrjrrrr>rsrrrrr r5s>  .   :3X  T"   6r)# __author__ __copyright__ __license__rxossysrgcollections.abcr ImportError collectionsrr; banmanagerrripdnsr jailthreadr r/r r r mytimer observerrutilsrhelpersrr&rVrrrrr s6