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 sys
from twisted.internet import ssl as twisted_ssl
try:
import OpenSSL
except ImportError:
print(" SSL_ENABLED requires PyOpenSSL.")
sys.exit(5)
from twisted.internet import ssl as twisted_ssl
except ImportError as err:
raise ImportError("SSL_ENABLED requires PyOpenSSL.")
from django.conf import settings
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):
"""
Communication is the same as telnet, except data transfer
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):
@ -46,9 +94,8 @@ def verify_SSL_key_and_cert(keyfile, certfile):
rsaKey = Key(RSA.generate(KEY_LENGTH))
keyString = rsaKey.toString(type="OPENSSH")
file(keyfile, 'w+b').write(keyString)
except Exception as e:
print("rsaKey error: %(e)s\n WARNING: Evennia could not auto-generate SSL private key." % {'e': e})
print("If this error persists, create game/%(keyfile)s yourself using third-party tools." % {'keyfile': keyfile})
except Exception as err:
print(NO_AUTOGEN.format(err=err, keyfile=keyfile))
sys.exit(5)
# 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
exestring = "openssl req -new -x509 -key %s -out %s -days %s" % (keyfile, certfile, CERT_EXPIRE)
try:
#, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
subprocess.call(exestring)
except OSError as e:
string = "\n".join([
" %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)
except OSError as err:
raise OSError(NO_AUTOCERT.format(err=err, certfile=certfile, keyfile=keyfile, exestring=exestring))
print("done.")
def getSSLContext():
"""
Returns an SSL context (key and certificate). This function
verifies that key/cert exists before obtaining the context, and if
not, creates them.
This is called by the portal when creating the SSL context
server-side.
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)
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
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):
"""
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.
# when it reaches 0 the portal/server syncs their data
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
self.naws = naws.Naws(self)