summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormakefu <github@syntax-fehler.de>2013-01-29 19:01:43 +0100
committermakefu <github@syntax-fehler.de>2013-01-29 19:01:43 +0100
commit14b5fb8d60919516950e9ac1e3ff895968ed3a3c (patch)
tree282921b51f5c780cdbe2e3f88b0f825aba901d1c
parent715b2e23b0cb347dbf6b6516e5811e45406324ac (diff)
parentd96cf23ac2c57d9791343c03d01fa54fe5295d2c (diff)
Merge branch 'master' of github.com:krebscode/painload
-rw-r--r--infest/bootstrap.sh2
-rw-r--r--retiolum/hosts/devstar (renamed from retiolum/hosts/Shepherd)0
-rw-r--r--retiolum/hosts/geisha11
-rw-r--r--retiolum/hosts/rage11
-rw-r--r--retiolum/hosts/seruundroid12
-rw-r--r--retiolum/scripts/adv_graphgen/find_super.py43
-rwxr-xr-xretiolum/scripts/adv_graphgen/parse_tinc_stats.py8
-rwxr-xr-xretiolum/scripts/tinc_setup/new_install.sh67
-rw-r--r--services/Makefile38
-rw-r--r--services/authorized_keys4
-rwxr-xr-xservices/bin/services24
-rw-r--r--services/checkers.py25
-rw-r--r--services/services.txt7
-rw-r--r--services/test.py108
14 files changed, 318 insertions, 42 deletions
diff --git a/infest/bootstrap.sh b/infest/bootstrap.sh
index 723e78f0..66a1cfdd 100644
--- a/infest/bootstrap.sh
+++ b/infest/bootstrap.sh
@@ -14,7 +14,7 @@ command -v git || \
pacman -Sy git || \
{ echo "please install git manually!"; exit 1;} || exit 1
-[ -e "$KREBSDIR" ] || git clone https://github.com/krebscode/painload.git "$KREBSDIR" \
+[ -e "$KREBSDIR" ] || git clone --depth 1 https://github.com/krebscode/painload.git "$KREBSDIR" \
|| { echo "cloning failed :(" ; exit 1; } || exit 1
cd $KREBSDIR || { echo "cannot change into $KREBSDIR folder:(" ; exit 1; } || exit 1
diff --git a/retiolum/hosts/Shepherd b/retiolum/hosts/devstar
index 875f62e2..875f62e2 100644
--- a/retiolum/hosts/Shepherd
+++ b/retiolum/hosts/devstar
diff --git a/retiolum/hosts/geisha b/retiolum/hosts/geisha
new file mode 100644
index 00000000..6a3a2788
--- /dev/null
+++ b/retiolum/hosts/geisha
@@ -0,0 +1,11 @@
+Subnet = 10.243.175.29
+Subnet = 42:b6aa:9052:fffc:807b:4829:8756:860c
+
+-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEA0kVV9ezFx/kZ6GvSALhXODkWlwHSjdA5hBJ90bdNcILeltVa3FIv
+K2E+L6EG/jsETWKutxOk08+B/Z3p1SONgEksTNBdXx/Crww5PZGN/ocVSKZj61/N
+lCej/Jcu88a4/R7JHIiSMdmqRCGHnwnxRA0iDQZIunriUH83NqMBQk6Drkphr/9a
+5U8PhlqC5oSzZrg0uReRuBK86KmU03vp9/DndaLn18G835dtWRBQ2aEfIrrlaTPJ
+ZKN/0xYZJU3v8YJYPi+UeRSymecSNgFQg36v95r3s4j3trk+yXVzVwT347AZRm4a
+d/AHdk0+blXyUr5CFBsjA71cJfzqIIJJrwIDAQAB
+-----END RSA PUBLIC KEY-----
diff --git a/retiolum/hosts/rage b/retiolum/hosts/rage
new file mode 100644
index 00000000..dd9a70e2
--- /dev/null
+++ b/retiolum/hosts/rage
@@ -0,0 +1,11 @@
+Subnet = 10.243.211.81
+Subnet = 42:73d5:8402:f8f1:0250:0bc3:e2ec:850d
+
+-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEA6dOSRjCwkdx/nOSQwiiCw889YBSlf0ZAymBSaWJ+XdLnktqqZIvQ
++1RMdfpTTsIaHoLDwvBI6gW9dhV5MEeP3AlWfKPZAMCWg8l3PkTERZILWGSLiizs
+zCyJgLpsb2MP7rT3RlLlHyTNdx9QXxDX2K1Y/fJsjXuTTgwg3JPlPM2huGTZtWgM
+GDFsRpfe37hIuIheYBgnP99OvEgx3rLyCDvd16kIMd2Pjx4SouVQqaBmvEmg+UEH
+zD79GaO7c2xkqq6JggJw1q/xZnH+5CF8280kh/niXVqy8R/hP75FU1rvjHnMJvfo
+nyPGC8ir2m6iy4CR07YBIYo1PRTXGDC1vwIDAQAB
+-----END RSA PUBLIC KEY-----
diff --git a/retiolum/hosts/seruundroid b/retiolum/hosts/seruundroid
new file mode 100644
index 00000000..b4f0848e
--- /dev/null
+++ b/retiolum/hosts/seruundroid
@@ -0,0 +1,12 @@
+Subnet = 10.243.127.2
+Subnet = 42:81de:f850:152b:0988:1942:265d:dacb
+
+-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEAvNtSbaaacF05L2mAxxA5SYc6DuoZEAkXlhcvLTlpu9f/0vZwUWh7
+175pLn6VqUijVoFb9vyoOwkrs9Uk3aX8mYws+5yJLwXhIje+U3uiVTphowKva+m9
+BzV6waZ5dLbh+3CGimx1TBkFTly3NkdZs886QWSO4aXLdU6lt3jRYsuay0Eop/j0
+eQ0BWg9o0QEcfDRQ7RirXrD0B7TSo6qZC0b4NSAMHTE+dvOMo7c+Z7cIPNLS0B+T
+Am7ju3gF7UU68kKPyczrNSPPPZayEvZYUZE4PHt8dyIsppojoRq0SJqsMr/mOC15
+dg/KnoKezn9nqUWzisRWrrqWStAKITJkjQIDAQAB
+-----END RSA PUBLIC KEY-----
+
diff --git a/retiolum/scripts/adv_graphgen/find_super.py b/retiolum/scripts/adv_graphgen/find_super.py
index df01734e..ae0fae8f 100644
--- a/retiolum/scripts/adv_graphgen/find_super.py
+++ b/retiolum/scripts/adv_graphgen/find_super.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-def find_super(path="/etc/tinc/retiolum/hosts"):
+def find_potential_super(path="/etc/tinc/retiolum/hosts"):
import os
import re
@@ -23,28 +23,37 @@ def find_super(path="/etc/tinc/retiolum/hosts"):
if addrs : yield (f ,[(addr ,int(port)) for addr in addrs])
-def check_super(path="/etc/tinc/retiolum/hosts"):
- from socket import socket,AF_INET,SOCK_STREAM
- for host,addrs in find_super(path):
+def try_connect(addr):
+ try:
+ from socket import socket,AF_INET,SOCK_STREAM
+ s = socket(AF_INET,SOCK_STREAM)
+ s.settimeout(2)
+ s.connect(addr)
+ s.settimeout(None)
+ s.close()
+ return addr
+ except Exception as e:
+ pass
+ #return ()
+
+def check_one_super(ha):
+ host,addrs = ha
valid_addrs = []
for addr in addrs:
- try:
- s = socket(AF_INET,SOCK_STREAM)
- s.settimeout(3)
- s.connect(addr)
- #print("success connecting %s:%d"%(addr))
- s.settimeout(None)
- s.close()
- valid_addrs.append(addr)
- except Exception as e:
- pass
- #print("cannot connect to %s:%d"%(addr))
- if valid_addrs: yield (host,valid_addrs)
+ ret = try_connect(addr)
+ if ret: valid_addrs.append(ret)
+ if valid_addrs: return (host,valid_addrs)
+
+def check_all_the_super(path="/etc/tinc/retiolum/hosts"):
+ from multiprocessing import Pool
+ p = Pool(20)
+ return filter(None,p.map(check_one_super,find_potential_super(path)))
+
if __name__ == "__main__":
"""
usage
"""
- for host,addrs in check_super():
+ for host,addrs in check_all_the_super():
print host,addrs
diff --git a/retiolum/scripts/adv_graphgen/parse_tinc_stats.py b/retiolum/scripts/adv_graphgen/parse_tinc_stats.py
index 76a3ffcd..e5bd96a8 100755
--- a/retiolum/scripts/adv_graphgen/parse_tinc_stats.py
+++ b/retiolum/scripts/adv_graphgen/parse_tinc_stats.py
@@ -2,7 +2,7 @@
# -*- coding: utf8 -*-
from BackwardsReader import BackwardsReader
import sys,json
-from find_super import check_super
+from find_super import check_all_the_super
try:
from time import time
import socket
@@ -18,7 +18,7 @@ except Exception as e:
sys.stderr.write("Cannot connect to graphite: %s\n" % str(e))
supernodes= [ ]
-for supernode,addr in check_super():
+for supernode,addr in check_all_the_super():
supernodes.append(supernode)
""" TODO: Refactoring needed to pull the edges out of the node structures again,
it should be easier to handle both structures"""
@@ -39,6 +39,7 @@ def write_digraph(nodes):
for k,v in nodes.iteritems():
write_node(k,v)
print ('}')
+
def dump_graph(nodes):
from time import time
graph = {}
@@ -48,6 +49,7 @@ def dump_graph(nodes):
json.dump(graph,f)
f.write('\n')
f.close()
+
def write_stat_node(nodes):
''' Write a `stats` node in the corner
This node contains infos about the current number of active nodes and connections inside the network
@@ -95,6 +97,7 @@ def generate_stats(nodes):
v['avg_weight'] = get_node_avg_weight(conns)
v['availability'] = get_node_availability(k,jlines)
sys.stderr.write( "%s -> %f\n" %(k ,v['availability']))
+
def get_node_avg_weight(conns):
""" calculates the average weight for the given connections """
if not conns:
@@ -143,6 +146,7 @@ def delete_unused_nodes(nodes):
#del(new_nodes[k])
del(k)
return new_nodes
+
def merge_edges(nodes):
""" merge back and forth edges into one
DESTRUCTS the current structure by deleting "connections" in the nodes
diff --git a/retiolum/scripts/tinc_setup/new_install.sh b/retiolum/scripts/tinc_setup/new_install.sh
index 4dc973d9..1ff42e54 100755
--- a/retiolum/scripts/tinc_setup/new_install.sh
+++ b/retiolum/scripts/tinc_setup/new_install.sh
@@ -12,9 +12,10 @@ SUBNET4=${SUBNET4:-10.243}
SUBNET6=${SUBNET6:-42}
TEMPDIR=${TEMPDIR:-auto}
TINCDIR=${TINCDIR:-auto}
+exists() { type "$1" >/dev/null 2>/dev/null; }
-if type hostname >/dev/null ;then SYSHOSTN=${HOSTNAME:-$(hostname)}
-elif type uci >/dev/null ;then SYSHOSTN=$(uci get system.@system[0].hostname)
+if exists hostname ;then SYSHOSTN=${HOSTNAME:-$(hostname)}
+elif exists uci ;then SYSHOSTN=$(uci get system.@system[0].hostname)
elif [ -e /etc/hostname ] ;then SYSHOSTN=$(cat /etc/hostname)
else SYSHOSTN="unknown"
fi
@@ -28,7 +29,7 @@ RMASK=${RMASK:-255.255.0.0}
URL=${URL:-http://euer.krebsco.de/retiolum/hosts.tar.gz}
SURL=${SURL:-http://euer.krebsco.de/retiolum/supernodes.tar.gz}
-IRCCHANNEL=${IRCCHANNEL:-"#krebsco"}
+IRCCHANNEL=${IRCCHANNEL:-"#krebs"}
IRCSERVER=${IRCSERVER:-"irc.freenode.net"}
IRCPORT=${IRCPORT:-6667}
@@ -105,14 +106,16 @@ get_hostname()
find_os()
{
if grep -qe 'Linux' /etc/*release 2>/dev/null || grep -qe 'Linux' /etc/issue 2>/dev/null; then
- OS=1
- elif type getprop >/dev/null; then
- OS=2
+ OS='linux'
+ elif exists getprop ; then
+ OS='android'
elif test -e /etc/openwrt_release; then
- OS=3
+ OS='openwrt'
+ elif uname -s | grep -qi 'darwin'; then
+ OS='osx'
else
echo "Cannot determine your operating system, falling back to Linux"
- OS=1
+ OS='linux'
fi
}
@@ -135,13 +138,13 @@ if [ $OS -eq 0 ]; then
fi
#check if everything is installed
-if ! type awk >/dev/null; then
+if ! exists awk ; then
echo "Please install awk"
exit 1
fi
-if ! type curl >/dev/null; then
- if ! type wget >/dev/null; then
+if ! exists curl ; then
+ if ! exists wget ; then
echo "Please install curl or wget"
exit 1
else
@@ -157,23 +160,37 @@ if ! $(ping -c 1 -W 5 euer.krebsco.de 1>/dev/null) ;then
fi
#check if everything is installed
-if [ $OS -eq 2 ]; then
+if [ $OS = 'android' ]; then
if ! test -e /data/data/org.poirsouille.tinc_gui/files/tincd; then
echo "Please install tinc-gui"
exit 1
else
TINCBIN=/data/data/org.poirsouille.tinc_gui/files/tincd
- if [ $TINCDIR = 'auto' ]; then TINCDIR=/usr/local/etc/tinc ;fi
- if [ $TEMPDIR = 'auto' ]; then TEMPDIR=/data/secure/data ;fi
+ DEV="/dev/tun"
+ if [ $TINCDIR = 'auto' ]; then TINCDIR="/usr/local/etc/tinc" ;fi
+ if [ $TEMPDIR = 'auto' ]; then TEMPDIR="/storage/sdcard0/tinc-fu" ;fi
+ mount -o remount,rw /
+ mount -o remount,rw /system
+ fi
+elif [ $OS = 'osx' ]; then
+ if ! exists tincd >/dev/null; then
+ echo "Please install tinc"
+ exit 1
+ else
+ TINCBIN=tincd
+ DEV="/dev/net/tun"
+ if [ $TINCDIR = 'auto' ]; then TINCDIR="/usr/local/etc/tinc" ;fi
+ if [ $TEMPDIR = 'auto' ]; then TEMPDIR="/tmp/tinc-install-fu" ;fi
fi
else
- if ! type tincd >/dev/null; then
+ if ! exists tincd >/dev/null; then
echo "Please install tinc"
exit 1
else
TINCBIN=tincd
- if [ $TINCDIR = 'auto' ]; then TINCDIR=/etc/tinc ;fi
- if [ $TEMPDIR = 'auto' ]; then TEMPDIR=/tmp/tinc-install-fu ;fi
+ DEV="/dev/net/tun"
+ if [ $TINCDIR = 'auto' ]; then TINCDIR="/etc/tinc" ;fi
+ if [ $TEMPDIR = 'auto' ]; then TEMPDIR="/tmp/tinc-install-fu" ;fi
fi
fi
@@ -229,7 +246,7 @@ get_hostname $HOSTN
mkdir -p $TINCDIR/$NETNAME
cd $TINCDIR/$NETNAME
-if [ $OS -eq 3 ]; then
+if [ $OS = 'openwrt' ]; then
mkdir hosts
$LOADER $SURL | tar xz -C hosts/
else
@@ -243,7 +260,7 @@ echo "Subnet = $IP6" >> hosts/$HOSTN
cat>tinc.conf<<EOF
Name = $HOSTN
-Device = /dev/net/tun
+Device = $DEV
#newer tinc features
LocalDiscovery = yes
@@ -258,7 +275,7 @@ EOF
host2subnet $MASK4
#check if ip is installed
-if type ip >/dev/null; then
+if exists ip >/dev/null; then
echo 'dirname="`dirname "$0"`"' > tinc-up
echo '' >> tinc-up
echo 'conf=$dirname/tinc.conf' >> tinc-up
@@ -292,16 +309,22 @@ fi
#fix permissions
chmod +x tinc-up
-chown -R root:root .
+chown -R 0:0 .
#generate keys with tinc
-if type tincctl >/dev/null; then
+if exists tincctl ; then
yes | tincctl -n $NETNAME generate-keys
cat rsa_key.pub >> hosts/$HOSTN
else
yes | $TINCBIN -n $NETNAME -K
fi
+if [ $OS = 'android' ]; then
+ mkdir /etc/tinc
+ cd /
+ mv $TINCDIR/$NETNAME /etc/tinc/
+ cd /etc/tinc/$NETNAME
+fi
#write to irc-channel
NICK="${HOSTN}_$(head /dev/urandom | tr -dc "0123456789" | head -c3)"
diff --git a/services/Makefile b/services/Makefile
new file mode 100644
index 00000000..3ef670a3
--- /dev/null
+++ b/services/Makefile
@@ -0,0 +1,38 @@
+help:;@cat Makefile
+export authorized_keys_file := authorized_keys
+export services_file := services.txt
+export host_key_file := test.key
+export services_home := /opt/services
+
+.PHONY: authorized_keys
+
+service-user: $(services_home)/services.txt $(services_home)/.ssh/authorized_keys
+ @echo 'also make sure that the user is created: make create-service-user'
+
+create-service-user:
+ mkdir -p $(services_home)
+ rmdir $(services_home)
+ useradd -m -r -l -f -1 -d $(services_home) services
+
+$(services_home)/.ssh:
+ mkdir $@
+ chown services:services $@
+
+$(services_home)/.ssh/authorized_keys: $(services_home)/.ssh $(authorized_keys_file)
+ cp $(authorized_keys_file) $(services_home)/.ssh/authorized_keys
+ @echo "restricting authorized_keys..."
+ @sed -i 's#^#command="/bin/cat $(services_home)/services.txt",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty #' $(services_home)/.ssh/authorized_keys
+
+$(services_home)/services.txt:
+ @echo 'make sure to configure the services correctly in $(services_home)/services.txt'
+ cp $(services_file) $(services_home)/services.txt
+
+
+test-client:
+ ssh localhost -p 1337 2>/dev/null
+
+test-server:
+ python test.py
+
+$(host_key_file):
+ ssh-keygen -t rsa -P '' -f $@
diff --git a/services/authorized_keys b/services/authorized_keys
new file mode 100644
index 00000000..2eae1f4d
--- /dev/null
+++ b/services/authorized_keys
@@ -0,0 +1,4 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7YrLdnXDRU2XEdZDu1BmgiT0Vaxplf3bfvSm+5o3g4AcR2yCv7h2D633c9uA0gq52EJ3V5m8B1ZcxqA0zqDptKwx+ZTMUGDls7StH5xpJyk9j5gf8DzyDLQPQG2IYszCH+8esKjo3BOFxfey8NaX+k6gvQsG3lyV0PjLvvIy4gDuMn6dPZfVAlwNYFOUNgwpku3W3A0d+UFyVjt3/sgZxM+8C3y6QE1gwT5/NfBbHM5vaEqjHcVq1ui+7a4iOXFGKkZDcd7EX6cQZSbCzZL7sZ0OmB1WpAsDCvIXfzX1YfNA0sso7ldSF6ZUGNgwEk1LootnQlCK/dfbM+i62SZ+1 tv@iiso
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCv9TTt4FkzT3jlQ0VS2tX/GpQO9Ef0wIQ+g96foe4qSniBwR667T1gIhURrod/p7N9oQcWRrNohjgmSBZRYA0kW6ZyqYJkLvRv54nXv6j/8Xq2nG/KVfDqL0kp8if+JGeFlQElpWJiAbGifYkopFy69QiLYU2ndR7aPbx+5qm/dcwPJ7K+n6dyePynCZadtcabm3PuBFUxGLdT9ImDXMOPfXxPMlN/3eb78byuEuHnhCIvIGLMBGx+8QTXvu7kHpZObvkbsF1xjVs9fDpwVLjh7GWdwf3BZ/agFlI24ffyqCPFnuaxUVyfUZeqf4twRsIZkTTB47lHDhYiVkyGe8gd root@pigstarter.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl3RTOHd5DLiVeUbUr/GSiKoRWknXQnbkIf+uNiFO+XxiqZVojPlumQUVhasY8UzDzj9tSDruUKXpjut50FhIO5UFAgsBeMJyoZbgY/+R+QKU00Q19+IiUtxeFol/9dCO+F4o937MC0OpAC10LbOXN/9SYIXueYk3pJxIycXwUqhYmyEqtDdVh9Rx32LBVqlBoXRHpNGPLiswV2qNe0b5p919IGcslzf1XoUzfE3a3yjk/XbWh/59xnl4V7Oe7+iQheFxOT6rFA30WYwEygs5As//ZYtxvnn0gA02gOnXJsNjOW9irlxOUeP7IOU6Ye3WRKFRR0+7PS+w8IJLag2xb makefu@pornocauster
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7df1RfMGNHPJe0iF6rD9DBs/4VujN6nNr7RbRCFk7HF/JzLXSn9Vcwk+3JefP4/d/bUo0h03rhQaRohDhBScrJidj2YacF6gmZOuTf3AMWprdz9D/1dDkN/ytwzGhADhqbHEWeomIllsa8Up4PvEeDcIHJGzYvuc0BbGqRk0XgxwqIrLAhdpTfEKaTbt7IzmUqEofxThTZ/4k020PKn2WDBWKQYGZJ9Ba2WzlKUXWx842ncW29oxC2faRz4M3eMPy0JMpBLkK9U3dccE75dgT/89/4ofVjM7+J3FOP3dgXzrtk+A5aN5a/veJUViQ9xdGxXvoa++iCr5q/BVRv0Bb sammy@muhbaasu.de
diff --git a/services/bin/services b/services/bin/services
new file mode 100755
index 00000000..c142a363
--- /dev/null
+++ b/services/bin/services
@@ -0,0 +1,24 @@
+#! /bin/sh
+# usage: services [user@]hostname[:port]
+# environment:
+# services_identity_file path to ssh(1) identity_file
+set -euf
+
+user=services
+hostname=${1-localhost}
+port=1337
+
+if test -n "${services_identity_file-}"; then
+ options="${options+$options }-i $services_identity_file"
+fi
+
+if echo $hostname | grep -q @; then
+ user=`echo $hostname | cut -d@ -f1`
+ hostname=`echo $hostname | cut -d@ -f2`
+fi
+if echo $hostname | grep -q :; then
+ port=`echo $hostname | cut -d: -f2`
+ hostname=`echo $hostname | cut -d: -f1`
+fi
+
+ssh $options $user@$hostname -p $port
diff --git a/services/checkers.py b/services/checkers.py
new file mode 100644
index 00000000..dbfe1323
--- /dev/null
+++ b/services/checkers.py
@@ -0,0 +1,25 @@
+
+import base64, binascii
+from twisted.python.filepath import FilePath
+from twisted.conch.checkers import SSHPublicKeyDatabase
+
+
+class PublicKeyChecker(SSHPublicKeyDatabase):
+
+ def __init__(self, filename):
+ self.filepath = FilePath(filename)
+
+ def getAuthorizedKeysFiles(self, credentials):
+ return [self.filepath]
+
+ def checkKey(self, credentials):
+ for line in self.filepath.open():
+ parts = line.split()
+ if len(parts) < 2:
+ continue
+ try:
+ if base64.decodestring(parts[1]) == credentials.blob:
+ return True
+ except binascii.Error:
+ continue
+ return False
diff --git a/services/services.txt b/services/services.txt
new file mode 100644
index 00000000..dc88cbac
--- /dev/null
+++ b/services/services.txt
@@ -0,0 +1,7 @@
+owner:
+type:
+mail:
+expires:
+location:
+services://{{hostname}}:22/
+tinc://{{hostname}}/
diff --git a/services/test.py b/services/test.py
new file mode 100644
index 00000000..06340a54
--- /dev/null
+++ b/services/test.py
@@ -0,0 +1,108 @@
+#! /usr/bin/env python
+
+from os import environ as env
+
+authorized_keys_file = env.get('authorized_keys_file', '/dev/null')
+services_file = env.get('services_file', '/dev/null')
+host_key_file = env.get('host_key_file', '/dev/null')
+host_key_pub_file = host_key_file + '.pub'
+
+
+from checkers import PublicKeyChecker
+from twisted.conch.avatar import ConchUser
+from twisted.conch.ssh.connection import SSHConnection
+from twisted.conch.ssh.factory import SSHFactory
+from twisted.conch.ssh.keys import Key
+from twisted.conch.ssh.session import SSHSession, ISession, wrapProtocol
+from twisted.conch.ssh.userauth import SSHUserAuthServer
+from twisted.cred.error import UnauthorizedLogin
+from twisted.cred.portal import IRealm, Portal
+from twisted.internet.protocol import Protocol
+from twisted.internet.reactor import listenTCP, run
+from twisted.python.components import registerAdapter
+from zope.interface import implements
+
+from twisted.python.log import startLogging
+from sys import stderr
+startLogging(stderr)
+
+
+class MyRealm:
+ implements(IRealm)
+
+ def requestAvatar(self, avatarId, mind, *interfaces):
+ return interfaces[0], MyUser(), lambda: None
+
+
+class MyUser(ConchUser):
+ def __init__(self):
+ ConchUser.__init__(self)
+ self.channelLookup.update({ 'session': SSHSession })
+
+
+class MySession:
+
+ def __init__(self, avatar):
+ pass
+
+ def getPty(self, term, windowSize, attrs):
+ pass
+
+ def execCommand(self, proto, cmd):
+ raise Exception("no executing commands")
+
+ def openShell(self, trans):
+ ep = MyProtocol()
+ ep.makeConnection(trans)
+ trans.makeConnection(wrapProtocol(ep))
+
+ def eofReceived(self):
+ pass
+
+ def closed(self):
+ pass
+
+
+registerAdapter(MySession, MyUser, ISession)
+
+
+def slurpTextfile(filename):
+ file = open(filename, 'r')
+ try:
+ return file.read()
+ finally:
+ file.close()
+
+class MyProtocol(Protocol):
+ def connectionMade(self):
+ data = slurpTextfile(services_file).replace('\n', '\r\n')
+ self.transport.write(data)
+ self.transport.loseConnection()
+
+ #def dataReceived(self, data):
+ # if data == '\r':
+ # data = '\r\n'
+ # elif data == '\x03': #^C
+ # self.transport.loseConnection()
+ # return
+ # self.transport.write(data)
+
+
+class MyFactory(SSHFactory):
+ privateKeys = {
+ 'ssh-rsa': Key.fromFile(filename=host_key_file)
+ }
+ publicKeys = {
+ 'ssh-rsa': Key.fromFile(filename=host_key_pub_file)
+ }
+ services = {
+ 'ssh-userauth': SSHUserAuthServer,
+ 'ssh-connection': SSHConnection
+ }
+
+if __name__ == '__main__':
+ portal = Portal(MyRealm())
+ portal.registerChecker(PublicKeyChecker(authorized_keys_file))
+ MyFactory.portal = portal
+ listenTCP(1337, MyFactory())
+ run()