client.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  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. //
  11. // [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00
  12. package agent
  13. import (
  14. "bytes"
  15. "crypto/dsa"
  16. "crypto/ecdsa"
  17. "crypto/ed25519"
  18. "crypto/elliptic"
  19. "crypto/rsa"
  20. "encoding/base64"
  21. "encoding/binary"
  22. "errors"
  23. "fmt"
  24. "io"
  25. "math/big"
  26. "sync"
  27. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/ssh"
  28. )
  29. // SignatureFlags represent additional flags that can be passed to the signature
  30. // requests an defined in [PROTOCOL.agent] section 4.5.1.
  31. type SignatureFlags uint32
  32. // SignatureFlag values as defined in [PROTOCOL.agent] section 5.3.
  33. const (
  34. SignatureFlagReserved SignatureFlags = 1 << iota
  35. SignatureFlagRsaSha256
  36. SignatureFlagRsaSha512
  37. )
  38. // Agent represents the capabilities of an ssh-agent.
  39. type Agent interface {
  40. // List returns the identities known to the agent.
  41. List() ([]*Key, error)
  42. // Sign has the agent sign the data using a protocol 2 key as defined
  43. // in [PROTOCOL.agent] section 2.6.2.
  44. Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error)
  45. // Add adds a private key to the agent.
  46. Add(key AddedKey) error
  47. // Remove removes all identities with the given public key.
  48. Remove(key ssh.PublicKey) error
  49. // RemoveAll removes all identities.
  50. RemoveAll() error
  51. // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
  52. Lock(passphrase []byte) error
  53. // Unlock undoes the effect of Lock
  54. Unlock(passphrase []byte) error
  55. // Signers returns signers for all the known keys.
  56. Signers() ([]ssh.Signer, error)
  57. }
  58. type ExtendedAgent interface {
  59. Agent
  60. // SignWithFlags signs like Sign, but allows for additional flags to be sent/received
  61. SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error)
  62. // Extension processes a custom extension request. Standard-compliant agents are not
  63. // required to support any extensions, but this method allows agents to implement
  64. // vendor-specific methods or add experimental features. See [PROTOCOL.agent] section 4.7.
  65. // If agent extensions are unsupported entirely this method MUST return an
  66. // ErrExtensionUnsupported error. Similarly, if just the specific extensionType in
  67. // the request is unsupported by the agent then ErrExtensionUnsupported MUST be
  68. // returned.
  69. //
  70. // In the case of success, since [PROTOCOL.agent] section 4.7 specifies that the contents
  71. // of the response are unspecified (including the type of the message), the complete
  72. // response will be returned as a []byte slice, including the "type" byte of the message.
  73. Extension(extensionType string, contents []byte) ([]byte, error)
  74. }
  75. // ConstraintExtension describes an optional constraint defined by users.
  76. type ConstraintExtension struct {
  77. // ExtensionName consist of a UTF-8 string suffixed by the
  78. // implementation domain following the naming scheme defined
  79. // in Section 4.2 of RFC 4251, e.g. "foo@example.com".
  80. ExtensionName string
  81. // ExtensionDetails contains the actual content of the extended
  82. // constraint.
  83. ExtensionDetails []byte
  84. }
  85. // AddedKey describes an SSH key to be added to an Agent.
  86. type AddedKey struct {
  87. // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey,
  88. // ed25519.PrivateKey or *ecdsa.PrivateKey, which will be inserted into the
  89. // agent.
  90. PrivateKey interface{}
  91. // Certificate, if not nil, is communicated to the agent and will be
  92. // stored with the key.
  93. Certificate *ssh.Certificate
  94. // Comment is an optional, free-form string.
  95. Comment string
  96. // LifetimeSecs, if not zero, is the number of seconds that the
  97. // agent will store the key for.
  98. LifetimeSecs uint32
  99. // ConfirmBeforeUse, if true, requests that the agent confirm with the
  100. // user before each use of this key.
  101. ConfirmBeforeUse bool
  102. // ConstraintExtensions are the experimental or private-use constraints
  103. // defined by users.
  104. ConstraintExtensions []ConstraintExtension
  105. }
  106. // See [PROTOCOL.agent], section 3.
  107. const (
  108. agentRequestV1Identities = 1
  109. agentRemoveAllV1Identities = 9
  110. // 3.2 Requests from client to agent for protocol 2 key operations
  111. agentAddIdentity = 17
  112. agentRemoveIdentity = 18
  113. agentRemoveAllIdentities = 19
  114. agentAddIDConstrained = 25
  115. // 3.3 Key-type independent requests from client to agent
  116. agentAddSmartcardKey = 20
  117. agentRemoveSmartcardKey = 21
  118. agentLock = 22
  119. agentUnlock = 23
  120. agentAddSmartcardKeyConstrained = 26
  121. // 3.7 Key constraint identifiers
  122. agentConstrainLifetime = 1
  123. agentConstrainConfirm = 2
  124. // Constraint extension identifier up to version 2 of the protocol. A
  125. // backward incompatible change will be required if we want to add support
  126. // for SSH_AGENT_CONSTRAIN_MAXSIGN which uses the same ID.
  127. agentConstrainExtensionV00 = 3
  128. // Constraint extension identifier in version 3 and later of the protocol.
  129. agentConstrainExtension = 255
  130. )
  131. // maxAgentResponseBytes is the maximum agent reply size that is accepted. This
  132. // is a sanity check, not a limit in the spec.
  133. const maxAgentResponseBytes = 16 << 20
  134. // Agent messages:
  135. // These structures mirror the wire format of the corresponding ssh agent
  136. // messages found in [PROTOCOL.agent].
  137. // 3.4 Generic replies from agent to client
  138. const agentFailure = 5
  139. type failureAgentMsg struct{}
  140. const agentSuccess = 6
  141. type successAgentMsg struct{}
  142. // See [PROTOCOL.agent], section 2.5.2.
  143. const agentRequestIdentities = 11
  144. type requestIdentitiesAgentMsg struct{}
  145. // See [PROTOCOL.agent], section 2.5.2.
  146. const agentIdentitiesAnswer = 12
  147. type identitiesAnswerAgentMsg struct {
  148. NumKeys uint32 `sshtype:"12"`
  149. Keys []byte `ssh:"rest"`
  150. }
  151. // See [PROTOCOL.agent], section 2.6.2.
  152. const agentSignRequest = 13
  153. type signRequestAgentMsg struct {
  154. KeyBlob []byte `sshtype:"13"`
  155. Data []byte
  156. Flags uint32
  157. }
  158. // See [PROTOCOL.agent], section 2.6.2.
  159. // 3.6 Replies from agent to client for protocol 2 key operations
  160. const agentSignResponse = 14
  161. type signResponseAgentMsg struct {
  162. SigBlob []byte `sshtype:"14"`
  163. }
  164. type publicKey struct {
  165. Format string
  166. Rest []byte `ssh:"rest"`
  167. }
  168. // 3.7 Key constraint identifiers
  169. type constrainLifetimeAgentMsg struct {
  170. LifetimeSecs uint32 `sshtype:"1"`
  171. }
  172. type constrainExtensionAgentMsg struct {
  173. ExtensionName string `sshtype:"255|3"`
  174. ExtensionDetails []byte
  175. // Rest is a field used for parsing, not part of message
  176. Rest []byte `ssh:"rest"`
  177. }
  178. // See [PROTOCOL.agent], section 4.7
  179. const agentExtension = 27
  180. const agentExtensionFailure = 28
  181. // ErrExtensionUnsupported indicates that an extension defined in
  182. // [PROTOCOL.agent] section 4.7 is unsupported by the agent. Specifically this
  183. // error indicates that the agent returned a standard SSH_AGENT_FAILURE message
  184. // as the result of a SSH_AGENTC_EXTENSION request. Note that the protocol
  185. // specification (and therefore this error) does not distinguish between a
  186. // specific extension being unsupported and extensions being unsupported entirely.
  187. var ErrExtensionUnsupported = errors.New("agent: extension unsupported")
  188. type extensionAgentMsg struct {
  189. ExtensionType string `sshtype:"27"`
  190. // NOTE: this matches OpenSSH's PROTOCOL.agent, not the IETF draft [PROTOCOL.agent],
  191. // so that it matches what OpenSSH actually implements in the wild.
  192. Contents []byte `ssh:"rest"`
  193. }
  194. // Key represents a protocol 2 public key as defined in
  195. // [PROTOCOL.agent], section 2.5.2.
  196. type Key struct {
  197. Format string
  198. Blob []byte
  199. Comment string
  200. }
  201. func clientErr(err error) error {
  202. return fmt.Errorf("agent: client error: %v", err)
  203. }
  204. // String returns the storage form of an agent key with the format, base64
  205. // encoded serialized key, and the comment if it is not empty.
  206. func (k *Key) String() string {
  207. s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob)
  208. if k.Comment != "" {
  209. s += " " + k.Comment
  210. }
  211. return s
  212. }
  213. // Type returns the public key type.
  214. func (k *Key) Type() string {
  215. return k.Format
  216. }
  217. // Marshal returns key blob to satisfy the ssh.PublicKey interface.
  218. func (k *Key) Marshal() []byte {
  219. return k.Blob
  220. }
  221. // Verify satisfies the ssh.PublicKey interface.
  222. func (k *Key) Verify(data []byte, sig *ssh.Signature) error {
  223. pubKey, err := ssh.ParsePublicKey(k.Blob)
  224. if err != nil {
  225. return fmt.Errorf("agent: bad public key: %v", err)
  226. }
  227. return pubKey.Verify(data, sig)
  228. }
  229. type wireKey struct {
  230. Format string
  231. Rest []byte `ssh:"rest"`
  232. }
  233. func parseKey(in []byte) (out *Key, rest []byte, err error) {
  234. var record struct {
  235. Blob []byte
  236. Comment string
  237. Rest []byte `ssh:"rest"`
  238. }
  239. if err := ssh.Unmarshal(in, &record); err != nil {
  240. return nil, nil, err
  241. }
  242. var wk wireKey
  243. if err := ssh.Unmarshal(record.Blob, &wk); err != nil {
  244. return nil, nil, err
  245. }
  246. return &Key{
  247. Format: wk.Format,
  248. Blob: record.Blob,
  249. Comment: record.Comment,
  250. }, record.Rest, nil
  251. }
  252. // client is a client for an ssh-agent process.
  253. type client struct {
  254. // conn is typically a *net.UnixConn
  255. conn io.ReadWriter
  256. // mu is used to prevent concurrent access to the agent
  257. mu sync.Mutex
  258. }
  259. // NewClient returns an Agent that talks to an ssh-agent process over
  260. // the given connection.
  261. func NewClient(rw io.ReadWriter) ExtendedAgent {
  262. return &client{conn: rw}
  263. }
  264. // call sends an RPC to the agent. On success, the reply is
  265. // unmarshaled into reply and replyType is set to the first byte of
  266. // the reply, which contains the type of the message.
  267. func (c *client) call(req []byte) (reply interface{}, err error) {
  268. buf, err := c.callRaw(req)
  269. if err != nil {
  270. return nil, err
  271. }
  272. reply, err = unmarshal(buf)
  273. if err != nil {
  274. return nil, clientErr(err)
  275. }
  276. return reply, nil
  277. }
  278. // callRaw sends an RPC to the agent. On success, the raw
  279. // bytes of the response are returned; no unmarshalling is
  280. // performed on the response.
  281. func (c *client) callRaw(req []byte) (reply []byte, err error) {
  282. c.mu.Lock()
  283. defer c.mu.Unlock()
  284. msg := make([]byte, 4+len(req))
  285. binary.BigEndian.PutUint32(msg, uint32(len(req)))
  286. copy(msg[4:], req)
  287. if _, err = c.conn.Write(msg); err != nil {
  288. return nil, clientErr(err)
  289. }
  290. var respSizeBuf [4]byte
  291. if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil {
  292. return nil, clientErr(err)
  293. }
  294. respSize := binary.BigEndian.Uint32(respSizeBuf[:])
  295. if respSize > maxAgentResponseBytes {
  296. return nil, clientErr(errors.New("response too large"))
  297. }
  298. buf := make([]byte, respSize)
  299. if _, err = io.ReadFull(c.conn, buf); err != nil {
  300. return nil, clientErr(err)
  301. }
  302. return buf, nil
  303. }
  304. func (c *client) simpleCall(req []byte) error {
  305. resp, err := c.call(req)
  306. if err != nil {
  307. return err
  308. }
  309. if _, ok := resp.(*successAgentMsg); ok {
  310. return nil
  311. }
  312. return errors.New("agent: failure")
  313. }
  314. func (c *client) RemoveAll() error {
  315. return c.simpleCall([]byte{agentRemoveAllIdentities})
  316. }
  317. func (c *client) Remove(key ssh.PublicKey) error {
  318. req := ssh.Marshal(&agentRemoveIdentityMsg{
  319. KeyBlob: key.Marshal(),
  320. })
  321. return c.simpleCall(req)
  322. }
  323. func (c *client) Lock(passphrase []byte) error {
  324. req := ssh.Marshal(&agentLockMsg{
  325. Passphrase: passphrase,
  326. })
  327. return c.simpleCall(req)
  328. }
  329. func (c *client) Unlock(passphrase []byte) error {
  330. req := ssh.Marshal(&agentUnlockMsg{
  331. Passphrase: passphrase,
  332. })
  333. return c.simpleCall(req)
  334. }
  335. // List returns the identities known to the agent.
  336. func (c *client) List() ([]*Key, error) {
  337. // see [PROTOCOL.agent] section 2.5.2.
  338. req := []byte{agentRequestIdentities}
  339. msg, err := c.call(req)
  340. if err != nil {
  341. return nil, err
  342. }
  343. switch msg := msg.(type) {
  344. case *identitiesAnswerAgentMsg:
  345. if msg.NumKeys > maxAgentResponseBytes/8 {
  346. return nil, errors.New("agent: too many keys in agent reply")
  347. }
  348. keys := make([]*Key, msg.NumKeys)
  349. data := msg.Keys
  350. for i := uint32(0); i < msg.NumKeys; i++ {
  351. var key *Key
  352. var err error
  353. if key, data, err = parseKey(data); err != nil {
  354. return nil, err
  355. }
  356. keys[i] = key
  357. }
  358. return keys, nil
  359. case *failureAgentMsg:
  360. return nil, errors.New("agent: failed to list keys")
  361. }
  362. panic("unreachable")
  363. }
  364. // Sign has the agent sign the data using a protocol 2 key as defined
  365. // in [PROTOCOL.agent] section 2.6.2.
  366. func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
  367. return c.SignWithFlags(key, data, 0)
  368. }
  369. func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) {
  370. req := ssh.Marshal(signRequestAgentMsg{
  371. KeyBlob: key.Marshal(),
  372. Data: data,
  373. Flags: uint32(flags),
  374. })
  375. msg, err := c.call(req)
  376. if err != nil {
  377. return nil, err
  378. }
  379. switch msg := msg.(type) {
  380. case *signResponseAgentMsg:
  381. var sig ssh.Signature
  382. if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil {
  383. return nil, err
  384. }
  385. return &sig, nil
  386. case *failureAgentMsg:
  387. return nil, errors.New("agent: failed to sign challenge")
  388. }
  389. panic("unreachable")
  390. }
  391. // unmarshal parses an agent message in packet, returning the parsed
  392. // form and the message type of packet.
  393. func unmarshal(packet []byte) (interface{}, error) {
  394. if len(packet) < 1 {
  395. return nil, errors.New("agent: empty packet")
  396. }
  397. var msg interface{}
  398. switch packet[0] {
  399. case agentFailure:
  400. return new(failureAgentMsg), nil
  401. case agentSuccess:
  402. return new(successAgentMsg), nil
  403. case agentIdentitiesAnswer:
  404. msg = new(identitiesAnswerAgentMsg)
  405. case agentSignResponse:
  406. msg = new(signResponseAgentMsg)
  407. case agentV1IdentitiesAnswer:
  408. msg = new(agentV1IdentityMsg)
  409. default:
  410. return nil, fmt.Errorf("agent: unknown type tag %d", packet[0])
  411. }
  412. if err := ssh.Unmarshal(packet, msg); err != nil {
  413. return nil, err
  414. }
  415. return msg, nil
  416. }
  417. type rsaKeyMsg struct {
  418. Type string `sshtype:"17|25"`
  419. N *big.Int
  420. E *big.Int
  421. D *big.Int
  422. Iqmp *big.Int // IQMP = Inverse Q Mod P
  423. P *big.Int
  424. Q *big.Int
  425. Comments string
  426. Constraints []byte `ssh:"rest"`
  427. }
  428. type dsaKeyMsg struct {
  429. Type string `sshtype:"17|25"`
  430. P *big.Int
  431. Q *big.Int
  432. G *big.Int
  433. Y *big.Int
  434. X *big.Int
  435. Comments string
  436. Constraints []byte `ssh:"rest"`
  437. }
  438. type ecdsaKeyMsg struct {
  439. Type string `sshtype:"17|25"`
  440. Curve string
  441. KeyBytes []byte
  442. D *big.Int
  443. Comments string
  444. Constraints []byte `ssh:"rest"`
  445. }
  446. type ed25519KeyMsg struct {
  447. Type string `sshtype:"17|25"`
  448. Pub []byte
  449. Priv []byte
  450. Comments string
  451. Constraints []byte `ssh:"rest"`
  452. }
  453. // Insert adds a private key to the agent.
  454. func (c *client) insertKey(s interface{}, comment string, constraints []byte) error {
  455. var req []byte
  456. switch k := s.(type) {
  457. case *rsa.PrivateKey:
  458. if len(k.Primes) != 2 {
  459. return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
  460. }
  461. k.Precompute()
  462. req = ssh.Marshal(rsaKeyMsg{
  463. Type: ssh.KeyAlgoRSA,
  464. N: k.N,
  465. E: big.NewInt(int64(k.E)),
  466. D: k.D,
  467. Iqmp: k.Precomputed.Qinv,
  468. P: k.Primes[0],
  469. Q: k.Primes[1],
  470. Comments: comment,
  471. Constraints: constraints,
  472. })
  473. case *dsa.PrivateKey:
  474. req = ssh.Marshal(dsaKeyMsg{
  475. Type: ssh.KeyAlgoDSA,
  476. P: k.P,
  477. Q: k.Q,
  478. G: k.G,
  479. Y: k.Y,
  480. X: k.X,
  481. Comments: comment,
  482. Constraints: constraints,
  483. })
  484. case *ecdsa.PrivateKey:
  485. nistID := fmt.Sprintf("nistp%d", k.Params().BitSize)
  486. req = ssh.Marshal(ecdsaKeyMsg{
  487. Type: "ecdsa-sha2-" + nistID,
  488. Curve: nistID,
  489. KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y),
  490. D: k.D,
  491. Comments: comment,
  492. Constraints: constraints,
  493. })
  494. case ed25519.PrivateKey:
  495. req = ssh.Marshal(ed25519KeyMsg{
  496. Type: ssh.KeyAlgoED25519,
  497. Pub: []byte(k)[32:],
  498. Priv: []byte(k),
  499. Comments: comment,
  500. Constraints: constraints,
  501. })
  502. // This function originally supported only *ed25519.PrivateKey, however the
  503. // general idiom is to pass ed25519.PrivateKey by value, not by pointer.
  504. // We still support the pointer variant for backwards compatibility.
  505. case *ed25519.PrivateKey:
  506. req = ssh.Marshal(ed25519KeyMsg{
  507. Type: ssh.KeyAlgoED25519,
  508. Pub: []byte(*k)[32:],
  509. Priv: []byte(*k),
  510. Comments: comment,
  511. Constraints: constraints,
  512. })
  513. default:
  514. return fmt.Errorf("agent: unsupported key type %T", s)
  515. }
  516. // if constraints are present then the message type needs to be changed.
  517. if len(constraints) != 0 {
  518. req[0] = agentAddIDConstrained
  519. }
  520. resp, err := c.call(req)
  521. if err != nil {
  522. return err
  523. }
  524. if _, ok := resp.(*successAgentMsg); ok {
  525. return nil
  526. }
  527. return errors.New("agent: failure")
  528. }
  529. type rsaCertMsg struct {
  530. Type string `sshtype:"17|25"`
  531. CertBytes []byte
  532. D *big.Int
  533. Iqmp *big.Int // IQMP = Inverse Q Mod P
  534. P *big.Int
  535. Q *big.Int
  536. Comments string
  537. Constraints []byte `ssh:"rest"`
  538. }
  539. type dsaCertMsg struct {
  540. Type string `sshtype:"17|25"`
  541. CertBytes []byte
  542. X *big.Int
  543. Comments string
  544. Constraints []byte `ssh:"rest"`
  545. }
  546. type ecdsaCertMsg struct {
  547. Type string `sshtype:"17|25"`
  548. CertBytes []byte
  549. D *big.Int
  550. Comments string
  551. Constraints []byte `ssh:"rest"`
  552. }
  553. type ed25519CertMsg struct {
  554. Type string `sshtype:"17|25"`
  555. CertBytes []byte
  556. Pub []byte
  557. Priv []byte
  558. Comments string
  559. Constraints []byte `ssh:"rest"`
  560. }
  561. // Add adds a private key to the agent. If a certificate is given,
  562. // that certificate is added instead as public key.
  563. func (c *client) Add(key AddedKey) error {
  564. var constraints []byte
  565. if secs := key.LifetimeSecs; secs != 0 {
  566. constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...)
  567. }
  568. if key.ConfirmBeforeUse {
  569. constraints = append(constraints, agentConstrainConfirm)
  570. }
  571. cert := key.Certificate
  572. if cert == nil {
  573. return c.insertKey(key.PrivateKey, key.Comment, constraints)
  574. }
  575. return c.insertCert(key.PrivateKey, cert, key.Comment, constraints)
  576. }
  577. func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error {
  578. var req []byte
  579. switch k := s.(type) {
  580. case *rsa.PrivateKey:
  581. if len(k.Primes) != 2 {
  582. return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
  583. }
  584. k.Precompute()
  585. req = ssh.Marshal(rsaCertMsg{
  586. Type: cert.Type(),
  587. CertBytes: cert.Marshal(),
  588. D: k.D,
  589. Iqmp: k.Precomputed.Qinv,
  590. P: k.Primes[0],
  591. Q: k.Primes[1],
  592. Comments: comment,
  593. Constraints: constraints,
  594. })
  595. case *dsa.PrivateKey:
  596. req = ssh.Marshal(dsaCertMsg{
  597. Type: cert.Type(),
  598. CertBytes: cert.Marshal(),
  599. X: k.X,
  600. Comments: comment,
  601. Constraints: constraints,
  602. })
  603. case *ecdsa.PrivateKey:
  604. req = ssh.Marshal(ecdsaCertMsg{
  605. Type: cert.Type(),
  606. CertBytes: cert.Marshal(),
  607. D: k.D,
  608. Comments: comment,
  609. Constraints: constraints,
  610. })
  611. case ed25519.PrivateKey:
  612. req = ssh.Marshal(ed25519CertMsg{
  613. Type: cert.Type(),
  614. CertBytes: cert.Marshal(),
  615. Pub: []byte(k)[32:],
  616. Priv: []byte(k),
  617. Comments: comment,
  618. Constraints: constraints,
  619. })
  620. // This function originally supported only *ed25519.PrivateKey, however the
  621. // general idiom is to pass ed25519.PrivateKey by value, not by pointer.
  622. // We still support the pointer variant for backwards compatibility.
  623. case *ed25519.PrivateKey:
  624. req = ssh.Marshal(ed25519CertMsg{
  625. Type: cert.Type(),
  626. CertBytes: cert.Marshal(),
  627. Pub: []byte(*k)[32:],
  628. Priv: []byte(*k),
  629. Comments: comment,
  630. Constraints: constraints,
  631. })
  632. default:
  633. return fmt.Errorf("agent: unsupported key type %T", s)
  634. }
  635. // if constraints are present then the message type needs to be changed.
  636. if len(constraints) != 0 {
  637. req[0] = agentAddIDConstrained
  638. }
  639. signer, err := ssh.NewSignerFromKey(s)
  640. if err != nil {
  641. return err
  642. }
  643. if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) {
  644. return errors.New("agent: signer and cert have different public key")
  645. }
  646. resp, err := c.call(req)
  647. if err != nil {
  648. return err
  649. }
  650. if _, ok := resp.(*successAgentMsg); ok {
  651. return nil
  652. }
  653. return errors.New("agent: failure")
  654. }
  655. // Signers provides a callback for client authentication.
  656. func (c *client) Signers() ([]ssh.Signer, error) {
  657. keys, err := c.List()
  658. if err != nil {
  659. return nil, err
  660. }
  661. var result []ssh.Signer
  662. for _, k := range keys {
  663. result = append(result, &agentKeyringSigner{c, k})
  664. }
  665. return result, nil
  666. }
  667. type agentKeyringSigner struct {
  668. agent *client
  669. pub ssh.PublicKey
  670. }
  671. func (s *agentKeyringSigner) PublicKey() ssh.PublicKey {
  672. return s.pub
  673. }
  674. func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
  675. // The agent has its own entropy source, so the rand argument is ignored.
  676. return s.agent.Sign(s.pub, data)
  677. }
  678. func (s *agentKeyringSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*ssh.Signature, error) {
  679. if algorithm == "" || algorithm == underlyingAlgo(s.pub.Type()) {
  680. return s.Sign(rand, data)
  681. }
  682. var flags SignatureFlags
  683. switch algorithm {
  684. case ssh.KeyAlgoRSASHA256:
  685. flags = SignatureFlagRsaSha256
  686. case ssh.KeyAlgoRSASHA512:
  687. flags = SignatureFlagRsaSha512
  688. default:
  689. return nil, fmt.Errorf("agent: unsupported algorithm %q", algorithm)
  690. }
  691. return s.agent.SignWithFlags(s.pub, data, flags)
  692. }
  693. var _ ssh.AlgorithmSigner = &agentKeyringSigner{}
  694. // certKeyAlgoNames is a mapping from known certificate algorithm names to the
  695. // corresponding public key signature algorithm.
  696. //
  697. // This map must be kept in sync with the one in certs.go.
  698. var certKeyAlgoNames = map[string]string{
  699. ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA,
  700. ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256,
  701. ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
  702. ssh.CertAlgoDSAv01: ssh.KeyAlgoDSA,
  703. ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,
  704. ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384,
  705. ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521,
  706. ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256,
  707. ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519,
  708. ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519,
  709. }
  710. // underlyingAlgo returns the signature algorithm associated with algo (which is
  711. // an advertised or negotiated public key or host key algorithm). These are
  712. // usually the same, except for certificate algorithms.
  713. func underlyingAlgo(algo string) string {
  714. if a, ok := certKeyAlgoNames[algo]; ok {
  715. return a
  716. }
  717. return algo
  718. }
  719. // Calls an extension method. It is up to the agent implementation as to whether or not
  720. // any particular extension is supported and may always return an error. Because the
  721. // type of the response is up to the implementation, this returns the bytes of the
  722. // response and does not attempt any type of unmarshalling.
  723. func (c *client) Extension(extensionType string, contents []byte) ([]byte, error) {
  724. req := ssh.Marshal(extensionAgentMsg{
  725. ExtensionType: extensionType,
  726. Contents: contents,
  727. })
  728. buf, err := c.callRaw(req)
  729. if err != nil {
  730. return nil, err
  731. }
  732. if len(buf) == 0 {
  733. return nil, errors.New("agent: failure; empty response")
  734. }
  735. // [PROTOCOL.agent] section 4.7 indicates that an SSH_AGENT_FAILURE message
  736. // represents an agent that does not support the extension
  737. if buf[0] == agentFailure {
  738. return nil, ErrExtensionUnsupported
  739. }
  740. if buf[0] == agentExtensionFailure {
  741. return nil, errors.New("agent: generic extension failure")
  742. }
  743. return buf, nil
  744. }