diff options
Diffstat (limited to 'src/pkg/crypto/x509/verify.go')
-rw-r--r-- | src/pkg/crypto/x509/verify.go | 245 |
1 files changed, 0 insertions, 245 deletions
diff --git a/src/pkg/crypto/x509/verify.go b/src/pkg/crypto/x509/verify.go deleted file mode 100644 index cad863db8..000000000 --- a/src/pkg/crypto/x509/verify.go +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package x509 - -import ( - "os" - "strings" - "time" -) - -type InvalidReason int - -const ( - // NotAuthorizedToSign results when a certificate is signed by another - // which isn't marked as a CA certificate. - NotAuthorizedToSign InvalidReason = iota - // Expired results when a certificate has expired, based on the time - // given in the VerifyOptions. - Expired - // CANotAuthorizedForThisName results when an intermediate or root - // certificate has a name constraint which doesn't include the name - // being checked. - CANotAuthorizedForThisName -) - -// CertificateInvalidError results when an odd error occurs. Users of this -// library probably want to handle all these errors uniformly. -type CertificateInvalidError struct { - Cert *Certificate - Reason InvalidReason -} - -func (e CertificateInvalidError) String() string { - switch e.Reason { - case NotAuthorizedToSign: - return "x509: certificate is not authorized to sign other other certificates" - case Expired: - return "x509: certificate has expired or is not yet valid" - case CANotAuthorizedForThisName: - return "x509: a root or intermediate certificate is not authorized to sign in this domain" - } - return "x509: unknown error" -} - -// HostnameError results when the set of authorized names doesn't match the -// requested name. -type HostnameError struct { - Certificate *Certificate - Host string -} - -func (h HostnameError) String() string { - var valid string - c := h.Certificate - if len(c.DNSNames) > 0 { - valid = strings.Join(c.DNSNames, ", ") - } else { - valid = c.Subject.CommonName - } - return "certificate is valid for " + valid + ", not " + h.Host -} - - -// UnknownAuthorityError results when the certificate issuer is unknown -type UnknownAuthorityError struct { - cert *Certificate -} - -func (e UnknownAuthorityError) String() string { - return "x509: certificate signed by unknown authority" -} - -// VerifyOptions contains parameters for Certificate.Verify. It's a structure -// because other PKIX verification APIs have ended up needing many options. -type VerifyOptions struct { - DNSName string - Intermediates *CertPool - Roots *CertPool - CurrentTime int64 // if 0, the current system time is used. -} - -const ( - leafCertificate = iota - intermediateCertificate - rootCertificate -) - -// isValid performs validity checks on the c. -func (c *Certificate) isValid(certType int, opts *VerifyOptions) os.Error { - if opts.CurrentTime < c.NotBefore.Seconds() || - opts.CurrentTime > c.NotAfter.Seconds() { - return CertificateInvalidError{c, Expired} - } - - if len(c.PermittedDNSDomains) > 0 { - for _, domain := range c.PermittedDNSDomains { - if opts.DNSName == domain || - (strings.HasSuffix(opts.DNSName, domain) && - len(opts.DNSName) >= 1+len(domain) && - opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') { - continue - } - - return CertificateInvalidError{c, CANotAuthorizedForThisName} - } - } - - // KeyUsage status flags are ignored. From Engineering Security, Peter - // Gutmann: A European government CA marked its signing certificates as - // being valid for encryption only, but no-one noticed. Another - // European CA marked its signature keys as not being valid for - // signatures. A different CA marked its own trusted root certificate - // as being invalid for certificate signing. Another national CA - // distributed a certificate to be used to encrypt data for the - // country’s tax authority that was marked as only being usable for - // digital signatures but not for encryption. Yet another CA reversed - // the order of the bit flags in the keyUsage due to confusion over - // encoding endianness, essentially setting a random keyUsage in - // certificates that it issued. Another CA created a self-invalidating - // certificate by adding a certificate policy statement stipulating - // that the certificate had to be used strictly as specified in the - // keyUsage, and a keyUsage containing a flag indicating that the RSA - // encryption key could only be used for Diffie-Hellman key agreement. - - if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) { - return CertificateInvalidError{c, NotAuthorizedToSign} - } - - return nil -} - -// Verify attempts to verify c by building one or more chains from c to a -// certificate in opts.roots, using certificates in opts.Intermediates if -// needed. If successful, it returns one or chains where the first element of -// the chain is c and the last element is from opts.Roots. -// -// WARNING: this doesn't do any revocation checking. -func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err os.Error) { - if opts.CurrentTime == 0 { - opts.CurrentTime = time.Seconds() - } - err = c.isValid(leafCertificate, &opts) - if err != nil { - return - } - if len(opts.DNSName) > 0 { - err = c.VerifyHostname(opts.DNSName) - if err != nil { - return - } - } - return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts) -} - -func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { - n := make([]*Certificate, len(chain)+1) - copy(n, chain) - n[len(chain)] = cert - return n -} - -func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err os.Error) { - for _, rootNum := range opts.Roots.findVerifiedParents(c) { - root := opts.Roots.certs[rootNum] - err = root.isValid(rootCertificate, opts) - if err != nil { - continue - } - chains = append(chains, appendToFreshChain(currentChain, root)) - } - -nextIntermediate: - for _, intermediateNum := range opts.Intermediates.findVerifiedParents(c) { - intermediate := opts.Intermediates.certs[intermediateNum] - for _, cert := range currentChain { - if cert == intermediate { - continue nextIntermediate - } - } - err = intermediate.isValid(intermediateCertificate, opts) - if err != nil { - continue - } - var childChains [][]*Certificate - childChains, ok := cache[intermediateNum] - if !ok { - childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts) - cache[intermediateNum] = childChains - } - chains = append(chains, childChains...) - } - - if len(chains) > 0 { - err = nil - } - - if len(chains) == 0 && err == nil { - err = UnknownAuthorityError{c} - } - - return -} - -func matchHostnames(pattern, host string) bool { - if len(pattern) == 0 || len(host) == 0 { - return false - } - - patternParts := strings.Split(pattern, ".") - hostParts := strings.Split(host, ".") - - if len(patternParts) != len(hostParts) { - return false - } - - for i, patternPart := range patternParts { - if patternPart == "*" { - continue - } - if patternPart != hostParts[i] { - return false - } - } - - return true -} - -// VerifyHostname returns nil if c is a valid certificate for the named host. -// Otherwise it returns an os.Error describing the mismatch. -func (c *Certificate) VerifyHostname(h string) os.Error { - if len(c.DNSNames) > 0 { - for _, match := range c.DNSNames { - if matchHostnames(match, h) { - return nil - } - } - // If Subject Alt Name is given, we ignore the common name. - } else if matchHostnames(c.Subject.CommonName, h) { - return nil - } - - return HostnameError{c, h} -} |