Commit b5f9d29f55e1fbf302bd824e2d08c0885caa15d7

Authored by Valeriy Sizov
2 parents 4cbfe942 7284c58c

Merge pull request #1617 from dosire/reject-ssh-keys-that-break-gitolite

Reject ssh keys that break gitolite
app/models/key.rb
@@ -14,7 +14,7 @@ class Key < ActiveRecord::Base @@ -14,7 +14,7 @@ class Key < ActiveRecord::Base
14 before_save :set_identifier 14 before_save :set_identifier
15 before_validation :strip_white_space 15 before_validation :strip_white_space
16 delegate :name, :email, to: :user, prefix: true 16 delegate :name, :email, to: :user, prefix: true
17 - validate :unique_key 17 + validate :unique_key, :fingerprintable_key
18 18
19 def strip_white_space 19 def strip_white_space
20 self.key = self.key.strip unless self.key.blank? 20 self.key = self.key.strip unless self.key.blank?
@@ -28,6 +28,21 @@ class Key < ActiveRecord::Base @@ -28,6 +28,21 @@ class Key < ActiveRecord::Base
28 end 28 end
29 end 29 end
30 30
  31 + def fingerprintable_key
  32 + return true unless key # Don't test if there is no key.
  33 + # `ssh-keygen -lf /dev/stdin <<< "#{key}"` errors with: redirection unexpected
  34 + file = Tempfile.new('key_file')
  35 + begin
  36 + file.puts key
  37 + file.rewind
  38 + fingerprint_output = `ssh-keygen -lf #{file.path} 2>&1` # Catch stderr.
  39 + ensure
  40 + file.close
  41 + file.unlink # deletes the temp file
  42 + end
  43 + errors.add(:key, "can't be fingerprinted") if fingerprint_output.match("failed")
  44 + end
  45 +
31 def set_identifier 46 def set_identifier
32 if is_deploy_key 47 if is_deploy_key
33 self.identifier = "deploy_#{Digest::MD5.hexdigest(key)}" 48 self.identifier = "deploy_#{Digest::MD5.hexdigest(key)}"
features/steps/profile/profile_ssh_keys.rb
@@ -13,7 +13,7 @@ class ProfileSshKeys &lt; Spinach::FeatureSteps @@ -13,7 +13,7 @@ class ProfileSshKeys &lt; Spinach::FeatureSteps
13 13
14 And 'I submit new ssh key "Laptop"' do 14 And 'I submit new ssh key "Laptop"' do
15 fill_in "key_title", :with => "Laptop" 15 fill_in "key_title", :with => "Laptop"
16 - fill_in "key_key", :with => "ssh-rsa publickey234=" 16 + fill_in "key_key", :with => "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzrEJUIR6Y03TCE9rIJ+GqTBvgb8t1jI9h5UBzCLuK4VawOmkLornPqLDrGbm6tcwM/wBrrLvVOqi2HwmkKEIecVO0a64A4rIYScVsXIniHRS6w5twyn1MD3sIbN+socBDcaldECQa2u1dI3tnNVcs8wi77fiRe7RSxePsJceGoheRQgC8AZ510UdIlO+9rjIHUdVN7LLyz512auAfYsgx1OfablkQ/XJcdEwDNgi9imI6nAXhmoKUm1IPLT2yKajTIC64AjLOnE0YyCh6+7RFMpiMyu1qiOCpdjYwTgBRiciNRZCH8xIedyCoAmiUgkUT40XYHwLuwiPJICpkAzp7Q== user@laptop"
17 click_button "Save" 17 click_button "Save"
18 end 18 end
19 19
spec/factories.rb
@@ -89,11 +89,7 @@ FactoryGirl.define do @@ -89,11 +89,7 @@ FactoryGirl.define do
89 factory :key do 89 factory :key do
90 title 90 title
91 key do 91 key do
92 - """  
93 - ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4  
94 - 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4  
95 - soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=  
96 - """ 92 + "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
97 end 93 end
98 94
99 factory :deploy_key do 95 factory :deploy_key do
@@ -103,6 +99,12 @@ FactoryGirl.define do @@ -103,6 +99,12 @@ FactoryGirl.define do
103 factory :personal_key do 99 factory :personal_key do
104 user 100 user
105 end 101 end
  102 +
  103 + factory :key_with_a_space_in_the_middle do
  104 + key do
  105 + "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa ++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
  106 + end
  107 + end
106 end 108 end
107 109
108 factory :milestone do 110 factory :milestone do
spec/factories_spec.rb
1 require 'spec_helper' 1 require 'spec_helper'
2 2
3 FactoryGirl.factories.map(&:name).each do |factory_name| 3 FactoryGirl.factories.map(&:name).each do |factory_name|
  4 + next if :key_with_a_space_in_the_middle == factory_name
4 describe "#{factory_name} factory" do 5 describe "#{factory_name} factory" do
5 it 'should be valid' do 6 it 'should be valid' do
6 build(factory_name).should be_valid 7 build(factory_name).should be_valid
spec/models/key_spec.rb
@@ -51,4 +51,16 @@ describe Key do @@ -51,4 +51,16 @@ describe Key do
51 end 51 end
52 end 52 end
53 end 53 end
  54 +
  55 + context "validate it is a fingerprintable key" do
  56 + let(:user) { Factory.create(:user) }
  57 +
  58 + it "accepts the fingerprintable key" do
  59 + build(:key, user: user).should be_valid
  60 + end
  61 +
  62 + it "rejects the unfingerprintable key" do
  63 + build(:key_with_a_space_in_the_middle).should_not be_valid
  64 + end
  65 + end
54 end 66 end
spec/requests/projects_deploy_keys_spec.rb
@@ -42,7 +42,7 @@ describe &quot;Projects&quot;, &quot;DeployKeys&quot; do @@ -42,7 +42,7 @@ describe &quot;Projects&quot;, &quot;DeployKeys&quot; do
42 describe "fill in" do 42 describe "fill in" do
43 before do 43 before do
44 fill_in "key_title", with: "laptop" 44 fill_in "key_title", with: "laptop"
45 - fill_in "key_key", with: "ssh-rsa publickey234=" 45 + fill_in "key_key", with: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzrEJUIR6Y03TCE9rIJ+GqTBvgb8t1jI9h5UBzCLuK4VawOmkLornPqLDrGbm6tcwM/wBrrLvVOqi2HwmkKEIecVO0a64A4rIYScVsXIniHRS6w5twyn1MD3sIbN+socBDcaldECQa2u1dI3tnNVcs8wi77fiRe7RSxePsJceGoheRQgC8AZ510UdIlO+9rjIHUdVN7LLyz512auAfYsgx1OfablkQ/XJcdEwDNgi9imI6nAXhmoKUm1IPLT2yKajTIC64AjLOnE0YyCh6+7RFMpiMyu1qiOCpdjYwTgBRiciNRZCH8xIedyCoAmiUgkUT40XYHwLuwiPJICpkAzp7Q== user@laptop"
46 end 46 end
47 47
48 it { expect { click_button "Save" }.to change {Key.count}.by(1) } 48 it { expect { click_button "Save" }.to change {Key.count}.by(1) }