Show More
@@ -113,6 +113,7 def _hostsettings(ui, hostname): | |||
|
113 | 113 | |
|
114 | 114 | Returns a dict of settings relevant to that hostname. |
|
115 | 115 | """ |
|
116 | bhostname = pycompat.bytesurl(hostname) | |
|
116 | 117 | s = { |
|
117 | 118 | # Whether we should attempt to load default/available CA certs |
|
118 | 119 | # if an explicit ``cafile`` is not defined. |
@@ -162,14 +163,14 def _hostsettings(ui, hostname): | |||
|
162 | 163 | ui.warn(_('warning: connecting to %s using legacy security ' |
|
163 | 164 | 'technology (TLS 1.0); see ' |
|
164 | 165 | 'https://mercurial-scm.org/wiki/SecureConnections for ' |
|
165 | 'more info\n') % hostname) | |
|
166 | 'more info\n') % bhostname) | |
|
166 | 167 | defaultprotocol = 'tls1.0' |
|
167 | 168 | |
|
168 | 169 | key = 'minimumprotocol' |
|
169 | 170 | protocol = ui.config('hostsecurity', key, defaultprotocol) |
|
170 | 171 | validateprotocol(protocol, key) |
|
171 | 172 | |
|
172 | key = '%s:minimumprotocol' % hostname | |
|
173 | key = '%s:minimumprotocol' % bhostname | |
|
173 | 174 | protocol = ui.config('hostsecurity', key, protocol) |
|
174 | 175 | validateprotocol(protocol, key) |
|
175 | 176 | |
@@ -182,16 +183,16 def _hostsettings(ui, hostname): | |||
|
182 | 183 | s['protocol'], s['ctxoptions'], s['protocolui'] = protocolsettings(protocol) |
|
183 | 184 | |
|
184 | 185 | ciphers = ui.config('hostsecurity', 'ciphers') |
|
185 | ciphers = ui.config('hostsecurity', '%s:ciphers' % hostname, ciphers) | |
|
186 | ciphers = ui.config('hostsecurity', '%s:ciphers' % bhostname, ciphers) | |
|
186 | 187 | s['ciphers'] = ciphers |
|
187 | 188 | |
|
188 | 189 | # Look for fingerprints in [hostsecurity] section. Value is a list |
|
189 | 190 | # of <alg>:<fingerprint> strings. |
|
190 | fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname) | |
|
191 | fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % bhostname) | |
|
191 | 192 | for fingerprint in fingerprints: |
|
192 | 193 | if not (fingerprint.startswith(('sha1:', 'sha256:', 'sha512:'))): |
|
193 | 194 | raise error.Abort(_('invalid fingerprint for %s: %s') % ( |
|
194 | hostname, fingerprint), | |
|
195 | bhostname, fingerprint), | |
|
195 | 196 | hint=_('must begin with "sha1:", "sha256:", ' |
|
196 | 197 | 'or "sha512:"')) |
|
197 | 198 | |
@@ -200,7 +201,7 def _hostsettings(ui, hostname): | |||
|
200 | 201 | s['certfingerprints'].append((alg, fingerprint)) |
|
201 | 202 | |
|
202 | 203 | # Fingerprints from [hostfingerprints] are always SHA-1. |
|
203 | for fingerprint in ui.configlist('hostfingerprints', hostname): | |
|
204 | for fingerprint in ui.configlist('hostfingerprints', bhostname): | |
|
204 | 205 | fingerprint = fingerprint.replace(':', '').lower() |
|
205 | 206 | s['certfingerprints'].append(('sha1', fingerprint)) |
|
206 | 207 | s['legacyfingerprint'] = True |
@@ -223,11 +224,11 def _hostsettings(ui, hostname): | |||
|
223 | 224 | # If both fingerprints and a per-host ca file are specified, issue a warning |
|
224 | 225 | # because users should not be surprised about what security is or isn't |
|
225 | 226 | # being performed. |
|
226 | cafile = ui.config('hostsecurity', '%s:verifycertsfile' % hostname) | |
|
227 | cafile = ui.config('hostsecurity', '%s:verifycertsfile' % bhostname) | |
|
227 | 228 | if s['certfingerprints'] and cafile: |
|
228 | 229 | ui.warn(_('(hostsecurity.%s:verifycertsfile ignored when host ' |
|
229 | 230 | 'fingerprints defined; using host fingerprints for ' |
|
230 | 'verification)\n') % hostname) | |
|
231 | 'verification)\n') % bhostname) | |
|
231 | 232 | |
|
232 | 233 | # Try to hook up CA certificate validation unless something above |
|
233 | 234 | # makes it not necessary. |
@@ -237,8 +238,8 def _hostsettings(ui, hostname): | |||
|
237 | 238 | cafile = util.expandpath(cafile) |
|
238 | 239 | if not os.path.exists(cafile): |
|
239 | 240 | raise error.Abort(_('path specified by %s does not exist: %s') % |
|
240 |
('hostsecurity.%s:verifycertsfile' % |
|
|
241 | cafile)) | |
|
241 | ('hostsecurity.%s:verifycertsfile' % ( | |
|
242 | bhostname,), cafile)) | |
|
242 | 243 | s['cafile'] = cafile |
|
243 | 244 | else: |
|
244 | 245 | # Find global certificates file in config. |
@@ -390,7 +391,7 def wrapsocket(sock, keyfile, certfile, | |||
|
390 | 391 | else: |
|
391 | 392 | msg = e.args[1] |
|
392 | 393 | raise error.Abort(_('error loading CA file %s: %s') % ( |
|
393 | settings['cafile'], msg), | |
|
394 | settings['cafile'], util.forcebytestr(msg)), | |
|
394 | 395 | hint=_('file is empty or malformed?')) |
|
395 | 396 | caloaded = True |
|
396 | 397 | elif settings['allowloaddefaultcerts']: |
@@ -583,8 +584,10 def _dnsnamematch(dn, hostname, maxwildc | |||
|
583 | 584 | pats = [] |
|
584 | 585 | if not dn: |
|
585 | 586 | return False |
|
587 | dn = pycompat.bytesurl(dn) | |
|
588 | hostname = pycompat.bytesurl(hostname) | |
|
586 | 589 | |
|
587 |
pieces = dn.split( |
|
|
590 | pieces = dn.split('.') | |
|
588 | 591 | leftmost = pieces[0] |
|
589 | 592 | remainder = pieces[1:] |
|
590 | 593 | wildcards = leftmost.count('*') |
@@ -637,17 +640,17 def _verifycert(cert, hostname): | |||
|
637 | 640 | if _dnsnamematch(value, hostname): |
|
638 | 641 | return |
|
639 | 642 | except wildcarderror as e: |
|
640 | return e.args[0] | |
|
643 | return util.forcebytestr(e.args[0]) | |
|
641 | 644 | |
|
642 | 645 | dnsnames.append(value) |
|
643 | 646 | |
|
644 | 647 | if not dnsnames: |
|
645 | 648 | # The subject is only checked when there is no DNS in subjectAltName. |
|
646 | for sub in cert.get('subject', []): | |
|
649 | for sub in cert.get(r'subject', []): | |
|
647 | 650 | for key, value in sub: |
|
648 | 651 | # According to RFC 2818 the most specific Common Name must |
|
649 | 652 | # be used. |
|
650 | if key == 'commonName': | |
|
653 | if key == r'commonName': | |
|
651 | 654 | # 'subject' entries are unicode. |
|
652 | 655 | try: |
|
653 | 656 | value = value.encode('ascii') |
@@ -658,7 +661,7 def _verifycert(cert, hostname): | |||
|
658 | 661 | if _dnsnamematch(value, hostname): |
|
659 | 662 | return |
|
660 | 663 | except wildcarderror as e: |
|
661 | return e.args[0] | |
|
664 | return util.forcebytestr(e.args[0]) | |
|
662 | 665 | |
|
663 | 666 | dnsnames.append(value) |
|
664 | 667 | |
@@ -780,7 +783,8 def validatesocket(sock): | |||
|
780 | 783 | |
|
781 | 784 | The passed socket must have been created with ``wrapsocket()``. |
|
782 | 785 | """ |
|
783 | host = sock._hgstate['hostname'] | |
|
786 | shost = sock._hgstate['hostname'] | |
|
787 | host = pycompat.bytesurl(shost) | |
|
784 | 788 | ui = sock._hgstate['ui'] |
|
785 | 789 | settings = sock._hgstate['settings'] |
|
786 | 790 | |
@@ -856,7 +860,7 def validatesocket(sock): | |||
|
856 | 860 | 'hostsecurity.%s:fingerprints=%s to trust this server') % |
|
857 | 861 | (host, nicefingerprint)) |
|
858 | 862 | |
|
859 | msg = _verifycert(peercert2, host) | |
|
863 | msg = _verifycert(peercert2, shost) | |
|
860 | 864 | if msg: |
|
861 | 865 | raise error.Abort(_('%s certificate error: %s') % (host, msg), |
|
862 | 866 | hint=_('set hostsecurity.%s:certfingerprints=%s ' |
General Comments 0
You need to be logged in to leave comments.
Login now