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

org.jwall.audit.server.ModSecurity2AuditStream Maven / Gradle / Ivy

/*
 *  Copyright (C) 2007-2014 Christian Bockermann 
 *
 *  This file is part of the  web-audit  library.
 *
 *  web-audit library 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.
 *
 *  The  web-audit  library 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.audit.server;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import org.jwall.web.audit.AuditEvent;
import org.jwall.web.audit.AuditEventListener;
import org.jwall.web.audit.AuditEventType;
import org.jwall.web.audit.ModSecurity;
import org.jwall.web.audit.io.AbstractAuditEventReader;
import org.jwall.web.audit.io.AuditEventIterator;
import org.jwall.web.audit.io.AuditEventReader;
import org.jwall.web.audit.io.ModSecurity2AuditReader;
import org.jwall.web.audit.io.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 
 * This class implements a parser for audit-logfile for the modsecurity2. It
 * also implements the AuditEventSource interface.
 * 
 * @author Christian Bockermann <[email protected]>
 * 
 */
public class ModSecurity2AuditStream extends AbstractAuditEventReader
	implements AuditEventReader, Runnable
{
    /** A unique logger for this class */
    static Logger log = LoggerFactory.getLogger( ModSecurity2AuditReader.class );
    
    /** A flag indicating whether this reader should poll new events after hitting EOF */
    boolean tail;
    
    String prefix = null;
    String sensor = "";
    AuditEventListener listener;
    
    /**
     * This constructor creates an audit-event-Reader that reads from the
     * given input stream.
     * 
     * @param in The stream to read from.
     * @throws IOException In case the stream cannot be opened or another IO error occurs.
     */
    public ModSecurity2AuditStream( InputStream in, AuditEventListener listener )
    throws IOException
    {
    	this( in, listener, true );
    }

    
    /**
     * This constructor creates an audit-event-Reader that reads from the
     * given input stream.
     * 
     * @param in The stream to read from.
     * @throws IOException In case the stream cannot be opened or another IO error occurs.
     */
    public ModSecurity2AuditStream( InputStream in, AuditEventListener listener, boolean persist )
    throws IOException
    {
        super( in );
        this.listener = listener;
        this.tail = persist;
    }

    
    /**
     * @see org.jwall.web.audit.io.AuditEventReader#readNext()
     */
    public AuditEvent readNext() throws IOException, ParseException, EOFException
    {
        //log.info( "readEvent " + counter );
        
        counter++;
        
        String line = readLine();  // this holds the current line to be worked on
        long offset = (long) getDataRead();
        
        // this array of strings is filled with the appropriate section-strings
        // stringbuffers are needed because the sections are read one line at a time
        StringBuffer[] sections = new StringBuffer[ModSecurity.SECTIONS.length()];  // at maximum 26 sections are possible;
        for(int i = 0; i < sections.length; i++)
            sections[i] = new StringBuffer();
    
        // ptr always points to the stringbuffer which is to be read
        int ptr = 0;
    
        try {
            // 
            // we skip lines until we found an audit-start-line, which has the form "--[0-9a-f]*-A--"
            // if the reader hits EOF => line is null and an exception will be thrown, catched below and null is returned 
            //
            while((! line.matches("--[\\-\\@0-9A-Za-z]*-A--"))){
            	line = readLine();
                bytesRead += line.length() + 1.0d;
            }            
            
            String id = line.replaceFirst("--", "").replaceAll("-A--", "");
            
            //
            // ok, now line points to the beginning-separator-line of the audit event.
            //
            while(!(line.startsWith("--") && line.endsWith("-Z--"))){
                //log.info( "line: {}", line ); // this is the section-beginning-marker
                
                ptr = getSectionIndex(line);
                
                line = readLine();  // now line is the first line of the sections body
                bytesRead += line.length() + 1.0d;
    
                //
                // if ptr is -1 an invalid section-name was found !
                //
                if(ptr >= 0){
                    //
                    // no we read a section, until a new one begins
                    //
                    sections[ptr] = new StringBuffer();
                    do {
                        sections[ptr].append(line+"\n");
                        line = readLine();
                        
                        bytesRead += line.length();
                        //log.info("line: {}", line);
                    } while(!( line.trim().matches("^--.*-[A-Z]--$") ) );
                } else {
                    //
                    // invalid section-name
                    //
                    log.debug( "Line contains invalid section-name: " + line );
                }
            }
    
            //
            // We need to convert the stringBuffer-array into a string-array
            // as the AuditEvent-constructor expects a string-array
            //
            String[] data = new String[ModSecurity.SECTIONS.length()];
            for(int i = 0; i < data.length; i++)
                data[i] = sections[i].toString();
    
            //
            // the A-section is empty - it seems that the EOF has been reached
            //
            if(data[0].equals(""))
                return null;
            
            AuditEvent event = eventFactory.createAuditEvent( id, data, inputFile, offset, (long) bytesRead - offset, AuditEventType.ModSecurity2 );
            event.set( AuditEvent.SENSOR_NAME, sensor );
            return event;
            
        } catch ( EOFException eof ) {
            System.out.println( "End-of-file reached!" );
            eofReached = true;
            throw eof;
        } catch ( Exception e ) {
            e.printStackTrace();
            return null;
        }
    }
    
    
    private String readLine() throws IOException {
    	
    	String line = reader.readLine();
    	if( line == null )
    		throw new EOFException( "End of file reached!");

    	if( prefix == "" )
    		return line;
    	
    	int idx = line.indexOf( ": " );
    	if( idx > 0 ){
    		prefix = ": ";
    		int b = idx;
    		while( b > 0 && line.charAt( b ) != ' ')
    			b--;
    			
    		sensor = line.substring( b, idx );
    		return line.substring( idx + 2 );
    	} else
    		prefix = "";
    	
    	return line;
    }


    @Override
	public void run() {
    	while( true ){
    		try {
    			AuditEvent event = readNext();
    			listener.eventArrived( event );
    		} catch (Exception e) {
    			e.printStackTrace();
    			//System.exit(0);
    			return;
    		}
    	}
	}


	@Override
    public Iterator iterator()
    {
        try {
            return new AuditEventIterator( this );
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy