github.com/maenmax/kairep@v0.0.0-20210218001208-55bf3df36788/src/golang.org/x/crypto/ssh/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 "golang.org/x/crypto/ssh" 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 agentLockMsg 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 parseRSAKey(req []byte) (*AddedKey, error) { 159 var k rsaKeyMsg 160 if err := ssh.Unmarshal(req, &k); err != nil { 161 return nil, err 162 } 163 if k.E.BitLen() > 30 { 164 return nil, errors.New("agent: RSA public exponent too large") 165 } 166 priv := &rsa.PrivateKey{ 167 PublicKey: rsa.PublicKey{ 168 E: int(k.E.Int64()), 169 N: k.N, 170 }, 171 D: k.D, 172 Primes: []*big.Int{k.P, k.Q}, 173 } 174 priv.Precompute() 175 176 return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil 177 } 178 179 func parseEd25519Key(req []byte) (*AddedKey, error) { 180 var k ed25519KeyMsg 181 if err := ssh.Unmarshal(req, &k); err != nil { 182 return nil, err 183 } 184 priv := ed25519.PrivateKey(k.Priv) 185 return &AddedKey{PrivateKey: &priv, Comment: k.Comments}, nil 186 } 187 188 func parseDSAKey(req []byte) (*AddedKey, error) { 189 var k dsaKeyMsg 190 if err := ssh.Unmarshal(req, &k); err != nil { 191 return nil, err 192 } 193 priv := &dsa.PrivateKey{ 194 PublicKey: dsa.PublicKey{ 195 Parameters: dsa.Parameters{ 196 P: k.P, 197 Q: k.Q, 198 G: k.G, 199 }, 200 Y: k.Y, 201 }, 202 X: k.X, 203 } 204 205 return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil 206 } 207 208 func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) { 209 priv = &ecdsa.PrivateKey{ 210 D: privScalar, 211 } 212 213 switch curveName { 214 case "nistp256": 215 priv.Curve = elliptic.P256() 216 case "nistp384": 217 priv.Curve = elliptic.P384() 218 case "nistp521": 219 priv.Curve = elliptic.P521() 220 default: 221 return nil, fmt.Errorf("agent: unknown curve %q", curveName) 222 } 223 224 priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes) 225 if priv.X == nil || priv.Y == nil { 226 return nil, errors.New("agent: point not on curve") 227 } 228 229 return priv, nil 230 } 231 232 func parseEd25519Cert(req []byte) (*AddedKey, error) { 233 var k ed25519CertMsg 234 if err := ssh.Unmarshal(req, &k); err != nil { 235 return nil, err 236 } 237 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 238 if err != nil { 239 return nil, err 240 } 241 priv := ed25519.PrivateKey(k.Priv) 242 cert, ok := pubKey.(*ssh.Certificate) 243 if !ok { 244 return nil, errors.New("agent: bad ED25519 certificate") 245 } 246 return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil 247 } 248 249 func parseECDSAKey(req []byte) (*AddedKey, error) { 250 var k ecdsaKeyMsg 251 if err := ssh.Unmarshal(req, &k); err != nil { 252 return nil, err 253 } 254 255 priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D) 256 if err != nil { 257 return nil, err 258 } 259 260 return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil 261 } 262 263 func parseRSACert(req []byte) (*AddedKey, error) { 264 var k rsaCertMsg 265 if err := ssh.Unmarshal(req, &k); err != nil { 266 return nil, err 267 } 268 269 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 270 if err != nil { 271 return nil, err 272 } 273 274 cert, ok := pubKey.(*ssh.Certificate) 275 if !ok { 276 return nil, errors.New("agent: bad RSA certificate") 277 } 278 279 // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go 280 var rsaPub struct { 281 Name string 282 E *big.Int 283 N *big.Int 284 } 285 if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil { 286 return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) 287 } 288 289 if rsaPub.E.BitLen() > 30 { 290 return nil, errors.New("agent: RSA public exponent too large") 291 } 292 293 priv := rsa.PrivateKey{ 294 PublicKey: rsa.PublicKey{ 295 E: int(rsaPub.E.Int64()), 296 N: rsaPub.N, 297 }, 298 D: k.D, 299 Primes: []*big.Int{k.Q, k.P}, 300 } 301 priv.Precompute() 302 303 return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil 304 } 305 306 func parseDSACert(req []byte) (*AddedKey, error) { 307 var k dsaCertMsg 308 if err := ssh.Unmarshal(req, &k); err != nil { 309 return nil, err 310 } 311 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 312 if err != nil { 313 return nil, err 314 } 315 cert, ok := pubKey.(*ssh.Certificate) 316 if !ok { 317 return nil, errors.New("agent: bad DSA certificate") 318 } 319 320 // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go 321 var w struct { 322 Name string 323 P, Q, G, Y *big.Int 324 } 325 if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil { 326 return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) 327 } 328 329 priv := &dsa.PrivateKey{ 330 PublicKey: dsa.PublicKey{ 331 Parameters: dsa.Parameters{ 332 P: w.P, 333 Q: w.Q, 334 G: w.G, 335 }, 336 Y: w.Y, 337 }, 338 X: k.X, 339 } 340 341 return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil 342 } 343 344 func parseECDSACert(req []byte) (*AddedKey, error) { 345 var k ecdsaCertMsg 346 if err := ssh.Unmarshal(req, &k); err != nil { 347 return nil, err 348 } 349 350 pubKey, err := ssh.ParsePublicKey(k.CertBytes) 351 if err != nil { 352 return nil, err 353 } 354 cert, ok := pubKey.(*ssh.Certificate) 355 if !ok { 356 return nil, errors.New("agent: bad ECDSA certificate") 357 } 358 359 // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go 360 var ecdsaPub struct { 361 Name string 362 ID string 363 Key []byte 364 } 365 if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil { 366 return nil, err 367 } 368 369 priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D) 370 if err != nil { 371 return nil, err 372 } 373 374 return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil 375 } 376 377 func (s *server) insertIdentity(req []byte) error { 378 var record struct { 379 Type string `sshtype:"17|25"` 380 Rest []byte `ssh:"rest"` 381 } 382 383 if err := ssh.Unmarshal(req, &record); err != nil { 384 return err 385 } 386 387 var addedKey *AddedKey 388 var err error 389 390 switch record.Type { 391 case ssh.KeyAlgoRSA: 392 addedKey, err = parseRSAKey(req) 393 case ssh.KeyAlgoDSA: 394 addedKey, err = parseDSAKey(req) 395 case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: 396 addedKey, err = parseECDSAKey(req) 397 case ssh.KeyAlgoED25519: 398 addedKey, err = parseEd25519Key(req) 399 case ssh.CertAlgoRSAv01: 400 addedKey, err = parseRSACert(req) 401 case ssh.CertAlgoDSAv01: 402 addedKey, err = parseDSACert(req) 403 case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: 404 addedKey, err = parseECDSACert(req) 405 case ssh.CertAlgoED25519v01: 406 addedKey, err = parseEd25519Cert(req) 407 default: 408 return fmt.Errorf("agent: not implemented: %q", record.Type) 409 } 410 411 if err != nil { 412 return err 413 } 414 return s.agent.Add(*addedKey) 415 } 416 417 // ServeAgent serves the agent protocol on the given connection. It 418 // returns when an I/O error occurs. 419 func ServeAgent(agent Agent, c io.ReadWriter) error { 420 s := &server{agent} 421 422 var length [4]byte 423 for { 424 if _, err := io.ReadFull(c, length[:]); err != nil { 425 return err 426 } 427 l := binary.BigEndian.Uint32(length[:]) 428 if l > maxAgentResponseBytes { 429 // We also cap requests. 430 return fmt.Errorf("agent: request too large: %d", l) 431 } 432 433 req := make([]byte, l) 434 if _, err := io.ReadFull(c, req); err != nil { 435 return err 436 } 437 438 repData := s.processRequestBytes(req) 439 if len(repData) > maxAgentResponseBytes { 440 return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) 441 } 442 443 binary.BigEndian.PutUint32(length[:], uint32(len(repData))) 444 if _, err := c.Write(length[:]); err != nil { 445 return err 446 } 447 if _, err := c.Write(repData); err != nil { 448 return err 449 } 450 } 451 }