
    ogft                     L   d Z dZdZddlZddlZddlZddlZddlZddlZddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZmZ  ee      Zd Zej4                  dk\  rd Zd Zn	d Zd Zd Z ej<                  ee        ej@                  de       d Z! G d de"      Z#y)zSteven Hiscocksz"Copyright (c) 2013 Steven HiscocksGPL    Nwraps)RLock   )MyTime)
FailTicket)Utils   )	getLogger
uni_string
PREFER_ENCc                 N    t        | t              rt        |       } t        |       S )z/Avoid errors on types unknown in json-adapters.)
isinstancesetlistr   )xs    :/usr/lib/python3/dist-packages/fail2ban/server/database.py_json_defaultr   *   s    q#
1g!1    )   c                     	 t        j                  | dt              j                  t        d      } | S # t
        $ r:}t        j                  d|t        j                         dk         d} Y d }~| S d }~ww xY w)NFensure_asciidefaultreplacejson dumps failed: %r   exc_info{})	jsondumpsr   encoder   	ExceptionlogSyserrorgetEffectiveLevelr   es     r   _json_dumps_safer+   1   sn    zz!%?FF	1 
(	 
 	<<'V5M5M5OST5T<U1	
(	s   04 	A7/A22A7c                     	 t        j                  | j                  t        d            } | S # t        $ r:}t
        j                  d|t
        j                         dk         i } Y d }~| S d }~ww xY wNr   zjson loads failed: %rr   r   r"   loadsdecoder   r%   r&   r'   r(   r)   s     r   _json_loads_safer1   ;   e    
zz!((:y121
 
(	 
 
	<<'V5M5M5OST5T<U	1	
(	
   )- 	A0/A++A0c                    t        | t              r t        d | j                         D              S t        | t        t        f      r| D cg c]  }t        |       c}S t        | t              r)| j                  t        d      j                  t              S t        | t              r| j                  t        d      S | S c c}w )Nc              3   N   K   | ]  \  }}t        |      t        |      f  y wN)
_normalize).0kvs      r   	<genexpr>z_normalize.<locals>.<genexpr>F   s!     D$!Q
1z!}-Ds   #%r   )
r   dictitemsr   r   r7   strr$   r   r0   )r   elements     r   r7   r7   D   s    4
D!'')D
DD!dC[!./
07:g
00!S
((:y
)
0
0
<<!S
((:y
))	
( 1s   Cc                     	 t        j                  t        |       dt              } | S # t        $ r:}t
        j                  d|t
        j                         dk         d} Y d }~| S d }~ww xY w)NFr   r   r   r   r!   )r"   r#   r7   r   r%   r&   r'   r(   r)   s     r   r+   r+   P   sb    zz*Q-e]K1
 
(	 
 	<<'V5M5M5OST5T<U1	
(	s   %) 	A,/A''A,c                     	 t        j                  | j                  t        d            } | S # t        $ r:}t
        j                  d|t
        j                         dk         i } Y d }~| S d }~ww xY wr-   r.   r)   s     r   r1   r1   Y   r2   r3   JSONc                 .     t                fd       }|S )Nc                 :   | j                   5  | j                  5  | j                  j                         }	  | |g|i ||j                          cd d d        cd d d        S # |j                          w xY w# 1 sw Y   nxY w	 d d d        y # 1 sw Y   y xY wr6   )_lock_dbcursorclose)selfargskwargscurfs       r   wrapperz"commitandrollback.<locals>.wrapperg   s    zz  
