本站源代码
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.

571 lines
13KB

  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. var sig *ssh.Signature
  105. var err error
  106. if extendedAgent, ok := s.agent.(ExtendedAgent); ok {
  107. sig, err = extendedAgent.SignWithFlags(k, req.Data, SignatureFlags(req.Flags))
  108. } else {
  109. sig, err = s.agent.Sign(k, req.Data)
  110. }
  111. if err != nil {
  112. return nil, err
  113. }
  114. return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil
  115. case agentRequestIdentities:
  116. keys, err := s.agent.List()
  117. if err != nil {
  118. return nil, err
  119. }
  120. rep := identitiesAnswerAgentMsg{
  121. NumKeys: uint32(len(keys)),
  122. }
  123. for _, k := range keys {
  124. rep.Keys = append(rep.Keys, marshalKey(k)...)
  125. }
  126. return rep, nil
  127. case agentAddIDConstrained, agentAddIdentity:
  128. return nil, s.insertIdentity(data)
  129. case agentExtension:
  130. // Return a stub object where the whole contents of the response gets marshaled.
  131. var responseStub struct {
  132. Rest []byte `ssh:"rest"`
  133. }
  134. if extendedAgent, ok := s.agent.(ExtendedAgent); !ok {
  135. // If this agent doesn't implement extensions, [PROTOCOL.agent] section 4.7
  136. // requires that we return a standard SSH_AGENT_FAILURE message.
  137. responseStub.Rest = []byte{agentFailure}
  138. } else {
  139. var req extensionAgentMsg
  140. if err := ssh.Unmarshal(data, &req); err != nil {
  141. return nil, err
  142. }
  143. res, err := extendedAgent.Extension(req.ExtensionType, req.Contents)
  144. if err != nil {
  145. // If agent extensions are unsupported, return a standard SSH_AGENT_FAILURE
  146. // message as required by [PROTOCOL.agent] section 4.7.
  147. if err == ErrExtensionUnsupported {
  148. responseStub.Rest = []byte{agentFailure}
  149. } else {
  150. // As the result of any other error processing an extension request,
  151. // [PROTOCOL.agent] section 4.7 requires that we return a
  152. // SSH_AGENT_EXTENSION_FAILURE code.
  153. responseStub.Rest = []byte{agentExtensionFailure}
  154. }
  155. } else {
  156. if len(res) == 0 {
  157. return nil, nil
  158. }
  159. responseStub.Rest = res
  160. }
  161. }
  162. return responseStub, nil
  163. }
  164. return nil, fmt.Errorf("unknown opcode %d", data[0])
  165. }
  166. func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) {
  167. for len(constraints) != 0 {
  168. switch constraints[0] {
  169. case agentConstrainLifetime:
  170. lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5])
  171. constraints = constraints[5:]
  172. case agentConstrainConfirm:
  173. confirmBeforeUse = true
  174. constraints = constraints[1:]
  175. case agentConstrainExtension:
  176. var msg constrainExtensionAgentMsg
  177. if err = ssh.Unmarshal(constraints, &msg); err != nil {
  178. return 0, false, nil, err
  179. }
  180. extensions = append(extensions, ConstraintExtension{
  181. ExtensionName: msg.ExtensionName,
  182. ExtensionDetails: msg.ExtensionDetails,
  183. })
  184. constraints = msg.Rest
  185. default:
  186. return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0])
  187. }
  188. }
  189. return
  190. }
  191. func setConstraints(key *AddedKey, constraintBytes []byte) error {
  192. lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes)
  193. if err != nil {
  194. return err
  195. }
  196. key.LifetimeSecs = lifetimeSecs
  197. key.ConfirmBeforeUse = confirmBeforeUse
  198. key.ConstraintExtensions = constraintExtensions
  199. return nil
  200. }
  201. func parseRSAKey(req []byte) (*AddedKey, error) {
  202. var k rsaKeyMsg
  203. if err := ssh.Unmarshal(req, &k); err != nil {
  204. return nil, err
  205. }
  206. if k.E.BitLen() > 30 {
  207. return nil, errors.New("agent: RSA public exponent too large")
  208. }
  209. priv := &rsa.PrivateKey{
  210. PublicKey: rsa.PublicKey{
  211. E: int(k.E.Int64()),
  212. N: k.N,
  213. },
  214. D: k.D,
  215. Primes: []*big.Int{k.P, k.Q},
  216. }
  217. priv.Precompute()
  218. addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
  219. if err := setConstraints(addedKey, k.Constraints); err != nil {
  220. return nil, err
  221. }
  222. return addedKey, nil
  223. }
  224. func parseEd25519Key(req []byte) (*AddedKey, error) {
  225. var k ed25519KeyMsg
  226. if err := ssh.Unmarshal(req, &k); err != nil {
  227. return nil, err
  228. }
  229. priv := ed25519.PrivateKey(k.Priv)
  230. addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments}
  231. if err := setConstraints(addedKey, k.Constraints); err != nil {
  232. return nil, err
  233. }
  234. return addedKey, nil
  235. }
  236. func parseDSAKey(req []byte) (*AddedKey, error) {
  237. var k dsaKeyMsg
  238. if err := ssh.Unmarshal(req, &k); err != nil {
  239. return nil, err
  240. }
  241. priv := &dsa.PrivateKey{
  242. PublicKey: dsa.PublicKey{
  243. Parameters: dsa.Parameters{
  244. P: k.P,
  245. Q: k.Q,
  246. G: k.G,
  247. },
  248. Y: k.Y,
  249. },
  250. X: k.X,
  251. }
  252. addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
  253. if err := setConstraints(addedKey, k.Constraints); err != nil {
  254. return nil, err
  255. }
  256. return addedKey, nil
  257. }
  258. func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) {
  259. priv = &ecdsa.PrivateKey{
  260. D: privScalar,
  261. }
  262. switch curveName {
  263. case "nistp256":
  264. priv.Curve = elliptic.P256()
  265. case "nistp384":
  266. priv.Curve = elliptic.P384()
  267. case "nistp521":
  268. priv.Curve = elliptic.P521()
  269. default:
  270. return nil, fmt.Errorf("agent: unknown curve %q", curveName)
  271. }
  272. priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes)
  273. if priv.X == nil || priv.Y == nil {
  274. return nil, errors.New("agent: point not on curve")
  275. }
  276. return priv, nil
  277. }
  278. func parseEd25519Cert(req []byte) (*AddedKey, error) {
  279. var k ed25519CertMsg
  280. if err := ssh.Unmarshal(req, &k); err != nil {
  281. return nil, err
  282. }
  283. pubKey, err := ssh.ParsePublicKey(k.CertBytes)
  284. if err != nil {
  285. return nil, err
  286. }
  287. priv := ed25519.PrivateKey(k.Priv)
  288. cert, ok := pubKey.(*ssh.Certificate)
  289. if !ok {
  290. return nil, errors.New("agent: bad ED25519 certificate")
  291. }
  292. addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
  293. if err := setConstraints(addedKey, k.Constraints); err != nil {
  294. return nil, err
  295. }
  296. return addedKey, nil
  297. }
  298. func parseECDSAKey(req []byte) (*AddedKey, error) {
  299. var k ecdsaKeyMsg
  300. if err := ssh.Unmarshal(req, &k); err != nil {
  301. return nil, err
  302. }
  303. priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D)
  304. if err != nil {
  305. return nil, err
  306. }
  307. addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
  308. if err := setConstraints(addedKey, k.Constraints); err != nil {
  309. return nil, err
  310. }
  311. return addedKey, nil
  312. }
  313. func parseRSACert(req []byte) (*AddedKey, error) {
  314. var k rsaCertMsg
  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 RSA certificate")
  325. }
  326. // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go
  327. var rsaPub struct {
  328. Name string
  329. E *big.Int
  330. N *big.Int
  331. }
  332. if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil {
  333. return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
  334. }
  335. if rsaPub.E.BitLen() > 30 {
  336. return nil, errors.New("agent: RSA public exponent too large")
  337. }
  338. priv := rsa.PrivateKey{
  339. PublicKey: rsa.PublicKey{
  340. E: int(rsaPub.E.Int64()),
  341. N: rsaPub.N,
  342. },
  343. D: k.D,
  344. Primes: []*big.Int{k.Q, k.P},
  345. }
  346. priv.Precompute()
  347. addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
  348. if err := setConstraints(addedKey, k.Constraints); err != nil {
  349. return nil, err
  350. }
  351. return addedKey, nil
  352. }
  353. func parseDSACert(req []byte) (*AddedKey, error) {
  354. var k dsaCertMsg
  355. if err := ssh.Unmarshal(req, &k); err != nil {
  356. return nil, err
  357. }
  358. pubKey, err := ssh.ParsePublicKey(k.CertBytes)
  359. if err != nil {
  360. return nil, err
  361. }
  362. cert, ok := pubKey.(*ssh.Certificate)
  363. if !ok {
  364. return nil, errors.New("agent: bad DSA certificate")
  365. }
  366. // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go
  367. var w struct {
  368. Name string
  369. P, Q, G, Y *big.Int
  370. }
  371. if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil {
  372. return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
  373. }
  374. priv := &dsa.PrivateKey{
  375. PublicKey: dsa.PublicKey{
  376. Parameters: dsa.Parameters{
  377. P: w.P,
  378. Q: w.Q,
  379. G: w.G,
  380. },
  381. Y: w.Y,
  382. },
  383. X: k.X,
  384. }
  385. addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
  386. if err := setConstraints(addedKey, k.Constraints); err != nil {
  387. return nil, err
  388. }
  389. return addedKey, nil
  390. }
  391. func parseECDSACert(req []byte) (*AddedKey, error) {
  392. var k ecdsaCertMsg
  393. if err := ssh.Unmarshal(req, &k); err != nil {
  394. return nil, err
  395. }
  396. pubKey, err := ssh.ParsePublicKey(k.CertBytes)
  397. if err != nil {
  398. return nil, err
  399. }
  400. cert, ok := pubKey.(*ssh.Certificate)
  401. if !ok {
  402. return nil, errors.New("agent: bad ECDSA certificate")
  403. }
  404. // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go
  405. var ecdsaPub struct {
  406. Name string
  407. ID string
  408. Key []byte
  409. }
  410. if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil {
  411. return nil, err
  412. }
  413. priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D)
  414. if err != nil {
  415. return nil, err
  416. }
  417. addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
  418. if err := setConstraints(addedKey, k.Constraints); err != nil {
  419. return nil, err
  420. }
  421. return addedKey, nil
  422. }
  423. func (s *server) insertIdentity(req []byte) error {
  424. var record struct {
  425. Type string `sshtype:"17|25"`
  426. Rest []byte `ssh:"rest"`
  427. }
  428. if err := ssh.Unmarshal(req, &record); err != nil {
  429. return err
  430. }
  431. var addedKey *AddedKey
  432. var err error
  433. switch record.Type {
  434. case ssh.KeyAlgoRSA:
  435. addedKey, err = parseRSAKey(req)
  436. case ssh.KeyAlgoDSA:
  437. addedKey, err = parseDSAKey(req)
  438. case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
  439. addedKey, err = parseECDSAKey(req)
  440. case ssh.KeyAlgoED25519:
  441. addedKey, err = parseEd25519Key(req)
  442. case ssh.CertAlgoRSAv01:
  443. addedKey, err = parseRSACert(req)
  444. case ssh.CertAlgoDSAv01:
  445. addedKey, err = parseDSACert(req)
  446. case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01:
  447. addedKey, err = parseECDSACert(req)
  448. case ssh.CertAlgoED25519v01:
  449. addedKey, err = parseEd25519Cert(req)
  450. default:
  451. return fmt.Errorf("agent: not implemented: %q", record.Type)
  452. }
  453. if err != nil {
  454. return err
  455. }
  456. return s.agent.Add(*addedKey)
  457. }
  458. // ServeAgent serves the agent protocol on the given connection. It
  459. // returns when an I/O error occurs.
  460. func ServeAgent(agent Agent, c io.ReadWriter) error {
  461. s := &server{agent}
  462. var length [4]byte
  463. for {
  464. if _, err := io.ReadFull(c, length[:]); err != nil {
  465. return err
  466. }
  467. l := binary.BigEndian.Uint32(length[:])
  468. if l == 0 {
  469. return fmt.Errorf("agent: request size is 0")
  470. }
  471. if l > maxAgentResponseBytes {
  472. // We also cap requests.
  473. return fmt.Errorf("agent: request too large: %d", l)
  474. }
  475. req := make([]byte, l)
  476. if _, err := io.ReadFull(c, req); err != nil {
  477. return err
  478. }
  479. repData := s.processRequestBytes(req)
  480. if len(repData) > maxAgentResponseBytes {
  481. return fmt.Errorf("agent: reply too large: %d bytes", len(repData))
  482. }
  483. binary.BigEndian.PutUint32(length[:], uint32(len(repData)))
  484. if _, err := c.Write(length[:]); err != nil {
  485. return err
  486. }
  487. if _, err := c.Write(repData); err != nil {
  488. return err
  489. }
  490. }
  491. }
上海开阖软件有限公司 沪ICP备12045867号-1