github.com/glycerine/xcryptossh@v7.0.4+incompatible/agent/server.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 agent 6 7 import ( 8 "crypto/dsa" 9 "crypto/ecdsa" 10 "crypto/elliptic" 11 "crypto/rsa" 12 "encoding/binary" 13 "errors" 14 "fmt" 15 "io" 16 "log" 17 "math/big" 18 19 "golang.org/x/crypto/ed25519" 20 "github.com/glycerine/xcryptossh" 21 ) 22 23 // Server wraps an Agent and uses it to implement the agent side of 24 // the SSH-agent, wire protocol. 25 type server struct { 26 agent Agent 27 } 28 29 func (s *server) processRequestBytes(reqData []byte) []byte { 30 rep, err := s.processRequest(reqData) 31 if err != nil { 32 if err != errLocked { 33 // TODO(hanwen): provide better logging interface? 34 log.Printf("agent %d: %v", reqData[0], err) 35 } 36 return []byte{agentFailure} 37 } 38 39 if err == nil && rep == nil { 40 return []byte{agentSuccess} 41 } 42 43 return ssh.Marshal(rep) 44 } 45 46 func marshalKey(k *Key) []byte { 47 var record struct { 48 Blob []byte 49 Comment string 50 } 51 record.Blob = k.Marshal() 52 record.Comment = k.Comment 53 54 return ssh.Marshal(&record) 55 } 56 57 // See [PROTOCOL.agent], section 2.5.1. 58 const agentV1IdentitiesAnswer = 2 59 60 type agentV1IdentityMsg struct { 61 Numkeys uint32 `sshtype:"2"` 62 } 63 64 type agentRemoveIdentityMsg struct { 65 KeyBlob []byte `sshtype:"18"` 66 } 67 68 type agentLockMsg struct { 69 Passphrase []byte `sshtype:"22"` 70 } 71 72 type agentUnlockMsg struct { 73 Passphrase []byte `sshtype:"23"` 74 } 75 76 func (s *server) processRequest(data []byte) (interface{}, error) { 77 switch data[0] { 78 case agentRequestV1Identities: 79 return &agentV1IdentityMsg{0}, nil 80 81 case agentRemoveAllV1Identities: 82 return nil, nil 83 84 case agentRemoveIdentity: 85 var req agentRemoveIdentityMsg 86 if err := ssh.Unmarshal(data, &req); err != nil { 87 return nil, err 88 } 89 90 var wk wireKey 91 if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { 92 return nil, err 93 } 94 95 return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) 96 97 case agentRemoveAllIdentities: 98 return nil, s.agent.RemoveAll() 99 100 case agentLock: 101 var req agentLockMsg 102 if err := ssh.Unmarshal(data, &req); err != nil { 103 return nil, err 104 } 105 106 return nil, s.agent.Lock(req.Passphrase) 107 108 case agentUnlock: 109 var req agentUnlockMsg 110 if err := ssh.Unmarshal(data, &req); err != nil { 111 return nil, err 112 } 113 return nil, s.agent.Unlock(req.Passphrase) 114 115 case agentSignRequest: 116 var req signRequestAgentMsg 117 if err := ssh.Unmarshal(data, &req); err != nil { 118 return nil, err 119 } 120 121 var wk wireKey 122 if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { 123 return nil, err 124 } 125 126 k := &Key{ 127 Format: wk.Format, 128 Blob: req.KeyBlob, 129 } 130 131 sig, err := s.agent.Sign(k, req.Data) // TODO(hanwen): flags. 132 if err != nil { 133 return nil, err 134 } 135 return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil 136 137 case agentRequestIdentities: 138 keys, err := s.agent.List() 139 if err != nil { 140 return nil, err 141 } 142 143 rep := identitiesAnswerAgentMsg{ 144 NumKeys: uint32(len(keys)), 145 } 146 for _, k := range keys { 147 rep.Keys = append(rep.Keys, marshalKey(k)...) 148 } 149 return rep, nil 150 151 case agentAddIdConstrained, agentAddIdentity: 152 return nil, s.insertIdentity(data) 153 } 154 155 return nil, fmt.Errorf("unknown opcode %d", data[0]) 156 } 157 158 func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) { 159 for len(constraints) != 0 { 160 switch constraints[0] { 161 case agentConstrainLifetime: 162 lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5]) 163 constraints = constraints[5:] 164 case agentConstrainConfirm: 165 confirmBeforeUse = true 166 constraints = constraints[1:] 167 case agentConstrainExtension: 168 var msg constrainExtensionAgentMsg 169 if err = ssh.Unmarshal(constraints, &msg); err != nil { 170 return 0, false, nil, err 171 } 172 extensions = append(extensions, ConstraintExtension{ 173 ExtensionName: msg.ExtensionName, 174 ExtensionDetails: msg.ExtensionDetails, 175 }) 176 constraints = msg.Rest 177 default: 178 return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0]) 179 } 180 } 181 return 182 } 183 184 func setConstraints(key *AddedKey, constraintBytes []byte) error { 185 lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes) 186 if err != nil { 187 return err 188 } 189 190 key.LifetimeSecs = lifetimeSecs 191 key.ConfirmBeforeUse = confirmBeforeUse 192 key.ConstraintExtensions = constraintExtensions 193 return nil 194 } 195 196 func parseRSAKey(req []byte) (*AddedKey, error) { 197 var k rsaKeyMsg 198 if err := ssh.Unmarshal(req, &k); err != nil { 199 return nil, err 200 } 201 if k.E.BitLen() > 30 { 202 return nil, errors.New("agent: RSA public exponent too large") 203 } 204 priv := &rsa.PrivateKey{ 205 PublicKey: rsa.PublicKey{ 206 E: int(k.E.Int64()), 207 N: k.N, 208 }, 209 D: k.D, 210 Primes: []*big.Int{k.P, k.Q}, 211 } 212 priv.Precompute() 213 214 addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} 215 if err := setConstraints(addedKey, k.Constraints); err != nil { 216 return nil, err 217 } 218 return addedKey, nil 219 } 220 221 func parseEd25519Key(req []byte) (*AddedKey, error) { 222 var k ed25519KeyMsg 223 if err := ssh.Unmarshal(req, &k); err != nil { 224 return nil, err 225 } 226 priv := ed25519.PrivateKey(k.Priv) 227 228 addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments} 229 if err := setConstraints(addedKey, k.Constraints); err != nil { 230 return nil, err 231 } 232 return addedKey, nil 233 } 234 235 func parseDSAKey(req []byte) (*AddedKey, error) { 236 var k dsaKeyMsg 237 if err := ssh.Unmarshal(req, &k); err != nil { 238 return nil, err 239 } 240 priv := &dsa.PrivateKey{ 241 PublicKey: dsa.PublicKey{ 242 Parameters: dsa.Parameters{ 243 P: k.P, 244 Q: k.Q, 245 G: k.G, 246 }, 247 Y: k.Y, 248 }, 249 X: k.X, 250 } 251 252 addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} 253 if err := setConstraints(addedKey, k.Constraints); err != nil { 254 return nil, err 255 } 256 return addedKey, nil 257 } 258 259 func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) { 260 priv = &ecdsa.PrivateKey{ 261 D: privScalar, 262 } 263 264 switch curveName { 265 case "nistp256": 266 priv.Curve = elliptic.P256() 267 case "nistp384": 268 priv.Curve = elliptic.P384() 269 case "nistp521": 270 priv.Curve = elliptic.P521() 271 default: 272 return nil, fmt.Errorf("agent: unknown curve %q", curveName) 273 } 274 275 priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes) 276 if priv.X == nil || priv.Y == nil { 277 return nil, errors.New("agent: point not on curve") 278 } 279 280 return priv, nil 281 } 282 283 func parseEd25519Cert(req []byte) (*AddedKey, error) { 284 var k ed25519CertMsg 285 if err := ssh.Unmarshal(req, &k); err != nil { 286 return nil, err 287 } 288 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 289 if err != nil { 290 return nil, err 291 } 292 priv := ed25519.PrivateKey(k.Priv) 293 cert, ok := pubKey.(*ssh.Certificate) 294 if !ok { 295 return nil, errors.New("agent: bad ED25519 certificate") 296 } 297 298 addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} 299 if err := setConstraints(addedKey, k.Constraints); err != nil { 300 return nil, err 301 } 302 return addedKey, nil 303 } 304 305 func parseECDSAKey(req []byte) (*AddedKey, error) { 306 var k ecdsaKeyMsg 307 if err := ssh.Unmarshal(req, &k); err != nil { 308 return nil, err 309 } 310 311 priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D) 312 if err != nil { 313 return nil, err 314 } 315 316 addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} 317 if err := setConstraints(addedKey, k.Constraints); err != nil { 318 return nil, err 319 } 320 return addedKey, nil 321 } 322 323 func parseRSACert(req []byte) (*AddedKey, error) { 324 var k rsaCertMsg 325 if err := ssh.Unmarshal(req, &k); err != nil { 326 return nil, err 327 } 328 329 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 330 if err != nil { 331 return nil, err 332 } 333 334 cert, ok := pubKey.(*ssh.Certificate) 335 if !ok { 336 return nil, errors.New("agent: bad RSA certificate") 337 } 338 339 // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go 340 var rsaPub struct { 341 Name string 342 E *big.Int 343 N *big.Int 344 } 345 if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil { 346 return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) 347 } 348 349 if rsaPub.E.BitLen() > 30 { 350 return nil, errors.New("agent: RSA public exponent too large") 351 } 352 353 priv := rsa.PrivateKey{ 354 PublicKey: rsa.PublicKey{ 355 E: int(rsaPub.E.Int64()), 356 N: rsaPub.N, 357 }, 358 D: k.D, 359 Primes: []*big.Int{k.Q, k.P}, 360 } 361 priv.Precompute() 362 363 addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} 364 if err := setConstraints(addedKey, k.Constraints); err != nil { 365 return nil, err 366 } 367 return addedKey, nil 368 } 369 370 func parseDSACert(req []byte) (*AddedKey, error) { 371 var k dsaCertMsg 372 if err := ssh.Unmarshal(req, &k); err != nil { 373 return nil, err 374 } 375 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 376 if err != nil { 377 return nil, err 378 } 379 cert, ok := pubKey.(*ssh.Certificate) 380 if !ok { 381 return nil, errors.New("agent: bad DSA certificate") 382 } 383 384 // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go 385 var w struct { 386 Name string 387 P, Q, G, Y *big.Int 388 } 389 if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil { 390 return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) 391 } 392 393 priv := &dsa.PrivateKey{ 394 PublicKey: dsa.PublicKey{ 395 Parameters: dsa.Parameters{ 396 P: w.P, 397 Q: w.Q, 398 G: w.G, 399 }, 400 Y: w.Y, 401 }, 402 X: k.X, 403 } 404 405 addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} 406 if err := setConstraints(addedKey, k.Constraints); err != nil { 407 return nil, err 408 } 409 return addedKey, nil 410 } 411 412 func parseECDSACert(req []byte) (*AddedKey, error) { 413 var k ecdsaCertMsg 414 if err := ssh.Unmarshal(req, &k); err != nil { 415 return nil, err 416 } 417 418 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 419 if err != nil { 420 return nil, err 421 } 422 cert, ok := pubKey.(*ssh.Certificate) 423 if !ok { 424 return nil, errors.New("agent: bad ECDSA certificate") 425 } 426 427 // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go 428 var ecdsaPub struct { 429 Name string 430 ID string 431 Key []byte 432 } 433 if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil { 434 return nil, err 435 } 436 437 priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D) 438 if err != nil { 439 return nil, err 440 } 441 442 addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} 443 if err := setConstraints(addedKey, k.Constraints); err != nil { 444 return nil, err 445 } 446 return addedKey, nil 447 } 448 449 func (s *server) insertIdentity(req []byte) error { 450 var record struct { 451 Type string `sshtype:"17|25"` 452 Rest []byte `ssh:"rest"` 453 } 454 455 if err := ssh.Unmarshal(req, &record); err != nil { 456 return err 457 } 458 459 var addedKey *AddedKey 460 var err error 461 462 switch record.Type { 463 case ssh.KeyAlgoRSA: 464 addedKey, err = parseRSAKey(req) 465 case ssh.KeyAlgoDSA: 466 addedKey, err = parseDSAKey(req) 467 case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: 468 addedKey, err = parseECDSAKey(req) 469 case ssh.KeyAlgoED25519: 470 addedKey, err = parseEd25519Key(req) 471 case ssh.CertAlgoRSAv01: 472 addedKey, err = parseRSACert(req) 473 case ssh.CertAlgoDSAv01: 474 addedKey, err = parseDSACert(req) 475 case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: 476 addedKey, err = parseECDSACert(req) 477 case ssh.CertAlgoED25519v01: 478 addedKey, err = parseEd25519Cert(req) 479 default: 480 return fmt.Errorf("agent: not implemented: %q", record.Type) 481 } 482 483 if err != nil { 484 return err 485 } 486 return s.agent.Add(*addedKey) 487 } 488 489 // ServeAgent serves the agent protocol on the given connection. It 490 // returns when an I/O error occurs. 491 func ServeAgent(agent Agent, c io.ReadWriter) error { 492 s := &server{agent} 493 494 var length [4]byte 495 for { 496 if _, err := io.ReadFull(c, length[:]); err != nil { 497 return err 498 } 499 l := binary.BigEndian.Uint32(length[:]) 500 if l > maxAgentResponseBytes { 501 // We also cap requests. 502 return fmt.Errorf("agent: request too large: %d", l) 503 } 504 505 req := make([]byte, l) 506 if _, err := io.ReadFull(c, req); err != nil { 507 return err 508 } 509 510 repData := s.processRequestBytes(req) 511 if len(repData) > maxAgentResponseBytes { 512 return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) 513 } 514 515 binary.BigEndian.PutUint32(length[:], uint32(len(repData))) 516 if _, err := c.Write(length[:]); err != nil { 517 return err 518 } 519 if _, err := c.Write(repData); err != nil { 520 return err 521 } 522 } 523 }