diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 0543c85d50..88297fe0d9 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -186,8 +186,8 @@ RUN_MODE = ; prod ;; default is the system temporary directory. ;SSH_KEY_TEST_PATH = ;; -;; Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call. -;SSH_KEYGEN_PATH = ssh-keygen +;; Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself. +;SSH_KEYGEN_PATH = ;; ;; Enable SSH Authorized Key Backup when rewriting all keys, default is true ;SSH_AUTHORIZED_KEYS_BACKUP = true diff --git a/docs/content/doc/administration/config-cheat-sheet.en-us.md b/docs/content/doc/administration/config-cheat-sheet.en-us.md index f976458f29..76952df40e 100644 --- a/docs/content/doc/administration/config-cheat-sheet.en-us.md +++ b/docs/content/doc/administration/config-cheat-sheet.en-us.md @@ -345,7 +345,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `SSH_SERVER_MACS`: **hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect - `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gogs.rsa**: For the built-in SSH server, choose the keypairs to offer as the host key. The private key should be at `SSH_SERVER_HOST_KEY` and the public `SSH_SERVER_HOST_KEY.pub`. Relative paths are made absolute relative to the `APP_DATA_PATH`. If no key exists a 4096 bit RSA key will be created for you. - `SSH_KEY_TEST_PATH`: **/tmp**: Directory to create temporary files in when testing public keys using ssh-keygen, default is the system temporary directory. -- `SSH_KEYGEN_PATH`: **ssh-keygen**: Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call. +- `SSH_KEYGEN_PATH`: **\**: Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself. - `SSH_EXPOSE_ANONYMOUS`: **false**: Enable exposure of SSH clone URL to anonymous visitors, default is false. - `SSH_PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the SSH connections. (Set to -1 to disable all timeouts.) diff --git a/models/asymkey/ssh_key_parse.go b/models/asymkey/ssh_key_parse.go index 7e61e61dae..94b1cf112b 100644 --- a/models/asymkey/ssh_key_parse.go +++ b/models/asymkey/ssh_key_parse.go @@ -179,7 +179,7 @@ func CheckPublicKeyString(content string) (_ string, err error) { keyType string length int ) - if setting.SSH.StartBuiltinServer { + if len(setting.SSH.KeygenPath) == 0 { fnName = "SSHNativeParsePublicKey" keyType, length, err = SSHNativeParsePublicKey(content) } else { @@ -285,7 +285,12 @@ func SSHKeyGenParsePublicKey(key string) (string, int, error) { } }() - stdout, stderr, err := process.GetManager().Exec("SSHKeyGenParsePublicKey", setting.SSH.KeygenPath, "-lf", tmpName) + keygenPath := setting.SSH.KeygenPath + if len(keygenPath) == 0 { + keygenPath = "ssh-keygen" + } + + stdout, stderr, err := process.GetManager().Exec("SSHKeyGenParsePublicKey", keygenPath, "-lf", tmpName) if err != nil { return "", 0, fmt.Errorf("fail to parse public key: %s - %s", err, stderr) } diff --git a/models/asymkey/ssh_key_test.go b/models/asymkey/ssh_key_test.go index afd79ae6de..5378ef66ba 100644 --- a/models/asymkey/ssh_key_test.go +++ b/models/asymkey/ssh_key_test.go @@ -57,6 +57,14 @@ func Test_SSHParsePublicKey(t *testing.T) { assert.Equal(t, tc.keyType, keyTypeK) assert.EqualValues(t, tc.length, lengthK) }) + t.Run("SSHParseKeyNative", func(t *testing.T) { + keyTypeK, lengthK, err := SSHNativeParsePublicKey(tc.content) + if err != nil { + assert.Fail(t, "%v", err) + } + assert.Equal(t, tc.keyType, keyTypeK) + assert.EqualValues(t, tc.length, lengthK) + }) }) } } diff --git a/modules/setting/ssh.go b/modules/setting/ssh.go index e8796f98d6..a5a9da0b36 100644 --- a/modules/setting/ssh.go +++ b/modules/setting/ssh.go @@ -58,7 +58,7 @@ var SSH = struct { ServerCiphers: []string{"chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"}, ServerKeyExchanges: []string{"curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"}, ServerMACs: []string{"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1"}, - KeygenPath: "ssh-keygen", + KeygenPath: "", MinimumKeySizeCheck: true, MinimumKeySizes: map[string]int{"ed25519": 256, "ed25519-sk": 256, "ecdsa": 256, "ecdsa-sk": 256, "rsa": 2047}, ServerHostKeys: []string{"ssh/gitea.rsa", "ssh/gogs.rsa"}, @@ -134,7 +134,7 @@ func loadSSHFrom(rootCfg ConfigProvider) { } } - SSH.KeygenPath = sec.Key("SSH_KEYGEN_PATH").MustString("ssh-keygen") + SSH.KeygenPath = sec.Key("SSH_KEYGEN_PATH").String() SSH.Port = sec.Key("SSH_PORT").MustInt(22) SSH.ListenPort = sec.Key("SSH_LISTEN_PORT").MustInt(SSH.Port) SSH.UseProxyProtocol = sec.Key("SSH_SERVER_USE_PROXY_PROTOCOL").MustBool(false)