tests/test-url.py
changeset 43076 2372284d9457
parent 37999 d088810c496e
child 45682 d2e1dcd4490d
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
     1 # coding=utf-8
     1 # coding=utf-8
     2 from __future__ import absolute_import, print_function
     2 from __future__ import absolute_import, print_function
     3 
     3 
     4 import doctest
     4 import doctest
     5 import os
     5 import os
       
     6 
     6 
     7 
     7 def check(a, b):
     8 def check(a, b):
     8     if a != b:
     9     if a != b:
     9         print((a, b))
    10         print((a, b))
    10 
    11 
       
    12 
    11 def cert(cn):
    13 def cert(cn):
    12     return {'subject': ((('commonName', cn),),)}
    14     return {'subject': ((('commonName', cn),),)}
    13 
    15 
    14 from mercurial import (
    16 
    15     sslutil,
    17 from mercurial import sslutil
    16 )
       
    17 
    18 
    18 _verifycert = sslutil._verifycert
    19 _verifycert = sslutil._verifycert
    19 # Test non-wildcard certificates
    20 # Test non-wildcard certificates
    20 check(_verifycert(cert('example.com'), 'example.com'),
    21 check(_verifycert(cert('example.com'), 'example.com'), None)
    21       None)
    22 check(
    22 check(_verifycert(cert('example.com'), 'www.example.com'),
    23     _verifycert(cert('example.com'), 'www.example.com'),
    23       b'certificate is for example.com')
    24     b'certificate is for example.com',
    24 check(_verifycert(cert('www.example.com'), 'example.com'),
    25 )
    25       b'certificate is for www.example.com')
    26 check(
       
    27     _verifycert(cert('www.example.com'), 'example.com'),
       
    28     b'certificate is for www.example.com',
       
    29 )
    26 
    30 
    27 # Test wildcard certificates
    31 # Test wildcard certificates
    28 check(_verifycert(cert('*.example.com'), 'www.example.com'),
    32 check(_verifycert(cert('*.example.com'), 'www.example.com'), None)
    29       None)
    33 check(
    30 check(_verifycert(cert('*.example.com'), 'example.com'),
    34     _verifycert(cert('*.example.com'), 'example.com'),
    31       b'certificate is for *.example.com')
    35     b'certificate is for *.example.com',
    32 check(_verifycert(cert('*.example.com'), 'w.w.example.com'),
    36 )
    33       b'certificate is for *.example.com')
    37 check(
       
    38     _verifycert(cert('*.example.com'), 'w.w.example.com'),
       
    39     b'certificate is for *.example.com',
       
    40 )
    34 
    41 
    35 # Test subjectAltName
    42 # Test subjectAltName
    36 san_cert = {'subject': ((('commonName', 'example.com'),),),
    43 san_cert = {
    37             'subjectAltName': (('DNS', '*.example.net'),
    44     'subject': ((('commonName', 'example.com'),),),
    38                                ('DNS', 'example.net'))}
    45     'subjectAltName': (('DNS', '*.example.net'), ('DNS', 'example.net')),
    39 check(_verifycert(san_cert, 'example.net'),
    46 }
    40       None)
    47 check(_verifycert(san_cert, 'example.net'), None)
    41 check(_verifycert(san_cert, 'foo.example.net'),
    48 check(_verifycert(san_cert, 'foo.example.net'), None)
    42       None)
       
    43 # no fallback to subject commonName when subjectAltName has DNS
    49 # no fallback to subject commonName when subjectAltName has DNS
    44 check(_verifycert(san_cert, 'example.com'),
    50 check(
    45       b'certificate is for *.example.net, example.net')
    51     _verifycert(san_cert, 'example.com'),
       
    52     b'certificate is for *.example.net, example.net',
       
    53 )
    46 # fallback to subject commonName when no DNS in subjectAltName
    54 # fallback to subject commonName when no DNS in subjectAltName
    47 san_cert = {'subject': ((('commonName', 'example.com'),),),
    55 san_cert = {
    48             'subjectAltName': (('IP Address', '8.8.8.8'),)}
    56     'subject': ((('commonName', 'example.com'),),),
       
    57     'subjectAltName': (('IP Address', '8.8.8.8'),),
       
    58 }
    49 check(_verifycert(san_cert, 'example.com'), None)
    59 check(_verifycert(san_cert, 'example.com'), None)
    50 
    60 
    51 # Avoid some pitfalls
    61 # Avoid some pitfalls
    52 check(_verifycert(cert('*.foo'), 'foo'),
    62 check(_verifycert(cert('*.foo'), 'foo'), b'certificate is for *.foo')
    53       b'certificate is for *.foo')
       
    54 check(_verifycert(cert('*o'), 'foo'), None)
    63 check(_verifycert(cert('*o'), 'foo'), None)
    55 
    64 
    56 check(_verifycert({'subject': ()},
    65 check(
    57                   'example.com'),
    66     _verifycert({'subject': ()}, 'example.com'),
    58       b'no commonName or subjectAltName found in certificate')
    67     b'no commonName or subjectAltName found in certificate',
    59 check(_verifycert(None, 'example.com'),
    68 )
    60       b'no certificate received')
    69 check(_verifycert(None, 'example.com'), b'no certificate received')
    61 
    70 
    62 # Unicode (IDN) certname isn't supported
    71 # Unicode (IDN) certname isn't supported
    63 check(_verifycert(cert(u'\u4f8b.jp'), 'example.jp'),
    72 check(
    64       b'IDN in certificate not supported')
    73     _verifycert(cert(u'\u4f8b.jp'), 'example.jp'),
       
    74     b'IDN in certificate not supported',
       
    75 )
    65 
    76 
    66 # The following tests are from CPython's test_ssl.py.
    77 # The following tests are from CPython's test_ssl.py.
    67 check(_verifycert(cert('example.com'), 'example.com'), None)
    78 check(_verifycert(cert('example.com'), 'example.com'), None)
    68 check(_verifycert(cert('example.com'), 'ExAmple.cOm'), None)
    79 check(_verifycert(cert('example.com'), 'ExAmple.cOm'), None)
    69 check(_verifycert(cert('example.com'), 'www.example.com'),
    80 check(
    70       b'certificate is for example.com')
    81     _verifycert(cert('example.com'), 'www.example.com'),
    71 check(_verifycert(cert('example.com'), '.example.com'),
    82     b'certificate is for example.com',
    72       b'certificate is for example.com')
    83 )
    73 check(_verifycert(cert('example.com'), 'example.org'),
    84 check(
    74       b'certificate is for example.com')
    85     _verifycert(cert('example.com'), '.example.com'),
    75 check(_verifycert(cert('example.com'), 'exampleXcom'),
    86     b'certificate is for example.com',
    76       b'certificate is for example.com')
    87 )
       
    88 check(
       
    89     _verifycert(cert('example.com'), 'example.org'),
       
    90     b'certificate is for example.com',
       
    91 )
       
    92 check(
       
    93     _verifycert(cert('example.com'), 'exampleXcom'),
       
    94     b'certificate is for example.com',
       
    95 )
    77 check(_verifycert(cert('*.a.com'), 'foo.a.com'), None)
    96 check(_verifycert(cert('*.a.com'), 'foo.a.com'), None)
    78 check(_verifycert(cert('*.a.com'), 'bar.foo.a.com'),
    97 check(
    79       b'certificate is for *.a.com')
    98     _verifycert(cert('*.a.com'), 'bar.foo.a.com'), b'certificate is for *.a.com'
    80 check(_verifycert(cert('*.a.com'), 'a.com'),
    99 )
    81       b'certificate is for *.a.com')
   100 check(_verifycert(cert('*.a.com'), 'a.com'), b'certificate is for *.a.com')
    82 check(_verifycert(cert('*.a.com'), 'Xa.com'),
   101 check(_verifycert(cert('*.a.com'), 'Xa.com'), b'certificate is for *.a.com')
    83       b'certificate is for *.a.com')
   102 check(_verifycert(cert('*.a.com'), '.a.com'), b'certificate is for *.a.com')
    84 check(_verifycert(cert('*.a.com'), '.a.com'),
       
    85       b'certificate is for *.a.com')
       
    86 
   103 
    87 # only match one left-most wildcard
   104 # only match one left-most wildcard
    88 check(_verifycert(cert('f*.com'), 'foo.com'), None)
   105 check(_verifycert(cert('f*.com'), 'foo.com'), None)
    89 check(_verifycert(cert('f*.com'), 'f.com'), None)
   106 check(_verifycert(cert('f*.com'), 'f.com'), None)
    90 check(_verifycert(cert('f*.com'), 'bar.com'),
   107 check(_verifycert(cert('f*.com'), 'bar.com'), b'certificate is for f*.com')
    91       b'certificate is for f*.com')
   108 check(_verifycert(cert('f*.com'), 'foo.a.com'), b'certificate is for f*.com')
    92 check(_verifycert(cert('f*.com'), 'foo.a.com'),
   109 check(_verifycert(cert('f*.com'), 'bar.foo.com'), b'certificate is for f*.com')
    93       b'certificate is for f*.com')
       
    94 check(_verifycert(cert('f*.com'), 'bar.foo.com'),
       
    95       b'certificate is for f*.com')
       
    96 
   110 
    97 # NULL bytes are bad, CVE-2013-4073
   111 # NULL bytes are bad, CVE-2013-4073
    98 check(_verifycert(cert('null.python.org\x00example.org'),
   112 check(
    99                   'null.python.org\x00example.org'), None)
   113     _verifycert(
   100 check(_verifycert(cert('null.python.org\x00example.org'),
   114         cert('null.python.org\x00example.org'), 'null.python.org\x00example.org'
   101                   'example.org'),
   115     ),
   102       b'certificate is for null.python.org\x00example.org')
   116     None,
   103 check(_verifycert(cert('null.python.org\x00example.org'),
   117 )
   104                   'null.python.org'),
   118 check(
   105       b'certificate is for null.python.org\x00example.org')
   119     _verifycert(cert('null.python.org\x00example.org'), 'example.org'),
       
   120     b'certificate is for null.python.org\x00example.org',
       
   121 )
       
   122 check(
       
   123     _verifycert(cert('null.python.org\x00example.org'), 'null.python.org'),
       
   124     b'certificate is for null.python.org\x00example.org',
       
   125 )
   106 
   126 
   107 # error cases with wildcards
   127 # error cases with wildcards
   108 check(_verifycert(cert('*.*.a.com'), 'bar.foo.a.com'),
   128 check(
   109       b'certificate is for *.*.a.com')
   129     _verifycert(cert('*.*.a.com'), 'bar.foo.a.com'),
   110 check(_verifycert(cert('*.*.a.com'), 'a.com'),
   130     b'certificate is for *.*.a.com',
   111       b'certificate is for *.*.a.com')
   131 )
   112 check(_verifycert(cert('*.*.a.com'), 'Xa.com'),
   132 check(_verifycert(cert('*.*.a.com'), 'a.com'), b'certificate is for *.*.a.com')
   113       b'certificate is for *.*.a.com')
   133 check(_verifycert(cert('*.*.a.com'), 'Xa.com'), b'certificate is for *.*.a.com')
   114 check(_verifycert(cert('*.*.a.com'), '.a.com'),
   134 check(_verifycert(cert('*.*.a.com'), '.a.com'), b'certificate is for *.*.a.com')
   115       b'certificate is for *.*.a.com')
   135 
   116 
   136 check(_verifycert(cert('a.*.com'), 'a.foo.com'), b'certificate is for a.*.com')
   117 check(_verifycert(cert('a.*.com'), 'a.foo.com'),
   137 check(_verifycert(cert('a.*.com'), 'a..com'), b'certificate is for a.*.com')
   118       b'certificate is for a.*.com')
   138 check(_verifycert(cert('a.*.com'), 'a.com'), b'certificate is for a.*.com')
   119 check(_verifycert(cert('a.*.com'), 'a..com'),
       
   120       b'certificate is for a.*.com')
       
   121 check(_verifycert(cert('a.*.com'), 'a.com'),
       
   122       b'certificate is for a.*.com')
       
   123 
   139 
   124 # wildcard doesn't match IDNA prefix 'xn--'
   140 # wildcard doesn't match IDNA prefix 'xn--'
   125 idna = u'püthon.python.org'.encode('idna').decode('ascii')
   141 idna = u'püthon.python.org'.encode('idna').decode('ascii')
   126 check(_verifycert(cert(idna), idna), None)
   142 check(_verifycert(cert(idna), idna), None)
   127 check(_verifycert(cert('x*.python.org'), idna),
   143 check(
   128       b'certificate is for x*.python.org')
   144     _verifycert(cert('x*.python.org'), idna),
   129 check(_verifycert(cert('xn--p*.python.org'), idna),
   145     b'certificate is for x*.python.org',
   130       b'certificate is for xn--p*.python.org')
   146 )
       
   147 check(
       
   148     _verifycert(cert('xn--p*.python.org'), idna),
       
   149     b'certificate is for xn--p*.python.org',
       
   150 )
   131 
   151 
   132 # wildcard in first fragment and  IDNA A-labels in sequent fragments
   152 # wildcard in first fragment and  IDNA A-labels in sequent fragments
   133 # are supported.
   153 # are supported.
   134 idna = u'www*.pythön.org'.encode('idna').decode('ascii')
   154 idna = u'www*.pythön.org'.encode('idna').decode('ascii')
   135 check(_verifycert(cert(idna),
   155 check(
   136                   u'www.pythön.org'.encode('idna').decode('ascii')),
   156     _verifycert(cert(idna), u'www.pythön.org'.encode('idna').decode('ascii')),
   137       None)
   157     None,
   138 check(_verifycert(cert(idna),
   158 )
   139                   u'www1.pythön.org'.encode('idna').decode('ascii')),
   159 check(
   140       None)
   160     _verifycert(cert(idna), u'www1.pythön.org'.encode('idna').decode('ascii')),
   141 check(_verifycert(cert(idna),
   161     None,
   142                   u'ftp.pythön.org'.encode('idna').decode('ascii')),
   162 )
   143       b'certificate is for www*.xn--pythn-mua.org')
   163 check(
   144 check(_verifycert(cert(idna),
   164     _verifycert(cert(idna), u'ftp.pythön.org'.encode('idna').decode('ascii')),
   145                   u'pythön.org'.encode('idna').decode('ascii')),
   165     b'certificate is for www*.xn--pythn-mua.org',
   146       b'certificate is for www*.xn--pythn-mua.org')
   166 )
       
   167 check(
       
   168     _verifycert(cert(idna), u'pythön.org'.encode('idna').decode('ascii')),
       
   169     b'certificate is for www*.xn--pythn-mua.org',
       
   170 )
   147 
   171 
   148 c = {
   172 c = {
   149     'notAfter': 'Jun 26 21:41:46 2011 GMT',
   173     'notAfter': 'Jun 26 21:41:46 2011 GMT',
   150     'subject': (((u'commonName', u'linuxfrz.org'),),),
   174     'subject': (((u'commonName', u'linuxfrz.org'),),),
   151     'subjectAltName': (
   175     'subjectAltName': (
   152         ('DNS', 'linuxfr.org'),
   176         ('DNS', 'linuxfr.org'),
   153         ('DNS', 'linuxfr.com'),
   177         ('DNS', 'linuxfr.com'),
   154         ('othername', '<unsupported>'),
   178         ('othername', '<unsupported>'),
   155     )
   179     ),
   156 }
   180 }
   157 check(_verifycert(c, 'linuxfr.org'), None)
   181 check(_verifycert(c, 'linuxfr.org'), None)
   158 check(_verifycert(c, 'linuxfr.com'), None)
   182 check(_verifycert(c, 'linuxfr.com'), None)
   159 # Not a "DNS" entry
   183 # Not a "DNS" entry
   160 check(_verifycert(c, '<unsupported>'),
   184 check(
   161       b'certificate is for linuxfr.org, linuxfr.com')
   185     _verifycert(c, '<unsupported>'),
       
   186     b'certificate is for linuxfr.org, linuxfr.com',
       
   187 )
   162 # When there is a subjectAltName, commonName isn't used
   188 # When there is a subjectAltName, commonName isn't used
   163 check(_verifycert(c, 'linuxfrz.org'),
   189 check(
   164       b'certificate is for linuxfr.org, linuxfr.com')
   190     _verifycert(c, 'linuxfrz.org'),
       
   191     b'certificate is for linuxfr.org, linuxfr.com',
       
   192 )
   165 
   193 
   166 # A pristine real-world example
   194 # A pristine real-world example
   167 c = {
   195 c = {
   168     'notAfter': 'Dec 18 23:59:59 2011 GMT',
   196     'notAfter': 'Dec 18 23:59:59 2011 GMT',
   169     'subject': (
   197     'subject': (
   188         ((u'stateOrProvinceName', u'California'),),
   216         ((u'stateOrProvinceName', u'California'),),
   189         ((u'localityName', u'Mountain View'),),
   217         ((u'localityName', u'Mountain View'),),
   190         ((u'organizationName', u'Google Inc'),),
   218         ((u'organizationName', u'Google Inc'),),
   191     ),
   219     ),
   192 }
   220 }
   193 check(_verifycert(c, 'mail.google.com'),
   221 check(
   194       b'no commonName or subjectAltName found in certificate')
   222     _verifycert(c, 'mail.google.com'),
       
   223     b'no commonName or subjectAltName found in certificate',
       
   224 )
   195 
   225 
   196 # No DNS entry in subjectAltName but a commonName
   226 # No DNS entry in subjectAltName but a commonName
   197 c = {
   227 c = {
   198     'notAfter': 'Dec 18 23:59:59 2099 GMT',
   228     'notAfter': 'Dec 18 23:59:59 2099 GMT',
   199     'subject': (
   229     'subject': (
   215         ((u'localityName', u'Mountain View'),),
   245         ((u'localityName', u'Mountain View'),),
   216         ((u'organizationName', u'Google Inc'),),
   246         ((u'organizationName', u'Google Inc'),),
   217     ),
   247     ),
   218     'subjectAltName': (('othername', 'blabla'),),
   248     'subjectAltName': (('othername', 'blabla'),),
   219 }
   249 }
   220 check(_verifycert(c, 'google.com'),
   250 check(
   221       b'no commonName or subjectAltName found in certificate')
   251     _verifycert(c, 'google.com'),
       
   252     b'no commonName or subjectAltName found in certificate',
       
   253 )
   222 
   254 
   223 # Empty cert / no cert
   255 # Empty cert / no cert
   224 check(_verifycert(None, 'example.com'), b'no certificate received')
   256 check(_verifycert(None, 'example.com'), b'no certificate received')
   225 check(_verifycert({}, 'example.com'), b'no certificate received')
   257 check(_verifycert({}, 'example.com'), b'no certificate received')
   226 
   258 
   227 # avoid denials of service by refusing more than one
   259 # avoid denials of service by refusing more than one
   228 # wildcard per fragment.
   260 # wildcard per fragment.
   229 check(_verifycert({'subject': (((u'commonName', u'a*b.com'),),)},
   261 check(
   230                   'axxb.com'), None)
   262     _verifycert({'subject': (((u'commonName', u'a*b.com'),),)}, 'axxb.com'),
   231 check(_verifycert({'subject': (((u'commonName', u'a*b.co*'),),)},
   263     None,
   232                   'axxb.com'), b'certificate is for a*b.co*')
   264 )
   233 check(_verifycert({'subject': (((u'commonName', u'a*b*.com'),),)},
   265 check(
   234                   'axxbxxc.com'),
   266     _verifycert({'subject': (((u'commonName', u'a*b.co*'),),)}, 'axxb.com'),
   235       b'too many wildcards in certificate DNS name: a*b*.com')
   267     b'certificate is for a*b.co*',
       
   268 )
       
   269 check(
       
   270     _verifycert({'subject': (((u'commonName', u'a*b*.com'),),)}, 'axxbxxc.com'),
       
   271     b'too many wildcards in certificate DNS name: a*b*.com',
       
   272 )
       
   273 
   236 
   274 
   237 def test_url():
   275 def test_url():
   238     """
   276     """
   239     >>> from mercurial import error, pycompat
   277     >>> from mercurial import error, pycompat
   240     >>> from mercurial.util import url
   278     >>> from mercurial.util import url
   416     'file:foo/bar/baz'
   454     'file:foo/bar/baz'
   417     >>> pycompat.bytestr(u.localpath())
   455     >>> pycompat.bytestr(u.localpath())
   418     'foo/bar/baz'
   456     'foo/bar/baz'
   419     """
   457     """
   420 
   458 
       
   459 
   421 if 'TERM' in os.environ:
   460 if 'TERM' in os.environ:
   422     del os.environ['TERM']
   461     del os.environ['TERM']
   423 
   462 
   424 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
   463 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)