~ubuntu-branches/ubuntu/saucy/golang/saucy

« back to all changes in this revision

Viewing changes to src/pkg/crypto/x509/verify.go

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-07-08 05:52:37 UTC
  • mfrom: (29.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130708055237-at01839e0hp8z3ni
Tags: 2:1.1-1ubuntu1
016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
package x509
6
6
 
7
7
import (
 
8
        "net"
8
9
        "runtime"
9
10
        "strings"
10
11
        "time"
27
28
        // TooManyIntermediates results when a path length constraint is
28
29
        // violated.
29
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
30
34
)
31
35
 
32
36
// CertificateInvalidError results when an odd error occurs. Users of this
39
43
func (e CertificateInvalidError) Error() string {
40
44
        switch e.Reason {
41
45
        case NotAuthorizedToSign:
42
 
                return "x509: certificate is not authorized to sign other other certificates"
 
46
                return "x509: certificate is not authorized to sign other certificates"
43
47
        case Expired:
44
48
                return "x509: certificate has expired or is not yet valid"
45
49
        case CANotAuthorizedForThisName:
46
50
                return "x509: a root or intermediate certificate is not authorized to sign in this domain"
47
51
        case TooManyIntermediates:
48
52
                return "x509: too many intermediates for path length constraint"
 
53
        case IncompatibleUsage:
 
54
                return "x509: certificate specifies an incompatible key usage"
49
55
        }
50
56
        return "x509: unknown error"
51
57
}
58
64
}
59
65
 
60
66
func (h HostnameError) Error() string {
 
67
        c := h.Certificate
 
68
 
61
69
        var valid string
62
 
        c := h.Certificate
63
 
        if len(c.DNSNames) > 0 {
64
 
                valid = strings.Join(c.DNSNames, ", ")
 
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
                }
65
81
        } else {
66
 
                valid = c.Subject.CommonName
 
82
                if len(c.DNSNames) > 0 {
 
83
                        valid = strings.Join(c.DNSNames, ", ")
 
84
                } else {
 
85
                        valid = c.Subject.CommonName
 
86
                }
67
87
        }
68
 
        return "certificate is valid for " + valid + ", not " + h.Host
 
88
        return "x509: certificate is valid for " + valid + ", not " + h.Host
69
89
}
70
90
 
71
91
// UnknownAuthorityError results when the certificate issuer is unknown
77
97
        return "x509: certificate signed by unknown authority"
78
98
}
79
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
 
80
108
// VerifyOptions contains parameters for Certificate.Verify. It's a structure
81
109
// because other PKIX verification APIs have ended up needing many options.
82
110
type VerifyOptions struct {
84
112
        Intermediates *CertPool
85
113
        Roots         *CertPool // if nil, the system roots are used
86
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
87
120
}
88
121
 
89
122
const (
160
193
 
161
194
        if opts.Roots == nil {
162
195
                opts.Roots = systemRootsPool()
 
196
                if opts.Roots == nil {
 
197
                        return nil, SystemRootsError{}
 
198
                }
163
199
        }
164
200
 
165
201
        err = c.isValid(leafCertificate, nil, &opts)
174
210
                }
175
211
        }
176
212
 
177
 
        return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
 
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
178
242
}
179
243
 
180
244
func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
285
349
// VerifyHostname returns nil if c is a valid certificate for the named host.
286
350
// Otherwise it returns an error describing the mismatch.
287
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
 
288
368
        lowered := toLowerCaseASCII(h)
289
369
 
290
370
        if len(c.DNSNames) > 0 {
300
380
 
301
381
        return HostnameError{c, h}
302
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
}