#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This is a python program that basicaly does the same job as
# ssh-faker by Charles Howes, but aims to fix some of the issues I had
# with that program.

# Copyright (C) 2008 Patrik Lembke <blambi@chebab.com>

# This program 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.

PASSWORD = "password"
FAKE_VERSION = "SSH-1.99-OpenSSH_3.7.1p1"
JUST_DROP=False # If false emulates ssh-faker more.
TIMEOUT=60 # sec
SYSLOG_NAME="sshd"

import sys, signal, syslog, time

def write_syslog( ip, message ):
    """Write message to syslog."""
    syslog.openlog( SYSLOG_NAME )
    syslog.syslog( 'Got "%s" from %s' %( message, ip ) )
    syslog.closelog()

def unlock_ip( ip ):
    allow = open( "/etc/hosts.allow", 'a+' )
    allow.write( "# %s\n" % time.strftime("Added at %c") )
    allow.write( "sshd: %s : ALLOW\n" % ip )
    allow.close()
    print "Yay! You can now ssh to this computer from %s" % remote_ip

def kick( input ):
    """Closes the conection by sending a faked ssh package missmatch"""
    if input.startswith( "SSH-" ):
        # -- Following is a "translation" of code from ssh-faker.pl --
        print "%c%c%c%c" %( 0x00, 0x00, 0x00, 0x61 ), # length of packet
        print "%c%c%c%c" %( 0x00, 0x00, 0x00, 0x00 ), # dunno
        print "%c%c%c%c" %( 0x00, 0x00, 0x00, 0x01 ), # opcode
        print "%c%c%c%c" %( 0x00, 0x00, 0x00, 0x58 ), # length of text:
        print "Your ssh version is too old and is no longer supported.",
        print "  Please install a newer version.",
        print "%c%c%c%c" %( 0x4F, 0x9D, 0xE0, 0xF2 )  # CRC32 checksum
        # -- End of ssh-fake.pl translation --
    else:
        print "Protocol mismatch."

def drop():
    sys.exit( 1 )

def timeout( signum, frame ):
    write_syslog( remote_ip, "-time out-" )
    drop()

# main
if __name__ == '__main__':
    if len( sys.argv ) < 2:
        print "Error: please put the following into your /etc/hosts.deny"
        print "  sshd : ALL : twist /path/%s" % sys.argv[0]
        sys.exit( 1 )
    else:
        remote_ip =  sys.argv[1]

        # SSH banner
        sys.stdout.write( "%s\r\n" % FAKE_VERSION )
        sys.stdout.flush()

        signal.signal( signal.SIGALRM, timeout )
        signal.alarm( TIMEOUT )
        
        read_input = raw_input()
        
        if read_input == PASSWORD:
            unlock_ip( remote_ip )
        else: # Log other data to syslog
            write_syslog( remote_ip, read_input )
            if JUST_DROP:
                drop()
            else:
                kick( read_input )
        signal.alarm( 0 ) # be nice to EPA

