Skip to content

Commit

Permalink
basic signed communication works
Browse files Browse the repository at this point in the history
  • Loading branch information
rambo committed Feb 13, 2011
1 parent 9ccb448 commit f6e14d1
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 62 deletions.
108 changes: 46 additions & 62 deletions software/tcpserver/testclient.py
@@ -1,95 +1,79 @@
#!/usr/bin/env python
#!/usr/bin/env python -i
import sys,os
local_module_dir = os.path.join(os.path.dirname( os.path.realpath( __file__ ) ), 'libs')
if os.path.isdir(local_module_dir):
sys.path.append(local_module_dir)
import utils, hmac, hashlib
import ConfigParser
import socket, threading

# client example from http://www.oluyede.org/blog/2008/08/31/twisted-interactive-console/

from twisted.internet import defer, stdio, protocol, reactor
from twisted.protocols import basic
class testclient:
def __init__(self, address_tuple, config):
self.config = config
print self.config.get('auth', 'shared_secret')
self.socket = socket.create_connection(address_tuple)

class Repl(basic.LineReceiver):
delimiter = '\n'
prompt_string = '>>> '

def prompt(self):
self.transport.write(self.prompt_string)

def connectionMade(self):
self.sendLine('Welcome to Repl')
# store factory and connector upon connection to the stdout
self.factory = CFactory()
self.connector = reactor.connectTCP('127.0.0.1', 8080, self.factory)
self.prompt()

def lineReceived(self, line):
if not line:
self.prompt()
return

self.issueCommand(line)

def issueCommand(self, command):
# write to the connector's transport, not the one writing on stdout
#self.connector.transport.write("%s%s" % (command, self.delimiter))
self.connector.send_signed(command)
# register the callback on the factory's deferred
self.factory.deferred.addCallback(self._checkResponse)

def _checkResponse(self, message):
self.sendLine(message)
self.prompt()
# recreate the deferred each time we have the response
self.factory.deferred = defer.Deferred()

class Client(basic.LineReceiver):
delimiter = '\n'

def connectionMade(self):
pass
self.receiver_thread = threading.Thread(target=self.tcp_reader)
self.receiver_thread.setDaemon(1)
self.receiver_thread.start()


def lineReceived(self, data):
print "Client: got data %s" % data
if data[0:6] == "HELLO\t":
self.session_key = utils.hex_decode(data.split("\t")[1])
self.hmac_key = self.session_key + self.config.get('auth', 'shared_secret')
message = self.verify_data(data)
#print "Client: Got message %s\n" % message
#print "Client: self.session_key=%s" % utils.hex_encode(self.session_key)
if message == False:
self.factory.deferred.callback("ERROR Hash mismatch")
print "ERROR Hash mismatch"
return

self.factory.deferred.callback(message)

def verify_data(self, data):
sent_hash = utils.hex_decode(data[-40:])
#print "got hash %s" % utils.hex_encode(sent_hash)
message = data[:-41]
h = hmac.new(self.session_key, message, hashlib.sha1)
#print "got message %s" % repr(message)
h = hmac.new(self.hmac_key, message, hashlib.sha1)
if sent_hash != h.digest():
return False
return message

def send_signed(self, message):
h = hmac.new(self.session_key, message, hashlib.sha1)
self.transport.write(message + "\t" + h.hexdigest() + "\n")
h = hmac.new(self.hmac_key, message, hashlib.sha1)
#print "session key %s" % utils.hex_encode(self.session_key)
#print "hmac key %s" % repr(self.hmac_key)
self.socket.sendall(message + "\t" + h.hexdigest() + "\n")

def tcp_reader(self):
alive = True
charbuffer = ''
try:
while alive:
data = self.socket.recv(4096)
if data == '':
continue

# TODO: hex-encode unprintable characters (but keep newlines)
sys.stdout.write(data)

def responseFinished(self, num_lines, data):
# just fire the callback
self.factory.deferred.callback((
self.cmd_success, num_lines, data))
charbuffer += data
# Partition the charbuffer at newlines and parse the command until we have no newlines left
while charbuffer.find("\n") != -1:
part = charbuffer.partition("\n")
charbuffer = part[2]
self.lineReceived(part[0])

def connectionLost(self, reason):
reactor.stop()
except Exception, e:
print e
self.alive = False


class CFactory(protocol.ClientFactory):
protocol = Client

def __init__(self):
self.deferred = defer.Deferred()
if __name__ == '__main__':
config = ConfigParser.SafeConfigParser()
config.read('tcpserver.conf')
c = testclient(('127.0.0.1', '8080'), config)

if __name__ == "__main__":
stdio.StandardIO(Repl())
reactor.run()
95 changes: 95 additions & 0 deletions software/tcpserver/testclient_twisted_b0rked.py
@@ -0,0 +1,95 @@
#!/usr/bin/env python
import sys,os
local_module_dir = os.path.join(os.path.dirname( os.path.realpath( __file__ ) ), 'libs')
if os.path.isdir(local_module_dir):
sys.path.append(local_module_dir)
import utils, hmac, hashlib

# client example from http://www.oluyede.org/blog/2008/08/31/twisted-interactive-console/

from twisted.internet import defer, stdio, protocol, reactor
from twisted.protocols import basic

class Repl(basic.LineReceiver):
delimiter = '\n'
prompt_string = '>>> '

def prompt(self):
self.transport.write(self.prompt_string)

def connectionMade(self):
self.sendLine('Welcome to Repl')
# store factory and connector upon connection to the stdout
self.factory = CFactory()
self.connector = reactor.connectTCP('127.0.0.1', 8080, self.factory)
self.prompt()

def lineReceived(self, line):
if not line:
self.prompt()
return

self.issueCommand(line)

def issueCommand(self, command):
# write to the connector's transport, not the one writing on stdout
#self.connector.transport.write("%s%s" % (command, self.delimiter))
self.connector.send_signed(command)
# register the callback on the factory's deferred
self.factory.deferred.addCallback(self._checkResponse)

def _checkResponse(self, message):
self.sendLine(message)
self.prompt()
# recreate the deferred each time we have the response
self.factory.deferred = defer.Deferred()

class Client(basic.LineReceiver):
delimiter = '\n'

def connectionMade(self):
pass

def lineReceived(self, data):
print "Client: got data %s" % data
if data[0:6] == "HELLO\t":
self.session_key = utils.hex_decode(data.split("\t")[1])
message = self.verify_data(data)
#print "Client: Got message %s\n" % message
#print "Client: self.session_key=%s" % utils.hex_encode(self.session_key)
if message == False:
self.factory.deferred.callback("ERROR Hash mismatch")
return

self.factory.deferred.callback(message)

def verify_data(self, data):
sent_hash = utils.hex_decode(data[-40:])
message = data[:-41]
h = hmac.new(self.session_key, message, hashlib.sha1)
if sent_hash != h.digest():
return False
return message

def send_signed(self, message):
h = hmac.new(self.session_key, message, hashlib.sha1)
self.transport.write(message + "\t" + h.hexdigest() + "\n")

def responseFinished(self, num_lines, data):
# just fire the callback
self.factory.deferred.callback((
self.cmd_success, num_lines, data))

def connectionLost(self, reason):
reactor.stop()


class CFactory(protocol.ClientFactory):
protocol = Client

def __init__(self):
self.deferred = defer.Deferred()

if __name__ == "__main__":
stdio.StandardIO(Repl())
reactor.run()

0 comments on commit f6e14d1

Please sign in to comment.