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