Mercurial > hg
comparison mercurial/sslutil.py @ 28850:3819c349b194
sslutil: document and slightly refactor validation logic
This main purpose of this patch is to make it clearer that fingerprint
pinning takes precedence over CA verification. This will make
subsequent refactoring to the validation code easier to read.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 10 Apr 2016 11:02:58 -0700 |
parents | 1fde84d42f9c |
children | 693b856a4d45 |
comparison
equal
deleted
inserted
replaced
28849:1fde84d42f9c | 28850:3819c349b194 |
---|---|
262 self.ui = ui | 262 self.ui = ui |
263 self.host = host | 263 self.host = host |
264 | 264 |
265 def __call__(self, sock, strict=False): | 265 def __call__(self, sock, strict=False): |
266 host = self.host | 266 host = self.host |
267 cacerts = self.ui.config('web', 'cacerts') | |
268 hostfingerprints = self.ui.configlist('hostfingerprints', host) | |
269 | 267 |
270 if not sock.cipher(): # work around http://bugs.python.org/issue13721 | 268 if not sock.cipher(): # work around http://bugs.python.org/issue13721 |
271 raise error.Abort(_('%s ssl connection error') % host) | 269 raise error.Abort(_('%s ssl connection error') % host) |
272 try: | 270 try: |
273 peercert = sock.getpeercert(True) | 271 peercert = sock.getpeercert(True) |
276 raise error.Abort(_('%s ssl connection error') % host) | 274 raise error.Abort(_('%s ssl connection error') % host) |
277 | 275 |
278 if not peercert: | 276 if not peercert: |
279 raise error.Abort(_('%s certificate error: ' | 277 raise error.Abort(_('%s certificate error: ' |
280 'no certificate received') % host) | 278 'no certificate received') % host) |
279 | |
280 # If a certificate fingerprint is pinned, use it and only it to | |
281 # validate the remote cert. | |
282 hostfingerprints = self.ui.configlist('hostfingerprints', host) | |
281 peerfingerprint = util.sha1(peercert).hexdigest() | 283 peerfingerprint = util.sha1(peercert).hexdigest() |
282 nicefingerprint = ":".join([peerfingerprint[x:x + 2] | 284 nicefingerprint = ":".join([peerfingerprint[x:x + 2] |
283 for x in xrange(0, len(peerfingerprint), 2)]) | 285 for x in xrange(0, len(peerfingerprint), 2)]) |
284 if hostfingerprints: | 286 if hostfingerprints: |
285 fingerprintmatch = False | 287 fingerprintmatch = False |
292 raise error.Abort(_('certificate for %s has unexpected ' | 294 raise error.Abort(_('certificate for %s has unexpected ' |
293 'fingerprint %s') % (host, nicefingerprint), | 295 'fingerprint %s') % (host, nicefingerprint), |
294 hint=_('check hostfingerprint configuration')) | 296 hint=_('check hostfingerprint configuration')) |
295 self.ui.debug('%s certificate matched fingerprint %s\n' % | 297 self.ui.debug('%s certificate matched fingerprint %s\n' % |
296 (host, nicefingerprint)) | 298 (host, nicefingerprint)) |
297 elif cacerts != '!': | 299 return |
300 | |
301 # No pinned fingerprint. Establish trust by looking at the CAs. | |
302 cacerts = self.ui.config('web', 'cacerts') | |
303 if cacerts != '!': | |
298 msg = _verifycert(peercert2, host) | 304 msg = _verifycert(peercert2, host) |
299 if msg: | 305 if msg: |
300 raise error.Abort(_('%s certificate error: %s') % (host, msg), | 306 raise error.Abort(_('%s certificate error: %s') % (host, msg), |
301 hint=_('configure hostfingerprint %s or use ' | 307 hint=_('configure hostfingerprint %s or use ' |
302 '--insecure to connect insecurely') % | 308 '--insecure to connect insecurely') % |