a =*fa@sdZdZdZddlZddlZddlZddlZzddlmZWne yZddl mZYn0ddl m Z ddl m Z mZdd lmZdd lmZdd lmZmZmZdd lmZdd lmZddlmZddlmZeeZ GdddeeZ!dS)z Cyril Jaquierz Copyright (c) 2004 Cyril JaquierZGPLN)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/ZdEd0d1ZdFd2d3Zd4d5ZdGd6d7ZdHd8d9ZdId:d;Z dJd=d>Z!dS)KActionsaHandles 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 banManagerbanEpoch _Actions__lastConsistencyCheckTM banPrecedence unbanMaxCount)selfjailr;/usr/lib/python3.9/site-packages/fail2ban/server/actions.pyrNszActions.__init__cCsFt|}t|ds"td|n t|jtsBtd||jjf|S)NActionz&%s module does not have 'Action' classz0%s module %s does not implement required methods)rZload_python_modulehasattr RuntimeError issubclassr r __name__) pythonModulemodrrr_load_python_module\s   zActions._load_python_moduleNFcCs||jvrN|std||j|}t|drNt|drJ|||j|<dS|durdt|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(actionZcustomActionModulerrraddis       z Actions.addTcs|rt_ntdrjD]0\}}|jvr"j|jfi|rJ|niq"tfddjD}t|rjd|ddj |dt ddS) z@ Begin or end of reloading resp. refreshing of all parameters r+c3s$|]\}}|jvr||fVqdSN)r+.0rr-rrr s  z!Actions.reload..FT)dbactionsstopr5N) dictr+r!itemsrr(rlen_Actions__flushBan stopActionsdelattr)rZbeginrr,Zdelactsrr2rr(s     zActions.reloadcCs0z |j|WSty*td|Yn0dSNzInvalid Action name: %srKeyErrorrrrrr __getitem__s  zActions.__getitem__cCs0z |j|=Wnty*td|Yn0dSr>r?rArrr __delitem__s  zActions.__delitem__cCs t|jSr/)iterrr2rrr__iter__szActions.__iter__cCs t|jSr/)r:rr2rrr__len__szActions.__len__cCsdSNFr)rotherrrr__eq__szActions.__eq__cCst|Sr/)idr2rrr__hash__szActions.__hash__cCs(t|}|j|td|dS)Nz banTime: %s)r Z str2secondsr setBanTimelogSysinfo)rvaluerrrrLs  zActions.setBanTimecCs |jSr/)r getBanTimer2rrrrPszActions.getBanTimecsD|j|sSt|dkr2|dvr.dSdSfdd|DS)Nrrcsg|]}|vrdndqS)rrrr1iplstrr z%Actions.getBanned..)r getBanListr:)rZidsrrSr getBanneds   zActions.getBannedcCs|jjd|dS)zkReturns the list of banned IP addresses. Returns ------- list The list of banned IP addresses. T)ZorderedwithTime)rrW)rrYrrrrWszActions.getBanListcs<tt|tr&fdd|D}n t|f}||S)zBan an IP or list of IPs.c3s|]}t|VqdSr/)rrQZunixTimerrr3rVz&Actions.addBannedIP..)r time isinstancelistr_Actions__checkBan)rrRticketsrrZr addBannedIPs   zActions.addBannedIPc Cs2|dur||St|ttfr~g}d}|D]<}z|||||7}Wq,tyf|sb||Yq,0q,|rztd||S|r|jjdur|jj |j||j |}|dur| |nnt|t st |}|jstt|j|j } | r|| ||Sd|} ttj| |r&dSt| dS)aORemoves banned IP calling actions' unban method Remove a banned IP now, rather than waiting for it to expire, even if set to never expire. Parameters ---------- ip : list, str, IPAddr or None The IP address (or multiple IPs as list) to unban or all IPs if None Raises ------ ValueError If `ip` is not banned Nrznot banned: %rz%s is not bannedr)r;r\r]tupleremoveBannedIPr*appendrdatabasedelBanrZ getTicketByID_Actions__unBanrZisSinglefiltercontainsrWrMlogloggingZMSG) rrRr4ZifexistsZmissedcntiticketZipaipsmsgrrrrbs>      zActions.removeBannedIPc Cs|dur|j}tt|D]v\}}z |WnFtyx}z.tjd|jj ||t t j kdWYd}~n d}~00|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)rreversedr]r9r6 ExceptionrMerrorrrgetEffectiveLevelrjDEBUGdebug)rr5rr-errrr</s   zActions.stopActionsc sd}jD]\\}}z |Wqtyh}z.tjdjj||tt j kdWYd}~qd}~00qj rƐzj rt dtfddddjt d Wqld}tjjjt}td d |jtfd d|r}||7}|r|jkrzj rv|d 9}td d|rF|jkrF|nj|j|rn|jkrn|njd}Wqlty}z,tjdjj|tt j kdWYd}~qld}~00qljdddS)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': %srpNzActions: enter idle modecsj pj Sr/)activeidlerr2rrVrVzActions.run..cSsdSrGrrrrrr{WrVzActions: leave idle modez1Actions: wait for pending tickets %s (default %s)csj pjjSr/)ryrZhasFailTicketsrr2rrr{^rVrz+Actions: check-unban %s, bancnt %s, max: %sz*[%s] unhandled error in actions thread: %sT)r6)rr9startrsrMrtrrrurjrvryrzrwrwait_forZ sleeptimeminrZ_nextUnbanTimer r[rir^rr_Actions__checkUnBanr;r<)rrkrr-rxZbancntZwtrr2rrun?sL       ,"  z Actions.runc@seZdZdZddddddddddddd dd dd dd dd dd%dddddddddddddddddddddZejdZddefddZddZd d!Z d&d#d$Z dS)'zActions.ActionInfo)fid raw-ticketcCs |jSr/)_ActionInfo__ticketZgetIPr2rrrr{wrVzActions.ActionInfo.cCs |djSNrR)Z familyStrr2rrrr{xrVcCs|ddS)NrR)ZgetPTRr2rrrr{yrVcCs |dSr)ZgetHostr2rrrr{zrVcCs |jSr/)rgetIDr2rrrr{{rVcCs |jSr/)r getAttemptr2rrrr{|rVcCs |jSr/)rgetTimer2rrrr{}rVcCs|Sr/) _getBanTimer2rrrr{~rVcCs |jSr/)rZ getBanCountr2rrrr{rVcCsd|jSN )joinr getMatchesr2rrrr{rVcCs|jjr dSdS)Nrr)rrestoredr2rrrr{rVNcCs |j|Sr/)rZgetData)rtagrrrr{rVcCsd|dS)NrTr_mi4iprr2rrrr{rVcCsd|Srrr2rrrr{rVcCs|dS)NTrrr2rrrr{rVcCs |Sr/rr2rrrr{rVcCs t|jSr/)reprrr2rrrr{rVcCs|jjjSr/)_ActionInfo__jailr5rsizer2rrrr{rVcCs|jjjSr/)rr5r getBanTotalr2rrrr{rVcCs|jjjSr/)rrg failManagerrr2rrrr{rVcCs|jjjSr/)rrgrZ getFailTotalr2rrrr{rV)rRZfamilyzip-revzip-hostrZfailuresr[ZbantimeZbancountmatchesrzF-*Z ipmatchesZ ipjailmatchesZ ipfailuresZipjailfailuresrz jail.bannedzjail.banned_totalz jail.foundzjail.found_total)Z__ticketZ__jail__mi4ipTcCs$||_||_t|_||_||_dSr/)rrr8Zstorage immutabledata)rrmrrrrrrrs zActions.ActionInfo.__init__cCs||j|j|j|jSr/) __class__rrrrcopyr2rrrrszActions.ActionInfo.copycCs&|j}|dur|jj}t|Sr/)rrPrr5int)rbtimerrrrs zActions.ActionInfo._getBanTimeFc Cst|dsi|_|j}|rdnd}||vrD||dur>||S|jSzT|j}|d}d||<|jsj|jWS|r|jj|d||<n|jj||d||<WnDty}z,tjd||j |t t j kd WYd}~n d}~00||dur||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 rallrNrR)rR)rRrz+Failed to get %s bans merged, jail '%s': %srp) r!Z_ActionInfo__mi4iprrrdZ getBansMergedrsrMrtrrurjrv)rZ overalljailsmiidxrrRrxrrrrs,   zActions.ActionInfo._mi4ip)N)F) r$ __module__ __qualname__Z CM_REPR_ITEMSZAI_DICTr __slots__rrrrrrrr ActionInfors8 rcCs$|stdt}t||j}|S)Nr)rr r[rrr)rrmaInforrr_getActionInfoszActions._getActionInfodccs0d}||kr,|j}|sq,|V|d7}qdS)zAGenerator to get maximal count failure tickets from fail-manager.rrN)rZ getFailTicket)rcountrkrmrrrZ__getFailTicketss zActions.__getFailTicketsc sd}|s||j}d}|D]n}t|||j}}|}i}|jj|drX|d7}t j durj st j d|j |td|j jj sdnd||jD]\} } z2j rt| d d rWq|js|| |Wqty<} z0tjd |j j| || ttjkd WYd} ~ qd} ~ 00qd _|jr|j_q|ddrztd|j j|q|djr~| } | dkrtjn| dkrtj!ntj"} t#| d|j j|j|jkr:| dkr:|s:t$%|j&dkr:t$%|_&|j'D]} t(| dr| )qj|jkr|sjt*fdd|jD}||j+|d7}q||+7}q|rt,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)reasonrZbanFoundz [%s] %sBan %srzRestore norestoredF9Failed to execute ban jail '%s' action '%s' info '%r': %srpTZexpiredz[%s] Ignore %s, expired bantimerm<z[%s] %s already bannedconsistencyCheckc3s&|]\}}|jjkr||fVqdSr/)rr0ZbTicketrrr3's z%Actions.__checkBan..r7z"Banned %s / %s, %s ticket(s) in %r)/_Actions__getFailTicketsrrwraprPrrrZ addBanTicketr ZMainrr.rrMnoticerrr9getattrrresetZbanrsrtrurjrvbannedrgetrNrZNOTICEZWARNINGrir r[rvaluesr!rr8_Actions__reBanrwrr)rr_rkZ rebanactsrmrrRrrrr-rxZdiftmZllrrrZ __checkBanst            zActions.__checkBanc Cs|p|j}|}||}|rTtd|jj|t|dkrNdt| dnd| D]\}}z0t d|jj|||j s| ||Wq\ty}z4tjd|jj|||ttjkdWYd }~dSd }~00q\d |_|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%srz , action %rrrz[%s] action %r: reban %sz;Failed to execute reban jail '%s' action '%s' info '%r': %srpNT)rrrrMrrrr:r]keysr9rwrrZrebanrsrtrurjrvrr) rrmr5rirRrrr-rxrrrZ__reBan4s*  4  zActions.__reBanc Cs|j|sdSd}|jD]\}}zN|jr>t|ddr>Wq|jsHWq|durZ||}|jsh| | |Wqt y}z0t j d|jj|||t tjkdWYd}~qd}~00qdS)NrFrrp)rZ _inBanListrr9rrZ _prolongablerrrZprolongrsrMrtrrrurjrv)rrmrrr-rxrrr _prolongBanVs$   zActions._prolongBancCsP|jt|}|D]}||qt|}|rLtd||j|j j |S)zKCheck for IP address to unban. Unban IP addresses which are outdated. zUnbanned %s, %s ticket(s) in %r) rZ unBanListr r[rfr:rMrwrrr)rZmaxCountrTrmrkrrrZ __checkUnBanms zActions.__checkUnBanc sd}|dur"td|j}nd}t|j}d}i}|durD|n|jD]\}z._beforeRepairz! Unban tickets each individuallyz Flush jail in database)r5rirz! Unbanned %s, %s ticket(s) in %r)rMrwrZ flushBanListrDrr9r!r\r Z actionflushrrrrrsrtrurjrvrNrrdrerfr) rr4r5r6rirTrk unbactionsrrxrrmrrrZ __flushBan{sJ        "    zActions.__flushBanc Cs|dur|j}n|}|}||}|rs*