All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jwall.apache.modsecurity.MSCollectionStore Maven / Gradle / Ivy

The newest version!
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *   Copyright (C) 2010-2014 Christian Bockermann 
 *    
 *   This file is part of the jwall.org apache-config library. The apache-config library is
 *   a parsing library to handle Apache HTTPD configuration files.
 *
 *   More information and documentation for the jwall-tools can be found at
 *   
 *                      http://www.jwall.org/apache-config
 *   
 *   This program is free software; you can redistribute it and/or modify it under
 *   the terms of the GNU General Public License as published by the Free Software
 *   Foundation; either version 3 of the License, or (at your option) any later version.
 *   
 *   This program is distributed in the hope that it will be useful, but WITHOUT ANY
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *   FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 *   You should have received a copy of the GNU General Public License along with this 
 *   program; if not, see .
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package org.jwall.apache.modsecurity;

import java.io.File;
import java.io.FilenameFilter;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Logger;

import org.solinger.sdbm.Sdbm;


/**
 * 

* This class implements a collection store, i.e. a set of collections which have a name and a special * key. These collections can be accessed from within ModSecurity and are usually stored on disk using * a simple SDBM database file. *

*

* This implementation is a wrapper for reading collections saved by ModSecurity. *

*

* Currently, this store implementation does not provide the possibility to write modified * collections to disk as this might interfere with the ModSecurity implementation. *

* * @author Christian Bockermann <[email protected]> * */ public class MSCollectionStore implements FilenameFilter { static Logger log = Logger.getLogger( "MSCollectionStore" ); /* The directory where the collections are read from (.dir, .pag files for SDBM) */ File dataDir; /* A map of strings to sets collections, e.g. IP -> {...}, SESSION -> {...}, TX -> {...} */ Map> collections = new HashMap>(); /* */ Map databases = new HashMap(); /* A map containing the time stamp of the last update of a set of collections */ Map lastRead = new HashMap(); Long lastModified = 0L; /** * Create a new instance of a MSCollectionStore. The store will immediately * check for data files and parse all existing collections. * * @param secDataDir The directory, specified by the SecDataDir directive. * @throws Exception In case the given file is not a directory or cannot be read. */ public MSCollectionStore( File secDataDir ) throws Exception { dataDir = secDataDir; if( ! dataDir.isDirectory() ) throw new Exception( "Data directory \"" + dataDir.getAbsolutePath() + "\" is not a directory!" ); long start = System.currentTimeMillis(); reload(); long end = System.currentTimeMillis(); log.finest( "Collection loading took " + ( end - start ) + " ms." ); } /** * This method will reload all collections if their files have changed or they have not * been loaded before. */ public void reload() throws Exception { for( File f : dataDir.listFiles( this ) ){ String colName = f.getName().replaceAll( "\\.dir$", "" ); log.finest( "Reading \"" + colName + "\" collections from " + f.getAbsolutePath() ); if( needReload( f ) ){ log.fine( "File \"" + f.getAbsolutePath() + "\" changed, reloading collections..." ); long start = System.currentTimeMillis(); reload( f ); long end = System.currentTimeMillis(); log.finest( "Parsing collection-file took " + ( end - start ) + " ms." ); } } } public boolean storeChanged( long since ){ for( Long lastUpdate : this.lastRead.values() ) if( lastUpdate > since ) return true; return false; } /* * * Reload the collections from the specified file. The file does determine the name of * the collection. * */ private void reload( File dirFile ) throws Exception { log.finest( "Reloading collections from " + dirFile.getAbsolutePath() ); String name = dirFile.getName().replaceAll( "\\.dir$" , "" ); HashMap cols = new HashMap(); Sdbm db = null; //this.databases.get( name ); if( db == null ){ db = new Sdbm( dataDir, name, "r" ); databases.put( name , db ); } Enumeration en = db.keys(); while( en.hasMoreElements() ){ String key = (String) en.nextElement(); try { long start = System.currentTimeMillis(); MSCollection col = MSCollection.unpack( db.get( key ).getBytes() ); long end = System.currentTimeMillis(); col.name = name.trim(); key = key.trim(); log.finest( "Unpacking a small collection took " + (end-start) + " ms "); log.finest( "storing collection " + name + " with key \"" + key + "\"" ); cols.put( key, col ); } catch (Exception e) { e.printStackTrace(); } } // close the database so we don't end up with thousands of open-files... // db.close(); // update the lastRead time for this collection // lastRead.put( name, System.currentTimeMillis() ); // // store the collections in the global index // collections.put( name, cols ); } public boolean needReload( File dirFile ){ if( ! dirFile.exists() ) return false; Long lastUpdate = lastRead.get( dirFile.getName().replaceAll( "\\.dir$", "" ) ); return lastUpdate == null || lastUpdate < dirFile.lastModified(); } public boolean accept(File dir, String name) { return name.endsWith( ".dir" ); } public MSCollection getCollection( String name, String key ){ Map colMap = this.collections.get( name ); if( colMap == null ) return null; MSCollection c = colMap.get( key ); return c; } /** * Returns the names of all collections known to this store. * * @return A list of collection names. */ public Set getCollectionNames(){ return collections.keySet(); } /** * Returns the set of keys known for a specific set of collections, * referred to by name. * * @param name The name of the collection from which to return the keys. * @return The set of keys for this collection, or null if * this collection does not exit (i.e. expired, or not yet initialized). */ public Set getCollectionKeys( String name ){ if( collections.containsKey( name ) ) return collections.get( name ).keySet(); return null; } public String toString( boolean all, boolean verbose ){ StringBuffer s = new StringBuffer(); TreeSet cols = new TreeSet( new Sorter() ); for( String name : getCollectionNames() ){ for( String key : getCollectionKeys( name ) ){ MSCollection col = getCollection( name, key ); if( !col.isExpired() || all ){ cols.add( col ); } } } for( MSCollection col : cols ){ s.append( "Collection " + col.name + ", last read @ " + new Date( this.lastRead.get( col.name ) )+ " \n" ); s.append( col.toString( verbose ) + "\n" ); } return s.toString(); } class Sorter implements Comparator { public int compare( MSCollection col1, MSCollection col2 ){ int nc = col1.name.compareTo( col2.name ); if( nc == 0 ) return col1.expires.compareTo( col2.expires ); else return nc; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy