From 77c72c0081c82ee9485e4ce795d8f2aae4292579 Mon Sep 17 00:00:00 2001 From: Toby Padilla Date: Fri, 30 Jul 2021 16:51:30 -0500 Subject: [PATCH] Use authorized keys file to gate git write access --- main.go | 9 ++++---- server/middleware/git/git.go | 43 ++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index c36ff2a90ee21008d65c8f55d22e1b214b59d918..34c7c444bfef7f505bab53c414e76f5c83ffe084 100644 --- a/main.go +++ b/main.go @@ -13,9 +13,10 @@ import ( ) type Config struct { - Port int `env:"SMOOTHIE_PORT" default:"23231"` - KeyPath string `env:"SMOOTHIE_KEY_PATH" default:".ssh/smoothie_server_ed25519"` - RepoPath string `env:"SMOOTHIE_REPO_PATH" default:".repos"` + Port int `env:"SMOOTHIE_PORT" default:"23231"` + KeyPath string `env:"SMOOTHIE_KEY_PATH" default:".ssh/smoothie_server_ed25519"` + RepoAuthPath string `env:"SMOOTHIE_KEY_PATH" default:".ssh/smoothie_git_authorized_keys"` + RepoPath string `env:"SMOOTHIE_REPO_PATH" default:".repos"` } func main() { @@ -28,7 +29,7 @@ func main() { cfg.Port, cfg.KeyPath, bm.Middleware(tui.SessionHandler, tea.WithAltScreen()), - gm.Middleware(cfg.RepoPath), + gm.Middleware(cfg.RepoPath, cfg.RepoAuthPath), lm.Middleware(), ) if err != nil { diff --git a/server/middleware/git/git.go b/server/middleware/git/git.go index 33ef2f0c32a2c626ce117b179ce91f86ae7173a8..d098a62bb6a1bd4d68da089fc2a3e2888f96b755 100644 --- a/server/middleware/git/git.go +++ b/server/middleware/git/git.go @@ -1,8 +1,10 @@ package git import ( + "bufio" "context" "fmt" + "log" "os" "os/exec" "smoothie/server/middleware" @@ -10,13 +12,50 @@ import ( "github.com/gliderlabs/ssh" ) -func Middleware(repoDir string) middleware.Middleware { +func Middleware(repoDir string, authorizedKeysPath string) middleware.Middleware { + authedKeys := make([]ssh.PublicKey, 0) + hasAuth, err := fileExists(authorizedKeysPath) + if err != nil { + log.Fatal(err) + } + if hasAuth { + f, err := os.Open(authorizedKeysPath) + if err != nil { + log.Fatal(err) + } + defer f.Close() + scanner := bufio.NewScanner(f) + for scanner.Scan() { + pt := scanner.Text() + log.Printf("Adding authorized key: %s", pt) + pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pt)) + if err != nil { + log.Fatal(err) + } + authedKeys = append(authedKeys, pk) + } + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + } return func(sh ssh.Handler) ssh.Handler { return func(s ssh.Session) { cmd := s.Command() if len(cmd) == 2 { switch cmd[0] { - case "git-upload-pack", "git-receive-pack", "git-upload-archive": + case "git-upload-pack", "git-upload-archive", "git-receive-pack": + if hasAuth && cmd[0] == "git-receive-pack" { + authed := false + for _, pk := range authedKeys { + if ssh.KeysEqual(pk, s.PublicKey()) { + authed = true + } + } + if !authed { + fatalGit(s, fmt.Errorf("you are not authorized to do this")) + break + } + } r := cmd[1] rp := fmt.Sprintf("%s%s", repoDir, r) ctx := s.Context()