def processMessage(self, msg): """ An EchoProfile simply sends a RPY to each MSG it receives containing the same payload as what was received. For demonstration purposes, this EchoProfile also asks the controlling session to shutdown() if more than 5 MSGs are received. @raise profile.TerminalProfileException: if any exception occurs during processing. """ # log.debug("EchoProfile: processing message: %s" % msg) try: if msg.isMSG(): log.debug("EchoProfile: sending RPY") self.channel.sendReply(msg.msgno, msg.payload) if msg.isRPY(): self.channel.deallocateMsgno(msg.msgno) self.numReplies += 1 log.debug('numReplies == %s' % self.numReplies) if self.numReplies > 5: self.session.shutdown() except Exception, e: raise profile.TerminalProfileException("Exception echoing: %s" % e)
def handleConnect(self, sock, reactor): """ A connect event occurred. """ self.proto = self.protocol() self.proto.handleConnect(self, sock) log.debug('Connect event received') self.sock = sock self.reactor = reactor self.connected = 1 pass
def sendTime(self): """ This method gets called every self.interval """ if self.sending: ## We've been asked to stop sending, so we ## send one more ANS and then stop. log.debug('sending answer to msgno: %s' % self.msgno) self.channel.sendAnswer(self.msgno, 'The time is: %s\n' % time.asctime()) self.callLater(self.interval, self.sendTime)
def requestReverb(self, number, delay, content): """ Ask the remote end to reverb back to me """ msgno = self.channel.sendMessage('%s %s %s' % (number, delay, content) ) ## Record what I've asked for self.replyDict[msgno] = [ number, delay, content ] log.debug('Started replyDict: %s' % self.replyDict) return msgno
def dataReceived(self, data): log.debug('data received: %s' % data) self.databuf += data log.debug('databuf is: %s' % self.databuf) ## We're a line receiver, so we need to check for newlines if self.line_mode: line, self.databuf = self.databuf.split(self.delimiter, 1) if line: self.lineReceived(line) else: self.rawDataReceived(data)
def test_TLSClient(self): factory = TLSEchoClientFactory() factory.addProfile(echoprofile) factory.addProfile(tlsprofile) reactor.connectTCP("localhost", 1976, factory) reactor.run() log.debug("Finished reactor run") if factory.reason: log.debug("oh no! normal reason!") raise Exception(factory.reason.getErrorMessage())
def parseResponse(self, data): """ parseResponse() converts whatever we received from the other end into a bytestring. It needs to recognise word:, hex:, init-word: and init-hex formats. """ # for now just string off the hex: at the beginning and # convert from hex to bytes data = data[4:] log.debug('parsing response: %s' % data) data = self.generator.convertHexToBytes(data) log.debug('converted to: %s' % data) return data
def processMessage(self, msg): """ All processMessage should do is move the session from insecure to secured. """ try: error = self.parseError(msg) if error: log.debug('Error in payload: %s' % error) ready = self.parseReady(msg) if ready: ## If I receive a <ready> message then I'm the peer ## acting in server mode and should start TLS self.session.tuningBegin() log.debug('Ready to start TLS') data = '<proceed />' self.channel.sendReply(msg.msgno, data) self.session.tuningReset() proceed = self.parseProceed(msg) if proceed: ## If I receive a <proceed /> message then I'm the peer ## acting in the client mode. log.debug('Proceed to start TLS') self.session.tuningReset() except Exception, e: log.debug('%s' % e) traceback.print_exc() raise
def __init__(self, session, profileInit=None, init_callback=None): ## This is a method used to execute something at ## a later stage. It gets passed in from the upper ## layer that manages scheduling, such as a twisted reactor self.callLater = None self.interval = 1 self.sending = 0 self.msgno = 0 self.gotanswers = 0 profile.Profile.__init__(self, session, profileInit, init_callback) log.debug('finished initialising: %s' % self.callLater)
def parseReady(self, msg): """ Check data to see if it matches a 'ready' element """ readyPattern = '<ready\s(.*)/>' readyRE = re.compile(readyPattern, re.IGNORECASE) match = re.search(readyRE, msg.payload) if match: ## Need to add a version indicator log.debug('Got ready. Matchgroup: %s' % match.group(1) ) return match.group(1) else: return None
def authenticate(self, algo, username, bytestring): """ authenticate() takes the username and passphrase hash it receives (presumably from a client) and checks it against the expected OTP in the dbase. passhash is an 8 byte string """ dbEntry = self.retrieveDBEntry(username) mypasshash = self.generateHash(algo, bytestring) mypasshash = self.convertBytesToHex(mypasshash) log.debug('comparing dbEntry: %s to %s' % (dbEntry.passphrasehash, mypasshash) ) if mypasshash == dbEntry.passphrasehash: # Authentication successful, modify dbase to save current OTP dbEntry.passphrasehash = mypasshash self.storeDBEntry(dbEntry) return 1
def greetingReceived(self): log.debug("tls client has greeting") if not self.TLS: ## Start a new channel asking for TLS self.authchannel = self.newChannel(tlsprofile) log.debug("attempting to start channel %d..." % self.authchannel) else: log.debug("TLS channel is on.") self.echochannel = self.newChannel(echoprofile) log.debug("attempting to start echo channel %d..." % self.echochannel)
def startTLS(self): """ start the TLS layer """ if self.factory.privateKeyFileName: keyfile = self.factory.privateKeyFileName else: log.info('Private key filename not specified. Requesting it...') keyfile = self.factory.getPrivateKeyFilename() if self.factory.certificateFileName: certfile = self.factory.certificateFileName else: log.info('Certificate filename not specified. Requesting it...') certfile = self.factory.getCertificateFilename() log.debug('Starting server side TLS...') self.transport.startTLS(ServerTLSContext(keyfile, certfile)) self.TLS = 1 log.debug('Started server side TLS.')
def processMessage(self, msg): try: if msg.isMSG(): # MSG frame, so parse out what to do self.parseMSG(msg) pass if msg.isANS(): log.debug('Got reverb reply: %s' % msg.payload) if msg.isRPY(): self.channel.deallocateMsgno(msg.msgno) pass if msg.isERR(): self.channel.deallocateMsgno(msg.msgno) pass if msg.isNUL(): log.debug('Got final message for %s' % msg.msgno) del self.replyDict[msg.msgno] self.channel.deallocateMsgno(msg.msgno) ## If I've got all my reverb replies, finish if len(self.replyDict) == 0: log.debug('All reverbs received. Finishing...') self.session.shutdown() pass pass except Exception, e: raise profile.TerminalProfileException("Exception reverbing: %s: %s" % ( e.__class__, e) )
def respondToChallenge(self, challenge, msg): log.debug("Responding to challenge...") # The challenge string should be 4 tokens parts = string.split(challenge, ' ') if len(parts) != 4: raise ProfileException('Challenge (%s) has %d tokens, not 4' % (challenge, len(parts) ) ) # First part is the algorithm algo = parts[0][4:] sequence = string.atoi(parts[1]) # FIXME: This is commented out so I can test the library. if not self.passphrase: # passphrase = self.getPassphraseFromUser() log.debug("No passphrase...") raise ProfileException("Passphrase not set") # The OTP to be used is calculated as N-1 where N is the sequence # sent as part of the challenge. passhash = self.generator.createHash(self.session.userid, algo, parts[2], self.passphrase, sequence-1) data = 'hex:' + self.generator.convertBytesToHex(passhash) data = self.encodeBlob(data) self.channel.sendMessage(data)
def processMessage(self, msg): """ All processFrame should do is move the session from non-authenticated to authenticated. """ try: error = self.parseError(msg.payload) if error: log.error("Error while authenticating: %s: %s" % (error[1], error[2])) return status = self.parseStatus(msg.payload) if status: # do status code processing log.debug("status: %s" % status) if status == 'complete': self.session.authenticationSucceeded() elif status == 'abort': # other end has aborted negotiation, so we reset # to our initial state self.authentid = None self.authid = None elif status == 'continue': log.debug("continue during authentication") else: authentid = self.decodeBlob(msg.payload) if authentid: log.debug("authentid: %s" % authentid) self.authentid = authentid # I've now dealt with the message sufficiently for it to # be marked as such, so we deallocate the msgno self.channel.deallocateMsgno(msg.msgno) data = '<blob status="complete"/>' self.channel.sendReply(msg.msgno, data) log.debug("Queued success message") # self.session.authenticationComplete() except Exception, e: traceback.print_exc() raise TerminalProfileException("Exception: %s" % e)
def iterate(self): """ Check for inbound and outbound data """ log.debug('iterating factory: %s' % self) if not self.connected: raise ValueError('Factory not connected!') i, o, e = select.select([self.sock], [self.sock], [], 0.1) for sock in i: data = sock.recv(MAX_RECV) if data: log.debug('Received data on factory.') self.proto.dataReceived(data) else: log.debug('proto is: %s' % self.proto) log.debug(' %s' % self.proto.connectionLost) self.proto.connectionLost(ConnectionDone('Finished'))
def channelStarted(self, channelnum, uri): log.debug('started channel %d', channelnum) if channelnum == self.authchannel: log.debug('Authentication channel started successfully.') channel = self.getChannel(channelnum) msgno = channel.profile.sendAuth('hello!') elif channelnum == self.echochannel: log.debug('Echo channel started successfully.') channel = self.getChannel(channelnum) msgno = channel.sendMessage('Echo 1!') msgno = channel.sendMessage('Echo 2!') msgno = channel.sendMessage('Echo 3!') msgno = channel.sendMessage('Echo 4!') msgno = channel.sendMessage('Echo 5!') msgno = channel.sendMessage('Echo 6!') else: log.debug('Unknown channel created: %d' % channelnum)
def channelStarted(self, channelnum, uri): log.debug("started channel %d", channelnum) if channelnum == self.authchannel: log.debug("Authentication channel started successfully.") channel = self.getChannel(channelnum) msgno = channel.profile.sendAuth(self.passphrase, self.username) elif channelnum == self.echochannel: log.debug("Echo channel started successfully.") channel = self.getChannel(channelnum) msgno = channel.sendMessage("Echo 1!") msgno = channel.sendMessage("Echo 2!") msgno = channel.sendMessage("Echo 3!") msgno = channel.sendMessage("Echo 4!") msgno = channel.sendMessage("Echo 5!") msgno = channel.sendMessage("Echo 6!") else: log.debug("Unknown channel created: %d" % channelnum)
def parseMSG(self, msg): """parseMSG grabs the MSG payload and works out what to do """ try: number, delay, content = string.split(msg.payload, ' ', 2) number = int(number) delay = int(delay) log.debug("number: %d" % number) log.debug("delay: %d" % delay) log.debug("content: %s" % content) if number <= 0: self.channel.sendError(msg.msgno, 'Cannot echo a frame %d times.\n' % number) else: log.debug("Adding reverb for msgno: %d, %d times with %d second delay" % (msg.msgno, number, delay) ) self.reverbDict[msg.msgno] = [number, delay, content] self.callLater(delay, self.sendReverb, (msg.msgno) ) except ValueError, e: # A ValueError means the payload format is wrong. log.error('Payload format incorrect: %s' % e) self.channel.sendError(msg.msgno, 'Payload format incorrect\n')
def channelStarted(self, channelnum, uri): log.debug("started channel %d", channelnum) if not self.TLS: if channelnum == self.authchannel: log.debug("TLS channel started successfully.") channel = self.getChannel(channelnum) ## Turn on TLS msgno = channel.profile.sendReady() else: if channelnum == self.echochannel: log.debug("Echo channel started successfully.") channel = self.getChannel(channelnum) msgno = channel.sendMessage("Echo 1!") msgno = channel.sendMessage("Echo 2!") msgno = channel.sendMessage("Echo 3!") msgno = channel.sendMessage("Echo 4!") msgno = channel.sendMessage("Echo 5!") msgno = channel.sendMessage("Echo 6!")
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #import logging from beepy.core.debug import log #log = logging.getLogger('beepy') ## ## TLS related code ## try: from twisted.internet import ssl from OpenSSL import SSL except ImportError: log.debug('ssl not supported without twisted') raise #from POW import Ssl from tcp import BeepProtocol, BeepClientFactory, BeepServerFactory from beepy.core.tlssession import TLSListener, TLSInitiator ## This code adds the TLS functionality to the base protocol ## classes class TLSProtocol(BeepProtocol): """ The TLS Protocol implements the TLS transport layer """ TLS = 0
def processMessage(self, msg): """ Get the time every 5 seconds. @raise profile.TerminalProfileException: if any exception occurs during processing. """ log.debug("processing message: %s" % msg) try: if msg.isMSG(): command = msg.payload.split() log.debug('command is: %s' % command) if command[0] == 'time': log.debug('request for timing start') if not command[1]: log.debug('no time variable received') self.channel.sendError(msg.msgno, 'No time interval specified\n') return try: interval = int(command[1]) except ValueError, e: log.debug('FIXME! interval not an integer') self.channel.sendError(msg.msgno, 'Interval not an integer\n') return log.debug('request to send time every %d seconds' % interval) self.sending = 1 self.interval = interval self.msgno = msg.msgno log.debug('scheduling callLater: %s' % self.callLater) self.callLater(self.interval, self.sendTime) elif command[0] == 'stop': self.sending = 0 self.channel.sendReply(msg.msgno, 'Ok') self.channel.sendNul(self.msgno) if msg.isRPY(): self.channel.deallocateMsgno(msg.msgno) log.debug('got RPY') if msg.isANS(): log.debug('got ANS: %s' % msg) self.gotanswers += 1 ## Stop getting the time after 5 of them if self.gotanswers > 5: self.channel.sendMessage('stop') if msg.isNUL(): self.channel.deallocateMsgno(msg.msgno) log.debug("got NUL. Guess I'm stopping.") self.session.shutdown()
def __del__(self): log.debug('deleting TCPTransport: %s' % self) self.sock.close()
def close(self): log.debug('closing factory...') self.sock.close() self.connected = 0 self.reactor.removeFactory(self)
def startTLS(self): log.debug('Starting client side TLS...') self.transport.startTLS(ClientTLSContext()) self.TLS = 1 log.debug('Started client side TLS.')
def greetingReceived(self): ## Start a channel using the SASL/ANONYMOUS profile self.authchannel = self.newChannel(saslanonymousprofile) log.debug('attempting to start channel %d...' % self.authchannel)
def rawDataReceived(line): log.debug('raw data received')
def authenticationSucceeded(self): log.debug('overloaded authComplete') self.echochannel = self.newChannel(echoprofile)
def connectionLost(self): log.debug('Connection lost!') self.connected = 0 self.transport.connectionLost()