summaryrefslogtreecommitdiffstats
path: root/modules/ssh
diff options
context:
space:
mode:
authorUnknwon <joe2010xtmf@163.com>2014-07-26 00:24:27 -0400
committerUnknwon <joe2010xtmf@163.com>2014-07-26 00:24:27 -0400
commit8dd07c0ddd99ae626a1ec8c06f75f27fed51269f (patch)
tree261d3c9911dabc58c1ac54e4e36b3dee24d2032b /modules/ssh
parent0a739cf9ac901f54484c34bba8322418dedb09b0 (diff)
downloadgitea-8dd07c0ddd99ae626a1ec8c06f75f27fed51269f.tar.gz
gitea-8dd07c0ddd99ae626a1ec8c06f75f27fed51269f.zip
New UI merge in progress
Diffstat (limited to 'modules/ssh')
-rw-r--r--modules/ssh/ssh.go119
1 files changed, 119 insertions, 0 deletions
diff --git a/modules/ssh/ssh.go b/modules/ssh/ssh.go
new file mode 100644
index 0000000000..78ad678dc5
--- /dev/null
+++ b/modules/ssh/ssh.go
@@ -0,0 +1,119 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// Prototype, git client looks like do not recognize req.Reply.
+package ssh
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/exec"
+ "strings"
+
+ "code.google.com/p/go.crypto/ssh"
+
+ "github.com/Unknwon/com"
+
+ "github.com/gogits/gogs-ng/modules/log"
+)
+
+func handleServerConn(keyId string, chans <-chan ssh.NewChannel) {
+ for newChan := range chans {
+ if newChan.ChannelType() != "session" {
+ newChan.Reject(ssh.UnknownChannelType, "unknown channel type")
+ continue
+ }
+ channel, requests, err := newChan.Accept()
+ if err != nil {
+ log.Error(3, "Could not accept channel: %v", err)
+ continue
+ }
+
+ go func(in <-chan *ssh.Request) {
+ defer channel.Close()
+ for req := range in {
+ ok, payload := false, strings.TrimLeft(string(req.Payload), "\x00")
+ fmt.Println("Request:", req.Type, req.WantReply, payload)
+ switch req.Type {
+ case "env":
+ args := strings.Split(strings.Replace(payload, "\x00", "", -1), "\v")
+ if len(args) != 2 {
+ break
+ }
+ args[0] = strings.TrimLeft(args[0], "\x04")
+ _, _, err := com.ExecCmdBytes("env", args[0]+"="+args[1])
+ if err != nil {
+ log.Error(3, "env: %v", err)
+ channel.Stderr().Write([]byte(err.Error()))
+ break
+ }
+ ok = true
+ case "exec":
+ os.Setenv("SSH_ORIGINAL_COMMAND", strings.TrimLeft(payload, "'("))
+ log.Info("Payload: %v", strings.TrimLeft(payload, "'("))
+ cmd := exec.Command("/Users/jiahuachen/Applications/Go/src/github.com/gogits/gogs-ng/gogs-ng", "serv", "key-"+keyId)
+ cmd.Stdout = channel
+ cmd.Stdin = channel
+ cmd.Stderr = channel.Stderr()
+ if err := cmd.Run(); err != nil {
+ log.Error(3, "exec: %v", err)
+ } else {
+ ok = true
+ }
+ }
+ fmt.Println("Done:", ok)
+ req.Reply(ok, nil) // BUG: Git on Mac seems not know this reply and hang?
+ }
+ fmt.Println("Done!!!")
+ }(requests)
+ }
+}
+
+func listen(config *ssh.ServerConfig, port string) {
+ listener, err := net.Listen("tcp", "0.0.0.0:"+port)
+ if err != nil {
+ panic(err)
+ }
+ for {
+ // Once a ServerConfig has been configured, connections can be accepted.
+ conn, err := listener.Accept()
+ if err != nil {
+ log.Error(3, "Fail to accept incoming connection: %v", err)
+ continue
+ }
+ // Before use, a handshake must be performed on the incoming net.Conn.
+ sConn, chans, reqs, err := ssh.NewServerConn(conn, config)
+ if err != nil {
+ log.Error(3, "Fail to handshake: %v", err)
+ continue
+ }
+ // The incoming Request channel must be serviced.
+ go ssh.DiscardRequests(reqs)
+ go handleServerConn(sConn.Permissions.Extensions["key-id"], chans)
+ }
+}
+
+// Listen starts a SSH server listens on given port.
+func Listen(port string) {
+ config := &ssh.ServerConfig{
+ PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
+ // keyCache[string(ssh.MarshalAuthorizedKey(key))] = 2
+ return &ssh.Permissions{Extensions: map[string]string{"key-id": "2"}}, nil
+ },
+ }
+
+ privateBytes, err := ioutil.ReadFile("/Users/jiahuachen/.ssh/id_rsa")
+ if err != nil {
+ panic("failed to load private key")
+ }
+ private, err := ssh.ParsePrivateKey(privateBytes)
+ if err != nil {
+ panic("failed to parse private key")
+ }
+ config.AddHostKey(private)
+
+ go listen(config, port)
+}