o _E@sdZdZdZddlZddlmZddlmZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZdd lmZdd lmZdd lmZeeZGd d d eZGdddZeZdS)zSerg G. Brester (sebres)z"Copyright (c) 2014 Serg G. BresterGPLN) JailThread)FailManagerEmpty) getLogger)MyTime)UtilscsNeZdZdZejdZfddZddZddZd d Z d d Z d dZ ddZ ddZ ddZddZddZddZddZddZdd Zd!d"ZdGd$d%Zfd&d'ZdHd*d+Zed,d-ZdGd.d/ZdGd0d1Zed2d3Zejd4d3Zed5d6Zd7d8Z d9d:Z!d;d<Z"Gd=d>d>Z#d?d@Z$dAdBZ%dCdDZ&dEdFZ'Z(S)IObserverThreada8Handles observing a database, managing bad ips and ban increment. Parameters ---------- 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. csZtt|jddd|_t|_g|_t|_ d|_ i|_ d|_ d|_ d|_d|_dS)Nz f2b/observer)nameT<Fi)superr __init__idle threadingRLock _queue_lock_queueEvent_notify sleeptime_timers_paused_ObserverThread__db"_ObserverThread__db_purge_intervaldaemonself __class__:/usr/lib/python3/dist-packages/fail2ban/server/observer.pyr?s   zObserverThread.__init__cCs(z|j|WStytd|w)NzInvalid event index : %srKeyErrorrir!r!r" __getitem__Ts    zObserverThread.__getitem__cCs*z|j|=WdStytd|w)NzInvalid event index: %sr#r%r!r!r" __delitem__Zs   zObserverThread.__delitem__cC t|jSN)iterrrr!r!r"__iter__` zObserverThread.__iter__cCr)r*)lenrrr!r!r"__len__cr-zObserverThread.__len__cCdS)NFr!)rotherr!r!r"__eq__fszObserverThread.__eq__cCst|Sr*)idrr!r!r"__hash__iszObserverThread.__hash__cGsD|j|d}|dur|t||j|}||j|<|dS)zAdd a named timer event to queue will start (and wake) in 'starttime' seconds Previous timer event with same name will be canceled and trigger self into queue after new 'starttime' value N)rgetcancelrTimeraddstart)rr starttimeeventtr!r!r"add_named_timerls   zObserverThread.add_named_timercGs^tjdur!|r!ttj|jt|t||f}|dSt||j |}|dS)zJAdd a timer event to queue will start (and wake) in 'starttime' seconds N) rmyTimerr7r DEFAULT_SLEEP_INTERVAL _delayedEventtimer9r8)rr:r;r<r!r!r" add_timerys  zObserverThread.add_timercCsRt|ks t|kr|jdg|RdSttj|j|||f}|dS)Nr) rrArBrr7r r?r@r9)r endMyTimeendTimer;r<r!r!r"r@s  zObserverThread._delayedEventcCs$|js|j}|r|dSdSdS)z1Notify wakeup (sets /and resets/ notify event) N)rrset)rnr!r!r" pulse_notifys  zObserverThread.pulse_notifycGs>|j|j|Wdn1swY|dS)z5Add a event to queue and notify thread to wake up. N)rrappendrGrr;r!r!r"r8s zObserverThread.addcGs8|j|j|WddS1swYdS)z=Add a event to queue withouth notifying thread to wake up. N)rrrHrIr!r!r"add_wns"zObserverThread.add_wncGs ||dSr*r!)rlargsr!r!r" call_lambdas zObserverThread.call_lambdac Cstd|d|jd|j|j|j|j|j|j |j ddddd }z| d|j rd |_ |jszDd }|jt|jrE|jd }Wd n1sOwY|d urZWn;|d }t|d sn||pmt||}||d d Wnty}ztjd |ddWYd }~nd }~ww|jr3|j}|rd|_ ||j||jrq*n ttj|j sn|j s-tdt|jd |_Wnty}ztjd|ddWYd }~nd }~ww|j g|_Wd n1swYd|_ dS)zMain loop for Threading. This function is the main loop of the thread. Returns ------- bool True when the thread exits nicely. zObserver start...DB_PURGEdb_purgecSr0Nr!r!r!r!r!r"z$ObserverThread.run..cSr0rPr!r!r!r!r"rQrR) calldb_setrOis_alive is_activer9stopnopshutdownrUFNrr%sTexc_infoz&Observer stopped, %s events remaining.z Observer stopped after error: %s)!logSysinfor=rrMrTrOisAliveisActiver9rWr8activerrrr.rpopcallabler5getattr ExceptionerrorrwaitrclearrAsleepr r?is_full)r_ObserverThread__methevmetherFr!r!r"runsr       $ zObserverThread.runcCr0)NTr!rr!r!r"r_szObserverThread.isAliveNcC|jSr*)ra)rfromStrr!r!r"r`szObserverThread.isActivecsP|j|jstt|WddSWddS1s!wYdSr*)rrarr r9rrr!r"r9s "zObserverThread.startTcCs|jrS|jrStd||j|d|j}|jd|_Wdn1s*wY||s6|rD|d|_d|_ d|_ n||_| t |doR|j SdS)Nz-Observer stop ... try to end queue %s secondsrYFTg?)rarr]r^rrJrE wait_emptyrhrr wait_idleminrj)rwtime forceQuitrFr!r!r"rW s    zObserverThread.stopcCs<|jt|jr dndWdS1swYdS)NTF)rr.rrr!r!r"rj#s$zObserverThread.is_fullcCsttj|durt|}|jdur$|d|jr$|jr$| |jr;|dur2t|kr2n ttj|js'| d|j S)zWWait observer is running and returns if observer has no more events (queue is empty) NrXgMbP?) rArir r?rrrJrjrrGrtrrrnr!r!r"rs(s       zObserverThread.wait_emptycCsdttj|jr dS|durt|}|js/|dur&t|kr& |jSttj|jr|jS)zJWait observer is running and returns if observer idle (observer sleeps) TN)rArir r?rrrxr!r!r"rt<s   zObserverThread.wait_idlecCrpr*)rrr!r!r"pausedJszObserverThread.pausedcCs |j|krdS||_|dSr*)rrG)rpauser!r!r"ryNs  cCr0)z/Status of observer to be implemented. [TODO] )r{r!rr!r!r"statusWszObserverThread.statuscCs ||_dSr*)r)rdbr!r!r"rTar-zObserverThread.db_setcCs2td|jdur|j|d|jddS)NzPurge database event occurredrNrO)r]debugrpurger=rrr!r!r"rOds   zObserverThread.db_purgec Cs|r |ds dS|}|}td|j|d}d}d}z|} |j} | durh| ||D]\}}} t || }d|dkrF|nd>dd}t || }|durh||krhtd|j|||WdS|dkroWdSt d |j|t||||| krd nd |||dd }|||| krz ||}||qty|tYWdSwWdSty} ztjd | ttjkdWYd} ~ dSd} ~ ww)z} Notify observer a failure for ip was found Observer will check ip was known (bad) and possibly increase an retry count incrementNz[%s] Observer: failure found %srrrz8[%s] Ignore failure %s before last ban %s < %s, restoredz%[%s] Found %s, bad - %s, %s # -> %s%sz, Banr{TrZr[)r_getBanTimeExtragetIPgetTimer]r~r getMaxRetrydatabasegetBanmax getBanCountrur^rtime2str addFailure setBanCounttoBan putFailTicketrcleanuprArerfgetEffectiveLevelloggingDEBUG) r failManagerjailticketipunixTimebanCount retryCount timeOfBanmaxRetryr} lastBanTimernr!r!r" failureFoundosX         (zObserverThread.failureFoundc@eZdZddZdS)zObserverThread.BanTimeIncrcCs||_||_dSr*)TimeCount)rbanTimerr!r!r"rs z#ObserverThread.BanTimeIncr.__init__N__name__ __module__ __qualname__rr!r!r!r" BanTimeIncr rcCs|}|d|||S)N evformula)rr)rrrrber!r!r" calcBanTimeszObserverThread.calcBanTimec CsX|r|js |S|}|}|}zx|dkr|ddr|jj|||dddD]]\}}} ||kr=||dt d||||dkrS|d| ||}| || |kr|t d |j||t|tjt|d tjt|d fnd |_W|SW|SW|SW|Sty} ztjd | ttjkd WYd} ~ |Sd} ~ ww)ztCheck for IP address to increment ban time (if was already banned). Returns ------- float new ban time. rrF overalljails)rrz"IP %s was already banned: %s #, %srz/[%s] IP %s is bad: %s # last %s - incr %s to %ssecondsTrZr[N)r_rrrr5rrrr]r~r setBanTimerr^r rrdatetime timedeltaintrestoredrerfrrr) rrrrrr orgBanTimerrrrnr!r!r" incrBanTimesD     $zObserverThread.incrBanTimec Cs|jrdSz|}|}td|j|||dkr3|dur3||||}|dks.||kr3|||dkr\||}t j t |dt |f}|t kr[td|dWdSnd}||krtjd |j||g|Rtd d |j|||f|td td ||d |j|||jdur|js|j||WdSWdSWdSty}ztjd|ttjkdWYd}~dSd}~ww) Notify observer a ban occured for ip Observer will check ip was known (bad) and possibly increase/prolong a ban time Secondary we will actualize the bans and bips (bad ip) in database Nz[%s] Observer: ban found %s, %srzIgnore old bantime %srF) permanentinfinitez$[%s] Increase Ban %s (%d # %s -> %s)rrz[%s] Observer: prolong %s in %sr rrZr[)rrr]r~r getBanTimerrrrrrrrrAnoticerlogrBrur prolongBanraddBanrerfrrr) rrrbtimeoldbtimerbendtimelogtimernr!r!r"banFoundsF    & (zObserverThread.banFoundc Csvz|}|}td|j|||j|WdSty:}ztjd|t t j kdWYd}~dSd}~ww)rz[%s] Observer: prolong %s, %srZr[N) rrr]r~r actions _prolongBanrerfrrr)rrrrrrnr!r!r"rs(zObserverThread.prolongBanr*)rrT))rrr__doc__r r?rr'r(r,r/r2r4r=rBr@rGr8rJrMror_r`r9rWpropertyrjrsrtrysetterr|rTrOrrrrrr __classcell__r!r!rr"r (sP     P           8)+r c@r) _ObserverscCs d|_dSr*)Mainrr!r!r"rr-z_Observers.__init__Nrr!r!r!r"rrr) __author__ __copyright__ __license__r jailthreadr failmanagerrosrrArmathjsonrandomsyshelpersrmytimerutilsr rr]r r Observersr!r!r!r"s$  8   o