OSDN Git Service

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