Browse Source

fix 1540 and experimental SSH server support

Unknwon 4 years ago
parent
commit
18c841050b
69 changed files with 171 additions and 15479 deletions
  1. 2 2
      cmd/serve.go
  2. 2 0
      conf/app.ini
  3. 16 24
      models/publickey.go
  4. 2 2
      models/repo.go
  5. 19 0
      modules/base/base.go
  6. 17 17
      modules/bindata/bindata.go
  7. 0 615
      modules/crypto/ssh/agent/client.go
  8. 0 287
      modules/crypto/ssh/agent/client_test.go
  9. 0 103
      modules/crypto/ssh/agent/forward.go
  10. 0 184
      modules/crypto/ssh/agent/keyring.go
  11. 0 209
      modules/crypto/ssh/agent/server.go
  12. 0 77
      modules/crypto/ssh/agent/server_test.go
  13. 0 64
      modules/crypto/ssh/agent/testdata_test.go
  14. 0 122
      modules/crypto/ssh/benchmark_test.go
  15. 0 98
      modules/crypto/ssh/buffer.go
  16. 0 87
      modules/crypto/ssh/buffer_test.go
  17. 0 501
      modules/crypto/ssh/certs.go
  18. 0 216
      modules/crypto/ssh/certs_test.go
  19. 0 631
      modules/crypto/ssh/channel.go
  20. 0 549
      modules/crypto/ssh/cipher.go
  21. 0 127
      modules/crypto/ssh/cipher_test.go
  22. 0 213
      modules/crypto/ssh/client.go
  23. 0 441
      modules/crypto/ssh/client_auth.go
  24. 0 393
      modules/crypto/ssh/client_auth_test.go
  25. 0 39
      modules/crypto/ssh/client_test.go
  26. 0 354
      modules/crypto/ssh/common.go
  27. 0 144
      modules/crypto/ssh/connection.go
  28. 0 18
      modules/crypto/ssh/doc.go
  29. 0 211
      modules/crypto/ssh/example_test.go
  30. 0 412
      modules/crypto/ssh/handshake.go
  31. 0 415
      modules/crypto/ssh/handshake_test.go
  32. 0 526
      modules/crypto/ssh/kex.go
  33. 0 50
      modules/crypto/ssh/kex_test.go
  34. 0 628
      modules/crypto/ssh/keys.go
  35. 0 306
      modules/crypto/ssh/keys_test.go
  36. 0 57
      modules/crypto/ssh/mac.go
  37. 0 110
      modules/crypto/ssh/mempipe_test.go
  38. 0 725
      modules/crypto/ssh/messages.go
  39. 0 254
      modules/crypto/ssh/messages_test.go
  40. 0 356
      modules/crypto/ssh/mux.go
  41. 0 525
      modules/crypto/ssh/mux_test.go
  42. 0 493
      modules/crypto/ssh/server.go
  43. 0 605
      modules/crypto/ssh/session.go
  44. 0 774
      modules/crypto/ssh/session_test.go
  45. 0 407
      modules/crypto/ssh/tcpip.go
  46. 0 20
      modules/crypto/ssh/tcpip_test.go
  47. 0 892
      modules/crypto/ssh/terminal/terminal.go
  48. 0 269
      modules/crypto/ssh/terminal/terminal_test.go
  49. 0 128
      modules/crypto/ssh/terminal/util.go
  50. 0 12
      modules/crypto/ssh/terminal/util_bsd.go
  51. 0 11
      modules/crypto/ssh/terminal/util_linux.go
  52. 0 174
      modules/crypto/ssh/terminal/util_windows.go
  53. 0 59
      modules/crypto/ssh/test/agent_unix_test.go
  54. 0 47
      modules/crypto/ssh/test/cert_test.go
  55. 0 7
      modules/crypto/ssh/test/doc.go
  56. 0 160
      modules/crypto/ssh/test/forward_unix_test.go
  57. 0 340
      modules/crypto/ssh/test/session_test.go
  58. 0 46
      modules/crypto/ssh/test/tcpip_test.go
  59. 0 261
      modules/crypto/ssh/test/test_unix_test.go
  60. 0 64
      modules/crypto/ssh/test/testdata_test.go
  61. 0 8
      modules/crypto/ssh/testdata/doc.go
  62. 0 43
      modules/crypto/ssh/testdata/keys.go
  63. 0 63
      modules/crypto/ssh/testdata_test.go
  64. 0 332
      modules/crypto/ssh/transport.go
  65. 0 109
      modules/crypto/ssh/transport_test.go
  66. 25 24
      modules/setting/setting.go
  67. 75 39
      modules/ssh/ssh.go
  68. 7 0
      modules/ssh/ssh_1.3.go
  69. 6 0
      routers/install.go

+ 2 - 2
cmd/serve.go

@@ -181,12 +181,12 @@ func runServ(c *cli.Context) {
181 181
 	if requestedMode == models.ACCESS_MODE_WRITE || repo.IsPrivate {
182 182
 		keys := strings.Split(c.Args()[0], "-")
183 183
 		if len(keys) != 2 {
184
-			fail("Key ID format error", "Invalid key ID: %s", c.Args()[0])
184
+			fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
185 185
 		}
186 186
 
187 187
 		key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
188 188
 		if err != nil {
189
-			fail("Key ID format error", "Invalid key ID[%s]: %v", c.Args()[0], err)
189
+			fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
190 190
 		}
191 191
 		keyID = key.ID
192 192
 

+ 2 - 0
conf/app.ini

@@ -48,6 +48,8 @@ HTTP_ADDR =
48 48
 HTTP_PORT = 3000
49 49
 ; Disable SSH feature when not available
50 50
 DISABLE_SSH = false
51
+; Whether use builtin SSH server or not.
52
+START_SSH_SERVER = false
51 53
 SSH_PORT = 22
52 54
 ; Disable CDN even in "prod" mode
53 55
 OFFLINE_MODE = false

+ 16 - 24
models/publickey.go

@@ -13,7 +13,6 @@ import (
13 13
 	"io"
14 14
 	"io/ioutil"
15 15
 	"os"
16
-	"os/exec"
17 16
 	"path"
18 17
 	"path/filepath"
19 18
 	"strings"
@@ -38,20 +37,7 @@ var (
38 37
 )
39 38
 
40 39
 var sshOpLocker = sync.Mutex{}
41
-
42
-var (
43
-	SSHPath string // SSH directory.
44
-	appPath string // Execution(binary) path.
45
-)
46
-
47
-// exePath returns the executable path.
48
-func exePath() (string, error) {
49
-	file, err := exec.LookPath(os.Args[0])
50
-	if err != nil {
51
-		return "", err
52
-	}
53
-	return filepath.Abs(file)
54
-}
40
+var SSHPath string // SSH directory.
55 41
 
56 42
 // homeDir returns the home directory of current user.
57 43
 func homeDir() string {
@@ -63,16 +49,9 @@ func homeDir() string {
63 49
 }
64 50
 
65 51
 func init() {
66
-	var err error
67
-
68
-	if appPath, err = exePath(); err != nil {
69
-		log.Fatal(4, "fail to get app path: %v\n", err)
70
-	}
71
-	appPath = strings.Replace(appPath, "\\", "/", -1)
72
-
73 52
 	// Determine and create .ssh path.
74 53
 	SSHPath = filepath.Join(homeDir(), ".ssh")
75
-	if err = os.MkdirAll(SSHPath, 0700); err != nil {
54
+	if err := os.MkdirAll(SSHPath, 0700); err != nil {
76 55
 		log.Fatal(4, "fail to create '%s': %v", SSHPath, err)
77 56
 	}
78 57
 }
@@ -114,7 +93,7 @@ func (k *PublicKey) OmitEmail() string {
114 93
 
115 94
 // GetAuthorizedString generates and returns formatted public key string for authorized_keys file.
116 95
 func (key *PublicKey) GetAuthorizedString() string {
117
-	return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.ID, setting.CustomConf, key.Content)
96
+	return fmt.Sprintf(_TPL_PUBLICK_KEY, setting.AppPath, key.ID, setting.CustomConf, key.Content)
118 97
 }
119 98
 
120 99
 func extractTypeFromBase64Key(key string) (string, error) {
@@ -373,6 +352,19 @@ func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
373 352
 	return key, nil
374 353
 }
375 354
 
355
+// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
356
+// and returns public key found.
357
+func SearchPublicKeyByContent(content string) (*PublicKey, error) {
358
+	key := new(PublicKey)
359
+	has, err := x.Where("content like ?", content+"%").Get(key)
360
+	if err != nil {
361
+		return nil, err
362
+	} else if !has {
363
+		return nil, ErrKeyNotExist{}
364
+	}
365
+	return key, nil
366
+}
367
+
376 368
 // ListPublicKeys returns a list of public keys belongs to given user.
377 369
 func ListPublicKeys(uid int64) ([]*PublicKey, error) {
378 370
 	keys := make([]*PublicKey, 0, 5)

+ 2 - 2
models/repo.go

@@ -380,7 +380,7 @@ func (repo *Repository) CloneLink() (cl CloneLink, err error) {
380 380
 	}
381 381
 
382 382
 	if setting.SSHPort != 22 {
383
-		cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.SSHDomain, setting.SSHPort, repo.Owner.LowerName, repo.LowerName)
383
+		cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.SSHDomain, setting.SSHPort, repo.Owner.Name, repo.Name)
384 384
 	} else {
385 385
 		cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.SSHDomain, repo.Owner.Name, repo.Name)
386 386
 	}
@@ -599,7 +599,7 @@ func createUpdateHook(repoPath string) error {
599 599
 	hookPath := path.Join(repoPath, "hooks/update")
600 600
 	os.MkdirAll(path.Dir(hookPath), os.ModePerm)
601 601
 	return ioutil.WriteFile(hookPath,
602
-		[]byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"", setting.CustomConf)), 0777)
602
+		[]byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf)), 0777)
603 603
 }
