diff --git a/SABnzbd.py b/SABnzbd.py
index 280b01f..93f72b0 100755
--- a/SABnzbd.py
+++ b/SABnzbd.py
@@ -1353,10 +1353,11 @@ def main():
logging.info("pygtk2 not found. No SysTray.")
print_modules()
-
- from sabnzbd.utils.sslinfo import sslversion, sslprotocols
- logging.info("SSL version %s", sslversion())
- logging.info("SSL supported protocols %s", str(sslprotocols()))
+
+ import sabnzbd.utils.sslinfo
+ logging.info("SSL version %s", sabnzbd.utils.sslinfo.ssl_version())
+ logging.info("SSL potentially supported protocols %s", str(sabnzbd.utils.sslinfo.ssl_potential()))
+ logging.info("SSL actually supported protocols %s", str(sabnzbd.utils.sslinfo.ssl_protocols()))
cherrylogtoscreen = False
sabnzbd.WEBLOGFILE = None
diff --git a/interfaces/Config/templates/config_server.tmpl b/interfaces/Config/templates/config_server.tmpl
index d073d83..ba5c5fb 100644
--- a/interfaces/Config/templates/config_server.tmpl
+++ b/interfaces/Config/templates/config_server.tmpl
@@ -62,10 +62,24 @@
$T('srv-explain-ssl_type')
@@ -174,10 +188,24 @@
$T('srv-explain-ssl_type')
diff --git a/sabnzbd/downloader.py b/sabnzbd/downloader.py
index e567b53..84c5d13 100644
--- a/sabnzbd/downloader.py
+++ b/sabnzbd/downloader.py
@@ -31,6 +31,7 @@ import sys
import sabnzbd
from sabnzbd.decorators import synchronized, synchronized_CV, CV
from sabnzbd.decoder import Decoder
+from sabnzbd.utils.sslinfo import ssl_protocols
from sabnzbd.newswrapper import NewsWrapper, request_server_info
import sabnzbd.growler as growler
from sabnzbd.constants import *
@@ -60,6 +61,12 @@ class Server(object):
def __init__(self, id, displayname, host, port, timeout, threads, priority, ssl, ssl_type, send_group, username=None,
password=None, optional=False, retention=0, categories=None):
+
+ # If no ssl is protocol set, used highest available one
+ protocols = ssl_protocols()
+ if ssl and protocols and ssl_type not in protocols:
+ ssl_type = protocols[0]
+
self.id = id
self.newid = None
self.restart = False
diff --git a/sabnzbd/interface.py b/sabnzbd/interface.py
index ea1d283..cf92846 100644
--- a/sabnzbd/interface.py
+++ b/sabnzbd/interface.py
@@ -48,6 +48,7 @@ from sabnzbd.downloader import Downloader
from sabnzbd.nzbqueue import NzbQueue
import sabnzbd.wizard
from sabnzbd.utils.servertests import test_nntp_server_dict
+from sabnzbd.utils.sslinfo import ssl_protocols
from sabnzbd.constants import \
REC_RAR_VERSION, NORMAL_PRIORITY, PNFO_NZO_ID_FIELD, PNFO_REPAIR_FIELD, \
@@ -1659,6 +1660,7 @@ class ConfigServer(object):
if sabnzbd.newswrapper.HAVE_SSL:
conf['have_ssl'] = 1
+ conf['ssl_protocols'] = ssl_protocols()
else:
conf['have_ssl'] = 0
diff --git a/sabnzbd/newswrapper.py b/sabnzbd/newswrapper.py
index e787e65..9a03a2a 100644
--- a/sabnzbd/newswrapper.py
+++ b/sabnzbd/newswrapper.py
@@ -30,6 +30,7 @@ import re
import sabnzbd
from sabnzbd.constants import *
import sabnzbd.cfg
+from sabnzbd.utils.sslinfo import ssl_method
try:
from OpenSSL import SSL
@@ -51,6 +52,8 @@ except ImportError:
def __str__(self):
return repr(self.parameter)
+
+
import threading
_RLock = threading.RLock
del threading
@@ -100,7 +103,7 @@ def GetServerParms(host, port):
port = 119
opt = sabnzbd.cfg.ipv6_servers()
''' ... with the following meaning for 'opt':
- Control the use of IPv6 Usenet server addresses. Meaning:
+ Control the use of IPv6 Usenet server addresses. Meaning:
0 = don't use
1 = use when available and reachable (DEFAULT)
2 = force usage (when SABnzbd's detection fails)
@@ -164,16 +167,6 @@ def con(sock, host, port, sslenabled, write_fds, nntp):
except _ssl.Error, e:
nntp.error(e)
-try:
- _SSL_TYPES = {
- 't1': _ssl.TLSv1_METHOD,
- 'v2': _ssl.SSLv2_METHOD,
- 'v3': _ssl.SSLv3_METHOD,
- 'v23': _ssl.SSLv23_METHOD
- }
-except:
- _SSL_TYPES = {}
-
def probablyipv4(ip):
if ip.count('.') == 3 and re.sub('[0123456789.]', '', ip) == '':
@@ -214,7 +207,7 @@ class NNTP(object):
af = socket.AF_INET6
if sslenabled and _ssl:
- ctx = _ssl.Context(_SSL_TYPES.get(ssl_type, _ssl.TLSv1_METHOD))
+ ctx = _ssl.Context(ssl_method(ssl_type))
self.sock = SSLConnection(ctx, socket.socket(af, socktype, proto))
elif sslenabled and not _ssl:
logging.error(T('Error importing OpenSSL module. Connecting with NON-SSL'))
@@ -470,3 +463,4 @@ class SSLConnection(object):
return apply(self._ssl_conn.%s, args)
finally:
self._lock.release()\n""" % (f, f)
+
diff --git a/sabnzbd/skintext.py b/sabnzbd/skintext.py
index 8fd34d9..fd3fd10 100644
--- a/sabnzbd/skintext.py
+++ b/sabnzbd/skintext.py
@@ -542,7 +542,7 @@ SKIN_TEXT = {
'srv-optional' : TT('Optional'), #: Server optional tickbox
'srv-enable' : TT('Enable'), #: Enable server tickbox
'srv-ssl_type' : TT('SSL type'),
- 'srv-explain-ssl_type' : TT('Use TLS1 unless your provider requires otherwise!'),
+ 'srv-explain-ssl_type' : TT('Use the top value, unless your Usenet provider requires otherwise!'),
'button-addServer' : TT('Add Server'), #: Button: Add server
'button-delServer' : TT('Remove Server'), #: Button: Remove server
'button-testServer' : TT('Test Server'), #: Button: Test server
@@ -868,7 +868,7 @@ SKIN_TEXT = {
'Plush-idle' : TT('IDLE'),
'Plush-downloads' : TT('Downloads'),
'Plush-tab-repair' : TT('Queue repair'),
-
+
#smpl skin
'smpl-purgehist' : TT('Delete Completed'),
'smpl-purgefailhistOK?' : TT('Delete the all failed items from the history?'),
diff --git a/sabnzbd/utils/sslinfo.py b/sabnzbd/utils/sslinfo.py
index 9af5ac5..6dbf359 100644
--- a/sabnzbd/utils/sslinfo.py
+++ b/sabnzbd/utils/sslinfo.py
@@ -1,36 +1,72 @@
-import ssl
-import logging
-def sslversion():
- try:
- return ssl.OPENSSL_VERSION
- except:
- logging.info("ssl.OPENSSL_VERSION not defined")
- return None
-
-def sslversioninfo():
+_ALL_PROTOCOLS = ('t12', 't11', 't1', 'v23', 'v3', 'v2')
+_SSL_PROTOCOLS = {}
+
+def ssl_potential():
+ ''' Return a list of potentially supported SSL protocols'''
try:
- return ssl.OPENSSL_VERSION_INFO
- except:
- logging.info("ssl.OPENSSL_VERSION_INFO not defined")
- return None
+ import ssl
+ except ImportError:
+ return []
+ return [p[9:] for p in dir(ssl) if p.startswith('PROTOCOL_')]
-def sslprotocols():
- protocollist = []
+try:
+ from OpenSSL import SSL
+
+ _potential = ssl_potential()
try:
- for i in dir(ssl):
- if i.find('PROTOCOL_') == 0:
- protocollist.append(i[9:])
- return protocollist
- except:
- return None
+ if 'TLSv1_2' in _potential:
+ _SSL_PROTOCOLS['t12'] = SSL.TLSv1_2_METHOD
+ except AttributeError:
+ pass
+ try:
+ if 'TLSv1_1' in _potential:
+ _SSL_PROTOCOLS['t11'] = SSL.TLSv1_1_METHOD
+ except AttributeError:
+ pass
+ try:
+ if 'TLSv1' in _potential:
+ _SSL_PROTOCOLS['t1'] = SSL.TLSv1_METHOD
+ except AttributeError:
+ pass
+ try:
+ if 'SSLv23' in _potential:
+ _SSL_PROTOCOLS['v23'] = SSL.SSLv23_METHOD
+ except AttributeError:
+ pass
+ try:
+ if 'SSLv3' in _potential:
+ _SSL_PROTOCOLS['v3'] = SSL.SSLv3_METHOD
+ except AttributeError:
+ pass
+ try:
+ if 'SSLv2' in _potential:
+ _SSL_PROTOCOLS['v2'] = SSL.SSLv2_METHOD
+ except AttributeError:
+ pass
+except ImportError:
+ SSL = None
-if __name__ == '__main__':
+def ssl_method(method):
+ ''' Translate SSL acronym to a method value '''
+ if method in _SSL_PROTOCOLS:
+ return _SSL_PROTOCOLS[method]
+ else:
+ return _SSL_PROTOCOLS[0]
- logger = logging.getLogger('')
- logger.setLevel(logging.INFO)
+def ssl_protocols():
+ ''' Return acronyms for SSL protocols, highest quality first '''
+ return [p for p in _ALL_PROTOCOLS if p in _SSL_PROTOCOLS]
- print sslversion()
- print sslversioninfo()
- print sslprotocols()
+def ssl_version():
+ if SSL:
+ return SSL.SSLeay_version(SSL.SSLEAY_VERSION)
+ else:
+ return None
+
+
+if __name__ == '__main__':
+ print 'SSL version: %s' % ssl_version()
+ print 'Potentials: %s' % ssl_potential()
+ print 'Actuals: %s' % ssl_protocols()