#! /usr/bin/env python2

# REQUIREMENTS:
# libnids (and libnet 1.0.2a, libpcap)
# python 2.2 or later
# pynids: http://pilcrow.madison.wi.us/pynids/

# shamelessly stolen from the pynids Example code ...
# passive HTTP referrer->request graphing tool.

# standard imports
import os, pwd, string, sys

# local imports ...
import nids

NOTROOT = "nobody"   	# edit to taste
end_states = (nids.NIDS_CLOSE, nids.NIDS_TIMEOUT, nids.NIDS_RESET)
f = open("/tmp/http-graph.dot", "w")

def handleTcpStream(tcp):
    import string

    req = ""
    ref = ""

    if tcp.nids_state == nids.NIDS_JUST_EST:
        ((src, sport), (dst, dport)) = tcp.addr
        if dport in (80, 8000, 8080):
            tcp.client.collect = 1
            tcp.server.collect = 1
    elif tcp.nids_state == nids.NIDS_DATA:
        # keep all of the stream's new data
        tcp.discard(0)
    elif tcp.nids_state in end_states:
        headers = string.split(tcp.server.data, "\n")	# grab client request
        for header in headers:
            if "Host:" in header:
                h = string.replace(header, "Host: ", "", 1)
            if "GET " in header: 		# get Server header
                req = string.replace(header, "GET ", "", 1)
                req = string.replace(req, "HTTP/1.0", "", 1)
                req = string.replace(req, "HTTP/1.1", "", 1)
            if "Referer: " in header:
                ref = string.replace(header, "Referer:", "", 1)
                f.write("\t \"%s\" -> \"http://%s%s\"\n" %(string.strip(ref), string.strip(h), string.strip(req)))
                f.flush()
                break

def main():
    nids.param("scan_num_hosts", 0)  # disable portscan detection
    if not nids.init():
        print "error -", nids.errbuf()
        sys.exit(1)

    (uid, gid) = pwd.getpwnam(NOTROOT)[2:4]
    os.setgroups([gid,])
    os.setgid(gid)
    os.setuid(uid)
    if 0 in [os.getuid(), os.getgid()] + list(os.getgroups()):
        print "error - drop root, please!"
        sys.exit(1)

    nids.register_tcp(handleTcpStream)
    f.write("digraph browsing {")
    try:
        nids.run()  # loop forever
    except KeyboardInterrupt:
        f.write("}")
        f.close()
        sys.exit(1)

if __name__ == '__main__':
    main()