604 604
 
605 605
 type CreateRepoOptions struct {

+ 19 - 0
modules/base/base.go

@@ -4,6 +4,12 @@
4 4
 
5 5
 package base
6 6
 
7
+import (
8
+	"os"
9
+	"os/exec"
10
+	"path/filepath"
11
+)
12
+
7 13
 const DOC_URL = "https://github.com/gogits/go-gogs-client/wiki"
8 14
 
9 15
 type (
@@ -11,3 +17,16 @@ type (
11 17
 )
12 18
 
13 19
 var GoGetMetas = make(map[string]bool)
20
+
21
+// ExecPath returns the executable path.
22
+func ExecPath() (string, error) {
23
+	file, err := exec.LookPath(os.Args[0])
24
+	if err != nil {
25
+		return "", err
26
+	}
27
+	p, err := filepath.Abs(file)
28
+	if err != nil {
29
+		return "", err
30
+	}
31
+	return p, nil
32
+}

File diff suppressed because it is too large
+ 17 - 17
modules/bindata/bindata.go


+ 0 - 615
modules/crypto/ssh/agent/client.go

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

+ 0 - 287
modules/crypto/ssh/agent/client_test.go

@@ -1,287 +0,0 @@
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
-	"bytes"
9
-	"crypto/rand"
10
-	"errors"
11
-	"net"
12
-	"os"
13
-	"os/exec"
14
-	"path/filepath"
15
-	"strconv"
16
-	"testing"
17
-
18
-	"github.com/gogits/gogs/modules/crypto/ssh"
19
-)
20
-
21
-// startAgent executes ssh-agent, and returns a Agent interface to it.
22
-func startAgent(t *testing.T) (client Agent, socket string, cleanup func()) {
23
-	if testing.Short() {
24
-		// ssh-agent is not always available, and the key
25
-		// types supported vary by platform.
26
-		t.Skip("skipping test due to -short")
27
-	}
28
-
29
-	bin, err := exec.LookPath("ssh-agent")
30
-	if err != nil {
31
-		t.Skip("could not find ssh-agent")
32
-	}
33
-
34
-	cmd := exec.Command(bin, "-s")
35
-	out, err := cmd.Output()
36
-	if err != nil {
37
-		t.Fatalf("cmd.Output: %v", err)
38
-	}
39
-
40
-	/* Output looks like:
41
-
42
-		   SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK;
43
-	           SSH_AGENT_PID=15542; export SSH_AGENT_PID;
44
-	           echo Agent pid 15542;
45
-	*/
46
-	fields := bytes.Split(out, []byte(";"))
47
-	line := bytes.SplitN(fields[0], []byte("="), 2)
48
-	line[0] = bytes.TrimLeft(line[0], "\n")
49
-	if string(line[0]) != "SSH_AUTH_SOCK" {
50
-		t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0])
51
-	}
52
-	socket = string(line[1])
53
-
54
-	line = bytes.SplitN(fields[2], []byte("="), 2)
55
-	line[0] = bytes.TrimLeft(line[0], "\n")
56
-	if string(line[0]) != "SSH_AGENT_PID" {
57
-		t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2])
58
-	}
59
-	pidStr := line[1]
60
-	pid, err := strconv.Atoi(string(pidStr))
61
-	if err != nil {
62
-		t.Fatalf("Atoi(%q): %v", pidStr, err)
63
-	}
64
-
65
-	conn, err := net.Dial("unix", string(socket))
66
-	if err != nil {
67
-		t.Fatalf("net.Dial: %v", err)
68
-	}
69
-
70
-	ac := NewClient(conn)
71
-	return ac, socket, func() {
72
-		proc, _ := os.FindProcess(pid)
73
-		if proc != nil {
74
-			proc.Kill()
75
-		}
76
-		conn.Close()
77
-		os.RemoveAll(filepath.Dir(socket))
78
-	}
79
-}
80
-
81
-func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
82
-	agent, _, cleanup := startAgent(t)
83
-	defer cleanup()
84
-
85
-	testAgentInterface(t, agent, key, cert, lifetimeSecs)
86
-}
87
-
88
-func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
89
-	signer, err := ssh.NewSignerFromKey(key)
90
-	if err != nil {
91
-		t.Fatalf("NewSignerFromKey(%T): %v", key, err)
92
-	}
93
-	// The agent should start up empty.
94
-	if keys, err := agent.List(); err != nil {
95
-		t.Fatalf("RequestIdentities: %v", err)
96
-	} else if len(keys) > 0 {
97
-		t.Fatalf("got %d keys, want 0: %v", len(keys), keys)
98
-	}
99
-
100
-	// Attempt to insert the key, with certificate if specified.
101
-	var pubKey ssh.PublicKey
102
-	if cert != nil {
103
-		err = agent.Add(AddedKey{
104
-			PrivateKey:   key,
105
-			Certificate:  cert,
106
-			Comment:      "comment",
107
-			LifetimeSecs: lifetimeSecs,
108
-		})
109
-		pubKey = cert
110
-	} else {
111
-		err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs})
112
-		pubKey = signer.PublicKey()
113
-	}
114
-	if err != nil {
115
-		t.Fatalf("insert(%T): %v", key, err)
116
-	}
117
-
118
-	// Did the key get inserted successfully?
119
-	if keys, err := agent.List(); err != nil {
120
-		t.Fatalf("List: %v", err)
121
-	} else if len(keys) != 1 {
122
-		t.Fatalf("got %v, want 1 key", keys)
123
-	} else if keys[0].Comment != "comment" {
124
-		t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment")
125
-	} else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) {
126
-		t.Fatalf("key mismatch")
127
-	}
128
-
129
-	// Can the agent make a valid signature?
130
-	data := []byte("hello")
131
-	sig, err := agent.Sign(pubKey, data)
132
-	if err != nil {
133
-		t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
134
-	}
135
-
136
-	if err := pubKey.Verify(data, sig); err != nil {
137
-		t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
138
-	}
139
-}
140
-
141
-func TestAgent(t *testing.T) {
142
-	for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
143
-		testAgent(t, testPrivateKeys[keyType], nil, 0)
144
-	}
145
-}
146
-
147
-func TestCert(t *testing.T) {
148
-	cert := &ssh.Certificate{
149
-		Key:         testPublicKeys["rsa"],
150
-		ValidBefore: ssh.CertTimeInfinity,
151
-		CertType:    ssh.UserCert,
152
-	}
153
-	cert.SignCert(rand.Reader, testSigners["ecdsa"])
154
-
155
-	testAgent(t, testPrivateKeys["rsa"], cert, 0)
156
-}
157
-
158
-func TestConstraints(t *testing.T) {
159
-	testAgent(t, testPrivateKeys["rsa"], nil, 3600 /* lifetime in seconds */)
160
-}
161
-
162
-// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
163
-// therefore is buffered (net.Pipe deadlocks if both sides start with
164
-// a write.)
165
-func netPipe() (net.Conn, net.Conn, error) {
166
-	listener, err := net.Listen("tcp", "127.0.0.1:0")
167
-	if err != nil {
168
-		return nil, nil, err
169
-	}
170
-	defer listener.Close()
171
-	c1, err := net.Dial("tcp", listener.Addr().String())
172
-	if err != nil {
173
-		return nil, nil, err
174
-	}
175
-
176
-	c2, err := listener.Accept()
177
-	if err != nil {
178
-		c1.Close()
179
-		return nil, nil, err
180
-	}
181
-
182
-	return c1, c2, nil
183
-}
184
-
185
-func TestAuth(t *testing.T) {
186
-	a, b, err := netPipe()
187
-	if err != nil {
188
-		t.Fatalf("netPipe: %v", err)
189
-	}
190
-
191
-	defer a.Close()
192
-	defer b.Close()
193
-
194
-	agent, _, cleanup := startAgent(t)
195
-	defer cleanup()
196
-
197
-	if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil {
198
-		t.Errorf("Add: %v", err)
199
-	}
200
-
201
-	serverConf := ssh.ServerConfig{}
202
-	serverConf.AddHostKey(testSigners["rsa"])
203
-	serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
204
-		if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
205
-			return nil, nil
206
-		}
207
-
208
-		return nil, errors.New("pubkey rejected")
209
-	}
210
-
211
-	go func() {
212
-		conn, _, _, err := ssh.NewServerConn(a, &serverConf)
213
-		if err != nil {
214
-			t.Fatalf("Server: %v", err)
215
-		}
216
-		conn.Close()
217
-	}()
218
-
219
-	conf := ssh.ClientConfig{}
220
-	conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
221
-	conn, _, _, err := ssh.NewClientConn(b, "", &conf)
222
-	if err != nil {
223
-		t.Fatalf("NewClientConn: %v", err)
224
-	}
225
-	conn.Close()
226
-}
227
-
228
-func TestLockClient(t *testing.T) {
229
-	agent, _, cleanup := startAgent(t)
230
-	defer cleanup()
231
-	testLockAgent(agent, t)
232
-}
233
-
234
-func testLockAgent(agent Agent, t *testing.T) {
235
-	if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil {
236
-		t.Errorf("Add: %v", err)
237
-	}
238
-	if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil {
239
-		t.Errorf("Add: %v", err)
240
-	}
241
-	if keys, err := agent.List(); err != nil {
242
-		t.Errorf("List: %v", err)
243
-	} else if len(keys) != 2 {
244
-		t.Errorf("Want 2 keys, got %v", keys)
245
-	}
246
-
247
-	passphrase := []byte("secret")
248
-	if err := agent.Lock(passphrase); err != nil {
249
-		t.Errorf("Lock: %v", err)
250
-	}
251
-
252
-	if keys, err := agent.List(); err != nil {
253
-		t.Errorf("List: %v", err)
254
-	} else if len(keys) != 0 {
255
-		t.Errorf("Want 0 keys, got %v", keys)
256
-	}
257
-
258
-	signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"])
259
-	if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil {
260
-		t.Fatalf("Sign did not fail")
261
-	}
262
-
263
-	if err := agent.Remove(signer.PublicKey()); err == nil {
264
-		t.Fatalf("Remove did not fail")
265
-	}
266
-
267
-	if err := agent.RemoveAll(); err == nil {
268
-		t.Fatalf("RemoveAll did not fail")
269
-	}
270
-
271
-	if err := agent.Unlock(nil); err == nil {
272
-		t.Errorf("Unlock with wrong passphrase succeeded")
273
-	}
274
-	if err := agent.Unlock(passphrase); err != nil {
275
-		t.Errorf("Unlock: %v", err)
276
-	}
277
-
278
-	if err := agent.Remove(signer.PublicKey()); err != nil {
279
-		t.Fatalf("Remove: %v", err)
280
-	}
281
-
282
-	if keys, err := agent.List(); err != nil {
283
-		t.Errorf("List: %v", err)
284
-	} else if len(keys) != 1 {
285
-		t.Errorf("Want 1 keys, got %v", keys)
286
-	}
287
-}