((//
CdC)$)&)YY[   	YY[    s9   BA;A&A;	B&A88A;;B	 BBr   )rM   rN   s   ` r   commitandrollbackrO   f   s     (  	r   c                      e Zd ZdZdZdZ ee      Zd'dZd(dZ	d Z
ed        Zd Zed	        Zed
        Zej                   d        Zd(dZed(d       Zd Zed        Zed        Zed        Zed        Zed)d       Zed        Zd*dZed)d       Zed        Zd Zed*d       Zed        Z ed        Z!ed        Z"ed+d       Z#d Z$d+d Z%ed,d!       Z&d,d"Z'	 	 d-d#Z(d$ Z)d% Z*ed&        Z+y).
Fail2BanDba  Fail2Ban database for storing persistent data.

	This allows after Fail2Ban is restarted to reinstated bans and
	to continue monitoring logs from the same point.

	This will either create a new Fail2Ban database, connect to an
	existing, and if applicable upgrade the schema in the process.

	Parameters
	----------
	filename : str
		File name for SQLite3 database, which will be created if
		doesn't already exist.
	purgeAge : int
		Purge age in seconds, used to remove old bans from
		database during purge.

	Raises
	------
	sqlite3.OperationalError
		Error connecting/creating a SQLite3 database.
	RuntimeError
		If exisiting database fails to update to new schema.

	Attributes
	----------
	filename
	purgeage
	r   ))
fail2banDbz7CREATE TABLE IF NOT EXISTS fail2banDb(version INTEGER);)jailszCREATE TABLE IF NOT EXISTS jails(name TEXT NOT NULL UNIQUE, enabled INTEGER NOT NULL DEFAULT 1);CREATE INDEX IF NOT EXISTS jails_name ON jails(name);)logsaS  CREATE TABLE IF NOT EXISTS logs(jail TEXT NOT NULL, path TEXT, firstlinemd5 TEXT, lastfilepos INTEGER DEFAULT 0, FOREIGN KEY(jail) REFERENCES jails(name) ON DELETE CASCADE, UNIQUE(jail, path),UNIQUE(jail, path, firstlinemd5));CREATE INDEX IF NOT EXISTS logs_path ON logs(path);CREATE INDEX IF NOT EXISTS logs_jail_path ON logs(jail, path);)bansa  CREATE TABLE IF NOT EXISTS bans(jail TEXT NOT NULL, ip TEXT, timeofban INTEGER NOT NULL, bantime INTEGER NOT NULL, bancount INTEGER NOT NULL default 1, data JSON, FOREIGN KEY(jail) REFERENCES jails(name) );CREATE INDEX IF NOT EXISTS bans_jail_timeofban_ip ON bans(jail, timeofban);CREATE INDEX IF NOT EXISTS bans_jail_ip ON bans(jail, ip);CREATE INDEX IF NOT EXISTS bans_ip ON bans(ip);)bipsaZ  CREATE TABLE IF NOT EXISTS bips(ip TEXT NOT NULL, jail TEXT NOT NULL, timeofban INTEGER NOT NULL, bantime INTEGER NOT NULL, bancount INTEGER NOT NULL default 1, data JSON, PRIMARY KEY(ip, jail), FOREIGN KEY(jail) REFERENCES jails(name) );CREATE INDEX IF NOT EXISTS bips_timeofban ON bips(timeofban);CREATE INDEX IF NOT EXISTS bips_ip ON bips(ip);c                 z    d| _         t               | _        || _        || _        || _        | j                          y )N
   )
maxMatchesr   rE   _dbFilename	_purgeAge_outDatedFactor
_connectDB)rI   filenamepurgeAgeoutDatedFactors       r   __init__zFail2BanDb.__init__   s3    $/w$*$$.'$//r   c           	      p   | j                   }	 t        j                  |dt        j                        | _        i | _        t        j                  d|       	 dd l}d}| j                  j                         }	 |j                  d       |j                  d       |s|j                  d	       |j                  d
       |j                  d       |j                         d   }|t         j"                  k7  rm| j%                  |      }|t         j"                  k(  rt        j'                  d||       n1t        j                  dt         j"                  ||       t)        d      |rt        j9                  d       | j;                  |d       t        j9                  d       t        j9                  d       |j                  d       |j=                         D ]'  }	t        j9                  ddj?                  |	             ) | j                  jA                          |r$|r|j                  d	       |j5                          y y # t        j                  $ r*}t        j                  d||j                  d           d }~ww xY w# t        $ r d}Y 3w xY w# t        j                  $ r( t        j'                  d| j+                                Y lt        j,                  $ rq}t        j                  d||j                  d          t.        j0                  j3                  |      s |j5                          d }| j7                          Y d }~d }~ww xY w# |rt        j9                  d       | j;                  |d       t        j9                  d       t        j9                  d       |j                  d       |j=                         D ]'  }	t        j9                  ddj?                  |	             ) | j                  jA                          |r$|r|j                  d	       |j5                          w w xY w)NF)check_same_threaddetect_typesz.Connected to fail2ban persistent database '%s'z9Error connecting to fail2ban persistent database '%s': %sr   TzPRAGMA foreign_keys = ONzPRAGMA synchronous = OFFzPRAGMA journal_mode = MEMORYzPRAGMA temp_store = MEMORY&SELECT version FROM fail2banDb LIMIT 1z"Database updated from '%r' to '%r'zIDatabase update failed to achieve version '%r': updated from '%r' to '%r'zFailed to fully updatez"New database created. Version '%r'z3Error opening fail2ban persistent database '%s': %sz#  Create missing tables/indices ...)incrementalz  -> okz  Check integrity ...zPRAGMA integrity_checkz  -> %s )!rZ   sqlite3connectPARSE_DECLTYPESrF   _bansMergedCacher&   infoOperationalErrorr'   rJ   __pypy__ImportErrorrG   executefetchonerQ   __version__updateDbwarningRuntimeErrorcreateDbErrorospathisfilerH   repairDBdebug	_createDbfetchalljoincommit)
rI   checkIntegrityr^   r*   rn   pypyrL   version
newversionss
             r   r]   zFail2BanDb._connectDB   sI   (	oo((*48 4	;;4h@
4 	#3;;)*;;)*
KK./;;+,;;78  \\^A7'''w'JZ+++^^9z \\ $gz3 011
LL67NN3DN)
LL
LL()KK()\\^ *\\)SXXa[)*HHOO	[[/0IIK	 
} 
	!	! 		<<?affQi 			 
 
4 
	!	! 	>>6MMO	 
	<<9affQi ''..
"	99;	3==??
0 
LL67NN3DN)
LL
LL()KK()\\^ *\\)SXXa[)*HHOO	[[/0IIK	 
sj   AI J 8AJ BM I?%I::I?JJ7MM M A&MM MM C!P5c                     t         j                  d       | j                  j                          t         j	                  d       y )Nz Close connection to database ...zConnection to database closed.)r&   r|   rF   rH   rl   rI   s    r   rH   zFail2BanDb.close  s*    ,,12((..++./r   c                     	 | j                   S # t        $ rL | j                  dz   t        j                  dt        j                               z   | _         | j                   cY S w xY w)N.z%Y%m%d-%H%M%S)_Fail2BanDb__dbBackupFilenameAttributeErrorrZ   timestrftimer   gmtimer   s    r   _dbBackupFilenamezFail2BanDb._dbBackupFilename#  s[    "

!
!!	 "!--3dmmOU[UbUbUd6ee4

!
!!"s    AA#"A#c           
          G d dt               }| j                  }d | _        	 t        j                  d| j                         t
        j                  j                  | j                        sKt        j                  | j                  | j                         t        j                  d| j                         nHt
        j                  j                  | j                        rt        j                  | j                         t        j                  d| j                  | j                  f       t        j                  | j                        j                  }|r)t        j                  d|       | j!                  d       nt        j                  d	|        |d
      	 || _        y # t         $ r}t        j#                  d| j                  |j$                  d   t'        ||       xr t        j)                         dk         t        j                  | j                         | j!                  d       Y d }~d }~ww xY w# || _        w xY w)Nc                       e Zd Zy),Fail2BanDb.repairDB.<locals>.RepairExceptionN)__name__
__module____qualname__ r   r   RepairExceptionr   ,  s    r   r   zTrying to repair database %s  Database backup created: %szHf2b_db=$0; f2b_dbbk=$1; sqlite3 "$f2b_dbbk" ".dump" | sqlite3 "$f2b_db" z5  Repair seems to be successful, restored %d byte(s).T)r   z1  Repair seems to be failed, restored %d byte(s).zRecreate ...z/  Error repairing of fail2ban database '%s': %sr   rX   r   )r%   r{   r&   rl   rZ   rx   ry   rz   r   shutilmoveremover
   
executeCmdstatst_sizer]   r'   rJ   r   r(   )rI   r   	_repairDB
dbFileSizer*   s        r   r{   zFail2BanDb.repairDB+  s   	  mm)$-	;;-t/?/?@
''..//
0
KK  $"8"89
KK/1G1GH
t''(IIddd,,. /(()11:
KKGTOO4O(
KKCZP
.
)) ) 4= 
 (	<<AaffQiQ00UV5M5M5OSU5U  X 99T??$?''( 4=s1   E:F' I '	H?0BH:5I :H??I 	Ic                     | j                   S )z&File name of SQLite3 database file.
		)rZ   r   s    r   r^   zFail2BanDb.filenameN  s     
		r   c                     | j                   S )zPurge age in seconds.
		)r[   r   s    r   purgeagezFail2BanDb.purgeageT  s     
r   c                 8    t        j                  |      | _        y r6   )r   str2secondsr[   )rI   values     r   r   zFail2BanDb.purgeageZ  s    %%e,$.r   c                     t         j                  D ]  \  }}|j                  |        |j                  dt         j                  f       |j                  d       |j                         d   S )z8Creates a new database, called during initialisation.
		z\INSERT INTO fail2banDb(version) SELECT ? WHERE NOT EXISTS (SELECT 1 FROM fail2banDb LIMIT 1)re   r   )rQ   _CREATE_SCRIPTSexecutescriptrp   rr   rq   )rI   rL   rf   nr   s        r   r}   zFail2BanDb._createDb^  sk     ** fq!Q ++ C ++67		r   c                 &    | j                  ||      S r6   )r}   )rI   rL   rf   s      r   rv   zFail2BanDb.createDbk  s    	[	))r   c                 ^    |j                  d|f       |j                         }|d uxr |d   S )NzQselect 1 where exists (select 1 from sqlite_master WHERE type='table' AND name=?)r   )rp   rq   )rI   rL   tableress       r   _tableExistszFail2BanDb._tableExistso  s8    ++ @BGK#	D	#SV#r   c                 4   |t         j                  kD  rt        d      	 t        j	                  d| j
                  |       t        j                  j                  | j
                        sJt        j                  | j                  | j
                         t        j	                  d| j
                         |dk  r7| j                  |d      r%|j                  dt         j                  d   z         |dk  r7| j                  |d      r%|j                  d	t         j                  d   z         |d
k  rZ| j                  |d      sH|j                  dt         j                  d   z         | j                  |d      r|j                  d       |j                  d       |j!                         d   S # t"        $ r_}t        j%                  d| j&                  |j(                  d   t        j+                         dk         | j-                          Y d}~yd}~ww xY w)zUpdate an existing database, called during initialisation.

		A timestamped backup is also created prior to attempting the update.
		zIAttempt to travel to future version of database ...how did you get here??z&Upgrade database: %s from version '%r'r   r   rT   zBEGIN TRANSACTION;CREATE TEMPORARY TABLE logs_temp AS SELECT * FROM logs;DROP TABLE logs;%s;INSERT INTO logs SELECT * from logs_temp;DROP TABLE logs_temp;UPDATE fail2banDb SET version = 2;COMMIT;r   rU   zBEGIN TRANSACTION;CREATE TEMPORARY TABLE bans_temp AS SELECT jail, ip, timeofban, -2 as bantime, 1 as bancount, data FROM bans;DROP TABLE bans;%s;
INSERT INTO bans SELECT * from bans_temp;DROP TABLE bans_temp;COMMIT;r   rV   z?BEGIN TRANSACTION;%s;
UPDATE fail2banDb SET version = 4;COMMIT;zINSERT OR REPLACE INTO bips(ip, jail, timeofban, bantime, bancount, data)  SELECT ip, jail, timeofban, bantime, bancount, data FROM bans order by timeofbanre   r   z#Failed to upgrade database '%s': %srX   r   N)rQ   rr   NotImplementedErrorr&   rl   r   rx   ry   rz   r   copyfiler^   r   r   _CREATE_TABSrp   rq   r%   r'   rZ   rJ   r(   r{   )rI   rL   r   r*   s       r   rs   zFail2BanDb.updateDbu  s    z%%%	Q
S S*	;;79O9OQXY
''..//
0
OODMM4#9#9:
KK/1G1GHkd''V4  **623 4 kd''V4  **623 4 k$++C8  **623 4 f%[[\] ;;78
,,.
	 	<<5affQi%%'2-  / ==??s   FF/ /	H8AHHc                     |j                  d|j                  f       |j                  dk  r|j                  d|j                  f       yy)zmAdds a jail to the database.

		Parameters
		----------
		jail : Jail
			Jail to be added to the database.
		z7INSERT OR IGNORE INTO jails(name, enabled) VALUES(?, 1)r   z<UPDATE jails SET enabled = 1 WHERE name = ? AND enabled != 1Nrp   namerowcountrI   rL   jails      r   addJailzFail2BanDb.addJail  sG     ++<II< 	\\Q;;B	YYL r   c                 >    |j                  d|j                  f       y)zvDeletes a jail from the database.

		Parameters
		----------
		jail : Jail
			Jail to be removed from the database.
		z'UPDATE jails SET enabled=0 WHERE name=?N)rp   r   r   s      r   delJailzFail2BanDb.delJail  s     ++,tyym=r   c                 &    |j                  d       y)z'Deletes all jails from the database.
		zUPDATE jails SET enabled=0Nrp   rI   rL   s     r   delAllJailszFail2BanDb.delAllJails  s    
 ++*+r   Nc                     ||j                  d       n|j                  dt        |             t        d |j                         D              S )zGet name of jails in database.

		Currently only used for testing purposes.

		Returns
		-------
		set
			Set of jail names.
		zSELECT name FROM jailsz%SELECT name FROM jails WHERE enabled=c              3   &   K   | ]	  }|d      ywr   Nr   r8   rows     r   r;   z*Fail2BanDb.getJailNames.<locals>.<genexpr>       /SV/   )rp   intr   	fetchmany)rI   rL   enableds      r   getJailNameszFail2BanDb.getJailNames  sE     _;;'(;;\ 	/s}}/	//r   c                     | j                  |||j                         |j                         |j                               S )a7  Adds a log to the database.

		Parameters
		----------
		jail : Jail
			Jail that log is being monitored by.
		container : FileContainer
			File container of the log file being added.

		Returns
		-------
		int
			If log was already present in database, value of last position
			in the log file; else `None`
		)_addLoggetFileNamegetPosgetHashrI   rL   r   	containers       r   addLogzFail2BanDb.addLog  s6    " 
c4!6!6!8):J:J:LiN_N_Na	bbr   c                     d }|j                  d|j                  |f       	 |j                         \  }}|$|s| |j                  d|j                  |||f       |||k7  rd }|S # t        $ r d }Y >w xY w)NzBSELECT firstlinemd5, lastfilepos FROM logs WHERE jail=? AND path=?UINSERT OR REPLACE INTO logs(jail, path, firstlinemd5, lastfilepos) VALUES(?, ?, ?, ?))rp   r   rq   	TypeError)rI   rL   r   r   posmd5lastLinePosfirstLineMD5s           r   r   zFail2BanDb._addLog  s    +++IIt"||~< sco;;!YYc379 	_,;	 
 <s   A& &A43A4c                     d}g }| |dz  }|j                  |j                         |j                  ||       t        d |j	                         D              S )zGets all the log paths from the database.

		Currently only for testing purposes.

		Parameters
		----------
		jail : Jail
			If specified, will only reutrn logs belonging to the jail.

		Returns
		-------
		set
			Set of log paths.
		zSELECT path FROM logsz WHERE jail=?c              3   &   K   | ]	  }|d      ywr   r   r   s     r   r;   z)Fail2BanDb.getLogPaths.<locals>.<genexpr>  r   r   )appendr   rp   r   r   )rI   rL   r   query	queryArgss        r   getLogPathszFail2BanDb.getLogPaths  sU      "%)	O5DII++eY	/s}}/	//r   c                     | j                  |||j                         |j                         |j                                y)zUpdates hash and last position in log file.

		Parameters
		----------
		jail : Jail
			Jail of which the log file belongs to.
		container : FileContainer
			File container of the log file being updated.
		N)
_updateLogr   r   r   r   s       r   	updateLogzFail2BanDb.updateLog  s3     //#tY224i6F6F6H)J[J[J]^r   c                     |j                  d|||j                  |f       |j                  s!|j                  d|j                  |||f       y y )NzEUPDATE logs SET firstlinemd5=?, lastfilepos=? WHERE jail=? AND path=?r   r   )rI   rL   r   r   r   r   s         r   r   zFail2BanDb._updateLog,  sR    ++ #S$))T:< 
;;!YYc379 
r   c                 ,    | j                  |||||      S )aA  Get journal position from database.

		Parameters
		----------
		jail : Jail
			Jail of which the journal belongs to.
		name, time, iso :
			Journal name (typically systemd-journal) and last known time.

		Returns
		-------
		int (or float)
			Last position (as time) if it was already present in database; else `None`
		)r   rI   rL   r   r   r   isos         r   getJournalPoszFail2BanDb.getJournalPos6  s      
c4tS	11r   c                 .    | j                  |||||       y)zUpdates last position (as time) of journal.

		Parameters
		----------
		jail : Jail
			Jail of which the journal belongs to.
		name, time, iso :
			Journal name (typically systemd-journal) and last known time.
		N)r   r   s         r   updateJournalzFail2BanDb.updateJournalH  s     //#tT4-r   c                    t        |j                               }	 | j                  ||f= 	 | j                  |df= |j	                         }|j                  d      }| j                  r>|rQt        |      | j                  kD  r9|j                         }|| j                   d |d<   n|r|j                         }|d= |j                  d|j                  |t        t        |j                                     |j                  |j                  j                               |j!                         |f       |j                  d||j                  t        t        |j                                     |j                  |j                  j                               |j!                         |f       y# t        $ r Y w xY w# t        $ r Y w xY w)zAdd a ban to the database.

		Parameters
		----------
		jail : Jail
			Jail in which the ban has occurred.
		ticket : BanTicket
			Ticket of the ban to be added.
		NmatcheszWINSERT INTO bans(jail, ip, timeofban, bantime, bancount, data) VALUES(?, ?, ?, ?, ?, ?)zbINSERT OR REPLACE INTO bips(ip, jail, timeofban, bantime, bancount, data) VALUES(?, ?, ?, ?, ?, ?))r>   getIDrk   KeyErrorgetDatagetrY   lencopyrp   r   r   roundgetTime
getBanTimeactionsgetBanCount)rI   rL   r   ticketipdatar   s          r   addBanzFail2BanDb.addBanU  s    6<<>"b$Z(b$Z( 
	$HHY'	__#g,099;Dt./0DO
))+4I++\IIr3uV^^-./1B1B4<<CZCZC\1]_e_q_q_s
 ++g		3uV^^-./1B1B4<<CZCZC\1]_e_q_q_s
) 
  
 s"   F) F9 )	F65F69	GGc                 .   d}d}|j                   g}t        |      s%|j                  ||       |j                  ||       y|dz  }|dz  }|j                  d       |D ]4  }t	        |      |d<   |j                  ||       |j                  ||       6 y)zDelete a single or multiple tickets from the database.

		Parameters
		----------
		jail : Jail
			Jail in which the ticket(s) should be removed.
		args : list of IP
			IPs to be removed, if not given all tickets of jail will be removed.
		zDELETE FROM bips WHERE jail = ?zDELETE FROM bans WHERE jail = ?Nz AND ip = ? r   )r   r   rp   r   r>   )rI   rL   r   rJ   query1query2r   r   s           r   delBanzFail2BanDb.delBan|  s     -&,&yyk)	T;;vy!;;vy!	M&M&2 #bb'9Q<;;vy!;;vy!#r   c                 4   d}g }| |dz  }|j                  |j                         |0|dk\  r+|dz  }|j                  t        j                         |z
         ||dz  }|j                  t	        |             |dz  }t        |j                  ||            S )Nz,SELECT ip, timeofban, data FROM bans WHERE 1 AND jail=?r    AND timeofban > ?	 AND ip=?z ORDER BY ip, timeofban desc)r   r   r   r   r>   r   rp   )rI   rL   r   bantimer   r   r   s          r   _getBanszFail2BanDb._getBans  s    
8%)	M5DIIW\  5FKKMG+,^K5CG))% 
ckk%+	,,r   c                     g } | j                   di |D ]5  \  }}}|j                  t        ||             |d   j                  |       7 |S )a  Get bans from the database.

		Parameters
		----------
		jail : Jail
			Jail that the ban belongs to. Default `None`; all jails.
		bantime : int
			Ban time in seconds, such that bans returned would still be
			valid now.  Negative values are equivalent to `None`.
			Default `None`; no limit.
		ip : str
			IP Address to filter bans by. Default `None`; all IPs.

		Returns
		-------
		list
			List of `Ticket`s for bans stored in database.
		r   )r  r   r	   setData)rI   rK   ticketsr   	timeofbanr   s         r   getBanszFail2BanDb.getBans  sY    & '*T]]4V4 b)T
>>*R+,
2;t 
.r   c                    | j                   5  d}||dk  r*||f}|| j                  v r| j                  |   cddd       S g }d}t        | j                  |||            }|r|d   d   }g }	d}
i }|D ]  \  }}}||k7  r7t	        ||	      }|j                  |
       |j                  |       |}g }	d}
i }|j                  dg       }| j                  t        |	      z
  }|dkD  rt        |      |k  r||	z   }	n	|| d |	z   }	|
|j                  dd      z  }
|
|d<   |	|d<   |j                  |       |} t	        |      }|j                  |       |r||n|| j                  |<   ||n|cddd       S # 1 sw Y   yxY w)a}  Get bans from the database, merged into single ticket.

		This is the same as `getBans`, but bans merged into single
		ticket.

		Parameters
		----------
		jail : Jail
			Jail that the ban belongs to. Default `None`; all jails.
		bantime : int
			Ban time in seconds, such that bans returned would still be
			valid now. Negative values are equivalent to `None`.
			Default `None`; no limit.
		ip : str
			IP Address to filter bans by. Default `None`; all IPs.

		Returns
		-------
		list or Ticket
			Single ticket representing bans stored in database per IP
			in a list. When `ip` argument passed, a single `Ticket` is
			returned.
		Nr   )r   r   r  r   failuresr   r   )rE   rk   r   r  r	   
setAttemptr   r   rY   r   update)rI   r   r   r  cacheKeyr
  r   results
prev_banipr   r  tickdatabanipr  r   prev_timeofbanmmaxadds                     r   getBansMergedzFail2BanDb.getBansMerged  s   0 zz -,8o1DzH4(((!!(+-, -, 76$--2D'-BC7AJGHH")  y$*ng>f!nnVjghh	)R	 QooG,V
	Q6	WwF78w&w*a((X T*T)___T^/ 0 ~H=FNN613gD(#Z'V[-, -, -,s   *E:D/E::Fc                 P   t        |      }|sd}nd}|dz  }|g}|s"| |dz  }|j                  |j                         |+|dz  }|j                  t        j                         |z
         ||dz  }|j                  |       |s||dz  }t        |j                  ||            S )Nz-SELECT bancount, timeofban, bantime FROM bipsz<SELECT sum(bancount), max(timeofban), sum(bantime) FROM bipsz WHERE ip = ?r  r  z, GROUP BY ip ORDER BY timeofban DESC LIMIT 1)r>   r   r   r   r   r   rp   )	rI   rL   r   r   
forbantimeoveralljailsfromtimer   r   s	            r   getBanzFail2BanDb.getBan
  s    
2w"	:5I5?%d)	$*M5DII  5FKKMJ./  5HT\::5	ckk%+	,,r   c                    g }|d}|j                  |j                         nd}||dz  }|j                  |       |dz  }|j                  |       |dvr|dz  }|j                  ||z
         ||dz  }n|dz  }|j                  ||      S )	NzDSELECT ip, timeofban, bantime, bancount, data FROM bips WHERE jail=?zDSELECT ip, max(timeofban), bantime, bancount, data FROM bips WHERE 1r  z/ AND (timeofban + bantime > ? OR bantime <= -1))Nr  r  z( GROUP BY ip ORDER BY ip, timeofban DESCz  ORDER BY timeofban DESC LIMIT 1)r   r   rp   )rI   rL   r   r   r  r  r   r   s           r   _getCurrentBanszFail2BanDb._getCurrentBans!  s    )	Q5DIIQ5^K5B<<%8z!  5Hz)*Z665..5	UI	&&r   c                 :   | j                   j                         }	 |t        j                         }g }d}	|du r||j	                         nd}|dk(  rd}| j
                  5  | j                  |||||      }
ddd       
D ]4  }		 |	\  }}}}}||dk(  rt        d|      |dk(  r#||j                  j                         n|r|nd}n|r|d	k\  r|dk(  s||kD  r|}|dk7  r%||z   |k  rt        j                  d
|||z   ||	       t        |||      }	|| j                  }|r6|	j                         }|r5t        |      |kD  r'|	j!                  || d        n|	j!                  d       |	j#                  |       |	j%                  |       ||	c |j'                          S |j)                  |	       7 	 |j'                          |S # 1 sw Y   WxY w# t        $ r"}t        j                  d|	|       Y d}~~d}~ww xY w# |j'                          w xY w)a  Reads tickets (with merged info) currently affected from ban from the database.
		
		There are all the tickets corresponding parameters jail/ip, forbantime,
		fromtime (normally now).
		
		If correctBanTime specified (default True) it will fix the restored ban-time 
		(and therefore endOfBan) of the ticket (normally it is ban-time of jail as maximum)
		for all tickets with ban-time greater (or persistent).
		NTr  )r   r   r  r  r   zunexpected value iX  r   zFignore ticket (with new max ban-time %r): too old %r <= %r, ticket: %rz$get current bans: ignore row %r - %sr  )rF   rG   r   r   getMaxBanTimerE   r!  
ValueErrorr   r   r&   r|   r	   rY   
getMatchesr   
setMatches
setBanTimesetBanCountrH   r   )rI   r   r   r  r  correctBanTime
maxmatchesrL   r
  r   rU   r  r  r  bancountr   r*   r   s                     r   getCurrentBanszFail2BanDb.getCurrentBans6  s5    	#7{{}H76-1-=T'')4Nd^

 $2X   D  'v17.UIw$"7882-1-='')'~S 
^q0	B'N2w2)g-9ll[	G#Xv7
 yt4F//Z  "WCL:--.t
g
x 	~f} 99; NN6O'R 99;	._ 2  \\8&!D( 99;sV   AH !G8H BGBH &H GH 	H#H :H  HH Hc                 &    |j                  d       y)z8Remove empty jails jails and log files from database.
		zDELETE FROM jails WHERE enabled = 0 AND NOT EXISTS(SELECT * FROM bans WHERE jail = jails.name) AND NOT EXISTS(SELECT * FROM bips WHERE jail = jails.name)Nr   r   s     r   _cleanjailszFail2BanDb._cleanjails~  s     ++ABr   c           	          |j                  dt        t        j                               | j                  z
  | j
                  t        t        j                               | j                  z
  f       y)zPurge old bad ips (jails and log files from database).
		Currently it is timed out IP, whose time since last ban is several times out-dated (outDatedFactor is default 3).
		Permanent banned ips will be never removed.
		zZDELETE FROM bips WHERE timeofban < ? and bantime != -1 and (timeofban + (bantime * ?)) < ?N)rp   r   r   r   r[   r\   r   s     r   _purge_bipszFail2BanDb._purge_bips  sO    
 ++_')=)=s6;;=?QTXTbTb?bcer   c                     i | _         |j                  dt        j                         | j                  z
  f       | j                  |       | j                  |       y)z5Purge old bans, jails and log files from database.
		z$DELETE FROM bans WHERE timeofban < ?N)rk   rp   r   r   r[   r1  r/  r   s     r   purgezFail2BanDb.purge  sN     $++)
KKMDNN"%' 33r   )iQ r   )Fr6   r   )NNN)NNNN)NNNNTN),r   r   r   __doc__rr   r   r<   r   ra   r]   rH   propertyr   r{   r^   r   setterr}   rO   rv   r   rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r!  r-  r/  r1  r3  r   r   r   rQ   rQ   s   s   : .^ _%Ob0
 " "!F  
  
 //- - + +$ 2 2h    
= 
= , , 0 0" c c$& 0 0. 
_ 
_9 3 3" 
/ 
/ $ $L # #2 - -$4E,N - -,'* IM"&FPBe  r   rQ   )$
__author____copyright____license__r"   rx   r   rh   sysr   	functoolsr   	threadingr   mytimer   r   r	   utilsr
   helpersr   r   r   r   r&   r   version_infor+   r1   r7   register_adapterr<   register_converterrO   objectrQ   r   r   r   <module>rD     s   ( 
4  	   
       7 7 
8	 t
   / 0   6#3 4
e er   