#! /usr/bin/env python

#############################################################################
##                                                                         ##
## logParser.py --- Analyse logs from mail server                          ##
##                  http://linuxch.org/tools/logParser.py                  ##
##                                                                         ##
## Needs :                                                                 ##
##       - Python 2.4 or above                                             ##
##       - Pyparsing : http://pyparsing.wikispaces.com/                    ##
##	 - GeoIP : http://www.maxmind.com/app/python                       ##
##       - GeoLite Country : http://www.maxmind.com/app/geolitecountry     ##
##                                                                         ##
## Copyright (C) 2007  public@linuxch.org                                  ##
##                                                                         ##
## This program is free software; you can redistribute it and/or modify it ##
## under the terms of the GNU General Public License version 2 as          ##
## published by the Free Software Foundation; version 2.                   ##
##                                                                         ##
## 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.                                ##
##                                                                         ##
#############################################################################

from pyparsing import *
from operator import itemgetter
import GeoIP
import socket
import fileinput

# Postfix logfile keyWords
keyWords = "connect from"

# Countries
countriesConnect = {}

# Open GeoIP database file
gi = GeoIP.open("GeoIP.dat",GeoIP.GEOIP_STANDARD)

cpt = 0

# Grammars to match
month = oneOf("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
dayOfMonth = Word(nums,max=2)
timeOfDay = Combine(Word(nums,exact=2)+":"+\
                Word(nums,exact=2)+":"+Word(nums,exact=2))
timeStamp = month + dayOfMonth + timeOfDay

source = Word(alphas)

deamon = Word(alphas)
processus = Suppress("/") + Word(alphas)
pid = Suppress("[") + Word(nums) + Suppress ("]:")

emailAddr = QuotedString("<",endQuoteChar=">")
countryCode = Upcase(delimitedList(Word(alphanums), Word(".-_"), combine=False))
hostAddr = delimitedList(Word(alphanums), Word(".-_"), combine=True)
ipAddr = Combine(Word(nums)+"."+Word(nums)+"."+Word(nums)+"."+Word(nums))
ipRef = hostAddr + Suppress("[") + ipAddr.setResultsName("ipAddress") + Suppress("]")

connectMsg = keyWords + ipRef

logMessage = timeStamp.setResultsName("timeStmap") + source + deamon + processus.setResultsName("processus") +\
	     pid.setResultsName("pid") + connectMsg

# Find Domain Name Country Suffix Codes
# with GeoIP
#
def findCountry (ip):
    return gi.country_code_by_name(ip)

# Create countries table
#
def countCountry (code, countries):
    if countries.has_key(code):
    	countries[code] += 1
    else:
        countries[code] = 1

# Count connections
#
def sumDict (dict):
    ret = 0
    for x in dict:
        ret = ret + dict[x]
    return ret

# Summary
#
def summary ():
    print "-----------"
    print "| Summary |"
    print "-----------"
    print
    print "Connections from :", sorted(countriesConnect.items(), key=itemgetter(1), reverse=True)
    print
    print "Number of countries :", len(countriesConnect)
    print
    print "Total connections :", sumDict (countriesConnect)


# Parse each line in logfile
for log in fileinput.input(['mail.log']):
    if log:
        try:
            results = logMessage.parseString(log)
	except ParseException:
	    # No "connect from" > line ignored
	    continue

	# Connect from
	if results[7] == keyWords:
            try:
	        code = findCountry (results["ipAddress"])
	    except KeyError:
	        print "Error: ipAddress not found" 
	    countCountry (code, countriesConnect)

# Print summary
summary()