+ 0 - 103
modules/crypto/ssh/agent/forward.go

@@ -1,103 +0,0 @@
1
-// Copyright 2014 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
-	"errors"
9
-	"io"
10
-	"net"
11
-	"sync"
12
-
13
-	"github.com/gogits/gogs/modules/crypto/ssh"
14
-)
15
-
16
-// RequestAgentForwarding sets up agent forwarding for the session.
17
-// ForwardToAgent or ForwardToRemote should be called to route
18
-// the authentication requests.
19
-func RequestAgentForwarding(session *ssh.Session) error {
20
-	ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil)
21
-	if err != nil {
22
-		return err
23
-	}
24
-	if !ok {
25
-		return errors.New("forwarding request denied")
26
-	}
27
-	return nil
28
-}
29
-
30
-// ForwardToAgent routes authentication requests to the given keyring.
31
-func ForwardToAgent(client *ssh.Client, keyring Agent) error {
32
-	channels := client.HandleChannelOpen(channelType)
33
-	if channels == nil {
34
-		return errors.New("agent: already have handler for " + channelType)
35
-	}
36
-
37
-	go func() {
38
-		for ch := range channels {
39
-			channel, reqs, err := ch.Accept()
40
-			if err != nil {
41
-				continue
42
-			}
43
-			go ssh.DiscardRequests(reqs)
44
-			go func() {
45
-				ServeAgent(keyring, channel)
46
-				channel.Close()
47
-			}()
48
-		}
49
-	}()
50
-	return nil
51
-}
52
-
53
-const channelType = "auth-agent@openssh.com"
54
-
55
-// ForwardToRemote routes authentication requests to the ssh-agent
56
-// process serving on the given unix socket.
57
-func ForwardToRemote(client *ssh.Client, addr string) error {
58
-	channels := client.HandleChannelOpen(channelType)
59
-	if channels == nil {
60
-		return errors.New("agent: already have handler for " + channelType)
61
-	}
62
-	conn, err := net.Dial("unix", addr)
63
-	if err != nil {
64
-		return err
65
-	}
66
-	conn.Close()
67
-
68
-	go func() {
69
-		for ch := range channels {
70
-			channel, reqs, err := ch.Accept()
71
-			if err != nil {
72
-				continue
73
-			}
74
-			go ssh.DiscardRequests(reqs)
75
-			go forwardUnixSocket(channel, addr)
76
-		}
77
-	}()
78
-	return nil
79
-}
80
-
81
-func forwardUnixSocket(channel ssh.Channel, addr string) {
82
-	conn, err := net.Dial("unix", addr)
83
-	if err != nil {
84
-		return
85
-	}
86
-
87
-	var wg sync.WaitGroup
88
-	wg.Add(2)
89
-	go func() {
90
-		io.Copy(conn, channel)
91
-		conn.(*net.UnixConn).CloseWrite()
92
-		wg.Done()
93
-	}()
94
-	go func() {
95
-		io.Copy(channel, conn)
96
-		channel.CloseWrite()
97
-		wg.Done()
98
-	}()
99
-
100
-	wg.Wait()
101
-	conn.Close()
102
-	channel.Close()
103
-}

+ 0 - 184
modules/crypto/ssh/agent/keyring.go

@@ -1,184 +0,0 @@
1
-// Copyright 2014 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
-	"bytes"
9
-	"crypto/rand"
10
-	"crypto/subtle"
11
-	"errors"
12
-	"fmt"
13
-	"sync"
14
-
15
-	"github.com/gogits/gogs/modules/crypto/ssh"
16
-)
17
-
18
-type privKey struct {
19
-	signer  ssh.Signer
20
-	comment string
21
-}
22
-
23
-type keyring struct {
24
-	mu   sync.Mutex
25
-	keys []privKey
26
-
27
-	locked     bool
28
-	passphrase []byte
29
-}
30
-
31
-var errLocked = errors.New("agent: locked")
32
-
33
-// NewKeyring returns an Agent that holds keys in memory.  It is safe
34
-// for concurrent use by multiple goroutines.
35
-func NewKeyring() Agent {
36
-	return &keyring{}
37
-}
38
-
39
-// RemoveAll removes all identities.
40
-func (r *keyring) RemoveAll() error {
41
-	r.mu.Lock()
42
-	defer r.mu.Unlock()
43
-	if r.locked {
44
-		return errLocked
45
-	}
46
-
47
-	r.keys = nil
48
-	return nil
49
-}
50
-
51
-// Remove removes all identities with the given public key.
52
-func (r *keyring) Remove(key ssh.PublicKey) error {
53
-	r.mu.Lock()
54
-	defer r.mu.Unlock()
55
-	if r.locked {
56
-		return errLocked
57
-	}
58
-
59
-	want := key.Marshal()
60
-	found := false
61
-	for i := 0; i < len(r.keys); {
62
-		if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) {
63
-			found = true
64
-			r.keys[i] = r.keys[len(r.keys)-1]
65
-			r.keys = r.keys[len(r.keys)-1:]
66
-			continue
67
-		} else {
68
-			i++
69
-		}
70
-	}
71
-
72
-	if !found {
73
-		return errors.New("agent: key not found")
74
-	}
75
-	return nil
76
-}
77
-
78
-// Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
79
-func (r *keyring) Lock(passphrase []byte) error {
80
-	r.mu.Lock()
81
-	defer r.mu.Unlock()
82
-	if r.locked {
83
-		return errLocked
84
-	}
85
-
86
-	r.locked = true
87
-	r.passphrase = passphrase
88
-	return nil
89
-}
90
-
91
-// Unlock undoes the effect of Lock
92
-func (r *keyring) Unlock(passphrase []byte) error {
93
-	r.mu.Lock()
94
-	defer r.mu.Unlock()
95
-	if !r.locked {
96
-		return errors.New("agent: not locked")
97
-	}
98
-	if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) {
99
-		return fmt.Errorf("agent: incorrect passphrase")
100
-	}
101
-
102
-	r.locked = false
103
-	r.passphrase = nil
104
-	return nil
105
-}
106
-
107
-// List returns the identities known to the agent.
108
-func (r *keyring) List() ([]*Key, error) {
109
-	r.mu.Lock()
110
-	defer r.mu.Unlock()
111
-	if r.locked {
112
-		// section 2.7: locked agents return empty.
113
-		return nil, nil
114
-	}
115
-
116
-	var ids []*Key
117
-	for _, k := range r.keys {
118
-		pub := k.signer.PublicKey()
119
-		ids = append(ids, &Key{
120
-			Format:  pub.Type(),
121
-			Blob:    pub.Marshal(),
122
-			Comment: k.comment})
123
-	}
124
-	return ids, nil
125
-}
126
-
127
-// Insert adds a private key to the keyring. If a certificate
128
-// is given, that certificate is added as public key. Note that
129
-// any constraints given are ignored.
130
-func (r *keyring) Add(key AddedKey) error {
131
-	r.mu.Lock()
132
-	defer r.mu.Unlock()
133
-	if r.locked {
134
-		return errLocked
135
-	}
136
-	signer, err := ssh.NewSignerFromKey(key.PrivateKey)
137
-
138
-	if err != nil {
139
-		return err
140
-	}
141
-
142
-	if cert := key.Certificate; cert != nil {
143
-		signer, err = ssh.NewCertSigner(cert, signer)
144
-		if err != nil {
145
-			return err
146
-		}
147
-	}
148
-
149
-	r.keys = append(r.keys, privKey{signer, key.Comment})
150
-
151
-	return nil
152
-}
153
-
154
-// Sign returns a signature for the data.
155
-func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
156
-	r.mu.Lock()
157
-	defer r.mu.Unlock()
158
-	if r.locked {
159
-		return nil, errLocked
160
-	}
161
-
162
-	wanted := key.Marshal()
163
-	for _, k := range r.keys {
164
-		if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) {
165
-			return k.signer.Sign(rand.Reader, data)
166
-		}
167
-	}
168
-	return nil, errors.New("not found")
169
-}
170
-
171
-// Signers returns signers for all the known keys.
172
-func (r *keyring) Signers() ([]ssh.Signer, error) {
173
-	r.mu.Lock()
174
-	defer r.mu.Unlock()
175
-	if r.locked {
176
-		return nil, errLocked
177
-	}
178
-
179
-	s := make([]ssh.Signer, 0, len(r.keys))
180
-	for _, k := range r.keys {
181
-		s = append(s, k.signer)
182
-	}
183
-	return s, nil
184
-}

