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 }