From 455a4fe91a32d0ab2de72d1e62a7a6edfcb40d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1o=20Stanovnik?= Date: Tue, 24 Mar 2015 00:11:41 +0100 Subject: Fixed generating SSH key fingerprints in OpenSSH 6.8. --- app/models/key.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/app/models/key.rb b/app/models/key.rb index e2e59296eed..b74daf50fec 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -86,7 +86,24 @@ class Key < ActiveRecord::Base Tempfile.open('gitlab_key_file') do |file| file.puts key file.rewind - cmd_output, cmd_status = popen(%W(ssh-keygen -lf #{file.path}), '/tmp') + + # OpenSSH 6.8 introduces a new default output format for fingerprints. + # Check the version and decide which command to use. + version_output, version_status = popen(%W(ssh -V)) + explicit_fingerprint_algorithm = false + if version_status.zero? + out, _ = version_output.scan /.*?(\d)\.(\d).*?,/ + major, minor = out[0], out[1] + if major.to_i > 6 or (major.to_i == 6 and minor.to_i >= 8) + explicit_fingerprint_algorithm = true + end + end + + if explicit_fingerprint_algorithm + cmd_output, cmd_status = popen(%W(ssh-keygen -E md5 -lf #{file.path}), '/tmp') + else + cmd_output, cmd_status = popen(%W(ssh-keygen -lf #{file.path}), '/tmp') + end end if cmd_status.zero? -- cgit v1.2.1 From 05d4658b3233b3f37876772c10fbf5e648682154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1o=20Stanovnik?= Date: Tue, 24 Mar 2015 00:49:30 +0100 Subject: Use 2 spaces for indentation, not 4. --- app/models/key.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/key.rb b/app/models/key.rb index b74daf50fec..1c41f8b8d7a 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -95,7 +95,7 @@ class Key < ActiveRecord::Base out, _ = version_output.scan /.*?(\d)\.(\d).*?,/ major, minor = out[0], out[1] if major.to_i > 6 or (major.to_i == 6 and minor.to_i >= 8) - explicit_fingerprint_algorithm = true + explicit_fingerprint_algorithm = true end end -- cgit v1.2.1 From 38384bd9521a42683d9ba33ac482993496c6f986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1o=20Stanovnik?= Date: Tue, 24 Mar 2015 10:55:31 +0100 Subject: The new fingerprint format wis incompatible with the previous regex. --- app/models/key.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/models/key.rb b/app/models/key.rb index 1c41f8b8d7a..480a16f9335 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -83,14 +83,14 @@ class Key < ActiveRecord::Base cmd_status = 0 cmd_output = '' + explicit_fingerprint_algorithm = false Tempfile.open('gitlab_key_file') do |file| file.puts key file.rewind - + # OpenSSH 6.8 introduces a new default output format for fingerprints. # Check the version and decide which command to use. version_output, version_status = popen(%W(ssh -V)) - explicit_fingerprint_algorithm = false if version_status.zero? out, _ = version_output.scan /.*?(\d)\.(\d).*?,/ major, minor = out[0], out[1] @@ -107,8 +107,15 @@ class Key < ActiveRecord::Base end if cmd_status.zero? - cmd_output.gsub /(\h{2}:)+\h{2}/ do |match| - self.fingerprint = match + if explicit_fingerprint_algorithm + cmd_output.gsub /(MD5:)(\h{2}:)+\h{2}/ do |match| + match.slice! /^MD5:/ + self.fingerprint = match + end + else + cmd_output.gsub /(\h{2}:)+\h{2}/ do |match| + self.fingerprint = match + end end end end -- cgit v1.2.1 From e245547ea1c7a5c6e85cbbd4c634c3d11b80036e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 14 Apr 2015 12:00:29 +0200 Subject: Add changelog entry. --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 25936eb1e1d..aaf01e009cc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.10.0 (unreleased) + - Fix generating SSH key fingerprints with OpenSSH 6.8. (Sašo Stanovnik) - Include missing events and fix save functionality in admin service template settings form (Stan Hu) - Fix "Import projects from" button to show the correct instructions (Stan Hu) - Fix dots in Wiki slugs causing errors (Stan Hu) -- cgit v1.2.1 From 1221bec56ca7d3bf1ba3b09e7a283ff5c11449f2 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 14 Apr 2015 12:00:43 +0200 Subject: Refactor key fingerprint generation. --- app/models/key.rb | 44 +++----------------------- lib/gitlab/key_fingerprint.rb | 55 +++++++++++++++++++++++++++++++++ spec/lib/gitlab/key_fingerprint_spec.rb | 12 +++++++ 3 files changed, 71 insertions(+), 40 deletions(-) create mode 100644 lib/gitlab/key_fingerprint.rb create mode 100644 spec/lib/gitlab/key_fingerprint_spec.rb diff --git a/app/models/key.rb b/app/models/key.rb index 480a16f9335..016eee86992 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -16,7 +16,6 @@ require 'digest/md5' class Key < ActiveRecord::Base include Sortable - include Gitlab::Popen belongs_to :user @@ -79,44 +78,9 @@ class Key < ActiveRecord::Base def generate_fingerprint self.fingerprint = nil - return unless key.present? - - cmd_status = 0 - cmd_output = '' - explicit_fingerprint_algorithm = false - Tempfile.open('gitlab_key_file') do |file| - file.puts key - file.rewind - - # OpenSSH 6.8 introduces a new default output format for fingerprints. - # Check the version and decide which command to use. - version_output, version_status = popen(%W(ssh -V)) - if version_status.zero? - out, _ = version_output.scan /.*?(\d)\.(\d).*?,/ - major, minor = out[0], out[1] - if major.to_i > 6 or (major.to_i == 6 and minor.to_i >= 8) - explicit_fingerprint_algorithm = true - end - end - - if explicit_fingerprint_algorithm - cmd_output, cmd_status = popen(%W(ssh-keygen -E md5 -lf #{file.path}), '/tmp') - else - cmd_output, cmd_status = popen(%W(ssh-keygen -lf #{file.path}), '/tmp') - end - end - - if cmd_status.zero? - if explicit_fingerprint_algorithm - cmd_output.gsub /(MD5:)(\h{2}:)+\h{2}/ do |match| - match.slice! /^MD5:/ - self.fingerprint = match - end - else - cmd_output.gsub /(\h{2}:)+\h{2}/ do |match| - self.fingerprint = match - end - end - end + + return unless self.key.present? + + self.fingerprint = Gitlab::KeyFingerprint.new(self.key).fingerprint end end diff --git a/lib/gitlab/key_fingerprint.rb b/lib/gitlab/key_fingerprint.rb new file mode 100644 index 00000000000..550b10a4c94 --- /dev/null +++ b/lib/gitlab/key_fingerprint.rb @@ -0,0 +1,55 @@ +module Gitlab + class KeyFingerprint + include Gitlab::Popen + + attr_accessor :key + + def initialize(key) + @key = key + end + + def fingerprint + cmd_status = 0 + cmd_output = '' + + Tempfile.open('gitlab_key_file') do |file| + file.puts key + file.rewind + + cmd = [] + cmd.push *%W(ssh-keygen) + cmd.push *%W(-E md5) if explicit_fingerprint_algorithm? + cmd.push *%W(-lf #{file.path}) + + cmd_output, cmd_status = popen(cmd, '/tmp') + end + + return nil unless cmd_status.zero? + + # 16 hex bytes separated by ':', optionally starting with "MD5:" + fingerprint_match = cmd_output.match(/(MD5:)?(?(?:\h{2}:){15}\h{2})/) + return nil unless fingerprint_match + + fingerprint_match[:fingerprint] + end + + private + + def explicit_fingerprint_algorithm? + # OpenSSH 6.8 introduces a new default output format for fingerprints. + # Check the version and decide which command to use. + + version_output, version_status = popen(%W(ssh -V)) + return false unless version_status.zero? + + version_matches = version_output.match(/OpenSSH_(?\d+)\.(?\d+)/) + return false unless version_matches + + version_info = Gitlab::VersionInfo.new(version_matches[:major].to_i, version_matches[:minor].to_i) + + required_version_info = Gitlab::VersionInfo.new(6, 8) + + version_info >= required_version_info + end + end +end diff --git a/spec/lib/gitlab/key_fingerprint_spec.rb b/spec/lib/gitlab/key_fingerprint_spec.rb new file mode 100644 index 00000000000..266eab6e793 --- /dev/null +++ b/spec/lib/gitlab/key_fingerprint_spec.rb @@ -0,0 +1,12 @@ +require "spec_helper" + +describe Gitlab::KeyFingerprint do + let(:key) { "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" } + let(:fingerprint) { "3f:a2:ee:de:b5:de:53:c3:aa:2f:9c:45:24:4c:47:7b" } + + describe "#fingerprint" do + it "generates the key's fingerprint" do + expect(Gitlab::KeyFingerprint.new(key).fingerprint).to eq(fingerprint) + end + end +end -- cgit v1.2.1 From 076494646d30cefd396e0d6a0ae879a31aecb454 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 14 Apr 2015 15:58:16 +0200 Subject: Simplify regex. --- lib/gitlab/key_fingerprint.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/key_fingerprint.rb b/lib/gitlab/key_fingerprint.rb index 550b10a4c94..baf52ff750d 100644 --- a/lib/gitlab/key_fingerprint.rb +++ b/lib/gitlab/key_fingerprint.rb @@ -27,10 +27,10 @@ module Gitlab return nil unless cmd_status.zero? # 16 hex bytes separated by ':', optionally starting with "MD5:" - fingerprint_match = cmd_output.match(/(MD5:)?(?(?:\h{2}:){15}\h{2})/) - return nil unless fingerprint_match + fingerprint_matches = cmd_output.match(/(MD5:)?(?(\h{2}:){15}\h{2})/) + return nil unless fingerprint_matches - fingerprint_match[:fingerprint] + fingerprint_matches[:fingerprint] end private -- cgit v1.2.1