+ 0 - 209
modules/crypto/ssh/agent/server.go

@@ -1,209 +0,0 @@
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/rsa"
9
-	"encoding/binary"
10
-	"fmt"
11
-	"io"
12
-	"log"
13
-	"math/big"
14
-
15
-	"github.com/gogits/gogs/modules/crypto/ssh"
16
-)
17
-
18
-// Server wraps an Agent and uses it to implement the agent side of
19
-// the SSH-agent, wire protocol.
20
-type server struct {
21
-	agent Agent
22
-}
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
-
34
-	if err == nil && rep == nil {
35
-		return []byte{agentSuccess}
36
-	}
37
-
38
-	return ssh.Marshal(rep)
39
-}
40
-
41
-func marshalKey(k *Key) []byte {
42
-	var record struct {
43
-		Blob    []byte
44
-		Comment string
45
-	}
46
-	record.Blob = k.Marshal()
47
-	record.Comment = k.Comment
48
-
49
-	return ssh.Marshal(&record)
50
-}
51
-
52
-type agentV1IdentityMsg struct {
53
-	Numkeys uint32 `sshtype:"2"`
54
-}
55
-
56
-type agentRemoveIdentityMsg struct {
57
-	KeyBlob []byte `sshtype:"18"`
58
-}
59
-
60
-type agentLockMsg struct {
61
-	Passphrase []byte `sshtype:"22"`
62
-}
63
-
64
-type agentUnlockMsg struct {
65
-	Passphrase []byte `sshtype:"23"`
66
-}
67
-
68
-func (s *server) processRequest(data []byte) (interface{}, error) {
69
-	switch data[0] {
70
-	case agentRequestV1Identities:
71
-		return &agentV1IdentityMsg{0}, nil
72
-	case agentRemoveIdentity:
73
-		var req agentRemoveIdentityMsg
74
-		if err := ssh.Unmarshal(data, &req); err != nil {
75
-			return nil, err
76
-		}
77
-
78
-		var wk wireKey
79
-		if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
80
-			return nil, err
81
-		}
82
-
83
-		return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob})
84
-
85
-	case agentRemoveAllIdentities:
86
-		return nil, s.agent.RemoveAll()
87
-
88
-	case agentLock:
89
-		var req agentLockMsg
90
-		if err := ssh.Unmarshal(data, &req); err != nil {
91
-			return nil, err
92
-		}
93
-
94
-		return nil, s.agent.Lock(req.Passphrase)
95
-
96
-	case agentUnlock:
97
-		var req agentLockMsg
98
-		if err := ssh.Unmarshal(data, &req); err != nil {
99
-			return nil, err
100
-		}
101
-		return nil, s.agent.Unlock(req.Passphrase)
102
-
103
-	case agentSignRequest:
104
-		var req signRequestAgentMsg
105
-		if err := ssh.Unmarshal(data, &req); err != nil {
106
-			return nil, err
107
-		}
108
-
109
-		var wk wireKey
110
-		if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
111
-			return nil, err
112
-		}
113
-
114
-		k := &Key{
115
-			Format: wk.Format,
116
-			Blob:   req.KeyBlob,
117
-		}
118
-
119
-		sig, err := s.agent.Sign(k, req.Data) //  TODO(hanwen): flags.
120
-		if err != nil {
121
-			return nil, err
122
-		}
123
-		return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil
124
-	case agentRequestIdentities:
125
-		keys, err := s.agent.List()
126
-		if err != nil {
127
-			return nil, err
128
-		}
129
-
130
-		rep := identitiesAnswerAgentMsg{
131
-			NumKeys: uint32(len(keys)),
132
-		}
133
-		for _, k := range keys {
134
-			rep.Keys = append(rep.Keys, marshalKey(k)...)
135
-		}
136
-		return rep, nil
137
-	case agentAddIdentity:
138
-		return nil, s.insertIdentity(data)
139
-	}
140
-
141
-	return nil, fmt.Errorf("unknown opcode %d", data[0])
142
-}
143
-
144
-func (s *server) insertIdentity(req []byte) error {
145
-	var record struct {
146
-		Type string `sshtype:"17"`
147
-		Rest []byte `ssh:"rest"`
148
-	}
149
-	if err := ssh.Unmarshal(req, &record); err != nil {
150
-		return err
151
-	}
152
-
153
-	switch record.Type {
154
-	case ssh.KeyAlgoRSA:
155
-		var k rsaKeyMsg
156
-		if err := ssh.Unmarshal(req, &k); err != nil {
157
-			return err
158
-		}
159
-
160
-		priv := rsa.PrivateKey{
161
-			PublicKey: rsa.PublicKey{
162
-				E: int(k.E.Int64()),
163
-				N: k.N,
164
-			},
165
-			D:      k.D,
166
-			Primes: []*big.Int{k.P, k.Q},
167
-		}
168
-		priv.Precompute()
169
-
170
-		return s.agent.Add(AddedKey{PrivateKey: &priv, Comment: k.Comments})
171
-	}
172
-	return fmt.Errorf("not implemented: %s", record.Type)
173
-}
174
-
175
-// ServeAgent serves the agent protocol on the given connection. It
176
-// returns when an I/O error occurs.
177
-func ServeAgent(agent Agent, c io.ReadWriter) error {
178
-	s := &server{agent}
179
-
180
-	var length [4]byte
181
-	for {
182
-		if _, err := io.ReadFull(c, length[:]); err != nil {
183
-			return err
184
-		}
185
-		l := binary.BigEndian.Uint32(length[:])
186
-		if l > maxAgentResponseBytes {
187
-			// We also cap requests.
188
-			return fmt.Errorf("agent: request too large: %d", l)
189
-		}
190
-
191
-		req := make([]byte, l)
192
-		if _, err := io.ReadFull(c, req); err != nil {
193
-			return err
194
-		}
195
-
196
-		repData := s.processRequestBytes(req)
197
-		if len(repData) > maxAgentResponseBytes {
198
-			return fmt.Errorf("agent: reply too large: %d bytes", len(repData))
199
-		}
200
-
201
-		binary.BigEndian.PutUint32(length[:], uint32(len(repData)))
202
-		if _, err := c.Write(length[:]); err != nil {
203
-			return err
204
-		}
205
-		if _, err := c.Write(repData); err != nil {
206
-			return err
207
-		}
208
-	}
209
-}

+ 0 - 77
modules/crypto/ssh/agent/server_test.go

