comparison mercurial/debugcommands.py @ 33493:9a9f95214f46

debug: add a method to check the state of, and built an SSL cert chain This is only useful on Windows, and avoids the need to use Internet Explorer to build the certificate chain. I can see this being extended in the future to print information about the certificate(s) to help debug issues on any platform. Maybe even perform some of the python checks listed on the secure connections wiki page. But for now, all I need is 1) a command that can be invoked in a setup script to ensure the certificate is installed, and 2) a command that the user can run if/when a certificate changes in the future. It would have been nice to leverage the sslutil library to pick up host specific settings, but attempting to use sslutil.wrapsocket() failed the 'not sslsocket.cipher()' check in it and aborted. The output is a little more chatty than some commands, but I've seen the update take 10+ seconds, and this is only a debug command.
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 30 Mar 2017 00:27:46 -0400
parents 8056481caa81
children e9672de52a23
comparison
equal deleted inserted replaced
33492:14af04391fb9 33493:9a9f95214f46
11 import errno 11 import errno
12 import operator 12 import operator
13 import os 13 import os
14 import random 14 import random
15 import socket 15 import socket
16 import ssl
16 import string 17 import string
17 import sys 18 import sys
18 import tempfile 19 import tempfile
19 import time 20 import time
20 21
2055 r2 = scmutil.revsingle(repo, rev2, 'null').node() 2056 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2056 2057
2057 with repo.wlock(): 2058 with repo.wlock():
2058 repo.setparents(r1, r2) 2059 repo.setparents(r1, r2)
2059 2060
2061 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2062 def debugssl(ui, repo, source=None, **opts):
2063 '''test a secure connection to a server
2064
2065 This builds the certificate chain for the server on Windows, installing the
2066 missing intermediates and trusted root via Windows Update if necessary. It
2067 does nothing on other platforms.
2068
2069 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2070 that server is used. See :hg:`help urls` for more information.
2071
2072 If the update succeeds, retry the original operation. Otherwise, the cause
2073 of the SSL error is likely another issue.
2074 '''
2075 if pycompat.osname != 'nt':
2076 raise error.Abort(_('Certificate chain building is only possible on '
2077 'Windows'))
2078
2079 if not source:
2080 source = "default"
2081 elif not repo:
2082 raise error.Abort(_("there is no Mercurial repository here, and no "
2083 "server specified"))
2084
2085 source, branches = hg.parseurl(ui.expandpath(source))
2086 url = util.url(source)
2087 addr = None
2088
2089 if url.scheme == 'https':
2090 addr = (url.host, url.port or 443)
2091 elif url.scheme == 'ssh':
2092 addr = (url.host, url.port or 22)
2093 else:
2094 raise error.Abort(_("Only https and ssh connections are supported"))
2095
2096 from . import win32
2097
2098 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2099 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2100
2101 try:
2102 s.connect(addr)
2103 cert = s.getpeercert(True)
2104
2105 ui.status(_('Checking the certificate chain for %s.\n') % url.host)
2106
2107 complete = win32.checkcertificatechain(cert, build=False)
2108
2109 if not complete:
2110 ui.status(_('The certificate chain is incomplete. Updating... '))
2111
2112 if not win32.checkcertificatechain(cert):
2113 ui.status(_('Failed.\n'))
2114 else:
2115 ui.status(_('Done.\n'))
2116 else:
2117 ui.status(_('The full certificate chain is available.\n'))
2118 finally:
2119 s.close()
2120
2060 @command('debugsub', 2121 @command('debugsub',
2061 [('r', 'rev', '', 2122 [('r', 'rev', '',
2062 _('revision to check'), _('REV'))], 2123 _('revision to check'), _('REV'))],
2063 _('[-r REV] [REV]')) 2124 _('[-r REV] [REV]'))
2064 def debugsub(ui, repo, rev=None): 2125 def debugsub(ui, repo, rev=None):