Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
e35f34d
Restore TCP4 and TCP6 server endpoints
albertosottile Feb 3, 2019
894f9dd
TLS: server listens on TLS via IPv4
albertosottile Feb 3, 2019
13fb63b
TLS: client-server implementation with self-issued certs on IPv4
albertosottile Feb 3, 2019
0890db8
TLS: server listens on both IPv4 and IPv6
albertosottile Feb 3, 2019
58ccca5
startTLS: enabled on server and client, TCP stays as default
albertosottile Feb 4, 2019
cecd992
startTLS: added --tls [file] argument in server
albertosottile Feb 4, 2019
09b035e
startTLS: avoid retrying TLS connection if hostname is an IP address
albertosottile Feb 4, 2019
fe11e66
startTLS: support Let's Encrypt certificates
albertosottile Feb 4, 2019
063a191
startTLS: fall back to TCP if server certificate is not validated
albertosottile Feb 4, 2019
a055e3b
startTLS: correct certificate loading and validation
albertosottile Feb 5, 2019
7dfe9d2
startTLS: fix server cert loading function
albertosottile Feb 5, 2019
18e39b4
startTLS: making TLS support (and dependencies) optional
albertosottile Feb 5, 2019
014483b
startTLS: handle ui messages
albertosottile Feb 5, 2019
6d5a618
startTLS: show negotiated TLS version
albertosottile Feb 5, 2019
93052b4
startTLS: separate not-supported messages for client and server
albertosottile Feb 5, 2019
cecb8c9
startTLS: get server certificate only after handshake
albertosottile Feb 7, 2019
51902c8
startTLS: get encrypted connection information after handshake
albertosottile Feb 7, 2019
810a791
startTLS: set minimum protocol version to TLS 1.2
albertosottile Feb 7, 2019
70feed3
startTLS: enable Diffie-Hellman based key exchange on server
albertosottile Feb 7, 2019
8e1f403
startTLS: change DH key parameter filename
albertosottile Feb 7, 2019
00799fa
Restore TCP4 and TCP6 server endpoints
albertosottile Feb 3, 2019
7f9e694
TLS: server listens on TLS via IPv4
albertosottile Feb 3, 2019
8bff90d
TLS: client-server implementation with self-issued certs on IPv4
albertosottile Feb 3, 2019
d7e577e
TLS: server listens on both IPv4 and IPv6
albertosottile Feb 3, 2019
3eeaeed
startTLS: enabled on server and client, TCP stays as default
albertosottile Feb 4, 2019
7910dde
startTLS: added --tls [file] argument in server
albertosottile Feb 4, 2019
81e0a20
startTLS: avoid retrying TLS connection if hostname is an IP address
albertosottile Feb 4, 2019
f16ceed
startTLS: support Let's Encrypt certificates
albertosottile Feb 4, 2019
dc5c63a
startTLS: fall back to TCP if server certificate is not validated
albertosottile Feb 4, 2019
07fd143
startTLS: correct certificate loading and validation
albertosottile Feb 5, 2019
2219bcf
startTLS: fix server cert loading function
albertosottile Feb 5, 2019
0c46f54
startTLS: making TLS support (and dependencies) optional
albertosottile Feb 5, 2019
3fc9dcf
startTLS: handle ui messages
albertosottile Feb 5, 2019
ff3e49b
startTLS: show negotiated TLS version
albertosottile Feb 5, 2019
e6912dc
startTLS: separate not-supported messages for client and server
albertosottile Feb 5, 2019
9e59a85
startTLS: get server certificate only after handshake
albertosottile Feb 7, 2019
abaf178
startTLS: get encrypted connection information after handshake
albertosottile Feb 7, 2019
b19f2ea
startTLS: set minimum protocol version to TLS 1.2
albertosottile Feb 7, 2019
9b43381
startTLS: enable Diffie-Hellman based key exchange on server
albertosottile Feb 7, 2019
9721cf3
startTLS: change DH key parameter filename
albertosottile Feb 7, 2019
dbb2b1c
startTLS: add accepted ciphers list and remove DH params
albertosottile Feb 11, 2019
6dcaf21
startTLS: drop connection if server certificate is not valid
albertosottile Feb 11, 2019
24cb681
startTLS: add link to 'startTLS-server-certificate-invalid' error mes…
albertosottile Feb 11, 2019
23f4d68
startTLS: client-side verification of the certifi bundle
albertosottile Feb 11, 2019
cb66180
startTLS: import and cosmetic fixes
albertosottile Feb 11, 2019
285428f
Check if the server is listening on either IPv4 or IPv6, avoid errors…
albertosottile Feb 11, 2019
8d52acb
Get exact error value from Twisted if IPv6 listener is dual stack
albertosottile Feb 11, 2019
466e853
Add secure connection icon to press for cert details
Et0h Feb 14, 2019
3695c31
startTLS: set lock button appearance on macOS
albertosottile Feb 15, 2019
b35a4fe
startTLS: add custom certificate info dialog
albertosottile Feb 15, 2019
b5f191b
startTLS: multilanguage strings in certificate dialog
albertosottile Feb 15, 2019
0add282
startTLS: set font size in dialog only on macOS
albertosottile Feb 15, 2019
8882c9b
startTLS: amend messages
albertosottile Feb 15, 2019
303032b
Amend green lock icon filenames
albertosottile Feb 15, 2019
6fa2eb0
Travis: add twisted[tls] and certifi modules
albertosottile Feb 15, 2019
8d2472b
buildpy2app: include cffi in the app bundle
albertosottile Feb 15, 2019
2ac6417
buildpy2app: include lua subfolder in the app bundle
albertosottile Feb 15, 2019
9132a9a
startTLS: find certifi.where() if embedded in a zip file
albertosottile Feb 15, 2019
0f10161
Remove unneeded wrapClientTLS import
albertosottile Feb 15, 2019
e16775c
Explicitely set TLS options to None when server config is not valid
albertosottile Feb 16, 2019
b655085
Update third-party-notices
albertosottile Feb 16, 2019
9e19fcc
Add missing space in TLS cipher messages
albertosottile Feb 17, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ venv