@@ -1,77 +0,0 @@
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
-	"testing"
9
-
10
-	"github.com/gogits/gogs/modules/crypto/ssh"
11
-)
12
-
13
-func TestServer(t *testing.T) {
14
-	c1, c2, err := netPipe()
15
-	if err != nil {
16
-		t.Fatalf("netPipe: %v", err)
17
-	}
18
-	defer c1.Close()
19
-	defer c2.Close()
20
-	client := NewClient(c1)
21
-
22
-	go ServeAgent(NewKeyring(), c2)
23
-
24
-	testAgentInterface(t, client, testPrivateKeys["rsa"], nil, 0)
25
-}
26
-
27
-func TestLockServer(t *testing.T) {
28
-	testLockAgent(NewKeyring(), t)
29
-}
30
-
31
-func TestSetupForwardAgent(t *testing.T) {
32
-	a, b, err := netPipe()
33
-	if err != nil {
34
-		t.Fatalf("netPipe: %v", err)
35
-	}
36
-
37
-	defer a.Close()
38
-	defer b.Close()
39
-
40
-	_, socket, cleanup := startAgent(t)
41
-	defer cleanup()
42
-
43
-	serverConf := ssh.ServerConfig{
44
-		NoClientAuth: true,
45
-	}
46
-	serverConf.AddHostKey(testSigners["rsa"])
47
-	incoming := make(chan *ssh.ServerConn, 1)
48
-	go func() {
49
-		conn, _, _, err := ssh.NewServerConn(a, &serverConf)
50
-		if err != nil {
51
-			t.Fatalf("Server: %v", err)
52
-		}
53
-		incoming <- conn
54
-	}()
55
-
56
-	conf := ssh.ClientConfig{}
57
-	conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
58
-	if err != nil {
59
-		t.Fatalf("NewClientConn: %v", err)
60
-	}
61
-	client := ssh.NewClient(conn, chans, reqs)
62
-
63
-	if err := ForwardToRemote(client, socket); err != nil {
64
-		t.Fatalf("SetupForwardAgent: %v", err)
65
-	}
66
-
67
-	server := <-incoming
68
-	ch, reqs, err := server.OpenChannel(channelType, nil)
69
-	if err != nil {
70
-		t.Fatalf("OpenChannel(%q): %v", channelType, err)
71
-	}
72
-	go ssh.DiscardRequests(reqs)
73
-
74
-	agentClient := NewClient(ch)
75
-	testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0)
76
-	conn.Close()
77
-}

+ 0 - 64
modules/crypto/ssh/agent/testdata_test.go

@@ -1,64 +0,0 @@
1
-// Copyright 2014 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
-// IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
6
-// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
7
-// instances.
8
-
9
-package agent
10
-
11
-import (
12
-	"crypto/rand"
13
-	"fmt"
14
-
15
-	"github.com/gogits/gogs/modules/crypto/ssh"
16
-	"github.com/gogits/gogs/modules/crypto/ssh/testdata"
17
-)
18
-
19
-var (
20
-	testPrivateKeys map[string]interface{}
21
-	testSigners     map[string]ssh.Signer
22
-	testPublicKeys  map[string]ssh.PublicKey
23
-)
24
-
25
-func init() {
26
-	var err error
27
-
28
-	n := len(testdata.PEMBytes)
29
-	testPrivateKeys = make(map[string]interface{}, n)
30
-	testSigners = make(map[string]ssh.Signer, n)
31
-	testPublicKeys = make(map[string]ssh.PublicKey, n)
32
-	for t, k := range testdata.PEMBytes {
33
-		testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
34
-		if err != nil {
35
-			panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
36
-		}
37
-		testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
38
-		if err != nil {
39
-			panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
40
-		}
41
-		testPublicKeys[t] = testSigners[t].PublicKey()
42
-	}
43
-
44
-	// Create a cert and sign it for use in tests.
45
-	testCert := &ssh.Certificate{
46
-		Nonce:           []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
47
-		ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
48
-		ValidAfter:      0,                              // unix epoch
49
-		ValidBefore:     ssh.CertTimeInfinity,           // The end of currently representable time.
50
-		Reserved:        []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
51
-		Key:             testPublicKeys["ecdsa"],
52
-		SignatureKey:    testPublicKeys["rsa"],
53
-		Permissions: ssh.Permissions{
54
-			CriticalOptions: map[string]string{},
55
-			Extensions:      map[string]string{},
56
-		},
57
-	}
58
-	testCert.SignCert(rand.Reader, testSigners["rsa"])
59
-	testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
60
-	testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
61
-	if err != nil {
62
-		panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
63
-	}
64
-}

+ 0 - 122
modules/crypto/ssh/benchmark_test.go

@@ -1,122 +0,0 @@
1
-// Copyright 2013 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 ssh
6
-
7
-import (
8
-	"errors"
9
-	"io"
10
-	"net"
11
-	"testing"
12
-)
13
-
14
-type server struct {
15
-	*ServerConn
16
-	chans <-chan NewChannel
17
-}
18
-
19
-func newServer(c net.Conn, conf *ServerConfig) (*server, error) {
20
-	sconn, chans, reqs, err := NewServerConn(c, conf)
21
-	if err != nil {
22
-		return nil, err
23
-	}
24
-	go DiscardRequests(reqs)
25
-	return &server{sconn, chans}, nil
26
-}
27
-
28
-func (s *server) Accept() (NewChannel, error) {
29
-	n, ok := <-s.chans
30
-	if !ok {
31
-		return nil, io.EOF
32
-	}
33
-	return n, nil
34
-}
35
-
36
-func sshPipe() (Conn, *server, error) {
37
-	c1, c2, err := netPipe()
38
-	if err != nil {
39
-		return nil, nil, err
40
-	}
41
-
42
-	clientConf := ClientConfig{
43
-		User: "user",
44
-	}
45
-	serverConf := ServerConfig{
46
-		NoClientAuth: true,
47
-	}
48
-	serverConf.AddHostKey(testSigners["ecdsa"])
49
-	done := make(chan *server, 1)
50
-	go func() {
51
-		server, err := newServer(c2, &serverConf)
52
-		if err != nil {
53
-			done <- nil
54
-		}
55
-		done <- server
56
-	}()
57
-
58
-	client, _, reqs, err := NewClientConn(c1, "", &clientConf)
59
-	if err != nil {
60
-		return nil, nil, err
61
-	}
62
-
63
-	server := <-done
64
-	if server == nil {
65
-		return nil, nil, errors.New("server handshake failed.")
66
-	}
67
-	go DiscardRequests(reqs)
68
-
69
-	return client, server, nil
70
-}
71
-
72
-func BenchmarkEndToEnd(b *testing.B) {
73
-	b.StopTimer()
74
-
75
-	client, server, err := sshPipe()
76
-	if err != nil {
77
-		b.Fatalf("sshPipe: %v", err)
78
-	}
79
-
80
-	defer client.Close()
81
-	defer server.Close()
82
-
83
-	size := (1 << 20)
84
-	input := make([]byte, size)
85
-	output := make([]byte, size)
86
-	b.SetBytes(int64(size))
87
-	done := make(chan int, 1)
88
-
89
-	go func() {
90
-		newCh, err := server.Accept()
91
-		if err != nil {
92
-			b.Fatalf("Client: %v", err)
93
-		}
94
-		ch, incoming, err := newCh.Accept()
95
-		go DiscardRequests(incoming)
96
-		for i := 0; i < b.N; i++ {
97
-			if _, err := io.ReadFull(ch, output); err != nil {
98
-				b.Fatalf("ReadFull: %v", err)
99
-			}
100
-		}
101
-		ch.Close()
102
-		done <- 1
103
-	}()
104
-
105
-	ch, in, err := client.OpenChannel("speed", nil)
106
-	if err != nil {
107
-		b.Fatalf("OpenChannel: %v", err)
108
-	}
109
-	go DiscardRequests(in)
110
-
111
-	b.ResetTimer()
112
-	b.StartTimer()
113
-	for i := 0; i < b.N; i++ {
114
-		if _, err := ch.Write(input); err != nil {
115
-			b.Fatalf("WriteFull: %v", err)
116
-		}
117
-	}
118
-	ch.Close()
119
-	b.StopTimer()
120
-
121
-	<-done
122
-}

+ 0 - 98
modules/crypto/ssh/buffer.go

@@ -1,98 +0,0 @@
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 ssh
6
-
7
-import (
8
-	"io"
9
-	"sync"
10
-)
11
-
12
-// buffer provides a linked list buffer for data exchange
13
-// between producer and consumer. Theoretically the buffer is
14
-// of unlimited capacity as it does no allocation of its own.
15
-type buffer struct {
16
-	// protects concurrent access to head, tail and closed
17
-	*sync.Cond
18
-
19
-	head *element // the buffer that will be read first
20
-	tail *element // the buffer that will be read last
21
-
22
-	closed bool
23
-}
24
-
25
-// An element represents a single link in a linked list.
26
-type element struct {
27
-	buf  []byte
28
-	next *element
29
-}
30
-
31
-// newBuffer returns an empty buffer that is not closed.
32
-func newBuffer() *buffer {
33
-	e := new(element)
34
-	b := &buffer{
35
-		Cond: newCond(),
36
-		head: e,
37
-		tail: e,
38
-	}
39
-	return b
40
-}
41
-
42
-// write makes buf available for Read to receive.
43
-// buf must not be modified after the call to write.
44
-func (b *buffer) write(buf []byte) {
45
-	b.Cond.L.Lock()
46
-	e := &element{buf: buf}
47
-	b.tail.next = e
48
-	b.tail = e
49
-	b.Cond.Signal()
50
-	b.Cond.L.Unlock()
51
-}
52
-
53
-// eof closes the buffer. Reads from the buffer once all
54
-// the data has been consumed will receive os.EOF.
55
-func (b *buffer) eof() error {
56
-	b.Cond.L.Lock()
57
-	b.closed = true
58
-	b.Cond.Signal()
59
-	b.Cond.L.Unlock()
60
-	return nil
61
-}
62
-
63
-// Read reads data from the internal buffer in buf.  Reads will block
64
-// if no data is available, or until the buffer is closed.
65
-func (b *buffer) Read(buf []byte) (n int, err error) {
66
-	b.Cond.L.Lock()
67
-	defer b.Cond.L.Unlock()
68
-
69
-	for len(buf) > 0 {
70
-		// if there is data in b.head, copy it
71
-		if len(b.head.buf) > 0 {
72
-			r := copy(buf, b.head.buf)
73
-			buf, b.head.buf = buf[r:], b.head.buf[r:]
74
-			n += r
75
-			continue
76
-		}
77
-		// if there is a next buffer, make it the head
78
-		if len(b.head.buf) == 0 && b.head != b.tail {
79
-			b.head = b.head.next
80
-			continue
81
-		}
82
-
83
-		// if at least one byte has been copied, return
84
-		if n > 0 {
85
-			break
86
-		}
87
-
88
-		// if nothing was read, and there is nothing outstanding
89
-		// check to see if the buffer is closed.
90
-		if b.closed {
91
-			err = io.EOF
92
-			break
93
-		}
94
-		// out of buffers, wait for producer
95
-		b.Cond.Wait()
96
-	}
97
-	return
98
-}

