github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/internal/credentials/xds/handshake_info_test.go (about)

     1  /*
     2   *
     3   * Copyright 2021 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package xds
    20  
    21  import (
    22  	"net"
    23  	"net/url"
    24  	"regexp"
    25  	"testing"
    26  
    27  	"github.com/hxx258456/ccgo/x509"
    28  
    29  	"github.com/hxx258456/ccgo/grpc/internal/xds/matcher"
    30  )
    31  
    32  func TestDNSMatch(t *testing.T) {
    33  	tests := []struct {
    34  		desc      string
    35  		host      string
    36  		pattern   string
    37  		wantMatch bool
    38  	}{
    39  		{
    40  			desc:      "invalid wildcard 1",
    41  			host:      "aa.example.com",
    42  			pattern:   "*a.example.com",
    43  			wantMatch: false,
    44  		},
    45  		{
    46  			desc:      "invalid wildcard 2",
    47  			host:      "aa.example.com",
    48  			pattern:   "a*.example.com",
    49  			wantMatch: false,
    50  		},
    51  		{
    52  			desc:      "invalid wildcard 3",
    53  			host:      "abc.example.com",
    54  			pattern:   "a*c.example.com",
    55  			wantMatch: false,
    56  		},
    57  		{
    58  			desc:      "wildcard in one of the middle components",
    59  			host:      "abc.test.example.com",
    60  			pattern:   "abc.*.example.com",
    61  			wantMatch: false,
    62  		},
    63  		{
    64  			desc:      "single component wildcard",
    65  			host:      "a.example.com",
    66  			pattern:   "*",
    67  			wantMatch: false,
    68  		},
    69  		{
    70  			desc:      "short host name",
    71  			host:      "a.com",
    72  			pattern:   "*.example.com",
    73  			wantMatch: false,
    74  		},
    75  		{
    76  			desc:      "suffix mismatch",
    77  			host:      "a.notexample.com",
    78  			pattern:   "*.example.com",
    79  			wantMatch: false,
    80  		},
    81  		{
    82  			desc:      "wildcard match across components",
    83  			host:      "sub.test.example.com",
    84  			pattern:   "*.example.com.",
    85  			wantMatch: false,
    86  		},
    87  		{
    88  			desc:      "host doesn't end in period",
    89  			host:      "test.example.com",
    90  			pattern:   "test.example.com.",
    91  			wantMatch: true,
    92  		},
    93  		{
    94  			desc:      "pattern doesn't end in period",
    95  			host:      "test.example.com.",
    96  			pattern:   "test.example.com",
    97  			wantMatch: true,
    98  		},
    99  		{
   100  			desc:      "case insensitive",
   101  			host:      "TEST.EXAMPLE.COM.",
   102  			pattern:   "test.example.com.",
   103  			wantMatch: true,
   104  		},
   105  		{
   106  			desc:      "simple match",
   107  			host:      "test.example.com",
   108  			pattern:   "test.example.com",
   109  			wantMatch: true,
   110  		},
   111  		{
   112  			desc:      "good wildcard",
   113  			host:      "a.example.com",
   114  			pattern:   "*.example.com",
   115  			wantMatch: true,
   116  		},
   117  	}
   118  
   119  	for _, test := range tests {
   120  		t.Run(test.desc, func(t *testing.T) {
   121  			gotMatch := dnsMatch(test.host, test.pattern)
   122  			if gotMatch != test.wantMatch {
   123  				t.Fatalf("dnsMatch(%s, %s) = %v, want %v", test.host, test.pattern, gotMatch, test.wantMatch)
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  func TestMatchingSANExists_FailureCases(t *testing.T) {
   130  	url1, err := url.Parse("http://golang.org")
   131  	if err != nil {
   132  		t.Fatalf("url.Parse() failed: %v", err)
   133  	}
   134  	url2, err := url.Parse("https://github.com/grpc/grpc-go")
   135  	if err != nil {
   136  		t.Fatalf("url.Parse() failed: %v", err)
   137  	}
   138  	inputCert := &x509.Certificate{
   139  		DNSNames:       []string{"foo.bar.example.com", "bar.baz.test.com", "*.example.com"},
   140  		EmailAddresses: []string{"foobar@example.com", "barbaz@test.com"},
   141  		IPAddresses:    []net.IP{net.ParseIP("192.0.0.1"), net.ParseIP("2001:db8::68")},
   142  		URIs:           []*url.URL{url1, url2},
   143  	}
   144  
   145  	tests := []struct {
   146  		desc        string
   147  		sanMatchers []matcher.StringMatcher
   148  	}{
   149  		{
   150  			desc: "exact match",
   151  			sanMatchers: []matcher.StringMatcher{
   152  				matcher.StringMatcherForTesting(newStringP("abcd.test.com"), nil, nil, nil, nil, false),
   153  				matcher.StringMatcherForTesting(newStringP("http://golang"), nil, nil, nil, nil, false),
   154  				matcher.StringMatcherForTesting(newStringP("HTTP://GOLANG.ORG"), nil, nil, nil, nil, false),
   155  			},
   156  		},
   157  		{
   158  			desc: "prefix match",
   159  			sanMatchers: []matcher.StringMatcher{
   160  				matcher.StringMatcherForTesting(nil, newStringP("i-aint-the-one"), nil, nil, nil, false),
   161  				matcher.StringMatcherForTesting(nil, newStringP("192.168.1.1"), nil, nil, nil, false),
   162  				matcher.StringMatcherForTesting(nil, newStringP("FOO.BAR"), nil, nil, nil, false),
   163  			},
   164  		},
   165  		{
   166  			desc: "suffix match",
   167  			sanMatchers: []matcher.StringMatcher{
   168  				matcher.StringMatcherForTesting(nil, nil, newStringP("i-aint-the-one"), nil, nil, false),
   169  				matcher.StringMatcherForTesting(nil, nil, newStringP("1::68"), nil, nil, false),
   170  				matcher.StringMatcherForTesting(nil, nil, newStringP(".COM"), nil, nil, false),
   171  			},
   172  		},
   173  		{
   174  			desc: "regex match",
   175  			sanMatchers: []matcher.StringMatcher{
   176  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`.*\.examples\.com`), false),
   177  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`192\.[0-9]{1,3}\.1\.1`), false),
   178  			},
   179  		},
   180  		{
   181  			desc: "contains match",
   182  			sanMatchers: []matcher.StringMatcher{
   183  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("i-aint-the-one"), nil, false),
   184  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("2001:db8:1:1::68"), nil, false),
   185  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("GRPC"), nil, false),
   186  			},
   187  		},
   188  	}
   189  
   190  	for _, test := range tests {
   191  		t.Run(test.desc, func(t *testing.T) {
   192  			hi := NewHandshakeInfo(nil, nil)
   193  			hi.SetSANMatchers(test.sanMatchers)
   194  
   195  			if hi.MatchingSANExists(inputCert) {
   196  				t.Fatalf("hi.MatchingSANExists(%+v) with SAN matchers +%v succeeded when expected to fail", inputCert, test.sanMatchers)
   197  			}
   198  		})
   199  	}
   200  }
   201  
   202  func TestMatchingSANExists_Success(t *testing.T) {
   203  	url1, err := url.Parse("http://golang.org")
   204  	if err != nil {
   205  		t.Fatalf("url.Parse() failed: %v", err)
   206  	}
   207  	url2, err := url.Parse("https://github.com/grpc/grpc-go")
   208  	if err != nil {
   209  		t.Fatalf("url.Parse() failed: %v", err)
   210  	}
   211  	inputCert := &x509.Certificate{
   212  		DNSNames:       []string{"baz.test.com", "*.example.com"},
   213  		EmailAddresses: []string{"foobar@example.com", "barbaz@test.com"},
   214  		IPAddresses:    []net.IP{net.ParseIP("192.0.0.1"), net.ParseIP("2001:db8::68")},
   215  		URIs:           []*url.URL{url1, url2},
   216  	}
   217  
   218  	tests := []struct {
   219  		desc        string
   220  		sanMatchers []matcher.StringMatcher
   221  	}{
   222  		{
   223  			desc: "no san matchers",
   224  		},
   225  		{
   226  			desc: "exact match dns wildcard",
   227  			sanMatchers: []matcher.StringMatcher{
   228  				matcher.StringMatcherForTesting(nil, newStringP("192.168.1.1"), nil, nil, nil, false),
   229  				matcher.StringMatcherForTesting(newStringP("https://github.com/grpc/grpc-java"), nil, nil, nil, nil, false),
   230  				matcher.StringMatcherForTesting(newStringP("abc.example.com"), nil, nil, nil, nil, false),
   231  			},
   232  		},
   233  		{
   234  			desc: "exact match ignore case",
   235  			sanMatchers: []matcher.StringMatcher{
   236  				matcher.StringMatcherForTesting(newStringP("FOOBAR@EXAMPLE.COM"), nil, nil, nil, nil, true),
   237  			},
   238  		},
   239  		{
   240  			desc: "prefix match",
   241  			sanMatchers: []matcher.StringMatcher{
   242  				matcher.StringMatcherForTesting(nil, nil, newStringP(".co.in"), nil, nil, false),
   243  				matcher.StringMatcherForTesting(nil, newStringP("192.168.1.1"), nil, nil, nil, false),
   244  				matcher.StringMatcherForTesting(nil, newStringP("baz.test"), nil, nil, nil, false),
   245  			},
   246  		},
   247  		{
   248  			desc: "prefix match ignore case",
   249  			sanMatchers: []matcher.StringMatcher{
   250  				matcher.StringMatcherForTesting(nil, newStringP("BAZ.test"), nil, nil, nil, true),
   251  			},
   252  		},
   253  		{
   254  			desc: "suffix  match",
   255  			sanMatchers: []matcher.StringMatcher{
   256  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`192\.[0-9]{1,3}\.1\.1`), false),
   257  				matcher.StringMatcherForTesting(nil, nil, newStringP("192.168.1.1"), nil, nil, false),
   258  				matcher.StringMatcherForTesting(nil, nil, newStringP("@test.com"), nil, nil, false),
   259  			},
   260  		},
   261  		{
   262  			desc: "suffix  match ignore case",
   263  			sanMatchers: []matcher.StringMatcher{
   264  				matcher.StringMatcherForTesting(nil, nil, newStringP("@test.COM"), nil, nil, true),
   265  			},
   266  		},
   267  		{
   268  			desc: "regex match",
   269  			sanMatchers: []matcher.StringMatcher{
   270  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("https://github.com/grpc/grpc-java"), nil, false),
   271  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`192\.[0-9]{1,3}\.1\.1`), false),
   272  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`.*\.test\.com`), false),
   273  			},
   274  		},
   275  		{
   276  			desc: "contains match",
   277  			sanMatchers: []matcher.StringMatcher{
   278  				matcher.StringMatcherForTesting(newStringP("https://github.com/grpc/grpc-java"), nil, nil, nil, nil, false),
   279  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("2001:68::db8"), nil, false),
   280  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("192.0.0"), nil, false),
   281  			},
   282  		},
   283  		{
   284  			desc: "contains match ignore case",
   285  			sanMatchers: []matcher.StringMatcher{
   286  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("GRPC"), nil, true),
   287  			},
   288  		},
   289  	}
   290  
   291  	for _, test := range tests {
   292  		t.Run(test.desc, func(t *testing.T) {
   293  			hi := NewHandshakeInfo(nil, nil)
   294  			hi.SetSANMatchers(test.sanMatchers)
   295  
   296  			if !hi.MatchingSANExists(inputCert) {
   297  				t.Fatalf("hi.MatchingSANExists(%+v) with SAN matchers +%v failed when expected to succeed", inputCert, test.sanMatchers)
   298  			}
   299  		})
   300  	}
   301  }
   302  
   303  func newStringP(s string) *string {
   304  	return &s
   305  }