client.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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 implements a client to an ssh-agent daemon.
  6. References:
  7. [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD
  8. */
  9. package agent // import "golang.org/x/crypto/ssh/agent"
  10. import (
  11. "bytes"
  12. "crypto/dsa"
  13. "crypto/ecdsa"
  14. "crypto/elliptic"
  15. "crypto/rsa"
  16. "encoding/base64"
  17. "encoding/binary"
  18. "errors"
  19. "fmt"
  20. "io"
  21. "math/big"
  22. "sync"
  23. "golang.org/x/crypto/ssh"
  24. )
  25. // Agent represents the capabilities of an ssh-agent.
  26. type Agent interface {
  27. // List returns the identities known to the agent.
  28. List() ([]*Key, error)
  29. // Sign has the agent sign the data using a protocol 2 key as defined
  30. // in [PROTOCOL.agent] section 2.6.2.
  31. Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error)
  32. // Insert adds a private key to the agent. If a certificate
  33. // is given, that certificate is added as public key.
  34. Add(s interface{}, cert *ssh.Certificate, comment string) error
  35. // Remove removes all identities with the given public key.
  36. Remove(key ssh.PublicKey) error
  37. // RemoveAll removes all identities.
  38. RemoveAll() error
  39. // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
  40. Lock(passphrase []byte) error
  41. // Unlock undoes the effect of Lock
  42. Unlock(passphrase []byte) error
  43. // Signers returns signers for all the known keys.
  44. Signers() ([]ssh.Signer, error)
  45. }
  46. // See [PROTOCOL.agent], section 3.
  47. const (
  48. agentRequestV1Identities = 1
  49. // 3.2 Requests from client to agent for protocol 2 key operations
  50. agentAddIdentity = 17
  51. agentRemoveIdentity = 18
  52. agentRemoveAllIdentities = 19
  53. agentAddIdConstrained = 25
  54. // 3.3 Key-type independent requests from client to agent
  55. agentAddSmartcardKey = 20
  56. agentRemoveSmartcardKey = 21
  57. agentLock = 22
  58. agentUnlock = 23
  59. agentAddSmartcardKeyConstrained = 26
  60. // 3.7 Key constraint identifiers
  61. agentConstrainLifetime = 1
  62. agentConstrainConfirm = 2
  63. )
  64. // maxAgentResponseBytes is the maximum agent reply size that is accepted. This
  65. // is a sanity check, not a limit in the spec.
  66. const maxAgentResponseBytes = 16 << 20
  67. // Agent messages:
  68. // These structures mirror the wire format of the corresponding ssh agent
  69. // messages found in [PROTOCOL.agent].
  70. // 3.4 Generic replies from agent to client
  71. const agentFailure = 5
  72. type failureAgentMsg struct{}
  73. const agentSuccess = 6
  74. type successAgentMsg struct{}
  75. // See [PROTOCOL.agent], section 2.5.2.
  76. const agentRequestIdentities = 11
  77. type requestIdentitiesAgentMsg struct{}
  78. // See [PROTOCOL.agent], section 2.5.2.
  79. const agentIdentitiesAnswer = 12
  80. type identitiesAnswerAgentMsg struct {
  81. NumKeys uint32 `sshtype:"12"`
  82. Keys []byte `ssh:"rest"`
  83. }
  84. // See [PROTOCOL.agent], section 2.6.2.
  85. const agentSignRequest = 13
  86. type signRequestAgentMsg struct {
  87. KeyBlob []byte `sshtype:"13"`
  88. Data []byte
  89. Flags uint32
  90. }
  91. // See [PROTOCOL.agent], section 2.6.2.
  92. // 3.6 Replies from agent to client for protocol 2 key operations
  93. const agentSignResponse = 14
  94. type signResponseAgentMsg struct {
  95. SigBlob []byte `sshtype:"14"`
  96. }
  97. type publicKey struct {
  98. Format string
  99. Rest []byte `ssh:"rest"`
  100. }
  101. // Key represents a protocol 2 public key as defined in
  102. // [PROTOCOL.agent], section 2.5.2.
  103. type Key struct {
  104. Format string
  105. Blob []byte
  106. Comment string
  107. }
  108. func clientErr(err error) error {
  109. return fmt.Errorf("agent: client error: %v", err)
  110. }
  111. // String returns the storage form of an agent key with the format, base64
  112. // encoded serialized key, and the comment if it is not empty.
  113. func (k *Key) String() string {
  114. s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob)
  115. if k.Comment != "" {
  116. s += " " + k.Comment
  117. }
  118. return s
  119. }
  120. // Type returns the public key type.
  121. func (k *Key) Type() string {
  122. return k.Format
  123. }
  124. // Marshal returns key blob to satisfy the ssh.PublicKey interface.
  125. func (k *Key) Marshal() []byte {
  126. return k.Blob
  127. }
  128. // Verify satisfies the ssh.PublicKey interface, but is not
  129. // implemented for agent keys.
  130. func (k *Key) Verify(data []byte, sig *ssh.Signature) error {
  131. return errors.New("agent: agent key does not know how to verify")
  132. }
  133. type wireKey struct {
  134. Format string
  135. Rest []byte `ssh:"rest"`
  136. }
  137. func parseKey(in []byte) (out *Key, rest []byte, err error) {
  138. var record struct {
  139. Blob []byte
  140. Comment string
  141. Rest []byte `ssh:"rest"`
  142. }
  143. if err := ssh.Unmarshal(in, &record); err != nil {
  144. return nil, nil, err
  145. }
  146. var wk wireKey
  147. if err := ssh.Unmarshal(record.Blob, &wk); err != nil {
  148. return nil, nil, err
  149. }
  150. return &Key{
  151. Format: wk.Format,
  152. Blob: record.Blob,
  153. Comment: record.Comment,
  154. }, record.Rest, nil
  155. }
  156. // client is a client for an ssh-agent process.
  157. type client struct {
  158. // conn is typically a *net.UnixConn
  159. conn io.ReadWriter
  160. // mu is used to prevent concurrent access to the agent
  161. mu sync.Mutex
  162. }
  163. // NewClient returns an Agent that talks to an ssh-agent process over
  164. // the given connection.
  165. func NewClient(rw io.ReadWriter) Agent {
  166. return &client{conn: rw}
  167. }
  168. // call sends an RPC to the agent. On success, the reply is
  169. // unmarshaled into reply and replyType is set to the first byte of
  170. // the reply, which contains the type of the message.
  171. func (c *client) call(req []byte) (reply interface{}, err error) {
  172. c.mu.Lock()
  173. defer c.mu.Unlock()
  174. msg := make([]byte, 4+len(req))
  175. binary.BigEndian.PutUint32(msg, uint32(len(req)))
  176. copy(msg[4:], req)
  177. if _, err = c.conn.Write(msg); err != nil {
  178. return nil, clientErr(err)
  179. }
  180. var respSizeBuf [4]byte
  181. if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil {
  182. return nil, clientErr(err)
  183. }
  184. respSize := binary.BigEndian.Uint32(respSizeBuf[:])
  185. if respSize > maxAgentResponseBytes {
  186. return nil, clientErr(err)
  187. }
  188. buf := make([]byte, respSize)
  189. if _, err = io.ReadFull(c.conn, buf); err != nil {
  190. return nil, clientErr(err)
  191. }
  192. reply, err = unmarshal(buf)
  193. if err != nil {
  194. return nil, clientErr(err)
  195. }
  196. return reply, err
  197. }
  198. func (c *client) simpleCall(req []byte) error {
  199. resp, err := c.call(req)
  200. if err != nil {
  201. return err
  202. }
  203. if _, ok := resp.(*successAgentMsg); ok {
  204. return nil
  205. }
  206. return errors.New("agent: failure")
  207. }
  208. func (c *client) RemoveAll() error {
  209. return c.simpleCall([]byte{agentRemoveAllIdentities})
  210. }
  211. func (c *client) Remove(key ssh.PublicKey) error {
  212. req := ssh.Marshal(&agentRemoveIdentityMsg{
  213. KeyBlob: key.Marshal(),
  214. })
  215. return c.simpleCall(req)
  216. }
  217. func (c *client) Lock(passphrase []byte) error {
  218. req := ssh.Marshal(&agentLockMsg{
  219. Passphrase: passphrase,
  220. })
  221. return c.simpleCall(req)
  222. }
  223. func (c *client) Unlock(passphrase []byte) error {
  224. req := ssh.Marshal(&agentUnlockMsg{
  225. Passphrase: passphrase,
  226. })
  227. return c.simpleCall(req)
  228. }
  229. // List returns the identities known to the agent.
  230. func (c *client) List() ([]*Key, error) {
  231. // see [PROTOCOL.agent] section 2.5.2.
  232. req := []byte{agentRequestIdentities}
  233. msg, err := c.call(req)
  234. if err != nil {
  235. return nil, err
  236. }
  237. switch msg := msg.(type) {
  238. case *identitiesAnswerAgentMsg:
  239. if msg.NumKeys > maxAgentResponseBytes/8 {
  240. return nil, errors.New("agent: too many keys in agent reply")
  241. }
  242. keys := make([]*Key, msg.NumKeys)
  243. data := msg.Keys
  244. for i := uint32(0); i < msg.NumKeys; i++ {
  245. var key *Key
  246. var err error
  247. if key, data, err = parseKey(data); err != nil {
  248. return nil, err
  249. }
  250. keys[i] = key
  251. }
  252. return keys, nil
  253. case *failureAgentMsg:
  254. return nil, errors.New("agent: failed to list keys")
  255. }
  256. panic("unreachable")
  257. }
  258. // Sign has the agent sign the data using a protocol 2 key as defined
  259. // in [PROTOCOL.agent] section 2.6.2.
  260. func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
  261. req := ssh.Marshal(signRequestAgentMsg{
  262. KeyBlob: key.Marshal(),
  263. Data: data,
  264. })
  265. msg, err := c.call(req)
  266. if err != nil {
  267. return nil, err
  268. }
  269. switch msg := msg.(type) {
  270. case *signResponseAgentMsg:
  271. var sig ssh.Signature
  272. if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil {
  273. return nil, err
  274. }
  275. return &sig, nil
  276. case *failureAgentMsg:
  277. return nil, errors.New("agent: failed to sign challenge")
  278. }
  279. panic("unreachable")
  280. }
  281. // unmarshal parses an agent message in packet, returning the parsed
  282. // form and the message type of packet.
  283. func unmarshal(packet []byte) (interface{}, error) {
  284. if len(packet) < 1 {
  285. return nil, errors.New("agent: empty packet")
  286. }
  287. var msg interface{}
  288. switch packet[0] {
  289. case agentFailure:
  290. return new(failureAgentMsg), nil
  291. case agentSuccess:
  292. return new(successAgentMsg), nil
  293. case agentIdentitiesAnswer:
  294. msg = new(identitiesAnswerAgentMsg)
  295. case agentSignResponse:
  296. msg = new(signResponseAgentMsg)
  297. default:
  298. return nil, fmt.Errorf("agent: unknown type tag %d", packet[0])
  299. }
  300. if err := ssh.Unmarshal(packet, msg); err != nil {
  301. return nil, err
  302. }
  303. return msg, nil
  304. }
  305. type rsaKeyMsg struct {
  306. Type string `sshtype:"17"`
  307. N *big.Int
  308. E *big.Int
  309. D *big.Int
  310. Iqmp *big.Int // IQMP = Inverse Q Mod P
  311. P *big.Int
  312. Q *big.Int
  313. Comments string
  314. }
  315. type dsaKeyMsg struct {
  316. Type string `sshtype:"17"`
  317. P *big.Int
  318. Q *big.Int
  319. G *big.Int
  320. Y *big.Int
  321. X *big.Int
  322. Comments string
  323. }
  324. type ecdsaKeyMsg struct {
  325. Type string `sshtype:"17"`
  326. Curve string
  327. KeyBytes []byte
  328. D *big.Int
  329. Comments string
  330. }
  331. // Insert adds a private key to the agent.
  332. func (c *client) insertKey(s interface{}, comment string) error {
  333. var req []byte
  334. switch k := s.(type) {
  335. case *rsa.PrivateKey:
  336. if len(k.Primes) != 2 {
  337. return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
  338. }
  339. k.Precompute()
  340. req = ssh.Marshal(rsaKeyMsg{
  341. Type: ssh.KeyAlgoRSA,
  342. N: k.N,
  343. E: big.NewInt(int64(k.E)),
  344. D: k.D,
  345. Iqmp: k.Precomputed.Qinv,
  346. P: k.Primes[0],
  347. Q: k.Primes[1],
  348. Comments: comment,
  349. })
  350. case *dsa.PrivateKey:
  351. req = ssh.Marshal(dsaKeyMsg{
  352. Type: ssh.KeyAlgoDSA,
  353. P: k.P,
  354. Q: k.Q,
  355. G: k.G,
  356. Y: k.Y,
  357. X: k.X,
  358. Comments: comment,
  359. })
  360. case *ecdsa.PrivateKey:
  361. nistID := fmt.Sprintf("nistp%d", k.Params().BitSize)
  362. req = ssh.Marshal(ecdsaKeyMsg{
  363. Type: "ecdsa-sha2-" + nistID,
  364. Curve: nistID,
  365. KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y),
  366. D: k.D,
  367. Comments: comment,
  368. })
  369. default:
  370. return fmt.Errorf("agent: unsupported key type %T", s)
  371. }
  372. resp, err := c.call(req)
  373. if err != nil {
  374. return err
  375. }
  376. if _, ok := resp.(*successAgentMsg); ok {
  377. return nil
  378. }
  379. return errors.New("agent: failure")
  380. }
  381. type rsaCertMsg struct {
  382. Type string `sshtype:"17"`
  383. CertBytes []byte
  384. D *big.Int
  385. Iqmp *big.Int // IQMP = Inverse Q Mod P
  386. P *big.Int
  387. Q *big.Int
  388. Comments string
  389. }
  390. type dsaCertMsg struct {
  391. Type string `sshtype:"17"`
  392. CertBytes []byte
  393. X *big.Int
  394. Comments string
  395. }
  396. type ecdsaCertMsg struct {
  397. Type string `sshtype:"17"`
  398. CertBytes []byte
  399. D *big.Int
  400. Comments string
  401. }
  402. // Insert adds a private key to the agent. If a certificate is given,
  403. // that certificate is added instead as public key.
  404. func (c *client) Add(s interface{}, cert *ssh.Certificate, comment string) error {
  405. if cert == nil {
  406. return c.insertKey(s, comment)
  407. } else {
  408. return c.insertCert(s, cert, comment)
  409. }
  410. }
  411. func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string) error {
  412. var req []byte
  413. switch k := s.(type) {
  414. case *rsa.PrivateKey:
  415. if len(k.Primes) != 2 {
  416. return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
  417. }
  418. k.Precompute()
  419. req = ssh.Marshal(rsaCertMsg{
  420. Type: cert.Type(),
  421. CertBytes: cert.Marshal(),
  422. D: k.D,
  423. Iqmp: k.Precomputed.Qinv,
  424. P: k.Primes[0],
  425. Q: k.Primes[1],
  426. Comments: comment,
  427. })
  428. case *dsa.PrivateKey:
  429. req = ssh.Marshal(dsaCertMsg{
  430. Type: cert.Type(),
  431. CertBytes: cert.Marshal(),
  432. X: k.X,
  433. Comments: comment,
  434. })
  435. case *ecdsa.PrivateKey:
  436. req = ssh.Marshal(ecdsaCertMsg{
  437. Type: cert.Type(),
  438. CertBytes: cert.Marshal(),
  439. D: k.D,
  440. Comments: comment,
  441. })
  442. default:
  443. return fmt.Errorf("agent: unsupported key type %T", s)
  444. }
  445. signer, err := ssh.NewSignerFromKey(s)
  446. if err != nil {
  447. return err
  448. }
  449. if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
  450. return errors.New("agent: signer and cert have different public key")
  451. }
  452. resp, err := c.call(req)
  453. if err != nil {
  454. return err
  455. }
  456. if _, ok := resp.(*successAgentMsg); ok {
  457. return nil
  458. }
  459. return errors.New("agent: failure")
  460. }
  461. // Signers provides a callback for client authentication.
  462. func (c *client) Signers() ([]ssh.Signer, error) {
  463. keys, err := c.List()
  464. if err != nil {
  465. return nil, err
  466. }
  467. var result []ssh.Signer
  468. for _, k := range keys {
  469. result = append(result, &agentKeyringSigner{c, k})
  470. }
  471. return result, nil
  472. }
  473. type agentKeyringSigner struct {
  474. agent *client
  475. pub ssh.PublicKey
  476. }
  477. func (s *agentKeyringSigner) PublicKey() ssh.PublicKey {
  478. return s.pub
  479. }
  480. func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
  481. // The agent has its own entropy source, so the rand argument is ignored.
  482. return s.agent.Sign(s.pub, data)
  483. }