org.jwall.apache.modsecurity.MSCollectionStore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apache-config Show documentation
Show all versions of apache-config Show documentation
A Java library for reading Apache httpd configuration files
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