annotate mercurial/sslutil.py @ 18887:2d7fac049d3a

sslutil: abort if peer certificate is not verified for secure use Before this patch, "sslutil.validator" may returns successfully, even if peer certificate is not verified because there is no information in "[hostfingerprints]" and "[web] cacerts". To prevent from sending authentication credential to untrustable SMTP server, validation should be aborted if peer certificate is not verified. This patch introduces "strict" optional argument, and "sslutil.validator" will abort if it is True and peer certificate is not verified.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Tue, 26 Mar 2013 02:28:10 +0900
parents 93b03a222c3e
children 074bd02352c0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
1 # sslutil.py - SSL handling for mercurial
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
2 #
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
6 #
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
7 # This software may be used and distributed according to the terms of the
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
8 # GNU General Public License version 2 or any later version.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
9 import os
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
10
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
11 from mercurial import util
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
12 from mercurial.i18n import _
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
13 try:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
14 # avoid using deprecated/broken FakeSocket in python 2.6
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
15 import ssl
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
16 CERT_REQUIRED = ssl.CERT_REQUIRED
15812
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
17 def ssl_wrap_socket(sock, keyfile, certfile,
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
18 cert_reqs=ssl.CERT_NONE, ca_certs=None):
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
19 sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
20 cert_reqs=cert_reqs, ca_certs=ca_certs)
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
21 # check if wrap_socket failed silently because socket had been closed
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
22 # - see http://bugs.python.org/issue13721
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
23 if not sslsocket.cipher():
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
24 raise util.Abort(_('ssl connection failed'))
0cc4ad757c77 sslutil: verify that wrap_socket really wrapped the socket
Mads Kiilerich <mads@kiilerich.com>
parents: 15160
diff changeset
25 return sslsocket
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
26 except ImportError:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
27 CERT_REQUIRED = 2
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
28
14616
64dfbe576455 sslutil: Restore missing imports of socket and httplib to sslutil
Stephen Thorne <stephen@thorne.id.au>
parents: 14204
diff changeset
29 import socket, httplib
64dfbe576455 sslutil: Restore missing imports of socket and httplib to sslutil
Stephen Thorne <stephen@thorne.id.au>
parents: 14204
diff changeset
30
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
31 def ssl_wrap_socket(sock, key_file, cert_file,
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
32 cert_reqs=CERT_REQUIRED, ca_certs=None):
15160
b2d4400398f3 sslutil: abort when ssl module is needed but not found
Mads Kiilerich <mads@kiilerich.com>
parents: 14667
diff changeset
33 if not util.safehasattr(socket, 'ssl'):
b2d4400398f3 sslutil: abort when ssl module is needed but not found
Mads Kiilerich <mads@kiilerich.com>
parents: 14667
diff changeset
34 raise util.Abort(_('Python SSL support not found'))
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
35 if ca_certs:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
36 raise util.Abort(_(
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
37 'certificate checking requires Python 2.6'))
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
38
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
39 ssl = socket.ssl(sock, key_file, cert_file)
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
40 return httplib.FakeSocket(sock, ssl)
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
41
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
42 def _verifycert(cert, hostname):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
43 '''Verify that cert (in socket.getpeercert() format) matches hostname.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
44 CRLs is not handled.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
45
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
46 Returns error message if any problems are found and None on success.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
47 '''
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
48 if not cert:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
49 return _('no certificate received')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
50 dnsname = hostname.lower()
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
51 def matchdnsname(certname):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
52 return (certname == dnsname or
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
53 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1])
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
54
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
55 san = cert.get('subjectAltName', [])
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
56 if san:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
57 certnames = [value.lower() for key, value in san if key == 'DNS']
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
58 for name in certnames:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
59 if matchdnsname(name):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
60 return None
14666
27b080aa880a sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents: 14616
diff changeset
61 if certnames:
27b080aa880a sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents: 14616
diff changeset
62 return _('certificate is for %s') % ', '.join(certnames)
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
63
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
64 # subject is only checked when subjectAltName is empty
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
65 for s in cert.get('subject', []):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
66 key, value = s[0]
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
67 if key == 'commonName':
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
68 try:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
69 # 'subject' entries are unicode
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
70 certname = value.lower().encode('ascii')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
71 except UnicodeEncodeError:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
72 return _('IDN in certificate not supported')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
73 if matchdnsname(certname):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
74 return None
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
75 return _('certificate is for %s') % certname
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
76 return _('no commonName or subjectAltName found in certificate')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
77
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
78
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
79 # CERT_REQUIRED means fetch the cert from the server all the time AND
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
80 # validate it against the CA store provided in web.cacerts.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
81 #
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
82 # We COMPLETELY ignore CERT_REQUIRED on Python <= 2.5, as it's totally
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
83 # busted on those versions.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
84
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
85 def sslkwargs(ui, host):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
86 cacerts = ui.config('web', 'cacerts')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
87 hostfingerprint = ui.config('hostfingerprints', host)
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
88 if cacerts and not hostfingerprint:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
89 cacerts = util.expandpath(cacerts)
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
90 if not os.path.exists(cacerts):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
91 raise util.Abort(_('could not find web.cacerts: %s') % cacerts)
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
92 return {'ca_certs': cacerts,
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
93 'cert_reqs': CERT_REQUIRED,
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
94 }
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
95 return {}
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
96
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
97 class validator(object):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
98 def __init__(self, ui, host):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
99 self.ui = ui
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
100 self.host = host
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
101
18887
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
102 def __call__(self, sock, strict=False):
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
103 host = self.host
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
104 cacerts = self.ui.config('web', 'cacerts')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
105 hostfingerprint = self.ui.config('hostfingerprints', host)
15813
3ae04eb5e38a sslutil: handle setups without .getpeercert() early in the validator
Mads Kiilerich <mads@kiilerich.com>
parents: 15812
diff changeset
106 if not getattr(sock, 'getpeercert', False): # python 2.5 ?
3ae04eb5e38a sslutil: handle setups without .getpeercert() early in the validator
Mads Kiilerich <mads@kiilerich.com>
parents: 15812
diff changeset
107 if hostfingerprint:
3ae04eb5e38a sslutil: handle setups without .getpeercert() early in the validator
Mads Kiilerich <mads@kiilerich.com>
parents: 15812
diff changeset
108 raise util.Abort(_("host fingerprint for %s can't be "
3ae04eb5e38a sslutil: handle setups without .getpeercert() early in the validator
Mads Kiilerich <mads@kiilerich.com>
parents: 15812
diff changeset
109 "verified (Python too old)") % host)
18887
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
110 if strict:
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
111 raise util.Abort(_("certificate for %s can't be verified "
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
112 "(Python too old)") % host)
16391
9cf7c9d529d0 ui: optionally quiesce ssl verification warnings on python 2.5
Steven Stallion <sstallion@gmail.com>
parents: 15997
diff changeset
113 if self.ui.configbool('ui', 'reportoldssl', True):
9cf7c9d529d0 ui: optionally quiesce ssl verification warnings on python 2.5
Steven Stallion <sstallion@gmail.com>
parents: 15997
diff changeset
114 self.ui.warn(_("warning: certificate for %s can't be verified "
9cf7c9d529d0 ui: optionally quiesce ssl verification warnings on python 2.5
Steven Stallion <sstallion@gmail.com>
parents: 15997
diff changeset
115 "(Python too old)\n") % host)
15813
3ae04eb5e38a sslutil: handle setups without .getpeercert() early in the validator
Mads Kiilerich <mads@kiilerich.com>
parents: 15812
diff changeset
116 return
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
117
15816
4bb59919c905 sslutil: work around validator crash getting certificate on failed sockets
Mads Kiilerich <mads@kiilerich.com>
parents: 15815
diff changeset
118 if not sock.cipher(): # work around http://bugs.python.org/issue13721
4bb59919c905 sslutil: work around validator crash getting certificate on failed sockets
Mads Kiilerich <mads@kiilerich.com>
parents: 15815
diff changeset
119 raise util.Abort(_('%s ssl connection error') % host)
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
120 try:
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
121 peercert = sock.getpeercert(True)
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
122 peercert2 = sock.getpeercert()
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
123 except AttributeError:
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
124 raise util.Abort(_('%s ssl connection error') % host)
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
125
15817
8f377751b510 sslutil: abort properly if no certificate received for https connection
Mads Kiilerich <mads@kiilerich.com>
parents: 15816
diff changeset
126 if not peercert:
8f377751b510 sslutil: abort properly if no certificate received for https connection
Mads Kiilerich <mads@kiilerich.com>
parents: 15816
diff changeset
127 raise util.Abort(_('%s certificate error: '
8f377751b510 sslutil: abort properly if no certificate received for https connection
Mads Kiilerich <mads@kiilerich.com>
parents: 15816
diff changeset
128 'no certificate received') % host)
15814
c3e958b50a22 sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents: 15813
diff changeset
129 peerfingerprint = util.sha1(peercert).hexdigest()
c3e958b50a22 sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents: 15813
diff changeset
130 nicefingerprint = ":".join([peerfingerprint[x:x + 2]
c3e958b50a22 sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents: 15813
diff changeset
131 for x in xrange(0, len(peerfingerprint), 2)])
15815
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
132 if hostfingerprint:
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
133 if peerfingerprint.lower() != \
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
134 hostfingerprint.replace(':', '').lower():
15997
a45516cb8d9f sslutil: more helpful fingerprint mismatch message
Matt Mackall <mpm@selenic.com>
parents: 15817
diff changeset
135 raise util.Abort(_('certificate for %s has unexpected '
a45516cb8d9f sslutil: more helpful fingerprint mismatch message
Matt Mackall <mpm@selenic.com>
parents: 15817
diff changeset
136 'fingerprint %s') % (host, nicefingerprint),
a45516cb8d9f sslutil: more helpful fingerprint mismatch message
Matt Mackall <mpm@selenic.com>
parents: 15817
diff changeset
137 hint=_('check hostfingerprint configuration'))
15815
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
138 self.ui.debug('%s certificate matched fingerprint %s\n' %
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
139 (host, nicefingerprint))
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
140 elif cacerts:
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
141 msg = _verifycert(peercert2, host)
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
142 if msg:
15814
c3e958b50a22 sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents: 15813
diff changeset
143 raise util.Abort(_('%s certificate error: %s') % (host, msg),
c3e958b50a22 sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents: 15813
diff changeset
144 hint=_('configure hostfingerprint %s or use '
c3e958b50a22 sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents: 15813
diff changeset
145 '--insecure to connect insecurely') %
c3e958b50a22 sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents: 15813
diff changeset
146 nicefingerprint)
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
147 self.ui.debug('%s certificate successfully verified\n' % host)
18887
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
148 elif strict:
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
149 raise util.Abort(_('%s certificate with fingerprint %s not '
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
150 'verified') % (host, nicefingerprint),
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
151 hint=_('check hostfingerprints or web.cacerts '
2d7fac049d3a sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18879
diff changeset
152 'config setting'))
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
153 else:
15815
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
154 self.ui.warn(_('warning: %s certificate with fingerprint %s not '
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
155 'verified (check hostfingerprints or web.cacerts '
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
156 'config setting)\n') %
edc3a901a63d sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents: 15814
diff changeset
157 (host, nicefingerprint))