+ 0 - 87
modules/crypto/ssh/buffer_test.go

@@ -1,87 +0,0 @@
1
-// Copyright 2011 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 ssh
6
-
7
-import (
8
-	"io"
9
-	"testing"
10
-)
11
-
12
-var alphabet = []byte("abcdefghijklmnopqrstuvwxyz")
13
-
14
-func TestBufferReadwrite(t *testing.T) {
15
-	b := newBuffer()
16
-	b.write(alphabet[:10])
17
-	r, _ := b.Read(make([]byte, 10))
18
-	if r != 10 {
19
-		t.Fatalf("Expected written == read == 10, written: 10, read %d", r)
20
-	}
21
-
22
-	b = newBuffer()
23
-	b.write(alphabet[:5])
24
-	r, _ = b.Read(make([]byte, 10))
25
-	if r != 5 {
26
-		t.Fatalf("Expected written == read == 5, written: 5, read %d", r)
27
-	}
28
-
29
-	b = newBuffer()
30
-	b.write(alphabet[:10])
31
-	r, _ = b.Read(make([]byte, 5))
32
-	if r != 5 {
33
-		t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r)
34
-	}
35
-
36
-	b = newBuffer()
37
-	b.write(alphabet[:5])
38
-	b.write(alphabet[5:15])
39
-	r, _ = b.Read(make([]byte, 10))
40
-	r2, _ := b.Read(make([]byte, 10))
41
-	if r != 10 || r2 != 5 || 15 != r+r2 {
42
-		t.Fatal("Expected written == read == 15")
43
-	}
44
-}
45
-
46
-func TestBufferClose(t *testing.T) {
47
-	b := newBuffer()
48
-	b.write(alphabet[:10])
49
-	b.eof()
50
-	_, err := b.Read(make([]byte, 5))
51
-	if err != nil {
52
-		t.Fatal("expected read of 5 to not return EOF")
53
-	}
54
-	b = newBuffer()
55
-	b.write(alphabet[:10])
56
-	b.eof()
57
-	r, err := b.Read(make([]byte, 5))
58
-	r2, err2 := b.Read(make([]byte, 10))
59
-	if r != 5 || r2 != 5 || err != nil || err2 != nil {
60
-		t.Fatal("expected reads of 5 and 5")
61
-	}
62
-
63
-	b = newBuffer()
64
-	b.write(alphabet[:10])
65
-	b.eof()
66
-	r, err = b.Read(make([]byte, 5))
67
-	r2, err2 = b.Read(make([]byte, 10))
68
-	r3, err3 := b.Read(make([]byte, 10))
69
-	if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF {
70
-		t.Fatal("expected reads of 5 and 5 and 0, with EOF")
71
-	}
72
-
73
-	b = newBuffer()
74
-	b.write(make([]byte, 5))
75
-	b.write(make([]byte, 10))
76
-	b.eof()
77
-	r, err = b.Read(make([]byte, 9))
78
-	r2, err2 = b.Read(make([]byte, 3))
79
-	r3, err3 = b.Read(make([]byte, 3))
80
-	r4, err4 := b.Read(make([]byte, 10))
81
-	if err != nil || err2 != nil || err3 != nil || err4 != io.EOF {
82
-		t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4)
83
-	}
84
-	if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 {
85
-		t.Fatal("Expected written == read == 15", r, r2, r3, r4)
86
-	}
87
-}

+ 0 - 501
modules/crypto/ssh/certs.go