/SyncPlay.egg-info
/build
/cert
/dist
/syncplay v*
/syncplay_v*
Expand All @@ -13,4 +14,4 @@ dist.7z
.*
!.travis.yml
!.appveyor.yml
__pycache__
__pycache__
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ before_install:
- python3 -c "from py2app.recipes import pyside2"

install:
- pip3 install twisted appnope requests
- pip3 install twisted[tls] appnope requests certifi

before_deploy:
- pip3 install dmgbuild
Expand Down
3 changes: 2 additions & 1 deletion buildPy2app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
APP = ['syncplayClient.py']
DATA_FILES = [
('resources', glob('resources/*.png') + glob('resources/*.rtf') + glob('resources/*.lua')),
('resources/lua/intf', glob('resources/lua/intf/*.lua'))
]
OPTIONS = {
'iconfile': 'resources/icon.icns',
'extra_scripts': 'syncplayServer.py',
'includes': {'PySide2.QtCore', 'PySide2.QtUiTools', 'PySide2.QtGui', 'PySide2.QtWidgets', 'certifi'},
'includes': {'PySide2.QtCore', 'PySide2.QtUiTools', 'PySide2.QtGui', 'PySide2.QtWidgets', 'certifi', 'cffi'},
'excludes': {'PySide', 'PySide.QtCore', 'PySide.QtUiTools', 'PySide.QtGui'},
'qt_plugins': [
'platforms/libqcocoa.dylib',
Expand Down
1 change: 1 addition & 0 deletions buildPy2exe.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ def run(self):
'resources/mpv.png', 'resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
'resources/lock_green.png', 'resources/lock_green_dialog.png',
'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png',
'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png', 'resources/arrow_switch.png',
'resources/film_go.png', 'resources/world_go.png', 'resources/arrow_refresh.png', 'resources/bullet_right_grey.png',
Expand Down
Binary file added resources/lock_green.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/lock_green_dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
163 changes: 142 additions & 21 deletions resources/third-party-notices.rtf
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\vieww13920\viewh8980\viewkind0
\deftab529
\pard\tx529\pardeftab529\pardirnatural\partightenfactor0

Expand All @@ -24,25 +25,6 @@ The above copyright notice and this permission notice shall be included in all\
copies or substantial portions of the Software.\
\

\b PySide\

\b0 \
Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).\
Contact: PySide team <contact@pyside.org>\
\
This library is free software; you can redistribute it and/or\
modify it under the terms of the GNU Lesser General Public\
License as published by the Free Software Foundation; either\
version 2.1 of the License, or (at your option) any later version.\
This library is distributed in the hope that it will be useful,\
but WITHOUT ANY WARRANTY; without even the implied warranty of\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\
Lesser General Public License for more details.\
\
You should have received a copy of the GNU Lesser General Public License\
along with this program. If not, see <http://www.gnu.org/licenses/>\
\

\b Qt for Python\

\b0 \
Expand Down Expand Up @@ -318,4 +300,143 @@ http://www.apache.org/licenses/LICENSE-2.0\
Unless required by applicable law or agreed to in writing, software distributed under the \
License is distributed on an \'93AS IS\'94 BASIS, WITHOUT WARRANTIES OR CONDI-\
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\
uage governing permissions and limitations under the License.}
uage governing permissions and limitations under the License.\
\

\b python-certifi
\b0 \
\
This Source Code Form is subject to the terms of the Mozilla Public License,\
v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain\
one at http://mozilla.org/MPL/2.0/.\
\

\b cffi
\b0 \
\
\pard\pardeftab720\partightenfactor0
\cf0 This package has been mostly done by Armin Rigo with help from\
Maciej Fija\uc0\u322 kowski. The idea is heavily based (although not directly\
copied) from LuaJIT ffi by Mike Pall.\
\
Other contributors:\
\
Google Inc.\
\pard\tx529\pardeftab529\pardirnatural\partightenfactor0
\cf0 \
The MIT License\
\
Permission is hereby granted, free of charge, to any person \
obtaining a copy of this software and associated documentation \
files (the "Software"), to deal in the Software without \
restriction, including without limitation the rights to use, \
copy, modify, merge, publish, distribute, sublicense, and/or \
sell copies of the Software, and to permit persons to whom the \
Software is furnished to do so, subject to the following conditions:\
\
The above copyright notice and this permission notice shall be included \
in all copies or substantial portions of the Software.\
\
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS \
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL \
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \
DEALINGS IN THE SOFTWARE.\
\

\b service-identity
\b0 \
\
Copyright (c) 2014 Hynek Schlawack\
\
Permission is hereby granted, free of charge, to any person obtaining a copy of\
this software and associated documentation files (the "Software"), to deal in\
the Software without restriction, including without limitation the rights to\
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\
of the Software, and to permit persons to whom the Software is furnished to do\
so, subject to the following conditions:\
\
The above copyright notice and this permission notice shall be included in all\
copies or substantial portions of the Software.\
\
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\
SOFTWARE.\
\

\b pyopenssl
\b0 \
\
Licensed under the Apache License, Version 2.0 (the \'93License\'94); you may not use this file\
except in compliance with the License. You may obtain a copy of the License at\
\
http://www.apache.org/licenses/LICENSE-2.0\
\
Unless required by applicable law or agreed to in writing, software distributed under the \
License is distributed on an \'93AS IS\'94 BASIS, WITHOUT WARRANTIES OR CONDI-\
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\
uage governing permissions and limitations under the License.\
\

\b cryptography
\b0 \
\
Authors listed here: https://github.com/pyca/cryptography/blob/master/AUTHORS.rst\
\
Licensed under the Apache License, Version 2.0 (the \'93License\'94); you may not use this file\
except in compliance with the License. You may obtain a copy of the License at\
\
http://www.apache.org/licenses/LICENSE-2.0\
\
Unless required by applicable law or agreed to in writing, software distributed under the \
License is distributed on an \'93AS IS\'94 BASIS, WITHOUT WARRANTIES OR CONDI-\
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\
uage governing permissions and limitations under the License.\
\

\b Icons\
\

\b0 Syncplay uses the following icons and images:\
\
- Silk icon set 1.3\
_________________________________________\
Mark James\
http://www.famfamfam.com/lab/icons/silk/\
_________________________________________\
\
This work is licensed under a\
Creative Commons Attribution 2.5 License.\
[ http://creativecommons.org/licenses/by/2.5/ ]\
\
This means you may use it for any purpose,\
and make any changes you like.\
All I ask is that you include a link back\
to this page in your credits.\
\
Are you using this icon set? Send me an email\
(including a link or picture if available) to\
mjames@gmail.com\
\
Any other questions about this icon set please\
contact mjames@gmail.com\
\
- Silk Companion 1\
\
\pard\pardeftab720\partightenfactor0
\cf0 Copyright Damien Guard - CC-BY 3.0\
https://damieng.com/creative/icons/silk-companion-1-icons\
\
- Padlock free icon\
CC-BY 3.0\
Icon made by Maxim Basinski from https://www.flaticon.com/free-icon/padlock_291248\
\
\pard\tx529\pardeftab529\pardirnatural\partightenfactor0
\cf0 \
}
2 changes: 1 addition & 1 deletion syncplay/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version = '1.6.3'
revision = ' beta'
milestone = 'Yoitsu'
release_number = '72'
release_number = '73'
projectURL = 'https://syncplay.pl/'
38 changes: 37 additions & 1 deletion syncplay/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import ast
import collections
import hashlib
import os
import os.path
import random
import re
Expand All @@ -16,6 +17,24 @@
from twisted.internet import reactor, task, defer, threads
from twisted.application.internet import ClientService

try:
import certifi
from twisted.internet.ssl import Certificate, optionsForClientTLS
certPath = certifi.where()
if os.path.exists(certPath):
os.environ['SSL_CERT_FILE'] = certPath
elif 'zip' in certPath:
import tempfile
import zipfile
zipPath, memberPath = certPath.split('.zip/')
zipPath += '.zip'
archive = zipfile.ZipFile(zipPath, 'r')
tmpDir = tempfile.gettempdir()
extractedPath = archive.extract(memberPath, tmpDir)
os.environ['SSL_CERT_FILE'] = extractedPath
except:
pass

from syncplay import utils, constants, version
from syncplay.constants import PRIVACY_SENDHASHED_MODE, PRIVACY_DONTSEND_MODE, \
PRIVACY_HIDDENFILENAME
Expand Down Expand Up @@ -108,6 +127,8 @@ def __init__(self, playerClass, ui, config):
self.fileSwitch = FileSwitchManager(self)
self.playlist = SyncplayPlaylist(self)

self._serverSupportsTLS = True

if constants.LIST_RELATIVE_CONFIGS and 'loadedRelativePaths' in self._config and self._config['loadedRelativePaths']:
paths = "; ".join(self._config['loadedRelativePaths'])
self.ui.showMessage(getMessage("relative-config-notification").format(paths), noPlayer=True, noTimestamp=True)
Expand Down Expand Up @@ -388,6 +409,7 @@ def setUserOffset(self, time):
self.ui.showMessage(getMessage("current-offset-notification").format(self._userOffset))

def onDisconnect(self):
self.ui.setSSLMode(False)
if self._config['pauseOnLeave']:
self.setPaused(True)
self.lastPausedOnLeaveTime = time.time()
Expand Down Expand Up @@ -704,9 +726,20 @@ def start(self, host, port):
host = host.strip('[]')
port = int(port)
self._endpoint = HostnameEndpoint(reactor, host, port)
try:
caCertFP = open(os.environ['SSL_CERT_FILE'])
caCertTwisted = Certificate.loadPEM(caCertFP.read())
caCertFP.close()
self.protocolFactory.options = optionsForClientTLS(hostname=host)
self._clientSupportsTLS = True
except Exception as e:
self.ui.showDebugMessage(str(e))
self.protocolFactory.options = None
self._clientSupportsTLS = False

def retry(retries):
self._lastGlobalUpdate = None
self.ui.setSSLMode(False)
if retries == 0:
self.onDisconnect()
if retries > constants.RECONNECT_RETRIES:
Expand All @@ -719,7 +752,7 @@ def retry(retries):
self.reconnecting = True
return(0.1 * (2 ** min(retries, 5)))

self._reconnectingService = ClientService(self._endpoint, self.protocolFactory , retryPolicy=retry)
self._reconnectingService = ClientService(self._endpoint, self.protocolFactory, retryPolicy=retry)
waitForConnection = self._reconnectingService.whenConnected(failAfterFailures=1)
self._reconnectingService.startService()

Expand Down Expand Up @@ -1456,6 +1489,9 @@ def showChatMessage(self, username, userMessage):
self.showOSDMessage(messageString, duration=constants.OSD_DURATION)
self.__ui.showMessage(messageString)

def setSSLMode(self, sslMode, sslInformation=""):
self.__ui.setSSLMode(sslMode, sslInformation)

def showMessage(self, message, noPlayer=False, noTimestamp=False, OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
if not noPlayer:
self.showOSDMessage(message, duration=constants.OSD_DURATION, OSDType=OSDType, mood=mood)
Expand Down
17 changes: 17 additions & 0 deletions syncplay/messages_de.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,20 @@
"userguide-menu-label": "&Benutzerhandbuch öffnen",
"update-menu-label": "auf &Aktualisierung prüfen",

# startTLS messages - TODO: Translate
"startTLS-initiated": "Attempting secure connection",
"startTLS-secure-connection-ok": "Secure connection established ({})",
"startTLS-server-certificate-invalid": 'Secure connection failed. The server uses an invalid security certificate. This communication could be intercepted by a third party. For further details and troubleshooting see <a href="https://syncplay.pl/trouble">here</a>.',
"startTLS-not-supported-client": "This client does not support TLS",
"startTLS-not-supported-server": "This server does not support TLS",

# TLS certificate dialog - TODO: Translate
"tls-information-title": "Certificate Details",
"tls-dialog-status-label": "<strong>Syncplay is using an encrypted connection to {}.</strong>",
"tls-dialog-desc-label": "Encryption with a digital certificate keeps information private as it is sent to or from the<br/>server {}.",
"tls-dialog-connection-label": "Information encrypted using Transport Layer Security (TLS), version {} with the cipher<br/>suite: {}.",
"tls-dialog-certificate-label": "Certificate issued by {} valid until {}.",

# About dialog - TODO: Translate
"about-menu-label": "&About Syncplay",
"about-dialog-title": "About Syncplay",
Expand Down Expand Up @@ -403,6 +417,8 @@
"reset-tooltip": "Alle Einstellungen auf Standardwerte zurücksetzen.",
"update-server-list-tooltip": "Mit syncplay.pl verbinden um die Liste öffentlicher Server zu aktualisieren.",

"sslconnection-tooltip": "Securely connected to server. Click for certificate details.", # TODO: Translate

"joinroom-tooltip": "Den aktuellen Raum verlassen und stattdessen den angegebenen betreten.",
"seektime-msgbox-label": "Springe zur angegebenen Zeit (in Sekunden oder min:sek). Verwende +/- zum relativen Springen.",
"ready-tooltip": "Zeigt an, ob du bereit zum anschauen bist",
Expand Down Expand Up @@ -438,6 +454,7 @@
"server-chat-maxchars-argument": "Maximum number of characters in a chat message (default is {})", # TODO: Translate
"server-maxusernamelength-argument": "Maximum number of characters in a username (default is {})", # TODO: Translate
"server-stats-db-file-argument": "Enable server stats using the SQLite db file provided", # TODO: Translate
"server-startTLS-argument": "Enable TLS connections using the certificate files in the path provided", # TODO: Translate
"server-messed-up-motd-unescaped-placeholders": "Die Nachricht des Tages hat unmaskierte Platzhalter. Alle $-Zeichen sollten verdoppelt werden ($$).",
"server-messed-up-motd-too-long": "Die Nachricht des Tages ist zu lang - Maximal {} Zeichen, aktuell {}.",

Expand Down
Loading