github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/crypto/x509/verify.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x509 6 7 import ( 8 "net" 9 "runtime" 10 "strings" 11 "time" 12 "unicode/utf8" 13 ) 14 15 type InvalidReason int 16 17 const ( 18 // NotAuthorizedToSign results when a certificate is signed by another 19 // which isn't marked as a CA certificate. 20 NotAuthorizedToSign InvalidReason = iota 21 // Expired results when a certificate has expired, based on the time 22 // given in the VerifyOptions. 23 Expired 24 // CANotAuthorizedForThisName results when an intermediate or root 25 // certificate has a name constraint which doesn't include the name 26 // being checked. 27 CANotAuthorizedForThisName 28 // TooManyIntermediates results when a path length constraint is 29 // violated. 30 TooManyIntermediates 31 // IncompatibleUsage results when the certificate's key usage indicates 32 // that it may only be used for a different purpose. 33 IncompatibleUsage 34 ) 35 36 // CertificateInvalidError results when an odd error occurs. Users of this 37 // library probably want to handle all these errors uniformly. 38 type CertificateInvalidError struct { 39 Cert *Certificate 40 Reason InvalidReason 41 } 42 43 func (e CertificateInvalidError) Error() string { 44 switch e.Reason { 45 case NotAuthorizedToSign: 46 return "x509: certificate is not authorized to sign other certificates" 47 case Expired: 48 return "x509: certificate has expired or is not yet valid" 49 case CANotAuthorizedForThisName: 50 return "x509: a root or intermediate certificate is not authorized to sign in this domain" 51 case TooManyIntermediates: 52 return "x509: too many intermediates for path length constraint" 53 case IncompatibleUsage: 54 return "x509: certificate specifies an incompatible key usage" 55 } 56 return "x509: unknown error" 57 } 58 59 // HostnameError results when the set of authorized names doesn't match the 60 // requested name. 61 type HostnameError struct { 62 Certificate *Certificate 63 Host string 64 } 65 66 func (h HostnameError) Error() string { 67 c := h.Certificate 68 69 var valid string 70 if ip := net.ParseIP(h.Host); ip != nil { 71 // Trying to validate an IP 72 if len(c.IPAddresses) == 0 { 73 return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs" 74 } 75 for _, san := range c.IPAddresses { 76 if len(valid) > 0 { 77 valid += ", " 78 } 79 valid += san.String() 80 } 81 } else { 82 if len(c.DNSNames) > 0 { 83 valid = strings.Join(c.DNSNames, ", ") 84 } else { 85 valid = c.Subject.CommonName 86 } 87 } 88 return "x509: certificate is valid for " + valid + ", not " + h.Host 89 } 90 91 // UnknownAuthorityError results when the certificate issuer is unknown 92 type UnknownAuthorityError struct { 93 cert *Certificate 94 } 95 96 func (e UnknownAuthorityError) Error() string { 97 return "x509: certificate signed by unknown authority" 98 } 99 100 // SystemRootsError results when we fail to load the system root certificates. 101 type SystemRootsError struct { 102 } 103 104 func (e SystemRootsError) Error() string { 105 return "x509: failed to load system roots and no roots provided" 106 } 107 108 // VerifyOptions contains parameters for Certificate.Verify. It's a structure 109 // because other PKIX verification APIs have ended up needing many options. 110 type VerifyOptions struct { 111 DNSName string 112 Intermediates *CertPool 113 Roots *CertPool // if nil, the system roots are used 114 CurrentTime time.Time // if zero, the current time is used 115 // KeyUsage specifies which Extended Key Usage values are acceptable. 116 // An empty list means ExtKeyUsageServerAuth. Key usage is considered a 117 // constraint down the chain which mirrors Windows CryptoAPI behaviour, 118 // but not the spec. To accept any key usage, include ExtKeyUsageAny. 119 KeyUsages []ExtKeyUsage 120 } 121 122 const ( 123 leafCertificate = iota 124 intermediateCertificate 125 rootCertificate 126 ) 127 128 // isValid performs validity checks on the c. 129 func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error { 130 now := opts.CurrentTime 131 if now.IsZero() { 132 now = time.Now() 133 } 134 if now.Before(c.NotBefore) || now.After(c.NotAfter) { 135 return CertificateInvalidError{c, Expired} 136 } 137 138 if len(c.PermittedDNSDomains) > 0 { 139 for _, domain := range c.PermittedDNSDomains { 140 if opts.DNSName == domain || 141 (strings.HasSuffix(opts.DNSName, domain) && 142 len(opts.DNSName) >= 1+len(domain) && 143 opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') { 144 continue 145 } 146 147 return CertificateInvalidError{c, CANotAuthorizedForThisName} 148 } 149 } 150 151 // KeyUsage status flags are ignored. From Engineering Security, Peter 152 // Gutmann: A European government CA marked its signing certificates as 153 // being valid for encryption only, but no-one noticed. Another 154 // European CA marked its signature keys as not being valid for 155 // signatures. A different CA marked its own trusted root certificate 156 // as being invalid for certificate signing. Another national CA 157 // distributed a certificate to be used to encrypt data for the 158 // country’s tax authority that was marked as only being usable for 159 // digital signatures but not for encryption. Yet another CA reversed 160 // the order of the bit flags in the keyUsage due to confusion over 161 // encoding endianness, essentially setting a random keyUsage in 162 // certificates that it issued. Another CA created a self-invalidating 163 // certificate by adding a certificate policy statement stipulating 164 // that the certificate had to be used strictly as specified in the 165 // keyUsage, and a keyUsage containing a flag indicating that the RSA 166 // encryption key could only be used for Diffie-Hellman key agreement. 167 168 if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) { 169 return CertificateInvalidError{c, NotAuthorizedToSign} 170 } 171 172 if c.BasicConstraintsValid && c.MaxPathLen >= 0 { 173 numIntermediates := len(currentChain) - 1 174 if numIntermediates > c.MaxPathLen { 175 return CertificateInvalidError{c, TooManyIntermediates} 176 } 177 } 178 179 return nil 180 } 181 182 // Verify attempts to verify c by building one or more chains from c to a 183 // certificate in opts.Roots, using certificates in opts.Intermediates if 184 // needed. If successful, it returns one or more chains where the first 185 // element of the chain is c and the last element is from opts.Roots. 186 // 187 // WARNING: this doesn't do any revocation checking. 188 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { 189 // Use Windows's own verification and chain building. 190 if opts.Roots == nil && runtime.GOOS == "windows" { 191 return c.systemVerify(&opts) 192 } 193 194 if opts.Roots == nil { 195 opts.Roots = systemRootsPool() 196 if opts.Roots == nil { 197 return nil, SystemRootsError{} 198 } 199 } 200 201 err = c.isValid(leafCertificate, nil, &opts) 202 if err != nil { 203 return 204 } 205 206 if len(opts.DNSName) > 0 { 207 err = c.VerifyHostname(opts.DNSName) 208 if err != nil { 209 return 210 } 211 } 212 213 candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts) 214 if err != nil { 215 return 216 } 217 218 keyUsages := opts.KeyUsages 219 if len(keyUsages) == 0 { 220 keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} 221 } 222 223 // If any key usage is acceptable then we're done. 224 for _, usage := range keyUsages { 225 if usage == ExtKeyUsageAny { 226 chains = candidateChains 227 return 228 } 229 } 230 231 for _, candidate := range candidateChains { 232 if checkChainForKeyUsage(candidate, keyUsages) { 233 chains = append(chains, candidate) 234 } 235 } 236 237 if len(chains) == 0 { 238 err = CertificateInvalidError{c, IncompatibleUsage} 239 } 240 241 return 242 } 243 244 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { 245 n := make([]*Certificate, len(chain)+1) 246 copy(n, chain) 247 n[len(chain)] = cert 248 return n 249 } 250 251 func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) { 252 for _, rootNum := range opts.Roots.findVerifiedParents(c) { 253 root := opts.Roots.certs[rootNum] 254 err = root.isValid(rootCertificate, currentChain, opts) 255 if err != nil { 256 continue 257 } 258 chains = append(chains, appendToFreshChain(currentChain, root)) 259 } 260 261 nextIntermediate: 262 for _, intermediateNum := range opts.Intermediates.findVerifiedParents(c) { 263 intermediate := opts.Intermediates.certs[intermediateNum] 264 for _, cert := range currentChain { 265 if cert == intermediate { 266 continue nextIntermediate 267 } 268 } 269 err = intermediate.isValid(intermediateCertificate, currentChain, opts) 270 if err != nil { 271 continue 272 } 273 var childChains [][]*Certificate 274 childChains, ok := cache[intermediateNum] 275 if !ok { 276 childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts) 277 cache[intermediateNum] = childChains 278 } 279 chains = append(chains, childChains...) 280 } 281 282 if len(chains) > 0 { 283 err = nil 284 } 285 286 if len(chains) == 0 && err == nil { 287 err = UnknownAuthorityError{c} 288 } 289 290 return 291 } 292 293 func matchHostnames(pattern, host string) bool { 294 if len(pattern) == 0 || len(host) == 0 { 295 return false 296 } 297 298 patternParts := strings.Split(pattern, ".") 299 hostParts := strings.Split(host, ".") 300 301 if len(patternParts) != len(hostParts) { 302 return false 303 } 304 305 for i, patternPart := range patternParts { 306 if patternPart == "*" { 307 continue 308 } 309 if patternPart != hostParts[i] { 310 return false 311 } 312 } 313 314 return true 315 } 316 317 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use 318 // an explicitly ASCII function to avoid any sharp corners resulting from 319 // performing Unicode operations on DNS labels. 320 func toLowerCaseASCII(in string) string { 321 // If the string is already lower-case then there's nothing to do. 322 isAlreadyLowerCase := true 323 for _, c := range in { 324 if c == utf8.RuneError { 325 // If we get a UTF-8 error then there might be 326 // upper-case ASCII bytes in the invalid sequence. 327 isAlreadyLowerCase = false 328 break 329 } 330 if 'A' <= c && c <= 'Z' { 331 isAlreadyLowerCase = false 332 break 333 } 334 } 335 336 if isAlreadyLowerCase { 337 return in 338 } 339 340 out := []byte(in) 341 for i, c := range out { 342 if 'A' <= c && c <= 'Z' { 343 out[i] += 'a' - 'A' 344 } 345 } 346 return string(out) 347 } 348 349 // VerifyHostname returns nil if c is a valid certificate for the named host. 350 // Otherwise it returns an error describing the mismatch. 351 func (c *Certificate) VerifyHostname(h string) error { 352 // IP addresses may be written in [ ]. 353 candidateIP := h 354 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { 355 candidateIP = h[1 : len(h)-1] 356 } 357 if ip := net.ParseIP(candidateIP); ip != nil { 358 // We only match IP addresses against IP SANs. 359 // https://tools.ietf.org/html/rfc6125#appendix-B.2 360 for _, candidate := range c.IPAddresses { 361 if ip.Equal(candidate) { 362 return nil 363 } 364 } 365 return HostnameError{c, candidateIP} 366 } 367 368 lowered := toLowerCaseASCII(h) 369 370 if len(c.DNSNames) > 0 { 371 for _, match := range c.DNSNames { 372 if matchHostnames(toLowerCaseASCII(match), lowered) { 373 return nil 374 } 375 } 376 // If Subject Alt Name is given, we ignore the common name. 377 } else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) { 378 return nil 379 } 380 381 return HostnameError{c, h} 382 } 383 384 func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { 385 usages := make([]ExtKeyUsage, len(keyUsages)) 386 copy(usages, keyUsages) 387 388 if len(chain) == 0 { 389 return false 390 } 391 392 usagesRemaining := len(usages) 393 394 // We walk down the list and cross out any usages that aren't supported 395 // by each certificate. If we cross out all the usages, then the chain 396 // is unacceptable. 397 398 for i := len(chain) - 1; i >= 0; i-- { 399 cert := chain[i] 400 if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 { 401 // The certificate doesn't have any extended key usage specified. 402 continue 403 } 404 405 for _, usage := range cert.ExtKeyUsage { 406 if usage == ExtKeyUsageAny { 407 // The certificate is explicitly good for any usage. 408 continue 409 } 410 } 411 412 const invalidUsage ExtKeyUsage = -1 413 414 NextRequestedUsage: 415 for i, requestedUsage := range usages { 416 if requestedUsage == invalidUsage { 417 continue 418 } 419 420 for _, usage := range cert.ExtKeyUsage { 421 if requestedUsage == usage { 422 continue NextRequestedUsage 423 } else if requestedUsage == ExtKeyUsageServerAuth && 424 (usage == ExtKeyUsageNetscapeServerGatedCrypto || 425 usage == ExtKeyUsageMicrosoftServerGatedCrypto) { 426 // In order to support COMODO 427 // certificate chains, we have to 428 // accept Netscape or Microsoft SGC 429 // usages as equal to ServerAuth. 430 continue NextRequestedUsage 431 } 432 } 433 434 usages[i] = invalidUsage 435 usagesRemaining-- 436 if usagesRemaining == 0 { 437 return false 438 } 439 } 440 } 441 442 return true 443 }