@@ -1,501 +0,0 @@
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 ssh
6
-
7
-import (
8
-	"bytes"
9
-	"errors"
10
-	"fmt"
11
-	"io"
12
-	"net"
13
-	"sort"
14
-	"time"
15
-)
16
-
17
-// These constants from [PROTOCOL.certkeys] represent the algorithm names
18
-// for certificate types supported by this package.
19
-const (
20
-	CertAlgoRSAv01      = "ssh-rsa-cert-v01@openssh.com"
21
-	CertAlgoDSAv01      = "ssh-dss-cert-v01@openssh.com"
22
-	CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
23
-	CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
24
-	CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
25
-)
26
-
27
-// Certificate types distinguish between host and user
28
-// certificates. The values can be set in the CertType field of
29
-// Certificate.
30
-const (
31
-	UserCert = 1
32
-	HostCert = 2
33
-)
34
-
35
-// Signature represents a cryptographic signature.
36
-type Signature struct {
37
-	Format string
38
-	Blob   []byte
39
-}
40
-
41
-// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
42
-// a certificate does not expire.
43
-const CertTimeInfinity = 1<<64 - 1
44
-
45
-// An Certificate represents an OpenSSH certificate as defined in
46
-// [PROTOCOL.certkeys]?rev=1.8.
47
-type Certificate struct {
48
-	Nonce           []byte
49
-	Key             PublicKey
50
-	Serial          uint64
51
-	CertType        uint32
52
-	KeyId           string
53
-	ValidPrincipals []string
54
-	ValidAfter      uint64
55
-	ValidBefore     uint64
56
-	Permissions
57
-	Reserved     []byte
58
-	SignatureKey PublicKey
59
-	Signature    *Signature
60
-}
61
-
62
-// genericCertData holds the key-independent part of the certificate data.
63
-// Overall, certificates contain an nonce, public key fields and
64
-// key-independent fields.
65
-type genericCertData struct {
66
-	Serial          uint64
67
-	CertType        uint32
68
-	KeyId           string
69
-	ValidPrincipals []byte
70
-	ValidAfter      uint64
71
-	ValidBefore     uint64
72
-	CriticalOptions []byte
73
-	Extensions      []byte
74
-	Reserved        []byte
75
-	SignatureKey    []byte
76
-	Signature       []byte
77
-}
78
-
79
-func marshalStringList(namelist []string) []byte {
80
-	var to []byte
81
-	for _, name := range namelist {
82
-		s := struct{ N string }{name}
83
-		to = append(to, Marshal(&s)...)
84
-	}
85
-	return to
86
-}
87
-
88
-type optionsTuple struct {
89
-	Key   string
90
-	Value []byte
91
-}
92
-
93
-type optionsTupleValue struct {
94
-	Value string
95
-}
96
-
97
-// serialize a map of critical options or extensions
98
-// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
99
-// we need two length prefixes for a non-empty string value
100
-func marshalTuples(tups map[string]string) []byte {
101
-	keys := make([]string, 0, len(tups))
102
-	for key := range tups {
103
-		keys = append(keys, key)
104
-	}
105
-	sort.Strings(keys)
106
-
107
-	var ret []byte
108
-	for _, key := range keys {
109
-		s := optionsTuple{Key: key}
110
-		if value := tups[key]; len(value) > 0 {
111
-			s.Value = Marshal(&optionsTupleValue{value})
112
-		}
113
-		ret = append(ret, Marshal(&s)...)
114
-	}
115
-	return ret
116
-}
117
-
118
-// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
119
-// we need two length prefixes for a non-empty option value
120
-func parseTuples(in []byte) (map[string]string, error) {
121
-	tups := map[string]string{}
122
-	var lastKey string
123
-	var haveLastKey bool
124
-
125
-	for len(in) > 0 {
126
-		var key, val, extra []byte
127
-		var ok bool
128
-
129
-		if key, in, ok = parseString(in); !ok {
130
-			return nil, errShortRead
131
-		}
132
-		keyStr := string(key)
133
-		// according to [PROTOCOL.certkeys], the names must be in
134
-		// lexical order.
135
-		if haveLastKey && keyStr <= lastKey {
136
-			return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
137
-		}
138
-		lastKey, haveLastKey = keyStr, true
139
-		// the next field is a data field, which if non-empty has a string embedded
140
-		if val, in, ok = parseString(in); !ok {
141
-			return nil, errShortRead
142
-		}
143
-		if len(val) > 0 {
144
-			val, extra, ok = parseString(val)
145
-			if !ok {
146
-				return nil, errShortRead
147
-			}
148
-			if len(extra) > 0 {
149
-				return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value")
150
-			}
151
-			tups[keyStr] = string(val)
152
-		} else {
153
-			tups[keyStr] = ""
154
-		}
155
-	}
156
-	return tups, nil
157
-}
158
-
159
-func parseCert(in []byte, privAlgo string) (*Certificate, error) {
160
-	nonce, rest, ok := parseString(in)
161
-	if !ok {
162
-		return nil, errShortRead
163
-	}
164
-
165
-	key, rest, err := parsePubKey(rest, privAlgo)
166
-	if err != nil {
167
-		return nil, err
168
-	}
169
-
170
-	var g genericCertData
171
-	if err := Unmarshal(rest, &g); err != nil {
172
-		return nil, err
173
-	}
174
-
175
-	c := &Certificate{
176
-		Nonce:       nonce,
177
-		Key:         key,
178
-		Serial:      g.Serial,
179
-		CertType:    g.CertType,
180
-		KeyId:       g.KeyId,
181
-		ValidAfter:  g.ValidAfter,
182
-		ValidBefore: g.ValidBefore,
183
-	}
184
-
185
-	for principals := g.ValidPrincipals; len(principals) > 0; {
186
-		principal, rest, ok := parseString(principals)
187
-		if !ok {
188
-			return nil, errShortRead
189
-		}
190
-		c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
191
-		principals = rest
192
-	}
193
-
194
-	c.CriticalOptions, err = parseTuples(g.CriticalOptions)
195
-	if err != nil {
196
-		return nil, err
197
-	}
198
-	c.Extensions, err = parseTuples(g.Extensions)
199
-	if err != nil {
200
-		return nil, err
201
-	}
202
-	c.Reserved = g.Reserved
203
-	k, err := ParsePublicKey(g.SignatureKey)
204
-	if err != nil {
205
-		return nil, err
206
-	}
207
-
208
-	c.SignatureKey = k
209
-	c.Signature, rest, ok = parseSignatureBody(g.Signature)
210
-	if !ok || len(rest) > 0 {
211
-		return nil, errors.New("ssh: signature parse error")
212
-	}
213
-
214
-	return c, nil
215
-}
216
-
217
-type openSSHCertSigner struct {
218
-	pub    *Certificate
219
-	signer Signer
220
-}
221
-
222
-// NewCertSigner returns a Signer that signs with the given Certificate, whose
223
-// private key is held by signer. It returns an error if the public key in cert
224
-// doesn't match the key used by signer.
225
-func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
226
-	if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
227
-		return nil, errors.New("ssh: signer and cert have different public key")
228
-	}
229
-
230
-	return &openSSHCertSigner{cert, signer}, nil
231
-}
232
-
233
-func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
234
-	return s.signer.Sign(rand, data)
235
-}
236
-
237
-func (s *openSSHCertSigner) PublicKey() PublicKey {
238
-	return s.pub
239
-}
240
-
241
-const sourceAddressCriticalOption = "source-address"
242
-
243
-// CertChecker does the work of verifying a certificate. Its methods
244
-// can be plugged into ClientConfig.HostKeyCallback and
245
-// ServerConfig.PublicKeyCallback. For the CertChecker to work,
246
-// minimally, the IsAuthority callback should be set.
247
-type CertChecker struct {
248
-	// SupportedCriticalOptions lists the CriticalOptions that the
249
-	// server application layer understands. These are only used
250
-	// for user certificates.
251
-	SupportedCriticalOptions []string
252
-
253
-	// IsAuthority should return true if the key is recognized as
254
-	// an authority. This allows for certificates to be signed by other
255
-	// certificates.
256
-	IsAuthority func(auth PublicKey) bool
257
-
258
-	// Clock is used for verifying time stamps. If nil, time.Now
259
-	// is used.
260
-	Clock func() time.Time
261
-
262
-	// UserKeyFallback is called when CertChecker.Authenticate encounters a
263
-	// public key that is not a certificate. It must implement validation
264
-	// of user keys or else, if nil, all such keys are rejected.
265
-	UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
266
-
267
-	// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
268
-	// public key that is not a certificate. It must implement host key
269
-	// validation or else, if nil, all such keys are rejected.
270
-	HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error
271
-
272
-	// IsRevoked is called for each certificate so that revocation checking
273
-	// can be implemented. It should return true if the given certificate
274
-	// is revoked and false otherwise. If nil, no certificates are
275
-	// considered to have been revoked.
276
-	IsRevoked func(cert *Certificate) bool
277
-}
278
-
279
-// CheckHostKey checks a host key certificate. This method can be
280
-// plugged into ClientConfig.HostKeyCallback.
281
-func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
282
-	cert, ok := key.(*Certificate)
283
-	if !ok {
284
-		if c.HostKeyFallback != nil {
285
-			return c.HostKeyFallback(addr, remote, key)
286
-		}
287
-		return errors.New("ssh: non-certificate host key")
288
-	}
289
-	if cert.CertType != HostCert {
290
-		return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
291
-	}
292
-
293
-	return c.CheckCert(addr, cert)
294
-}
295
-
296
-// Authenticate checks a user certificate. Authenticate can be used as
297
-// a value for ServerConfig.PublicKeyCallback.
298
-func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
299
-	cert, ok := pubKey.(*Certificate)
300
-	if !ok {
301
-		if c.UserKeyFallback != nil {
302
-			return c.UserKeyFallback(conn, pubKey)
303
-		}
304
-		return nil, errors.New("ssh: normal key pairs not accepted")
305
-	}
306
-
307
-	if cert.CertType != UserCert {
308
-		return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
309
-	}
310
-
311
-	if err := c.CheckCert(conn.User(), cert); err != nil {
312
-		return nil, err
313
-	}
314
-
315
-	return &cert.Permissions, nil
316
-}
317
-
318
-// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
319
-// the signature of the certificate.
320
-func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
321
-	if c.IsRevoked != nil && c.IsRevoked(cert) {
322
-		return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial)
323
-	}
324
-
325
-	for opt, _ := range cert.CriticalOptions {
326
-		// sourceAddressCriticalOption will be enforced by
327
-		// serverAuthenticate
328
-		if opt == sourceAddressCriticalOption {
329
-			continue
330
-		}
331
-
332
-		found := false
333
-		for _, supp := range c.SupportedCriticalOptions {
334
-			if supp == opt {
335
-				found = true
336
-				break
337
-			}
338
-		}
339
-		if !found {
340
-			return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
341
-		}
342
-	}
343
-
344
-	if len(cert.ValidPrincipals) > 0 {
345
-		// By default, certs are valid for all users/hosts.
346
-		found := false
347
-		for _, p := range cert.ValidPrincipals {
348
-			if p == principal {
349
-				found = true
350
-				break
351
-			}
352
-		}
353
-		if !found {
354
-			return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
355
-		}
356
-	}
357
-
358
-	if !c.IsAuthority(cert.SignatureKey) {
359
-		return fmt.Errorf("ssh: certificate signed by unrecognized authority")
360
-	}
361
-
362
-	clock := c.Clock
363
-	if clock == nil {
364
-		clock = time.Now
365
-	}
366
-
367
-	unixNow := clock().Unix()
368
-	if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
369
-		return fmt.Errorf("ssh: cert is not yet valid")
370
-	}
371
-	if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) {
372
-		return fmt.Errorf("ssh: cert has expired")
373
-	}
374
-	if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
375
-		return fmt.Errorf("ssh: certificate signature does not verify")
376
-	}
377
-
378
-	return nil
379
-}
380
-
381
-// SignCert sets c.SignatureKey to the authority's public key and stores a
382
-// Signature, by authority, in the certificate.
383
-func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
384
-	c.Nonce = make([]byte, 32)
385
-	if _, err := io.ReadFull(rand, c.Nonce); err != nil {
386
-		return err
387
-	}
388
-	c.SignatureKey = authority.PublicKey()
389
-
390
-	sig, err := authority.Sign(rand, c.bytesForSigning())
391
-	if err != nil {
392
-		return err
393
-	}
394
-	c.Signature = sig
395
-	return nil
396
-}
397
-
398
-var certAlgoNames = map[string]string{
399
-	KeyAlgoRSA:      CertAlgoRSAv01,
400
-	KeyAlgoDSA:      CertAlgoDSAv01,
401
-	KeyAlgoECDSA256: CertAlgoECDSA256v01,
402
-	KeyAlgoECDSA384: CertAlgoECDSA384v01,
403
-	KeyAlgoECDSA521: CertAlgoECDSA521v01,
404
-}
405
-
406
-// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
407
-// Panics if a non-certificate algorithm is passed.
408
-func certToPrivAlgo(algo string) string {
409
-	for privAlgo, pubAlgo := range certAlgoNames {
410
-		if pubAlgo == algo {
411
-			return privAlgo
412
-		}
413
-	}
414
-	panic("unknown cert algorithm")
415
-}
416
-
417
-func (cert *Certificate) bytesForSigning() []byte {
418
-	c2 := *cert
419
-	c2.Signature = nil
420
-	out := c2.Marshal()
421
-	// Drop trailing signature length.
422
-	return out[:len(out)-4]
423
-}
424
-
425
-// Marshal serializes c into OpenSSH's wire format. It is part of the
426
-// PublicKey interface.
427
-func (c *Certificate) Marshal() []byte {
428
-	generic := genericCertData{
429
-		Serial:          c.Serial,
430
-		CertType:        c.CertType,
431
-		KeyId:           c.KeyId,
432
-		ValidPrincipals: marshalStringList(c.ValidPrincipals),
433
-		ValidAfter:      uint64(c.ValidAfter),
434
-		ValidBefore:     uint64(c.ValidBefore),
435
-		CriticalOptions: marshalTuples(c.CriticalOptions),
436
-		Extensions:      marshalTuples(c.Extensions),
437
-		Reserved:        c.Reserved,
438
-		SignatureKey:    c.SignatureKey.Marshal(),
439
-	}
440
-	if c.Signature != nil {
441
-		generic.Signature = Marshal(c.Signature)
442
-	}
443
-	genericBytes := Marshal(&generic)
444
-	keyBytes := c.Key.Marshal()
445
-	_, keyBytes, _ = parseString(keyBytes)
446
-	prefix := Marshal(&struct {
447
-		Name  string
448
-		Nonce []byte
449
-		Key   []byte `ssh:"rest"`
450
-	}{c.Type(), c.Nonce, keyBytes})
451
-
452
-	result := make([]byte, 0, len(prefix)+len(genericBytes))
453
-	result = append(result, prefix...)
454
-	result = append(result, genericBytes...)
455
-	return result
456
-}
457
-
458
-// Type returns the key name. It is part of the PublicKey interface.
459
-func (c *Certificate) Type() string {
460
-	algo, ok := certAlgoNames[c.Key.Type()]
461
-	if !ok {
462
-		panic("unknown cert key type")
463
-	}
464
-	return algo
465
-}
466
-
467
-// Verify verifies a signature against the certificate's public
468
-// key. It is part of the PublicKey interface.
469
-func (c *Certificate) Verify(data []byte, sig *Signature) error {
470
-	return c.Key.Verify(data, sig)
471
-}
472
-
473
-func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
474
-	format, in, ok := parseString(in)
475
-	if !ok {
476
-		return
477
-	}
478
-
479
-	out = &Signature{
480
-		Format: string(format),
481
-	}
482
-
483
-	if out.Blob, in, ok = parseString(in); !ok {
484
-		return
485
-	}
486
-
487
-	return out, in, ok
488
-}
489
-
490
-func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
491
-	sigBytes, rest, ok := parseString(in)
492
-	if !ok {
493
-		return
494
-	}
495
-
496
-	out, trailing, ok := parseSignatureBody(sigBytes)
497
-	if !ok || len(trailing) > 0 {
498
-		return nil, nil, false
499
-	}
500
-	return
501
-}

