From 744972ec8c9b1c445e5fc013762bda05337f5c3d Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Wed, 5 Jun 2019 07:33:10 +0200 Subject: [PATCH 1/5] Use go method to calculate key fingerprint --- models/ssh_key.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/models/ssh_key.go b/models/ssh_key.go index fb5f9f399b757..c1188baea5167 100644 --- a/models/ssh_key.go +++ b/models/ssh_key.go @@ -361,18 +361,11 @@ func checkKeyFingerprint(e Engine, fingerprint string) error { func calcFingerprint(publicKeyContent string) (string, error) { // Calculate fingerprint. - tmpPath, err := writeTmpKeyFile(publicKeyContent) + pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKeyContent)) if err != nil { return "", err } - defer os.Remove(tmpPath) - stdout, stderr, err := process.GetManager().Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath) - if err != nil { - return "", fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr) - } else if len(stdout) < 2 { - return "", errors.New("not enough output for calculating fingerprint: " + stdout) - } - return strings.Split(stdout, " ")[1], nil + return ssh.FingerprintSHA256(pk), nil } func addKey(e Engine, key *PublicKey) (err error) { From 9eebeb17775d539588d3ae5b4d392b705fae092e Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Sun, 16 Jun 2019 01:02:26 +0200 Subject: [PATCH 2/5] add gitea copyright --- models/ssh_key.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models/ssh_key.go b/models/ssh_key.go index c1188baea5167..39fb9e1ec028d 100644 --- a/models/ssh_key.go +++ b/models/ssh_key.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2019 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. From 22d944ab1260701358e14c3033586afeba54a344 Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Sun, 16 Jun 2019 02:11:59 +0200 Subject: [PATCH 3/5] use native go method only for built-in server --- models/ssh_key.go | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/models/ssh_key.go b/models/ssh_key.go index 39fb9e1ec028d..530f9df32ad0a 100644 --- a/models/ssh_key.go +++ b/models/ssh_key.go @@ -360,7 +360,23 @@ func checkKeyFingerprint(e Engine, fingerprint string) error { return nil } -func calcFingerprint(publicKeyContent string) (string, error) { +func calcFingerprintSSHKeygen(publicKeyContent string) (string, error) { + // Calculate fingerprint. + tmpPath, err := writeTmpKeyFile(publicKeyContent) + if err != nil { + return "", err + } + defer os.Remove(tmpPath) + stdout, stderr, err := process.GetManager().Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath) + if err != nil { + return "", fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr) + } else if len(stdout) < 2 { + return "", errors.New("not enough output for calculating fingerprint: " + stdout) + } + return strings.Split(stdout, " ")[1], nil +} + +func calcFingerprintNative(publicKeyContent string) (string, error) { // Calculate fingerprint. pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKeyContent)) if err != nil { @@ -369,6 +385,25 @@ func calcFingerprint(publicKeyContent string) (string, error) { return ssh.FingerprintSHA256(pk), nil } +func calcFingerprint(publicKeyContent string) (string, error) { + //Call the method based on configuration + var ( + fnName, fp string + err error + ) + if setting.SSH.StartBuiltinServer { + fnName = "calcFingerprintNative" + fp, err = calcFingerprintNative(publicKeyContent) + } else { + fnName = "calcFingerprintSSHKeygen" + fp, err = calcFingerprintSSHKeygen(publicKeyContent) + } + if err != nil { + return "", fmt.Errorf("%s: %v", fnName, err) + } + return fp, nil +} + func addKey(e Engine, key *PublicKey) (err error) { if len(key.Fingerprint) == 0 { key.Fingerprint, err = calcFingerprint(key.Content) From 332751e15faedc5f5e6acfb35c00047f53905d1e Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Sun, 16 Jun 2019 02:30:08 +0200 Subject: [PATCH 4/5] refactor and add tests --- models/ssh_key_test.go | 81 +++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/models/ssh_key_test.go b/models/ssh_key_test.go index 82f5f9724bcdb..ae4e7313ad720 100644 --- a/models/ssh_key_test.go +++ b/models/ssh_key_test.go @@ -19,26 +19,67 @@ func init() { } func Test_SSHParsePublicKey(t *testing.T) { - test := func(name, keyType string, length int, content string) { - keyTypeN, lengthN, err := SSHNativeParsePublicKey(content) - assert.NoError(t, err) - assert.Equal(t, keyType, keyTypeN) - assert.EqualValues(t, length, lengthN) - - keyTypeK, lengthK, err := SSHKeyGenParsePublicKey(content) - if err != nil { - // Some servers do not support ecdsa format. - if !strings.Contains(err.Error(), "line 1 too long:") { - assert.Fail(t, "%v", err) - } - } - assert.Equal(t, keyType, keyTypeK) - assert.EqualValues(t, length, lengthK) + testCases := []struct { + name string + keyType string + length int + content string + }{ + {"dsa-1024", "dsa", 1024, "ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment"}, + {"rsa-1024", "rsa", 1024, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"}, + {"rsa-2048", "rsa", 2048, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment"}, + {"ecdsa-256", "ecdsa", 256, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment"}, + {"ecdsa-384", "ecdsa", 384, "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBINmioV+XRX1Fm9Qk2ehHXJ2tfVxW30ypUWZw670Zyq5GQfBAH6xjygRsJ5wWsHXBsGYgFUXIHvMKVAG1tpw7s6ax9oA+dJOJ7tj+vhn8joFqT+sg3LYHgZkHrfqryRasQ== nocomment"}, } - test("dsa-1024", "dsa", 1024, "ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment") - test("rsa-1024", "rsa", 1024, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n") - test("rsa-2048", "rsa", 2048, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment") - test("ecdsa-256", "ecdsa", 256, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment") - test("ecdsa-384", "ecdsa", 384, "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBINmioV+XRX1Fm9Qk2ehHXJ2tfVxW30ypUWZw670Zyq5GQfBAH6xjygRsJ5wWsHXBsGYgFUXIHvMKVAG1tpw7s6ax9oA+dJOJ7tj+vhn8joFqT+sg3LYHgZkHrfqryRasQ== nocomment") + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Run("Native", func(t *testing.T) { + keyTypeN, lengthN, err := SSHNativeParsePublicKey(tc.content) + assert.NoError(t, err) + assert.Equal(t, tc.keyType, keyTypeN) + assert.EqualValues(t, tc.length, lengthN) + }) + t.Run("SSHKeygen", func(t *testing.T) { + keyTypeK, lengthK, err := SSHKeyGenParsePublicKey(tc.content) + if err != nil { + // Some servers do not support ecdsa format. + if !strings.Contains(err.Error(), "line 1 too long:") { + assert.Fail(t, "%v", err) + } + } + assert.Equal(t, tc.keyType, keyTypeK) + assert.EqualValues(t, tc.length, lengthK) + }) + }) + } +} + +func Test_calcFingerprint(t *testing.T) { + testCases := []struct { + name string + fp string + content string + }{ + {"dsa-1024", "SHA256:fSIHQlpKMDsGPVAXI8BPYfRp+e2sfvSt1sMrPsFiXrc", "ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment"}, + {"rsa-1024", "SHA256:vSnDkvRh/xM6kMxPidLgrUhq3mCN7CDaronCEm2joyQ", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"}, + {"rsa-2048", "SHA256:ZHD//a1b9VuTq9XSunAeYjKeU1xDa2tBFZYrFr2Okkg", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment"}, + {"ecdsa-256", "SHA256:Bqx/xgWqRKLtkZ0Lr4iZpgb+5lYsFpSwXwVZbPwuTRw", "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment"}, + {"ecdsa-384", "SHA256:4qfJOgJDtUd8BrEjyVNdI8IgjiZKouztVde43aDhe1E", "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBINmioV+XRX1Fm9Qk2ehHXJ2tfVxW30ypUWZw670Zyq5GQfBAH6xjygRsJ5wWsHXBsGYgFUXIHvMKVAG1tpw7s6ax9oA+dJOJ7tj+vhn8joFqT+sg3LYHgZkHrfqryRasQ== nocomment"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Run("Native", func(t *testing.T) { + fpN, err := calcFingerprintNative(tc.content) + assert.NoError(t, err) + assert.Equal(t, tc.fp, fpN) + }) + t.Run("SSHKeygen", func(t *testing.T) { + fpK, err := calcFingerprintSSHKeygen(tc.content) + assert.NoError(t, err) + assert.Equal(t, tc.fp, fpK) + }) + }) + } } From 733485244e6529d240d62e8df2759f12e889eb72 Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Sun, 16 Jun 2019 02:32:41 +0200 Subject: [PATCH 5/5] add gitea copyright --- models/ssh_key_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models/ssh_key_test.go b/models/ssh_key_test.go index ae4e7313ad720..5d095f6378e86 100644 --- a/models/ssh_key_test.go +++ b/models/ssh_key_test.go @@ -1,4 +1,5 @@ // Copyright 2016 The Gogs Authors. All rights reserved. +// Copyright 2019 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.