Package org.jwall.web.audit

Source Code of org.jwall.web.audit.ModSecurityAuditEvent

/*
*  Copyright (C) 2007-2014 Christian Bockermann <chris@jwall.org>
*
*  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 <http://www.gnu.org/licenses/>.
*
*/
package org.jwall.web.audit;

import java.io.File;
import java.io.Serializable;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.jwall.audit.EventType;
import org.jwall.web.audit.io.AuditEventParser;
import org.jwall.web.audit.io.MessageParser;
import org.jwall.web.audit.io.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*
* This class defines an audit-event of <a target="_blank"
* href="http://www.modsecurity.org">modsecurity</a>.
*
* Currently this class stores the audit-event data as an internal string and
* has a few hash tables to hold specific properties/fields/parameters of the
* parsed request. However this will hopefully be turned into an interface to
* achieve independence of the actual implementations of an AuditEvent.
*
* @author Christian Bockermann &lt;chris@jwall.org&gt;
*/
public class ModSecurityAuditEvent implements Comparable<AuditEvent>,
    Serializable, AuditEvent {
  /** id for serialization */
  private static final long serialVersionUID = 7828115034635641145L;

  private static Logger log = LoggerFactory
      .getLogger(ModSecurityAuditEvent.class);

  /** a count of all events alive */
  protected static Long evtCount = Long.valueOf(0L);

  /** the format in which the date is printed out */
  public final static SimpleDateFormat fmt = new SimpleDateFormat(
      "d/MMM/y:HH:mm:ss Z", Locale.ENGLISH);

  /** the date, this event has been created */
  private Date createdAt;

  /** a unique event_id */
  protected String eventId = "";

  /** this holds the real data */
  private String[] sections;

  Map<String, List<String>> collections = null;

  /** a sessionId, to be externally set by a session-tracker */
  String sessionId;

  private URL url = null;

  private File file = null;

  private long offset = -1L;

  private long size = -1L;

  final AuditEventType type;

  AuditEventMessage[] messages = null;

  protected ModSecurityAuditEvent(AuditEventType type) {
    this.type = type;
    collections = new LinkedHashMap<String, List<String>>();
  }

  /**
   * This clone-constructor creates a copy of the given audit-event.
   *
   * @param evt
   *            The event to clone.
   */
  public ModSecurityAuditEvent(ModSecurityAuditEvent evt) throws Exception {
    this(evt.sections, evt.type);
  }

  public String[] getSections() {
    return sections;
  }

  public EventType getType() {
    return EventType.AUDIT;
  }

  /**
   * This creates an instance of this class by parsing all fields from the
   * given string-array.
   *
   * @param data
   *            An array containing all audit-sections.
   * @throws Exception
   *             in case parsing failed.
   */
  public ModSecurityAuditEvent(String[] data, AuditEventType type)
      throws ParseException {
    this(type);
    sections = data.clone();

    if (data.length < 1 || data[0] == null || "".equals(data[0]))
      throw new ParseException("No audit-header found !");

    try {
      log.debug("Parsing request-header...");
      AuditEventParser.parseHttpHeader(collections,
          sections[ModSecurity.SECTION_REQUEST_HEADER]);

      log.debug("Parsing response header...");
      AuditEventParser.parseHttpHeader(collections,
          sections[ModSecurity.SECTION_FINAL_RESPONSE_HEADER]);

      log.debug("Parsing audit-log trailer...");
      AuditEventParser.parseAuditTrailer(collections,
          sections[ModSecurity.SECTION_AUDIT_TRAILER]);

    } catch (ParseException e) {
      if (data != null && data.length > 0)
        log.debug("AuditHeader of event to be parsed: '" + data[0]
            + "'");
      else
        log.debug("ScriptEvent doesn't even contain an audit-header!");

      if (log.isDebugEnabled()) {
        StringBuffer b = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
          if (data[i] != null && !"".equals(data[i])) {
            String d = data[i];
            b.append("--SECTION-" + ModSecurity.SECTIONS.charAt(i)
                + "--\r\n");
            b.append(d);
          }
        }
        b.append("--SECTION-Z--\r\n");
        b.append("\r\n-------------------------------\r\n");
        log.debug(b.toString());
      }
    }

    parseSections(sections);

    if (collections.get(ModSecurity.QUERY_STRING) != null) {
      log.debug("Parsing parameters from query string: "
          + collections.get(ModSecurity.QUERY_STRING).get(0));
      AuditEventParser.parseParameters(collections,
          ModSecurity.QUERY_STRING,
          collections.get(ModSecurity.QUERY_STRING).get(0));
    }

    if (data.length >= ModSecurity.SECTION_FORM_DATA
        && data[ModSecurity.SECTION_FORM_DATA] != null) {
      log.debug("Parsing parameters from section-form-data...");
      AuditEventParser.parseParameters(collections,
          ModSecurity.REQUEST_BODY,
          data[ModSecurity.SECTION_REQUEST_BODY]);
    }

    if (data.length >= ModSecurity.SECTION_AUDIT_TRAILER
        && data[ModSecurity.SECTION_AUDIT_TRAILER] != null)
      AuditEventParser.parseAuditTrailer(collections,
          sections[ModSecurity.SECTION_AUDIT_TRAILER]);

    size = 0;
    for (String sec : sections) {
      this.size += sec.length();
    }

    sessionId = "";
    synchronized (evtCount) {
      evtCount++;
    }
  }

  /**
   *
   * @param id
   * @param data
   * @param f
   * @param off
   * @param size
   * @param type
   * @throws ParseException
   */
  public ModSecurityAuditEvent(String id, String[] data, File f, long off,
      long size, AuditEventType type) throws ParseException {
    this(data, type);
    eventId = id;
    file = f;
    offset = off;
    this.size = size;

    AuditEventParser.setValue(collections, ModSecurity.EVENT_ID, id);
  }

  /**
   * This constructor is used, when reading audit-events from a file. This way
   * you can make sure, that the id of the audit-event is the same as the one
   * in the file.
   *
   * @param id
   *            The id that the new event should contain.
   * @param data
   *            The section-data.
   * @throws Exception
   *             In case anything goes wrong (Parsing, etc...)
   */
  public ModSecurityAuditEvent(String id, String[] data, AuditEventType type)
      throws Exception {
    this(data, type);
    eventId = id;
  }

  public Long getTimestamp() {
    if (createdAt == null)
      createdAt = new Date(System.currentTimeMillis());
    return createdAt.getTime();
  }

  protected void parseSections(String[] sections) throws ParseException {
    createdAt = AuditEventParser
        .parseDate(sections[ModSecurity.SECTION_AUDIT_LOG_HEADER]);

    //
    // extract remote-addr, remote-port, server-addr, server-port from
    // AuditLog-Header
    // 0 1 2 3 4 5 6
    // s[] = [date, TZ], ID, Client-IP, Client-Port, Server-IP, Server-Port
    String[] s = sections[ModSecurity.SECTION_AUDIT_LOG_HEADER].trim()
        .split(" ");

    if (s.length < 7)
      throw new ParseException("Error while parsing AuditLog-Header: "
          + sections[ModSecurity.SECTION_AUDIT_LOG_HEADER]);

    eventId = Long.toHexString(createdAt.getTime());

    AuditEventParser.addValue(collections, ModSecurity.TX_ID, s[2]);
    AuditEventParser.addValue(collections, ModSecurity.REMOTE_ADDR, s[3]);
    AuditEventParser.addValue(collections, ModSecurity.REMOTE_HOST, s[3]);
    AuditEventParser.addValue(collections, ModSecurity.REMOTE_PORT, s[4]);
    AuditEventParser.addValue(collections, ModSecurity.SERVER_ADDR, s[5]);
    AuditEventParser.addValue(collections, ModSecurity.SERVER_NAME, s[5]);

    if (s[6].equals("www"))
      s[6] = "80";

    AuditEventParser.addValue(collections, ModSecurity.SERVER_PORT, s[6]);

    AuditEventParser.addValue(collections, ModSecurity.REMOTE_USER, "-");

    if (sections.length >= ModSecurity.SECTION_AUDIT_TRAILER
        && sections[ModSecurity.SECTION_AUDIT_TRAILER] != null) {
      AuditEventParser.addValue(collections,
          ModSecurity.AUDIT_LOG_TRAILER,
          sections[ModSecurity.SECTION_AUDIT_TRAILER]);

      AuditEventParser.parseAuditTrailer(collections,
          sections[ModSecurity.SECTION_AUDIT_TRAILER]);
    }

    AuditEventParser.setValue(collections, ModSecurity.REQUEST_HEADER,
        sections[ModSecurity.SECTION_REQUEST_HEADER]);

    if (sections[ModSecurity.SECTION_REQUEST_BODY] != null)
      AuditEventParser.setValue(collections, ModSecurity.REQUEST_BODY,
          sections[ModSecurity.SECTION_REQUEST_BODY]);

    if (sections[ModSecurity.SECTION_FINAL_RESPONSE_HEADER] != null)
      AuditEventParser.setValue(collections, ModSecurity.RESPONSE_HEADER,
          sections[ModSecurity.SECTION_FINAL_RESPONSE_HEADER]);

    if (ModSecurity.SECTION_META_INF > 0
        && sections[ModSecurity.SECTION_META_INF] != null)
      AuditEventParser.parseMetaInfSection(collections,
          sections[ModSecurity.SECTION_META_INF]);
  }

  /**
   * @see org.modsecurity.audit.AuditEvent#getEventId()
   */
  public String getEventId() {
    String id = get(ModSecurity.TX_ID);
    if (id != null)
      return id;
    return eventId;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getSection(int)
   */
  public String getSection(int i) {
    if (i >= 0 && i < sections.length)
      return sections[i];

    return null;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getAuditHeader()
   */
  public String getAuditHeader() {
    return sections[0];
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getRequestHeader()
   */
  public String getRequestHeader() {
    return sections[ModSecurity.SECTION_REQUEST_HEADER];
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getRequestBody()
   */
  public String getRequestBody() {
    return sections[ModSecurity.SECTION_REQUEST_BODY];
  }

  /**
   * @see org.modsecurity.audit.AuditEvent#getResponseHeader()
   * @deprecated
   */
  public String getResponseHeader() {
    return sections[ModSecurity.SECTION_FINAL_RESPONSE_HEADER];
  }

  /**
   * @deprecated
   */
  public String getAuditLogTrailer() {
    return sections[ModSecurity.SECTION_AUDIT_TRAILER];
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getDate()
   */
  public Date getDate() {
    return new Date(createdAt.getTime());
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getSessionId()
   */
  public String getSessionId() {
    return sessionId;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#setSessionId(java.lang.String)
   */
  public void setSessionId(String id) {
    sessionId = id;
    AuditEventParser.setValue(collections, ModSecurity.SESSIONID, id);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#isSet(java.lang.String)
   */
  public boolean isSet(String var) {

    if (var == null)
      return false;

    String v = var;
    if (!ModSecurity.isCaseSensitive(v)) {
      v = var.toUpperCase();
    }

    return collections.get(v) != null;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#get(java.lang.String)
   */
  public String get(String variable) {
    String var = variable;
    if (var == null)
      return "";

    if ("UNIQUE_ID".equals(variable)) // this is for backwards-compatibility
      return get(ModSecurity.TX_ID);

    if (!ModSecurity.isCaseSensitive(variable)) {
      var = variable.toUpperCase();
    }

    if (ModSecurity.__UNDEFINED__.equals(var))
      return "";

    if (var.startsWith("&")) {
      String col = var.substring(1);
      return "" + getAll(col).size();
    }

    if (collections.containsKey(var)) {
      if (collections.get(var).isEmpty())
        return "";

      return collections.get(var).get(0);
    }

    return "";
  }

  public List<String> getAll(String v) {

    String var = v;
    if (!ModSecurity.isCaseSensitive(v)) {
      var = v.toUpperCase();
    }

    if (collections.containsKey(var))
      return collections.get(var);

    List<String> vals = new LinkedList<String>();
    String val = this.get(var);
    if (!"".equals(val))
      vals.add(val);
    return vals;
  }

  public List<String> getVariables() {
    List<String> names = new LinkedList<String>();
    names.addAll(collections.keySet());
    return names;
  }

  public void set(String var, String val) {
    AuditEventParser.setValue(collections, var, val);
  }

  /**
   * Override <code>Object.toString()</code> by returning a String of all
   * sections.
   */
  public String toString() {
    StringBuffer s = new StringBuffer();

    for (int i = 0; i < sections.length; i++) {
      if (sections[i].length() > 0) {
        s.append("--" + this.getEventId() + "-"
            + ModSecurity.SECTIONS.charAt(i) + "--\n");
        s.append(sections[i]);
      }
    }
    s.append("--" + getEventId() + "-Z--\n");

    return s.toString();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#compareTo(java.lang.Object)
   */
  public int compareTo(AuditEvent o) {
    if (o instanceof ModSecurityAuditEvent)
      return compareTo((ModSecurityAuditEvent) o);

    return -1;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#compareTo(org.modsecurity.audit.
   * AuditEventImpl)
   */
  public int compareTo(ModSecurityAuditEvent o) {
    if (this.eventId.compareTo(o.eventId) == 0)
      return 0;

    int c = getDate().compareTo(o.getDate());
    if (c == 0)
      return eventId.compareTo(o.eventId);
    else
      return c;
  }

  public boolean equals(ModSecurityAuditEvent o) {
    return 0 == this.compareTo(o);
  }

  //
  //
  // some private methods for parsing, etc.
  //
  //

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getRawData()
   */
  public String[] getRawData() {
    return sections;
  }

  /*
   * (non-Javadoc)
   *
   * @see java.lang.Object#finalize()
   */
  @Override
  protected void finalize() throws Throwable {
    super.finalize();
    synchronized (evtCount) {
      evtCount--;
    }
  }

  public Long getCount() {
    return evtCount;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.modsecurity.audit.AuditEvent#getURL()
   */
  public URL getRequestURL() {
    return url;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jwall.web.audit.AuditEvent#getFile()
   */
  public File getFile() {
    return file;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jwall.web.audit.AuditEvent#getOffset()
   */
  public long getOffset() {
    return offset;
  }

  public long getSize() {
    return size;
  }

  public void recycle() {
  }

  public void tag(String tag) {
    List<String> tags = this.collections.get(TAGS);
    if (tags == null) {
      tags = new LinkedList<String>();
      collections.put(TAGS, tags);
    }

    if (!tags.contains(tag))
      tags.add(tag);
  }

  public void untag(String tag) {
    List<String> tags = collections.get(TAGS);
    if (tags != null)
      tags.remove(tag);
  }

  public Set<String> getTags() {
    LinkedHashSet<String> tags = new LinkedHashSet<String>();

    List<String> taglist = collections.get(TAGS);
    if (taglist != null)
      tags.addAll(taglist);

    return tags;
  }

  public static Long getInstanceCount() {
    return evtCount;
  }

  @Override
  public void setAll(String variable, List<String> values) {
    if (collections == null)
      collections = new LinkedHashMap<String, List<String>>();

    if (ModSecurity.isCaseSensitive(variable))
      collections.put(variable, values);
    else
      collections.put(variable.toUpperCase(), values);
  }

  @Override
  public AuditEventType getAuditEventType() {
    return type;
  }

  @Override
  public AuditEventMessage[] getEventMessages() {
    if (messages != null)
      return messages;

    List<AuditEventMessage> msgs = MessageParser.parseMessages(this);
    messages = msgs.toArray(new AuditEventMessage[msgs.size()]);
    return messages;
  }
}
TOP

Related Classes of org.jwall.web.audit.ModSecurityAuditEvent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.