mirror of https://github.com/Syncplay/syncplay
startTLS: enabled on server and client, TCP stays as default
This commit is contained in:
parent
0890db8364
commit
58ccca5766
|
@ -5,6 +5,7 @@ venv
|
||||||
|
|
||||||
/SyncPlay.egg-info
|
/SyncPlay.egg-info
|
||||||
/build
|
/build
|
||||||
|
/cert
|
||||||
/dist
|
/dist
|
||||||
/syncplay v*
|
/syncplay v*
|
||||||
/syncplay_v*
|
/syncplay_v*
|
||||||
|
@ -13,4 +14,4 @@ dist.7z
|
||||||
.*
|
.*
|
||||||
!.travis.yml
|
!.travis.yml
|
||||||
!.appveyor.yml
|
!.appveyor.yml
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
19
server.crt
19
server.crt
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDDjCCAfYCCQCi9L0SyIknmTANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJQ
|
|
||||||
TDETMBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UECgwIU3luY3BsYXkxEjAQBgNV
|
|
||||||
BAMMCWxvY2FsaG9zdDAeFw0xOTAyMDMxOTA0MTFaFw0yMTExMjMxOTA0MTFaMEkx
|
|
||||||
CzAJBgNVBAYTAlBMMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhTeW5j
|
|
||||||
cGxheTESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
|
||||||
MIIBCgKCAQEAxdnxzQ2ddPWLBHzHRlc2uGCML6MtPdTW5mOzQbj+jxHqhcJszIo4
|
|
||||||
5/ZoqCX11tgQ69cJphTmg0Pjd89xTiqQBOf/qD3kSycds6j26H4oiIsuvOCaa5LN
|
|
||||||
lE5jAGZQWWRrnAqXJgbnQZgW+2a8bhJGCospRRIK+h48FDazOwEoNHjmPC7DHWrt
|
|
||||||
HlU/BbuzGPLhekKzR7LTD8/32+4g1e2LMMEv22LYrN2cRpZqb8wXYgjsMRc7aqAA
|
|
||||||
NS7x0tspBhBfCigDLd4i+SuKPGkyI118uss7eKx7MDgmQp1vUiTOkKphgT1S/a7m
|
|
||||||
4EJ3xO+75WjIQ4bJPmLbdLWMKOXi2t7PVQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
|
|
||||||
AQCADrdRY64VpPeM8c9MCn7jXDR0B7xjwoQkiyFvISCRiWZwX8QE2atjZ6jGnuB3
|
|
||||||
LBattjmjHcCNwLEvc5dZT0ioeiAvNdEbcMitYS7d2x3QIQ2n2zpSMp3speAv7mdG
|
|
||||||
YkC/oE7bbORBksjsxLCAOPOrDYijyTwDN0oTkDcuhkdztbO5Frp/5vA/i/U29Sxv
|
|
||||||
ebbJ0JXl8LJKzJqslyRv6sVxsNFH0foX7rwbXzciO4TscHHrFDZwNBhjWYPITJ7J
|
|
||||||
BBgr8Cs9ZbKFQ7+o1bUob7B8n2tKtVxAHfTQfBe68ZlcdTHfFririLjhRDVXSAFw
|
|
||||||
8ZZzQoma7VJ/1l8jcoWhdfOe
|
|
||||||
-----END CERTIFICATE-----
|
|
46
server.pem
46
server.pem
|
@ -1,46 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDDjCCAfYCCQCi9L0SyIknmTANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJQ
|
|
||||||
TDETMBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UECgwIU3luY3BsYXkxEjAQBgNV
|
|
||||||
BAMMCWxvY2FsaG9zdDAeFw0xOTAyMDMxOTA0MTFaFw0yMTExMjMxOTA0MTFaMEkx
|
|
||||||
CzAJBgNVBAYTAlBMMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhTeW5j
|
|
||||||
cGxheTESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
|
||||||
MIIBCgKCAQEAxdnxzQ2ddPWLBHzHRlc2uGCML6MtPdTW5mOzQbj+jxHqhcJszIo4
|
|
||||||
5/ZoqCX11tgQ69cJphTmg0Pjd89xTiqQBOf/qD3kSycds6j26H4oiIsuvOCaa5LN
|
|
||||||
lE5jAGZQWWRrnAqXJgbnQZgW+2a8bhJGCospRRIK+h48FDazOwEoNHjmPC7DHWrt
|
|
||||||
HlU/BbuzGPLhekKzR7LTD8/32+4g1e2LMMEv22LYrN2cRpZqb8wXYgjsMRc7aqAA
|
|
||||||
NS7x0tspBhBfCigDLd4i+SuKPGkyI118uss7eKx7MDgmQp1vUiTOkKphgT1S/a7m
|
|
||||||
4EJ3xO+75WjIQ4bJPmLbdLWMKOXi2t7PVQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
|
|
||||||
AQCADrdRY64VpPeM8c9MCn7jXDR0B7xjwoQkiyFvISCRiWZwX8QE2atjZ6jGnuB3
|
|
||||||
LBattjmjHcCNwLEvc5dZT0ioeiAvNdEbcMitYS7d2x3QIQ2n2zpSMp3speAv7mdG
|
|
||||||
YkC/oE7bbORBksjsxLCAOPOrDYijyTwDN0oTkDcuhkdztbO5Frp/5vA/i/U29Sxv
|
|
||||||
ebbJ0JXl8LJKzJqslyRv6sVxsNFH0foX7rwbXzciO4TscHHrFDZwNBhjWYPITJ7J
|
|
||||||
BBgr8Cs9ZbKFQ7+o1bUob7B8n2tKtVxAHfTQfBe68ZlcdTHfFririLjhRDVXSAFw
|
|
||||||
8ZZzQoma7VJ/1l8jcoWhdfOe
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEAxdnxzQ2ddPWLBHzHRlc2uGCML6MtPdTW5mOzQbj+jxHqhcJs
|
|
||||||
zIo45/ZoqCX11tgQ69cJphTmg0Pjd89xTiqQBOf/qD3kSycds6j26H4oiIsuvOCa
|
|
||||||
a5LNlE5jAGZQWWRrnAqXJgbnQZgW+2a8bhJGCospRRIK+h48FDazOwEoNHjmPC7D
|
|
||||||
HWrtHlU/BbuzGPLhekKzR7LTD8/32+4g1e2LMMEv22LYrN2cRpZqb8wXYgjsMRc7
|
|
||||||
aqAANS7x0tspBhBfCigDLd4i+SuKPGkyI118uss7eKx7MDgmQp1vUiTOkKphgT1S
|
|
||||||
/a7m4EJ3xO+75WjIQ4bJPmLbdLWMKOXi2t7PVQIDAQABAoIBAFz8ZlE58eOzNyff
|
|
||||||
wQRFHvmenqQQ68Vgj7Nt7iSYXkM9Z1yAGQQ0fjQ+scc9OAJGQAWnZeiBcCkHMhPw
|
|
||||||
Ec9r343+v0AB/pZ3htUWNxzjlgc+arPoV4rxTt9By/O3IlIxCQYoUAtWOT+xzDNR
|
|
||||||
gIO24OY5qybEKRaOOSxC3Q+BJrUpvIMEf93w7YQQ5SqulcmSYsIK25t+ACdXAlkX
|
|
||||||
KpvszojDU+qfUH7Uz8/yvFcbZ8LeDdrv1Wcedx15VUIcrU+D9DBYK1NOFW2vuPJT
|
|
||||||
DJZOQFXMTxg6kSED0O8a4Z3VhaPEBiGdN4KOIkC1tUj8i+BM441Jg4nme8OLX/Vm
|
|
||||||
NGftpm0CgYEA93w8P6gp1wnO7R56FdRoL9nhfgoMQroqNMqHdoGlWPFZNDqtvbFW
|
|
||||||
vjhg1v98T8mBvQMsfLruUuDDykacOdDyHRAbPQ+gICUjRXDFgu+GhHcIRn3dcZli
|
|
||||||
cSRka/JsuqCuTFnIoa981IYEllAQTZ+3w+qR8d+BkoR7K55v5aRxNCsCgYEAzKiM
|
|
||||||
8u1W3d6/E6EgaiSVOuCwOB85zbQH1t1s6wQoD34u+CEKyW3/WCkZuNMlE6J8luwt
|
|
||||||
HfXilFq9ZfAdyxN/DhHIygulbIbGwtzYFI6rEmU3zL1bX27ZWStjuDUyWf3zX4T2
|
|
||||||
9vlBf9CwJWeotaKl+Or2aeGAiNP5830WIpikyn8CgYEA8AjjNqqXyiWNOZaxurKF
|
|
||||||
SsP8XQ7JzX5aqVE2Cc683INZjbrMAIwcIer0ohKyM4CyAO0vHNsBhAjUXUAXDkyG
|
|
||||||
R4HzqUmaeRMMHrG+H7zJr3jz4cr6GNA4FpzBeaFrq6dk5lC+s3NNk6NYl6GX7nHW
|
|
||||||
/oJogzvQpJcyD6Bfz0+rLHkCgYBr0uFvm1uIyTIiRWGuileVDYvKBamOlqsKqN4Z
|
|
||||||
c7cncnOMhtwIA8vjxsOmfJesII9DdGrQvhsBzky6yCbqNvtZjkUbLceZxegyAehV
|
|
||||||
7FR0/J7JX3okbWJVeGaxRlWg1ArE6Gi09d1sWaZ0Doj0KR0IZ8IrRoNRk1y8y8o9
|
|
||||||
r+4iQQKBgDyuv6nz4xV3GrW6ohVcCRg8R4yZmb65A4guxZIwMh3nbf+rHWO3RTxd
|
|
||||||
LMiCLSW3Py2xsxiMa5ICEm75Hke8+KHwRBL7SK1eqaFrdhzvTALQp0IfBu1/t7bR
|
|
||||||
5bJVa6EL55eNA0LcOZqX36rDYzpzZjaf46XNzshZ/p0X7NryEhNl
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -108,6 +108,8 @@ class SyncplayClient(object):
|
||||||
self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self)
|
self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self)
|
||||||
self.fileSwitch = FileSwitchManager(self)
|
self.fileSwitch = FileSwitchManager(self)
|
||||||
self.playlist = SyncplayPlaylist(self)
|
self.playlist = SyncplayPlaylist(self)
|
||||||
|
|
||||||
|
self._serverSupportsTLS = True
|
||||||
|
|
||||||
if constants.LIST_RELATIVE_CONFIGS and 'loadedRelativePaths' in self._config and self._config['loadedRelativePaths']:
|
if constants.LIST_RELATIVE_CONFIGS and 'loadedRelativePaths' in self._config and self._config['loadedRelativePaths']:
|
||||||
paths = "; ".join(self._config['loadedRelativePaths'])
|
paths = "; ".join(self._config['loadedRelativePaths'])
|
||||||
|
@ -704,11 +706,11 @@ class SyncplayClient(object):
|
||||||
if '[' in host:
|
if '[' in host:
|
||||||
host = host.strip('[]')
|
host = host.strip('[]')
|
||||||
port = int(port)
|
port = int(port)
|
||||||
with open('server.crt') as cert_file:
|
with open('cert/server.crt') as cert_file:
|
||||||
trust_root = Certificate.loadPEM(cert_file.read())
|
trust_root = Certificate.loadPEM(cert_file.read())
|
||||||
self._wrapped = HostnameEndpoint(reactor, host, port)
|
self._endpoint = HostnameEndpoint(reactor, host, port)
|
||||||
self._contextFactory = optionsForClientTLS(hostname=host, trustRoot=trust_root)
|
self.protocolFactory.options = optionsForClientTLS(hostname=host, trustRoot = trust_root)
|
||||||
self._endpoint = wrapClientTLS(self._contextFactory, self._wrapped)
|
|
||||||
|
|
||||||
def retry(retries):
|
def retry(retries):
|
||||||
self._lastGlobalUpdate = None
|
self._lastGlobalUpdate = None
|
||||||
|
|
|
@ -27,6 +27,8 @@ class JSONCommandProtocol(LineReceiver):
|
||||||
self.handleError(message[1])
|
self.handleError(message[1])
|
||||||
elif command == "Chat":
|
elif command == "Chat":
|
||||||
self.handleChat(message[1])
|
self.handleChat(message[1])
|
||||||
|
elif command == "TLS":
|
||||||
|
self.handleTLS(message[1])
|
||||||
else:
|
else:
|
||||||
self.dropWithError(getMessage("unknown-command-server-error").format(message[1])) # TODO: log, not drop
|
self.dropWithError(getMessage("unknown-command-server-error").format(message[1])) # TODO: log, not drop
|
||||||
|
|
||||||
|
@ -72,7 +74,11 @@ class SyncClientProtocol(JSONCommandProtocol):
|
||||||
|
|
||||||
def connectionMade(self):
|
def connectionMade(self):
|
||||||
self._client.initProtocol(self)
|
self._client.initProtocol(self)
|
||||||
self.sendHello()
|
if self._client._serverSupportsTLS:
|
||||||
|
self.sendTLS({"startTLS": "send"})
|
||||||
|
self._client.ui.showMessage("Attempting secure connection")
|
||||||
|
else:
|
||||||
|
self.sendHello()
|
||||||
|
|
||||||
def connectionLost(self, reason):
|
def connectionLost(self, reason):
|
||||||
self._client.destroyProtocol()
|
self._client.destroyProtocol()
|
||||||
|
@ -296,11 +302,24 @@ class SyncClientProtocol(JSONCommandProtocol):
|
||||||
})
|
})
|
||||||
|
|
||||||
def handleError(self, error):
|
def handleError(self, error):
|
||||||
self.dropWithError(error["message"])
|
if "startTLS" in error["message"] and not self.logged:
|
||||||
|
self._client.ui.showErrorMessage("This server does not support TLS")
|
||||||
|
self._client._serverSupportsTLS = False
|
||||||
|
else:
|
||||||
|
self.dropWithError(error["message"])
|
||||||
|
|
||||||
def sendError(self, message):
|
def sendError(self, message):
|
||||||
self.sendMessage({"Error": {"message": message}})
|
self.sendMessage({"Error": {"message": message}})
|
||||||
|
|
||||||
|
def sendTLS(self, message):
|
||||||
|
self.sendMessage({"TLS": message})
|
||||||
|
|
||||||
|
def handleTLS(self, message):
|
||||||
|
answer = message["startTLS"] if "startTLS" in message else None
|
||||||
|
if "true" in answer and not self.logged:
|
||||||
|
self.transport.startTLS(self._client.protocolFactory.options)
|
||||||
|
self._client.ui.showMessage("Secure connection established")
|
||||||
|
self.sendHello()
|
||||||
|
|
||||||
class SyncServerProtocol(JSONCommandProtocol):
|
class SyncServerProtocol(JSONCommandProtocol):
|
||||||
def __init__(self, factory):
|
def __init__(self, factory):
|
||||||
|
@ -602,6 +621,15 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||||
def sendError(self, message):
|
def sendError(self, message):
|
||||||
self.sendMessage({"Error": {"message": message}})
|
self.sendMessage({"Error": {"message": message}})
|
||||||
|
|
||||||
|
def sendTLS(self, message):
|
||||||
|
self.sendMessage({"TLS": message})
|
||||||
|
|
||||||
|
def handleTLS(self, message):
|
||||||
|
inquiry = message["startTLS"] if "startTLS" in message else None
|
||||||
|
if "send" in inquiry and not self.isLogged():
|
||||||
|
self.sendTLS({"startTLS": "true"})
|
||||||
|
self.transport.startTLS(self._factory.options)
|
||||||
|
|
||||||
|
|
||||||
class PingService(object):
|
class PingService(object):
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,14 @@ except AttributeError:
|
||||||
|
|
||||||
from OpenSSL import crypto
|
from OpenSSL import crypto
|
||||||
from twisted.internet import reactor, ssl
|
from twisted.internet import reactor, ssl
|
||||||
from twisted.internet.endpoints import SSL4ServerEndpoint
|
from twisted.internet.endpoints import TCP4ServerEndpoint, TCP6ServerEndpoint
|
||||||
|
|
||||||
from syncplay.server import SyncFactory, ConfigurationGetter
|
from syncplay.server import SyncFactory, ConfigurationGetter
|
||||||
|
|
||||||
with open('server.pem') as f:
|
with open('cert/server.pem') as f:
|
||||||
certData = f.read()
|
certData = f.read()
|
||||||
|
|
||||||
certificate = ssl.PrivateCertificate.loadPEM(certData).options()
|
cert = ssl.PrivateCertificate.loadPEM(certData).options()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
argsGetter = ConfigurationGetter()
|
argsGetter = ConfigurationGetter()
|
||||||
|
@ -39,8 +39,9 @@ if __name__ == '__main__':
|
||||||
args.max_username_length,
|
args.max_username_length,
|
||||||
args.stats_db_file
|
args.stats_db_file
|
||||||
)
|
)
|
||||||
endpoint4 = SSL4ServerEndpoint(reactor, int(args.port), certificate, interface='0.0.0.0')
|
factory.options = cert
|
||||||
|
endpoint4 = TCP4ServerEndpoint(reactor, int(args.port))
|
||||||
endpoint4.listen(factory)
|
endpoint4.listen(factory)
|
||||||
endpoint6 = SSL4ServerEndpoint(reactor, int(args.port), certificate, interface='::')
|
endpoint6 = TCP6ServerEndpoint(reactor, int(args.port))
|
||||||
endpoint6.listen(factory)
|
endpoint6.listen(factory)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
Loading…
Reference in New Issue