From 9b85c499a4ad52858b866bdf9b8dcc09be4ea83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 8 Mar 2017 10:44:01 +0100 Subject: [PATCH] Always verify certificate with CA The fingerprint is no more used for certificate verification but only to prevent fallback to plain http connection. The system CA is used by default if no ca_certs is configured. issue6270 review27991002 --- CHANGELOG | 1 + doc/installation.rst | 2 +- tryton/jsonrpc.py | 23 ++++++++++------------- tryton/rpc.py | 4 +++- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1dea97103b..c59653f991 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Verify certificate with default CA * Replace URL entry by a toolbar button Version 4.2.0 - 2016-11-28 diff --git a/doc/installation.rst b/doc/installation.rst index 6895965131..23564ae18d 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -4,7 +4,7 @@ Installing tryton Prerequisites ------------- - * Python 2.7 or later (http://www.python.org/) + * Python 2.7.9 or later (http://www.python.org/) * gtk+ 2.6 or later and pygtk 2.22 or later (http://www.pygtk.org/) * gtk+ 3.20 or later and py-gobject3 (http://www.gtk.org/) * librsvg (http://librsvg.sourceforge.net/) diff --git a/tryton/jsonrpc.py b/tryton/jsonrpc.py index 8f1d8cca13..0d8ab46d18 100644 --- a/tryton/jsonrpc.py +++ b/tryton/jsonrpc.py @@ -181,8 +181,7 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport): return self._connection[1] host, self._extra_headers, x509 = self.get_host_info(host) - ca_certs = self.__ca_certs - cert_reqs = ssl.CERT_REQUIRED if ca_certs else ssl.CERT_NONE + ssl_ctx = ssl.create_default_context(cafile=self.__ca_certs) class HTTPSConnection(httplib.HTTPSConnection): @@ -192,8 +191,8 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport): if self._tunnel_host: self.sock = sock self._tunnel() - self.sock = ssl.wrap_socket(sock, self.key_file, - self.cert_file, ca_certs=ca_certs, cert_reqs=cert_reqs) + self.sock = ssl_ctx.wrap_socket( + sock, server_hostname=self.host) def http_connection(): self._connection = host, httplib.HTTPConnection(host, @@ -203,7 +202,7 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport): sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) - def https_connection(): + def https_connection(allow_http=False): self._connection = host, HTTPSConnection(host, timeout=CONNECT_TIMEOUT) try: @@ -222,7 +221,10 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport): enumerate(value), '') return format_hash(hashlib.sha1(peercert).hexdigest()) except ssl.SSLError: - http_connection() + if allow_http: + http_connection() + else: + raise fingerprint = '' if self.__fingerprints is not None and host in self.__fingerprints: @@ -231,15 +233,10 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport): else: http_connection() else: - fingerprint = https_connection() + fingerprint = https_connection(allow_http=True) if self.__fingerprints is not None: - if host in self.__fingerprints and self.__fingerprints[host]: - if self.__fingerprints[host] != fingerprint: - self.close() - raise ssl.SSLError('BadFingerprint') - else: - self.__fingerprints[host] = fingerprint + self.__fingerprints[host] = fingerprint self._connection[1].timeout = DEFAULT_TIMEOUT self._connection[1].sock.settimeout(DEFAULT_TIMEOUT) return self._connection[1] diff --git a/tryton/rpc.py b/tryton/rpc.py index 695c5483be..d899a73431 100644 --- a/tryton/rpc.py +++ b/tryton/rpc.py @@ -3,6 +3,7 @@ import httplib import logging import socket +import ssl import os from functools import partial from tryton.jsonrpc import ServerProxy, ServerPool, Fault @@ -57,7 +58,8 @@ def server_version(host, port): result = connection.common.server.version() logging.getLogger(__name__).debug(repr(result)) return result - except (Fault, socket.error): + except (Fault, socket.error, ssl.SSLError, ssl.CertificateError), e: + logging.getLogger(__name__).error(e) return None