First cleanup of SSL connection, not working yet.

This commit is contained in:
Griatch 2016-02-20 22:03:16 +01:00
parent 006b898e66
commit 2dbae4d8a9
2 changed files with 72 additions and 26 deletions

View file

@ -7,22 +7,70 @@ from __future__ import print_function
import os import os
import sys import sys
from twisted.internet import ssl as twisted_ssl
try: try:
import OpenSSL import OpenSSL
except ImportError: from twisted.internet import ssl as twisted_ssl
print(" SSL_ENABLED requires PyOpenSSL.") except ImportError as err:
sys.exit(5) raise ImportError("SSL_ENABLED requires PyOpenSSL.")
from django.conf import settings
from evennia.server.portal.telnet import TelnetProtocol from evennia.server.portal.telnet import TelnetProtocol
_GAME_DIR = settings.GAME_DIR
# messages
NO_AUTOGEN = """
{err}
Evennia could not auto-generate the SSL private key. If this error
persists, create {keyfile} yourself using third-party tools.
"""
NO_AUTOCERT = """
{err}
Evennia's SSL context factory could not automatically, create an SSL
certificate {certfile}.
A private key {keyfile} was already created. Please create {certfile}
manually using the commands valid for your operating system, for
example (linux, using the openssl program):
{exestring}
"""
class SSLProtocol(TelnetProtocol): class SSLProtocol(TelnetProtocol):
""" """
Communication is the same as telnet, except data transfer Communication is the same as telnet, except data transfer
is done with encryption. is done with encryption.
""" """
pass def __init__(self, *args, **kwargs):
super(TelnetProtocol, self).__init__(*args, **kwargs)
self.protocol_name = "ssl"
def connectionMade(self):
print ("SSL connectionMade")
#self.iaw_mode = False
#self.no_lb_mode = False
#client_address = self.transport.client
#client_address = client_address[0] if client_address else None
#self.init_session(self.protocol_name, client_address, self.factory.sessionhandler)
#self.sessionhandler.connect(self)
super(SSLProtocol, self).connectionMade()
def connectionLost(self, reason):
print ("SSL connectionLost")
super(SSLProtocol, self).connectionLost(reason)
def dataReceived(self, data):
print("SSL dataReceived:", data)
super(SSLProtocol, self).dataReceived(data)
def send_text(self, *args, **kwargs):
print("SSL send_text:", args, kwargs)
super(SSLProtocol, self).send_text(*args, **kwargs)
def verify_SSL_key_and_cert(keyfile, certfile): def verify_SSL_key_and_cert(keyfile, certfile):
@ -46,9 +94,8 @@ def verify_SSL_key_and_cert(keyfile, certfile):
rsaKey = Key(RSA.generate(KEY_LENGTH)) rsaKey = Key(RSA.generate(KEY_LENGTH))
keyString = rsaKey.toString(type="OPENSSH") keyString = rsaKey.toString(type="OPENSSH")
file(keyfile, 'w+b').write(keyString) file(keyfile, 'w+b').write(keyString)
except Exception as e: except Exception as err:
print("rsaKey error: %(e)s\n WARNING: Evennia could not auto-generate SSL private key." % {'e': e}) print(NO_AUTOGEN.format(err=err, keyfile=keyfile))
print("If this error persists, create game/%(keyfile)s yourself using third-party tools." % {'keyfile': keyfile})
sys.exit(5) sys.exit(5)
# try to create the certificate # try to create the certificate
@ -57,29 +104,24 @@ def verify_SSL_key_and_cert(keyfile, certfile):
#openssl req -new -x509 -key ssl.key -out ssl.cert -days 7300 #openssl req -new -x509 -key ssl.key -out ssl.cert -days 7300
exestring = "openssl req -new -x509 -key %s -out %s -days %s" % (keyfile, certfile, CERT_EXPIRE) exestring = "openssl req -new -x509 -key %s -out %s -days %s" % (keyfile, certfile, CERT_EXPIRE)
try: try:
#, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
subprocess.call(exestring) subprocess.call(exestring)
except OSError as e: except OSError as err:
string = "\n".join([ raise OSError(NO_AUTOCERT.format(err=err, certfile=certfile, keyfile=keyfile, exestring=exestring))
" %s\n" % e,
" Evennia's SSL context factory could not automatically",
" create an SSL certificate game/%(cert)s." % {'cert': certfile},
" A private key 'ssl.key' was already created. Please",
" create %(cert)s manually using the commands valid" % {'cert': certfile},
" for your operating system.",
" Example (linux, using the openssl program): ",
" %s" % exestring])
print(string)
sys.exit(5)
print("done.") print("done.")
def getSSLContext(): def getSSLContext():
""" """
Returns an SSL context (key and certificate). This function This is called by the portal when creating the SSL context
verifies that key/cert exists before obtaining the context, and if server-side.
not, creates them.
Returns:
ssl_context (tuple): A key and certificate that is either
existing previously or or created on the fly.
""" """
keyfile, certfile = "ssl.key", "ssl.cert" keyfile = os.path.join(_GAME_DIR, "server", "ssl.key")
certfile = os.path.join(_GAME_DIR, "server", "ssl.cert")
verify_SSL_key_and_cert(keyfile, certfile) verify_SSL_key_and_cert(keyfile, certfile)
return twisted_ssl.DefaultOpenSSLContextFactory(keyfile, certfile) return twisted_ssl.DefaultOpenSSLContextFactory(keyfile, certfile)

View file

@ -31,6 +31,10 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
clients) gets a telnet protocol instance assigned to them. All clients) gets a telnet protocol instance assigned to them. All
communication between game and player goes through here. communication between game and player goes through here.
""" """
def __init__(self, *args, **kwargs):
self.protocol_name = "telnet"
super(TelnetProtocol, self).__init__(*args, **kwargs)
def connectionMade(self): def connectionMade(self):
""" """
This is called when the connection is first established. This is called when the connection is first established.
@ -44,7 +48,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
# this number is counted down for every handshake that completes. # this number is counted down for every handshake that completes.
# when it reaches 0 the portal/server syncs their data # when it reaches 0 the portal/server syncs their data
self.handshakes = 7 # naws, ttype, mccp, mssp, msdp, gmcp, mxp self.handshakes = 7 # naws, ttype, mccp, mssp, msdp, gmcp, mxp
self.init_session("telnet", client_address, self.factory.sessionhandler) self.init_session(self.protocol_name, client_address, self.factory.sessionhandler)
# negotiate client size # negotiate client size
self.naws = naws.Naws(self) self.naws = naws.Naws(self)