github.com/inflatablewoman/deis@v1.0.1-0.20141111034523-a4511c46a6ce/deisctl/Godeps/_workspace/src/code.google.com/p/go.crypto/ssh/certs.go (about) 1 // Copyright 2012 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 ssh 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "io" 12 "net" 13 "sort" 14 "time" 15 ) 16 17 // These constants from [PROTOCOL.certkeys] represent the algorithm names 18 // for certificate types supported by this package. 19 const ( 20 CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" 21 CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" 22 CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" 23 CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" 24 CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" 25 ) 26 27 // Certificate types distinguish between host and user 28 // certificates. The values can be set in the CertType field of 29 // Certificate. 30 const ( 31 UserCert = 1 32 HostCert = 2 33 ) 34 35 // Signature represents a cryptographic signature. 36 type Signature struct { 37 Format string 38 Blob []byte 39 } 40 41 // CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that 42 // a certificate does not expire. 43 const CertTimeInfinity = 1<<64 - 1 44 45 // An Certificate represents an OpenSSH certificate as defined in 46 // [PROTOCOL.certkeys]?rev=1.8. 47 type Certificate struct { 48 Nonce []byte 49 Key PublicKey 50 Serial uint64 51 CertType uint32 52 KeyId string 53 ValidPrincipals []string 54 ValidAfter uint64 55 ValidBefore uint64 56 Permissions 57 Reserved []byte 58 SignatureKey PublicKey 59 Signature *Signature 60 } 61 62 // genericCertData holds the key-independent part of the certificate data. 63 // Overall, certificates contain an nonce, public key fields and 64 // key-independent fields. 65 type genericCertData struct { 66 Serial uint64 67 CertType uint32 68 KeyId string 69 ValidPrincipals []byte 70 ValidAfter uint64 71 ValidBefore uint64 72 CriticalOptions []byte 73 Extensions []byte 74 Reserved []byte 75 SignatureKey []byte 76 Signature []byte 77 } 78 79 func marshalStringList(namelist []string) []byte { 80 var to []byte 81 for _, name := range namelist { 82 s := struct{ N string }{name} 83 to = append(to, Marshal(&s)...) 84 } 85 return to 86 } 87 88 func marshalTuples(tups map[string]string) []byte { 89 keys := make([]string, 0, len(tups)) 90 for k := range tups { 91 keys = append(keys, k) 92 } 93 sort.Strings(keys) 94 95 var r []byte 96 for _, k := range keys { 97 s := struct{ K, V string }{k, tups[k]} 98 r = append(r, Marshal(&s)...) 99 } 100 return r 101 } 102 103 func parseTuples(in []byte) (map[string]string, error) { 104 tups := map[string]string{} 105 var lastKey string 106 var haveLastKey bool 107 108 for len(in) > 0 { 109 nameBytes, rest, ok := parseString(in) 110 if !ok { 111 return nil, errShortRead 112 } 113 data, rest, ok := parseString(rest) 114 if !ok { 115 return nil, errShortRead 116 } 117 name := string(nameBytes) 118 119 // according to [PROTOCOL.certkeys], the names must be in 120 // lexical order. 121 if haveLastKey && name <= lastKey { 122 return nil, fmt.Errorf("ssh: certificate options are not in lexical order") 123 } 124 lastKey, haveLastKey = name, true 125 126 tups[name] = string(data) 127 in = rest 128 } 129 return tups, nil 130 } 131 132 func parseCert(in []byte, privAlgo string) (*Certificate, error) { 133 nonce, rest, ok := parseString(in) 134 if !ok { 135 return nil, errShortRead 136 } 137 138 key, rest, err := parsePubKey(rest, privAlgo) 139 if err != nil { 140 return nil, err 141 } 142 143 var g genericCertData 144 if err := Unmarshal(rest, &g); err != nil { 145 return nil, err 146 } 147 148 c := &Certificate{ 149 Nonce: nonce, 150 Key: key, 151 Serial: g.Serial, 152 CertType: g.CertType, 153 KeyId: g.KeyId, 154 ValidAfter: g.ValidAfter, 155 ValidBefore: g.ValidBefore, 156 } 157 158 for principals := g.ValidPrincipals; len(principals) > 0; { 159 principal, rest, ok := parseString(principals) 160 if !ok { 161 return nil, errShortRead 162 } 163 c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) 164 principals = rest 165 } 166 167 c.CriticalOptions, err = parseTuples(g.CriticalOptions) 168 if err != nil { 169 return nil, err 170 } 171 c.Extensions, err = parseTuples(g.Extensions) 172 if err != nil { 173 return nil, err 174 } 175 c.Reserved = g.Reserved 176 k, err := ParsePublicKey(g.SignatureKey) 177 if err != nil { 178 return nil, err 179 } 180 181 c.SignatureKey = k 182 c.Signature, rest, ok = parseSignatureBody(g.Signature) 183 if !ok || len(rest) > 0 { 184 return nil, errors.New("ssh: signature parse error") 185 } 186 187 return c, nil 188 } 189 190 type openSSHCertSigner struct { 191 pub *Certificate 192 signer Signer 193 } 194 195 // NewCertSigner returns a Signer that signs with the given Certificate, whose 196 // private key is held by signer. It returns an error if the public key in cert 197 // doesn't match the key used by signer. 198 func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { 199 if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { 200 return nil, errors.New("ssh: signer and cert have different public key") 201 } 202 203 return &openSSHCertSigner{cert, signer}, nil 204 } 205 206 func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { 207 return s.signer.Sign(rand, data) 208 } 209 210 func (s *openSSHCertSigner) PublicKey() PublicKey { 211 return s.pub 212 } 213 214 const sourceAddressCriticalOption = "source-address" 215 216 // CertChecker does the work of verifying a certificate. Its methods 217 // can be plugged into ClientConfig.HostKeyCallback and 218 // ServerConfig.PublicKeyCallback. For the CertChecker to work, 219 // minimally, the IsAuthority callback should be set. 220 type CertChecker struct { 221 // SupportedCriticalOptions lists the CriticalOptions that the 222 // server application layer understands. These are only used 223 // for user certificates. 224 SupportedCriticalOptions []string 225 226 // IsAuthority should return true if the key is recognized as 227 // an authority. This allows for certificates to be signed by other 228 // certificates. 229 IsAuthority func(auth PublicKey) bool 230 231 // Clock is used for verifying time stamps. If nil, time.Now 232 // is used. 233 Clock func() time.Time 234 235 // UserKeyFallback is called when CertChecker.Authenticate encounters a 236 // public key that is not a certificate. It must implement validation 237 // of user keys or else, if nil, all such keys are rejected. 238 UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) 239 240 // HostKeyFallback is called when CertChecker.CheckHostKey encounters a 241 // public key that is not a certificate. It must implement host key 242 // validation or else, if nil, all such keys are rejected. 243 HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error 244 245 // IsRevoked is called for each certificate so that revocation checking 246 // can be implemented. It should return true if the given certificate 247 // is revoked and false otherwise. If nil, no certificates are 248 // considered to have been revoked. 249 IsRevoked func(cert *Certificate) bool 250 } 251 252 // CheckHostKey checks a host key certificate. This method can be 253 // plugged into ClientConfig.HostKeyCallback. 254 func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { 255 cert, ok := key.(*Certificate) 256 if !ok { 257 if c.HostKeyFallback != nil { 258 return c.HostKeyFallback(addr, remote, key) 259 } 260 return errors.New("ssh: non-certificate host key") 261 } 262 if cert.CertType != HostCert { 263 return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) 264 } 265 266 return c.CheckCert(addr, cert) 267 } 268 269 // Authenticate checks a user certificate. Authenticate can be used as 270 // a value for ServerConfig.PublicKeyCallback. 271 func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { 272 cert, ok := pubKey.(*Certificate) 273 if !ok { 274 if c.UserKeyFallback != nil { 275 return c.UserKeyFallback(conn, pubKey) 276 } 277 return nil, errors.New("ssh: normal key pairs not accepted") 278 } 279 280 if cert.CertType != UserCert { 281 return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) 282 } 283 284 if err := c.CheckCert(conn.User(), cert); err != nil { 285 return nil, err 286 } 287 288 return &cert.Permissions, nil 289 } 290 291 // CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and 292 // the signature of the certificate. 293 func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { 294 if c.IsRevoked != nil && c.IsRevoked(cert) { 295 return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial) 296 } 297 298 for opt, _ := range cert.CriticalOptions { 299 // sourceAddressCriticalOption will be enforced by 300 // serverAuthenticate 301 if opt == sourceAddressCriticalOption { 302 continue 303 } 304 305 found := false 306 for _, supp := range c.SupportedCriticalOptions { 307 if supp == opt { 308 found = true 309 break 310 } 311 } 312 if !found { 313 return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) 314 } 315 } 316 317 if len(cert.ValidPrincipals) > 0 { 318 // By default, certs are valid for all users/hosts. 319 found := false 320 for _, p := range cert.ValidPrincipals { 321 if p == principal { 322 found = true 323 break 324 } 325 } 326 if !found { 327 return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) 328 } 329 } 330 331 if !c.IsAuthority(cert.SignatureKey) { 332 return fmt.Errorf("ssh: certificate signed by unrecognized authority") 333 } 334 335 clock := c.Clock 336 if clock == nil { 337 clock = time.Now 338 } 339 340 unixNow := clock().Unix() 341 if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { 342 return fmt.Errorf("ssh: cert is not yet valid") 343 } 344 if before := int64(cert.ValidBefore); cert.ValidBefore != CertTimeInfinity && (unixNow >= before || before < 0) { 345 return fmt.Errorf("ssh: cert has expired") 346 } 347 if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { 348 return fmt.Errorf("ssh: certificate signature does not verify") 349 } 350 351 return nil 352 } 353 354 // SignCert sets c.SignatureKey to the authority's public key and stores a 355 // Signature, by authority, in the certificate. 356 func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { 357 c.Nonce = make([]byte, 32) 358 if _, err := io.ReadFull(rand, c.Nonce); err != nil { 359 return err 360 } 361 c.SignatureKey = authority.PublicKey() 362 363 sig, err := authority.Sign(rand, c.bytesForSigning()) 364 if err != nil { 365 return err 366 } 367 c.Signature = sig 368 return nil 369 } 370 371 var certAlgoNames = map[string]string{ 372 KeyAlgoRSA: CertAlgoRSAv01, 373 KeyAlgoDSA: CertAlgoDSAv01, 374 KeyAlgoECDSA256: CertAlgoECDSA256v01, 375 KeyAlgoECDSA384: CertAlgoECDSA384v01, 376 KeyAlgoECDSA521: CertAlgoECDSA521v01, 377 } 378 379 // certToPrivAlgo returns the underlying algorithm for a certificate algorithm. 380 // Panics if a non-certificate algorithm is passed. 381 func certToPrivAlgo(algo string) string { 382 for privAlgo, pubAlgo := range certAlgoNames { 383 if pubAlgo == algo { 384 return privAlgo 385 } 386 } 387 panic("unknown cert algorithm") 388 } 389 390 func (cert *Certificate) bytesForSigning() []byte { 391 c2 := *cert 392 c2.Signature = nil 393 out := c2.Marshal() 394 // Drop trailing signature length. 395 return out[:len(out)-4] 396 } 397 398 // Marshal serializes c into OpenSSH's wire format. It is part of the 399 // PublicKey interface. 400 func (c *Certificate) Marshal() []byte { 401 generic := genericCertData{ 402 Serial: c.Serial, 403 CertType: c.CertType, 404 KeyId: c.KeyId, 405 ValidPrincipals: marshalStringList(c.ValidPrincipals), 406 ValidAfter: uint64(c.ValidAfter), 407 ValidBefore: uint64(c.ValidBefore), 408 CriticalOptions: marshalTuples(c.CriticalOptions), 409 Extensions: marshalTuples(c.Extensions), 410 Reserved: c.Reserved, 411 SignatureKey: c.SignatureKey.Marshal(), 412 } 413 if c.Signature != nil { 414 generic.Signature = Marshal(c.Signature) 415 } 416 genericBytes := Marshal(&generic) 417 keyBytes := c.Key.Marshal() 418 _, keyBytes, _ = parseString(keyBytes) 419 prefix := Marshal(&struct { 420 Name string 421 Nonce []byte 422 Key []byte `ssh:"rest"` 423 }{c.Type(), c.Nonce, keyBytes}) 424 425 result := make([]byte, 0, len(prefix)+len(genericBytes)) 426 result = append(result, prefix...) 427 result = append(result, genericBytes...) 428 return result 429 } 430 431 // Type returns the key name. It is part of the PublicKey interface. 432 func (c *Certificate) Type() string { 433 algo, ok := certAlgoNames[c.Key.Type()] 434 if !ok { 435 panic("unknown cert key type") 436 } 437 return algo 438 } 439 440 // Verify verifies a signature against the certificate's public 441 // key. It is part of the PublicKey interface. 442 func (c *Certificate) Verify(data []byte, sig *Signature) error { 443 return c.Key.Verify(data, sig) 444 } 445 446 func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { 447 format, in, ok := parseString(in) 448 if !ok { 449 return 450 } 451 452 out = &Signature{ 453 Format: string(format), 454 } 455 456 if out.Blob, in, ok = parseString(in); !ok { 457 return 458 } 459 460 return out, in, ok 461 } 462 463 func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { 464 sigBytes, rest, ok := parseString(in) 465 if !ok { 466 return 467 } 468 469 out, trailing, ok := parseSignatureBody(sigBytes) 470 if !ok || len(trailing) > 0 { 471 return nil, nil, false 472 } 473 return 474 }