You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

660 lines
16 KiB

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