Authentication Intercept script

Name: filter.py
Purpose: Authentication filter with Python
Author: jcornez
Type: Script
Requirements: Python
License: Public domain

Something like the following filter.py can be used as the auth script by ejabberd. This calls the "real" auth script and logs all traffic in between the two. It also tries to detect garbage and protect ejabberd from stuff that doesn't match the protocol. I don't think this script would be so great for long-term production, but as a development and debugging tool, it is quite handy. Should be fairly straight-forward for someone to modify.

I grant permission that this (or some derived work) could be used in a more official capacity by ejabberd. Acknowledgement would be appreciated, but officially this is public domain.

#!/usr/bin/python

import sys, os, fcntl
from struct import *
from subprocess import *

# auth_script = "/path/to/real/auth/script"
auth_script = "/etc/ejabberd/auth.py"

def from_ejabberd():
    input_length = sys.stdin.read(2)
    (size,) = unpack('>h', input_length)
    return sys.stdin.read(size)

def to_ejabberd(answer):
    token = pack('>hh', 2, answer)
    sys.stdout.write(token)
    sys.stdout.flush()


child = Popen([auth_script], stdin=PIPE, stdout=PIPE)
childout = child.stdout.fileno()
fcntl.fcntl(childout, fcntl.F_SETFL, os.O_NONBLOCK)
log = open("/var/log/ejabberd/auth-filter.log",'a+b',0)

while True:
    request = from_ejabberd()
    size = pack('>h', len(request))
    child.stdin.write(size)
    child.stdin.write(request)
    child.stdin.flush()

    log.write("Request: ")
    log.write(request)
    log.write('\n')

    result = 0
    response_start = ""
    while response_start == "":
        try:
            response_start = os.read(childout, 2)
        except OSError, err:
            pass
    (size,) = unpack('>h', response_start)
    log.write("Response: ")
    if size == 2:
        response_rest = os.read(childout, 2)
        (result,) = unpack('>h', response_rest)
        log.write( "%d" % result )
    else:
        done = False
        log.write(response_start)
        response_rest = ""
        while not done:
            try:
                char = os.read(childout, 1)
                response_rest += char
            except OSError, err:
                done = True
        log.write(response_rest)

    log.write('\n')
    log.flush()
    to_ejabberd(result)
Script originally published in the forum thread: A possible work-around
Syndicate content