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.
 
 
 

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