gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/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  	"gitee.com/zhaochuninhefei/gmgo/x509"
    28  
    29  	"gitee.com/zhaochuninhefei/gmgo/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  //goland:noinspection HttpUrlsUsage
   130  func TestMatchingSANExists_FailureCases(t *testing.T) {
   131  	url1, err := url.Parse("http://golang.org")
   132  	if err != nil {
   133  		t.Fatalf("url.Parse() failed: %v", err)
   134  	}
   135  	url2, err := url.Parse("https://github.com/grpc/grpc-go")
   136  	if err != nil {
   137  		t.Fatalf("url.Parse() failed: %v", err)
   138  	}
   139  	inputCert := &x509.Certificate{
   140  		DNSNames:       []string{"foo.bar.example.com", "bar.baz.test.com", "*.example.com"},
   141  		EmailAddresses: []string{"foobar@example.com", "barbaz@test.com"},
   142  		IPAddresses:    []net.IP{net.ParseIP("192.0.0.1"), net.ParseIP("2001:db8::68")},
   143  		URIs:           []*url.URL{url1, url2},
   144  	}
   145  
   146  	tests := []struct {
   147  		desc        string
   148  		sanMatchers []matcher.StringMatcher
   149  	}{
   150  		{
   151  			desc: "exact match",
   152  			sanMatchers: []matcher.StringMatcher{
   153  				matcher.StringMatcherForTesting(newStringP("abcd.test.com"), nil, nil, nil, nil, false),
   154  				matcher.StringMatcherForTesting(newStringP("http://golang"), nil, nil, nil, nil, false),
   155  				matcher.StringMatcherForTesting(newStringP("HTTP://GOLANG.ORG"), nil, nil, nil, nil, false),
   156  			},
   157  		},
   158  		{
   159  			desc: "prefix match",
   160  			sanMatchers: []matcher.StringMatcher{
   161  				matcher.StringMatcherForTesting(nil, newStringP("i-aint-the-one"), nil, nil, nil, false),
   162  				matcher.StringMatcherForTesting(nil, newStringP("192.168.1.1"), nil, nil, nil, false),
   163  				matcher.StringMatcherForTesting(nil, newStringP("FOO.BAR"), nil, nil, nil, false),
   164  			},
   165  		},
   166  		{
   167  			desc: "suffix match",
   168  			sanMatchers: []matcher.StringMatcher{
   169  				matcher.StringMatcherForTesting(nil, nil, newStringP("i-aint-the-one"), nil, nil, false),
   170  				matcher.StringMatcherForTesting(nil, nil, newStringP("1::68"), nil, nil, false),
   171  				matcher.StringMatcherForTesting(nil, nil, newStringP(".COM"), nil, nil, false),
   172  			},
   173  		},
   174  		{
   175  			desc: "regex match",
   176  			sanMatchers: []matcher.StringMatcher{
   177  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`.*\.examples\.com`), false),
   178  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`192\.[0-9]{1,3}\.1\.1`), false),
   179  			},
   180  		},
   181  		{
   182  			desc: "contains match",
   183  			sanMatchers: []matcher.StringMatcher{
   184  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("i-aint-the-one"), nil, false),
   185  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("2001:db8:1:1::68"), nil, false),
   186  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("GRPC"), nil, false),
   187  			},
   188  		},
   189  	}
   190  
   191  	for _, test := range tests {
   192  		t.Run(test.desc, func(t *testing.T) {
   193  			hi := NewHandshakeInfo(nil, nil)
   194  			hi.SetSANMatchers(test.sanMatchers)
   195  
   196  			if hi.MatchingSANExists(inputCert) {
   197  				t.Fatalf("hi.MatchingSANExists(%+v) with SAN matchers +%v succeeded when expected to fail", inputCert, test.sanMatchers)
   198  			}
   199  		})
   200  	}
   201  }
   202  
   203  //goland:noinspection HttpUrlsUsage
   204  func TestMatchingSANExists_Success(t *testing.T) {
   205  	url1, err := url.Parse("http://golang.org")
   206  	if err != nil {
   207  		t.Fatalf("url.Parse() failed: %v", err)
   208  	}
   209  	url2, err := url.Parse("https://github.com/grpc/grpc-go")
   210  	if err != nil {
   211  		t.Fatalf("url.Parse() failed: %v", err)
   212  	}
   213  	inputCert := &x509.Certificate{
   214  		DNSNames:       []string{"baz.test.com", "*.example.com"},
   215  		EmailAddresses: []string{"foobar@example.com", "barbaz@test.com"},
   216  		IPAddresses:    []net.IP{net.ParseIP("192.0.0.1"), net.ParseIP("2001:db8::68")},
   217  		URIs:           []*url.URL{url1, url2},
   218  	}
   219  
   220  	tests := []struct {
   221  		desc        string
   222  		sanMatchers []matcher.StringMatcher
   223  	}{
   224  		{
   225  			desc: "no san matchers",
   226  		},
   227  		{
   228  			desc: "exact match dns wildcard",
   229  			sanMatchers: []matcher.StringMatcher{
   230  				matcher.StringMatcherForTesting(nil, newStringP("192.168.1.1"), nil, nil, nil, false),
   231  				matcher.StringMatcherForTesting(newStringP("https://github.com/grpc/grpc-java"), nil, nil, nil, nil, false),
   232  				matcher.StringMatcherForTesting(newStringP("abc.example.com"), nil, nil, nil, nil, false),
   233  			},
   234  		},
   235  		{
   236  			desc: "exact match ignore case",
   237  			sanMatchers: []matcher.StringMatcher{
   238  				matcher.StringMatcherForTesting(newStringP("FOOBAR@EXAMPLE.COM"), nil, nil, nil, nil, true),
   239  			},
   240  		},
   241  		{
   242  			desc: "prefix match",
   243  			sanMatchers: []matcher.StringMatcher{
   244  				matcher.StringMatcherForTesting(nil, nil, newStringP(".co.in"), nil, nil, false),
   245  				matcher.StringMatcherForTesting(nil, newStringP("192.168.1.1"), nil, nil, nil, false),
   246  				matcher.StringMatcherForTesting(nil, newStringP("baz.test"), nil, nil, nil, false),
   247  			},
   248  		},
   249  		{
   250  			desc: "prefix match ignore case",
   251  			sanMatchers: []matcher.StringMatcher{
   252  				matcher.StringMatcherForTesting(nil, newStringP("BAZ.test"), nil, nil, nil, true),
   253  			},
   254  		},
   255  		{
   256  			desc: "suffix  match",
   257  			sanMatchers: []matcher.StringMatcher{
   258  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`192\.[0-9]{1,3}\.1\.1`), false),
   259  				matcher.StringMatcherForTesting(nil, nil, newStringP("192.168.1.1"), nil, nil, false),
   260  				matcher.StringMatcherForTesting(nil, nil, newStringP("@test.com"), nil, nil, false),
   261  			},
   262  		},
   263  		{
   264  			desc: "suffix  match ignore case",
   265  			sanMatchers: []matcher.StringMatcher{
   266  				matcher.StringMatcherForTesting(nil, nil, newStringP("@test.COM"), nil, nil, true),
   267  			},
   268  		},
   269  		{
   270  			desc: "regex match",
   271  			sanMatchers: []matcher.StringMatcher{
   272  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("https://github.com/grpc/grpc-java"), nil, false),
   273  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`192\.[0-9]{1,3}\.1\.1`), false),
   274  				matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(`.*\.test\.com`), false),
   275  			},
   276  		},
   277  		{
   278  			desc: "contains match",
   279  			sanMatchers: []matcher.StringMatcher{
   280  				matcher.StringMatcherForTesting(newStringP("https://github.com/grpc/grpc-java"), nil, nil, nil, nil, false),
   281  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("2001:68::db8"), nil, false),
   282  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("192.0.0"), nil, false),
   283  			},
   284  		},
   285  		{
   286  			desc: "contains match ignore case",
   287  			sanMatchers: []matcher.StringMatcher{
   288  				matcher.StringMatcherForTesting(nil, nil, nil, newStringP("GRPC"), nil, true),
   289  			},
   290  		},
   291  	}
   292  
   293  	for _, test := range tests {
   294  		t.Run(test.desc, func(t *testing.T) {
   295  			hi := NewHandshakeInfo(nil, nil)
   296  			hi.SetSANMatchers(test.sanMatchers)
   297  
   298  			if !hi.MatchingSANExists(inputCert) {
   299  				t.Fatalf("hi.MatchingSANExists(%+v) with SAN matchers +%v failed when expected to succeed", inputCert, test.sanMatchers)
   300  			}
   301  		})
   302  	}
   303  }
   304  
   305  func newStringP(s string) *string {
   306  	return &s
   307  }