def sstpMsgCallConnectRequestReceived(self, protocolId): if self.state in (CALL_ABORT_TIMEOUT_PENDING, CALL_ABORT_PENDING, CALL_DISCONNECT_ACK_PENDING, CALL_DISCONNECT_TIMEOUT_PENDING): return if self.state != SERVER_CONNECT_REQUEST_PENDING: logging.warn('Not in the state.') self.transport.loseConnection() return if protocolId != SSTP_ENCAPSULATED_PROTOCOL_PPP: logging.warn('Unsupported encapsulated protocol.') nak = SSTPControlPacket(SSTP_MSG_CALL_CONNECT_NAK) nak.attributes = [(SSTP_ATTRIB_ENCAPSULATED_PROTOCOL_ID, ATTRIB_STATUS_VALUE_NOT_SUPPORTED)] self.addRetryCounterOrAbrot() return self.nonce = os.urandom(32) ack = SSTPControlPacket(SSTP_MSG_CALL_CONNECT_ACK) # 3 bytes reserved + 1 byte hash bitmap (SHA-1 only) + nonce. ack.attributes = [(SSTP_ATTRIB_CRYPTO_BINDING_REQ, '\x00\x00\x00' + '\x03' + self.nonce)] ack.writeTo(self.transport.write) self.pppd = PPPDProtocol() self.pppd.sstp = self self.pppd.remote = self.factory.remotePool.apply() if self.pppd.remote is None: logging.warn('IP address pool is full. ' 'Cannot accpet new connection.') self.abort() addressArgument = '%s:%s' % (self.factory.local, self.pppd.remote) reactor.spawnProcess(self.pppd, self.factory.pppd, args=['local', 'file', self.factory.pppdConfigFile, '115200', addressArgument], usePTY=True) self.transport.registerProducer(self.pppd, True) self.pppd.resumeProducing() self.state = SERVER_CALL_CONNECTED_PENDING
def sstpMsgEchoRequest(self): if self.state == SERVER_CALL_CONNECTED: response = SSTPControlPacket(SSTP_MSG_ECHO_RESPONSE) response.writeTo(self.transport.write) elif self.state in (CALL_ABORT_TIMEOUT_PENDING, CALL_ABORT_PENDING, CALL_DISCONNECT_ACK_PENDING, CALL_DISCONNECT_TIMEOUT_PENDING): return self.abort(ATTRIB_STATUS_UNACCEPTED_FRAME_RECEIVED)
def sstpMsgCallDisconnect(self, status=None): if self.state in (CALL_ABORT_TIMEOUT_PENDING, CALL_ABORT_PENDING, CALL_DISCONNECT_TIMEOUT_PENDING): return logging.info('Received call disconnect request.') self.state = CALL_DISCONNECT_IN_PROGRESS_2 ack = SSTPControlPacket(SSTP_MSG_CALL_DISCONNECT_ACK) ack.writeTo(self.transport.write) self.state = CALL_DISCONNECT_TIMEOUT_PENDING reactor.callLater(1, self.transport.loseConnection)
def helloTimerExpired(self, close=False): if self.state == SERVER_CALL_DISCONNECTED: self.transport.loseConnection() # TODO: follow HTTP elif close: logging.warn('Ping time out.') self.abort(ATTRIB_STATUS_NEGOTIATION_TIMEOUT) else: logging.info('Send echo request.') echo = SSTPControlPacket(SSTP_MSG_ECHO_REQUEST) echo.writeTo(self.transport.write) self.helloTimer = reactor.callLater(60, self.helloTimerExpired, True)
def pppStoped(self): if (self.state != SERVER_CONNECT_REQUEST_PENDING and self.state != SERVER_CALL_CONNECTED_PENDING and self.state != SERVER_CALL_CONNECTED): self.transport.loseConnection() return self.state = CALL_DISCONNECT_IN_PROGRESS_1 msg = SSTPControlPacket(SSTP_MSG_CALL_DISCONNECT) msg.attributes = [(SSTP_ATTRIB_NO_ERROR, ATTRIB_STATUS_NO_ERROR)] msg.writeTo(self.transport.write) self.state = CALL_DISCONNECT_ACK_PENDING reactor.callLater(5, self.transport.loseConnection)
def abort(self, status=None): if status is None: logging.warn('Abort.') else: logging.warn('Abort (%s).' % ord(status[-1])) self.state = CALL_DISCONNECT_IN_PROGRESS_1 msg = SSTPControlPacket(SSTP_MSG_CALL_ABORT) if status is not None: msg.attributes = [(SSTP_ATTRIB_STATUS_INFO, status)] msg.writeTo(self.transport.write) self.state = CALL_ABORT_PENDING reactor.callLater(3, self.transport.loseConnection)
def sstpMsgCallAbort(self, status=None): if self.state in (CALL_ABORT_TIMEOUT_PENDING, CALL_DISCONNECT_TIMEOUT_PENDING): return logging.warn("Call abort.") if self.state == CALL_ABORT_PENDING: reactor.callLater(1, self.transport.loseConnection) return self.state = CALL_ABORT_IN_PROGRESS_2 msg = SSTPControlPacket(SSTP_MSG_CALL_ABORT) msg.writeTo(self.transport.write) self.state = CALL_ABORT_PENDING reactor.callLater(1, self.transport.loseConnection)
def sstpMsgCallConnectRequestReceived(self, protocolId): if self.state in (CALL_ABORT_TIMEOUT_PENDING, CALL_ABORT_PENDING, CALL_DISCONNECT_ACK_PENDING, CALL_DISCONNECT_TIMEOUT_PENDING): return if self.state != SERVER_CONNECT_REQUEST_PENDING: logging.warn('Not in the state.') self.transport.loseConnection() return if protocolId != SSTP_ENCAPSULATED_PROTOCOL_PPP: logging.warn('Unsupported encapsulated protocol.') nak = SSTPControlPacket(SSTP_MSG_CALL_CONNECT_NAK) nak.attributes = [(SSTP_ATTRIB_ENCAPSULATED_PROTOCOL_ID, ATTRIB_STATUS_VALUE_NOT_SUPPORTED)] self.addRetryCounterOrAbrot() return self.nonce = os.urandom(32) ack = SSTPControlPacket(SSTP_MSG_CALL_CONNECT_ACK) # 3 bytes reserved + 1 byte hash bitmap (SHA-1 only) + nonce. ack.attributes = [(SSTP_ATTRIB_CRYPTO_BINDING_REQ, '\x00\x00\x00' + '\x03' + self.nonce)] ack.writeTo(self.transport.write) self.pppd = PPPDProtocol() self.pppd.sstp = self if self.factory.remotePool: self.pppd.remote = self.factory.remotePool.apply() if self.pppd.remote is None: logging.warn('IP address pool is full. ' 'Cannot accpet new connection.') self.abort() else: self.pppd.remote = '' addressArgument = '%s:%s' % (self.factory.local, self.pppd.remote) reactor.spawnProcess(self.pppd, self.factory.pppd, args=['local', 'file', self.factory.pppdConfigFile, '115200', addressArgument, 'remotenumber', str(self.transport.getPeer().host)], usePTY=True) self.transport.registerProducer(self.pppd, True) self.pppd.resumeProducing() self.state = SERVER_CALL_CONNECTED_PENDING