@@ -426,6 +426,156 @@ def test_verify_certificate_identity
426426 end
427427 end
428428
429+ def test_verify_hostname
430+ assert_equal ( true , OpenSSL ::SSL . verify_hostname ( "www.example.com" , "*.example.com" ) )
431+ assert_equal ( false , OpenSSL ::SSL . verify_hostname ( "www.subdomain.example.com" , "*.example.com" ) )
432+ end
433+
434+ def test_verify_wildcard
435+ assert_equal ( false , OpenSSL ::SSL . verify_wildcard ( "foo" , "x*" ) )
436+ assert_equal ( true , OpenSSL ::SSL . verify_wildcard ( "foo" , "foo" ) )
437+ assert_equal ( true , OpenSSL ::SSL . verify_wildcard ( "foo" , "f*" ) )
438+ assert_equal ( true , OpenSSL ::SSL . verify_wildcard ( "foo" , "*" ) )
439+ assert_equal ( false , OpenSSL ::SSL . verify_wildcard ( "abc*bcd" , "abcd" ) )
440+ assert_equal ( false , OpenSSL ::SSL . verify_wildcard ( "xn--qdk4b9b" , "x*" ) )
441+ assert_equal ( false , OpenSSL ::SSL . verify_wildcard ( "xn--qdk4b9b" , "*--qdk4b9b" ) )
442+ assert_equal ( true , OpenSSL ::SSL . verify_wildcard ( "xn--qdk4b9b" , "xn--qdk4b9b" ) )
443+ end
444+
445+ # Comments in this test is excerpted from http://tools.ietf.org/html/rfc6125#page-27
446+ def test_post_connection_check_wildcard_san
447+ # case-insensitive ASCII comparison
448+ # RFC 6125, section 6.4.1
449+ #
450+ # "..matching of the reference identifier against the presented identifier
451+ # is performed by comparing the set of domain name labels using a
452+ # case-insensitive ASCII comparison, as clarified by [DNS-CASE] (e.g.,
453+ # "WWW.Example.Com" would be lower-cased to "www.example.com" for
454+ # comparison purposes)
455+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
456+ create_cert_with_san ( 'DNS:*.example.com' ) , 'www.example.com' ) )
457+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
458+ create_cert_with_san ( 'DNS:*.Example.COM' ) , 'www.example.com' ) )
459+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
460+ create_cert_with_san ( 'DNS:*.example.com' ) , 'WWW.Example.COM' ) )
461+ # 1. The client SHOULD NOT attempt to match a presented identifier in
462+ # which the wildcard character comprises a label other than the
463+ # left-most label (e.g., do not match bar.*.example.net).
464+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
465+ create_cert_with_san ( 'DNS:www.*.com' ) , 'www.example.com' ) )
466+ # 2. If the wildcard character is the only character of the left-most
467+ # label in the presented identifier, the client SHOULD NOT compare
468+ # against anything but the left-most label of the reference
469+ # identifier (e.g., *.example.com would match foo.example.com but
470+ # not bar.foo.example.com or example.com).
471+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
472+ create_cert_with_san ( 'DNS:*.example.com' ) , 'foo.example.com' ) )
473+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
474+ create_cert_with_san ( 'DNS:*.example.com' ) , 'bar.foo.example.com' ) )
475+ # 3. The client MAY match a presented identifier in which the wildcard
476+ # character is not the only character of the label (e.g.,
477+ # baz*.example.net and *baz.example.net and b*z.example.net would
478+ # be taken to match baz1.example.net and foobaz.example.net and
479+ # buzz.example.net, respectively). ...
480+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
481+ create_cert_with_san ( 'DNS:baz*.example.com' ) , 'baz1.example.com' ) )
482+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
483+ create_cert_with_san ( 'DNS:*baz.example.com' ) , 'foobaz.example.com' ) )
484+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
485+ create_cert_with_san ( 'DNS:b*z.example.com' ) , 'buzz.example.com' ) )
486+ # Section 6.4.3 of RFC6125 states that client should NOT match identifier
487+ # where wildcard is other than left-most label.
488+ #
489+ # Also implicitly mentions the wildcard character only in singular form,
490+ # and discourages matching against more than one wildcard.
491+ #
492+ # See RFC 6125, section 7.2, subitem 2.
493+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
494+ create_cert_with_san ( 'DNS:*b*.example.com' ) , 'abc.example.com' ) )
495+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
496+ create_cert_with_san ( 'DNS:*b*.example.com' ) , 'ab.example.com' ) )
497+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
498+ create_cert_with_san ( 'DNS:*b*.example.com' ) , 'bc.example.com' ) )
499+ # ... However, the client SHOULD NOT
500+ # attempt to match a presented identifier where the wildcard
501+ # character is embedded within an A-label or U-label [IDNA-DEFS] of
502+ # an internationalized domain name [IDNA-PROTO].
503+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
504+ create_cert_with_san ( 'DNS:xn*.example.com' ) , 'xn1ca.example.com' ) )
505+ # part of A-label
506+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
507+ create_cert_with_san ( 'DNS:xn--*.example.com' ) , 'xn--1ca.example.com' ) )
508+ # part of U-label
509+ # dNSName in RFC5280 is an IA5String so U-label should NOT be allowed
510+ # regardless of wildcard.
511+ #
512+ # See Section 7.2 of RFC 5280:
513+ # IA5String is limited to the set of ASCII characters.
514+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
515+ create_cert_with_san ( 'DNS:á*.example.com' ) , 'á1.example.com' ) )
516+ end
517+
518+ def test_post_connection_check_wildcard_cn
519+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
520+ create_cert_with_name ( '*.example.com' ) , 'www.example.com' ) )
521+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
522+ create_cert_with_name ( '*.Example.COM' ) , 'www.example.com' ) )
523+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
524+ create_cert_with_name ( '*.example.com' ) , 'WWW.Example.COM' ) )
525+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
526+ create_cert_with_name ( 'www.*.com' ) , 'www.example.com' ) )
527+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
528+ create_cert_with_name ( '*.example.com' ) , 'foo.example.com' ) )
529+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
530+ create_cert_with_name ( '*.example.com' ) , 'bar.foo.example.com' ) )
531+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
532+ create_cert_with_name ( 'baz*.example.com' ) , 'baz1.example.com' ) )
533+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
534+ create_cert_with_name ( '*baz.example.com' ) , 'foobaz.example.com' ) )
535+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
536+ create_cert_with_name ( 'b*z.example.com' ) , 'buzz.example.com' ) )
537+ # Section 6.4.3 of RFC6125 states that client should NOT match identifier
538+ # where wildcard is other than left-most label.
539+ #
540+ # Also implicitly mentions the wildcard character only in singular form,
541+ # and discourages matching against more than one wildcard.
542+ #
543+ # See RFC 6125, section 7.2, subitem 2.
544+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
545+ create_cert_with_name ( '*b*.example.com' ) , 'abc.example.com' ) )
546+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
547+ create_cert_with_name ( '*b*.example.com' ) , 'ab.example.com' ) )
548+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
549+ create_cert_with_name ( '*b*.example.com' ) , 'bc.example.com' ) )
550+ assert_equal ( true , OpenSSL ::SSL . verify_certificate_identity (
551+ create_cert_with_name ( 'xn*.example.com' ) , 'xn1ca.example.com' ) )
552+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
553+ create_cert_with_name ( 'xn--*.example.com' ) , 'xn--1ca.example.com' ) )
554+ # part of U-label
555+ # Subject in RFC5280 states case-insensitive ASCII comparison.
556+ #
557+ # See Section 7.2 of RFC 5280:
558+ # IA5String is limited to the set of ASCII characters.
559+ assert_equal ( false , OpenSSL ::SSL . verify_certificate_identity (
560+ create_cert_with_name ( 'á*.example.com' ) , 'á1.example.com' ) )
561+ end
562+
563+ def create_cert_with_san ( san )
564+ ef = OpenSSL ::X509 ::ExtensionFactory . new
565+ cert = OpenSSL ::X509 ::Certificate . new
566+ cert . subject = OpenSSL ::X509 ::Name . parse ( "/DC=some/DC=site/CN=Some Site" )
567+ ext = ef . create_ext ( 'subjectAltName' , san )
568+ cert . add_extension ( ext )
569+ cert
570+ end
571+
572+ def create_cert_with_name ( name )
573+ cert = OpenSSL ::X509 ::Certificate . new
574+ cert . subject = OpenSSL ::X509 ::Name . new ( [ [ 'DC' , 'some' ] , [ 'DC' , 'site' ] , [ 'CN' , name ] ] )
575+ cert
576+ end
577+
578+
429579 # Create NULL byte SAN certificate
430580 def create_null_byte_SAN_certificate ( critical = false )
431581 ef = OpenSSL ::X509 ::ExtensionFactory . new
0 commit comments