File diff suppressed because it is too large
+ 0 - 216
modules/crypto/ssh/certs_test.go


+ 0 - 631
modules/crypto/ssh/channel.go

@@ -1,631 +0,0 @@
1
-// Copyright 2011 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 ssh
6
-
7
-import (
8
-	"encoding/binary"
9
-	"errors"
10
-	"fmt"
11
-	"io"
12
-	"log"
13
-	"sync"
14
-)
15
-
16
-const (
17
-	minPacketLength = 9
18
-	// channelMaxPacket contains the maximum number of bytes that will be
19
-	// sent in a single packet. As per RFC 4253, section 6.1, 32k is also
20
-	// the minimum.
21
-	channelMaxPacket = 1 << 15
22
-	// We follow OpenSSH here.
23
-	channelWindowSize = 64 * channelMaxPacket
24
-)
25
-
26
-// NewChannel represents an incoming request to a channel. It must either be
27
-// accepted for use by calling Accept, or rejected by calling Reject.
28
-type NewChannel interface {
29
-	// Accept accepts the channel creation request. It returns the Channel
30
-	// and a Go channel containing SSH requests. The Go channel must be
31
-	// serviced otherwise the Channel will hang.
32
-	Accept() (Channel, <-chan *Request, error)
33
-
34
-	// Reject rejects the channel creation request. After calling
35
-	// this, no other methods on the Channel may be called.
36
-	Reject(reason RejectionReason, message string) error
37
-
38
-	// ChannelType returns the type of the channel, as supplied by the
39
-	// client.
40
-	ChannelType() string
41
-
42
-	// ExtraData returns the arbitrary payload for this channel, as supplied
43
-	// by the client. This data is specific to the channel type.
44
-	ExtraData() []byte
45
-}
46
-
47
-// A Channel is an ordered, reliable, flow-controlled, duplex stream
48
-// that is multiplexed over an SSH connection.
49
-type Channel interface {
50
-	// Read reads up to len(data) bytes from the channel.
51
-	Read(data []byte) (int, error)
52
-
53
-	// Write writes len(data) bytes to the channel.
54
-	Write(data []byte) (int, error)
55
-
56
-	// Close signals end of channel use. No data may be sent after this
57
-	// call.
58
-	Close() error
59
-
60
-	// CloseWrite signals the end of sending in-band
61
-	// data. Requests may still be sent, and the other side may
62
-	// still send data
63
-	CloseWrite() error
64
-
65
-	// SendRequest sends a channel request.  If wantReply is true,
66
-	// it will wait for a reply and return the result as a
67
-	// boolean, otherwise the return value will be false. Channel
68
-	// requests are out-of-band messages so they may be sent even
69
-	// if the data stream is closed or blocked by flow control.
70
-	SendRequest(name string, wantReply bool, payload []byte) (bool, error)
71
-
72
-	// Stderr returns an io.ReadWriter that writes to this channel
73
-	// with the extended data type set to stderr. Stderr may
74
-	// safely be read and written from a different goroutine than
75
-	// Read and Write respectively.
76
-	Stderr() io.ReadWriter
77
-}
78
-
79
-// Request is a request sent outside of the normal stream of
80
-// data. Requests can either be specific to an SSH channel, or they
81
-// can be global.
82
-type Request struct {
83
-	Type      string
84
-	WantReply bool
85
-	Payload   []byte
86
-
87
-	ch  *channel
88
-	mux *mux
89
-}
90
-
91
-// Reply sends a response to a request. It must be called for all requests
92
-// where WantReply is true and is a no-op otherwise. The payload argument is
93
-// ignored for replies to channel-specific requests.
94
-func (r *Request) Reply(ok bool, payload []byte) error {
95
-	if !r.WantReply {
96
-		return nil
97
-	}
98
-
99
-	if r.ch == nil {
100
-		return r.mux.ackRequest(ok, payload)
101
-	}
102
-
103
-	return r.ch.ackRequest(ok)
104
-}
105
-
106
-// RejectionReason is an enumeration used when rejecting channel creation
107
-// requests. See RFC 4254, section 5.1.
108
-type RejectionReason uint32
109
-
110
-const (
111
-	Prohibited RejectionReason = iota + 1
112
-	ConnectionFailed
113
-	UnknownChannelType
114
-	ResourceShortage
115
-)
116
-
117
-// String converts the rejection reason to human readable form.
118
-func (r RejectionReason) String() string {
119
-	switch r {
120
-	case Prohibited:
121
-		return "administratively prohibited"
122
-	case ConnectionFailed:
123
-		return "connect failed"
124
-	case UnknownChannelType:
125
-		return "unknown channel type"
126
-	case ResourceShortage:
127
-		return "resource shortage"
128
-	}
129
-	return fmt.Sprintf("unknown reason %d", int(r))
130
-}
131
-
132
-func min(a uint32, b int) uint32 {
133
-	if a < uint32(b) {
134
-		return a
135
-	}
136
-	return uint32(b)
137
-}
138
-
139
-type channelDirection uint8
140
-
141
-const (
142
-	channelInbound channelDirection = iota
143
-	channelOutbound
144
-)
145
-
146
-// channel is an implementation of the Channel interface that works
147
-// with the mux class.
148
-type channel struct {
149
-	// R/O after creation
150
-	chanType          string
151
-	extraData         []byte
152
-	localId, remoteId uint32
153
-
154
-	// maxIncomingPayload and maxRemotePayload are the maximum
155
-	// payload sizes of normal and extended data packets for
156
-	// receiving and sending, respectively. The wire packet will
157
-	// be 9 or 13 bytes larger (excluding encryption overhead).
158
-	maxIncomingPayload uint32
159
-	maxRemotePayload   uint32
160
-
161
-	mux *mux
162
-
163
-	// decided is set to true if an accept or reject message has been sent
164
-	// (for outbound channels) or received (for inbound channels).
165
-	decided bool
166
-
167
-	// direction contains either channelOutbound, for channels created
168
-	// locally, or channelInbound, for channels created by the peer.
169
-	direction channelDirection
170
-
171
-	// Pending internal channel messages.
172
-	msg chan interface{}
173
-
174
-	// Since requests have no ID, there can be only one request
175
-	// with WantReply=true outstanding.  This lock is held by a
176
-	// goroutine that has such an outgoing request pending.
177
-	sentRequestMu sync.Mutex
178
-
179
-	incomingRequests chan *Request
180
-
181
-	sentEOF bool
182
-
183
-	// thread-safe data
184
-	remoteWin  window
185
-	pending    *buffer
186
-	extPending *buffer
187
-
188
-	// windowMu protects myWindow, the flow-control window.
189
-	windowMu sync.Mutex
190
-	myWindow uint32
191
-
192
-	// writeMu serializes calls to mux.conn.writePacket() and
193
-	// protects sentClose and packetPool. This mutex must be
194