From f008f8936988f69561e27c9c5e2e3f0850f5f3ee Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 6 Feb 2019 21:05:45 +0800 Subject: [PATCH 1/2] use native golang SSH library but ssh-keygen when enable built-in SSH server to remove dependent on that command lines --- .../git_helper_for_declarative_test.go | 4 +- modules/ssh/ssh.go | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/integrations/git_helper_for_declarative_test.go b/integrations/git_helper_for_declarative_test.go index 572abe95a22f7..60c7c29f68148 100644 --- a/integrations/git_helper_for_declarative_test.go +++ b/integrations/git_helper_for_declarative_test.go @@ -12,20 +12,20 @@ import ( "net/http" "net/url" "os" - "os/exec" "path/filepath" "testing" "time" "code.gitea.io/git" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/ssh" "github.com/Unknwon/com" "github.com/stretchr/testify/assert" ) func withKeyFile(t *testing.T, keyname string, callback func(string)) { keyFile := filepath.Join(setting.AppDataPath, keyname) - err := exec.Command("ssh-keygen", "-f", keyFile, "-t", "rsa", "-N", "").Run() + err := ssh.GenKeyPair(keyFile) assert.NoError(t, err) //Setup ssh wrapper diff --git a/modules/ssh/ssh.go b/modules/ssh/ssh.go index 9b9c21278e5a2..ae367cf700d9c 100644 --- a/modules/ssh/ssh.go +++ b/modules/ssh/ssh.go @@ -5,6 +5,10 @@ package ssh import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" "io" "io/ioutil" "net" @@ -176,9 +180,9 @@ func Listen(host string, port int, ciphers []string, keyExchanges []string, macs log.Error(4, "Failed to create dir %s: %v", filePath, err) } - _, stderr, err := com.ExecCmd("ssh-keygen", "-f", keyPath, "-t", "rsa", "-N", "") + err := GenKeyPair(keyPath) if err != nil { - log.Fatal(4, "Failed to generate private key: %v - %s", err, stderr) + log.Fatal(4, "Failed to generate private key: %v", err) } log.Trace("SSH: New private key is generateed: %s", keyPath) } @@ -195,3 +199,39 @@ func Listen(host string, port int, ciphers []string, keyExchanges []string, macs go listen(config, host, port) } + +// GenKeyPair make a pair of public and private keys for SSH access. +// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file. +// Private Key generated is PEM encoded +func GenKeyPair(keyPath string) error { + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return err + } + + privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} + f, err := os.Create(keyPath) + if err != nil { + return err + } + defer f.Close() + + if err := pem.Encode(f, privateKeyPEM); err != nil { + return err + } + + // generate public key + pub, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + return err + } + + public := ssh.MarshalAuthorizedKey(pub) + p, err := os.Create(keyPath + ".pub") + if err != nil { + return err + } + defer p.Close() + _, err = p.Write(public) + return err +} From 079c2c59608310a73d7efafe2919500dcbe87353 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 7 Feb 2019 09:32:56 +0800 Subject: [PATCH 2/2] fix tests and add comment head --- modules/ssh/ssh.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/ssh/ssh.go b/modules/ssh/ssh.go index ae367cf700d9c..d9606488b21b1 100644 --- a/modules/ssh/ssh.go +++ b/modules/ssh/ssh.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2017 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -210,7 +211,7 @@ func GenKeyPair(keyPath string) error { } privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} - f, err := os.Create(keyPath) + f, err := os.OpenFile(keyPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } @@ -227,7 +228,7 @@ func GenKeyPair(keyPath string) error { } public := ssh.MarshalAuthorizedKey(pub) - p, err := os.Create(keyPath + ".pub") + p, err := os.OpenFile(keyPath+".pub", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err }