diff options
author | Runxi Yu <me@runxiyu.org> | 2025-02-12 17:08:27 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-02-12 17:08:27 +0800 |
commit | 78ef3b19d40aa6f63412ba961ab5c8bf0939237e (patch) | |
tree | d7758dc2071a8cedf02eeba9d731af4ea8ad5c3b | |
parent | router.go: Fix out-of-bounds read on /: (diff) | |
download | forge-78ef3b19d40aa6f63412ba961ab5c8bf0939237e.tar.gz forge-78ef3b19d40aa6f63412ba961ab5c8bf0939237e.tar.zst forge-78ef3b19d40aa6f63412ba961ab5c8bf0939237e.zip |
ssh.go: Add anonymous SSH cloning
-rw-r--r-- | config.go | 5 | ||||
-rw-r--r-- | forge.scfg | 6 | ||||
-rw-r--r-- | go.mod | 4 | ||||
-rw-r--r-- | main.go | 5 | ||||
-rw-r--r-- | ssh.go | 82 |
5 files changed, 101 insertions, 1 deletions
@@ -19,6 +19,11 @@ var config struct { Net string `scfg:"net"` Addr string `scfg:"addr"` } `scfg:"http"` + SSH struct { + Net string `scfg:"net"` + Addr string `scfg:"addr"` + Key string `scfg:"key"` + } `scfg:"ssh"` Git struct { Root string `scfg:"root"` } `scfg:"git"` @@ -3,6 +3,12 @@ http { addr :8080 } +ssh { + net ssh + addr :2222 + key /etc/ssh/ssh_host_ed25519_key +} + db { type postgres conn postgresql:///lindenii-forge?host=/var/run/postgresql @@ -4,18 +4,21 @@ go 1.23.5 require ( github.com/alecthomas/chroma/v2 v2.15.0 + github.com/gliderlabs/ssh v0.3.8 github.com/go-git/go-git/v5 v5.13.2 github.com/jackc/pgx/v5 v5.7.2 github.com/microcosm-cc/bluemonday v1.0.27 github.com/niklasfasching/go-org v1.7.0 github.com/yuin/goldmark v1.7.8 go.lindenii.runxiyu.org/lindenii-common v0.0.0-20250211153243-8946fae17bd0 + golang.org/x/crypto v0.33.0 ) require ( dario.cat/mergo v1.0.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ProtonMail/go-crypto v1.1.5 // indirect + github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/cloudflare/circl v1.6.0 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect @@ -34,7 +37,6 @@ require ( github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.33.0 // indirect golang.org/x/net v0.35.0 // indirect golang.org/x/sync v0.11.0 // indirect golang.org/x/sys v0.30.0 // indirect @@ -31,6 +31,11 @@ func main() { clog.Fatal(1, "Listening: "+err.Error()) } + err = serve_ssh() + if err != nil { + clog.Fatal(1, "Listening SSH: "+err.Error()) + } + err = http.Serve(listener, &http_router_t{}) if err != nil { clog.Fatal(1, "Serving: "+err.Error()) @@ -0,0 +1,82 @@ +package main + +import ( + "fmt" + "net" + "os" + "os/exec" + + glider_ssh "github.com/gliderlabs/ssh" + "go.lindenii.runxiyu.org/lindenii-common/clog" + go_ssh "golang.org/x/crypto/ssh" +) + +func serve_ssh() error { + hostKeyBytes, err := os.ReadFile(config.SSH.Key) + if err != nil { + return err + } + + hostKey, err := go_ssh.ParsePrivateKey(hostKeyBytes) + if err != nil { + return err + } + + server := &glider_ssh.Server{ + Handler: func(session glider_ssh.Session) { + client_public_key := session.PublicKey() + var client_public_key_string string + if client_public_key != nil { + client_public_key_string = string(go_ssh.MarshalAuthorizedKey(client_public_key)) + } + _ = client_public_key_string + + cmd := session.Command() + + if len(cmd) < 2 { + fmt.Fprintln(session.Stderr(), "Insufficient arguments") + return + } + + if cmd[0] != "git-upload-pack" { + fmt.Fprintln(session.Stderr(), "Unsupported command") + return + } + + proc := exec.CommandContext(session.Context(), cmd[0], "/home/runxiyu/git/forge.git") + proc.Stdin = session + proc.Stdout = session + proc.Stderr = session.Stderr() + + err := proc.Start() + if err != nil { + fmt.Fprintln(session.Stderr(), "Error while starting process:", err) + return + } + err = proc.Wait() + if exitError, ok := err.(*exec.ExitError); ok { + fmt.Fprintln(session.Stderr(), "Process exited with error", exitError.ExitCode()) + } else if err != nil { + fmt.Fprintln(session.Stderr(), "Error while waiting for process:", err) + } + }, + PublicKeyHandler: func(ctx glider_ssh.Context, key glider_ssh.PublicKey) bool { return true }, + KeyboardInteractiveHandler: func(ctx glider_ssh.Context, challenge go_ssh.KeyboardInteractiveChallenge) bool { return true }, + } + + server.AddHostKey(hostKey) + + listener, err := net.Listen("tcp", ":2222") + if err != nil { + return err + } + + go func() { + err = server.Serve(listener) + if err != nil { + clog.Fatal(1, "Serving SSH: "+err.Error()) + } + }() + + return nil +} |