Revert "Add support for ecdsa keys"
[gitorious:mainline.git] / app / validators / ssh_key_validator.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2013 Gitorious AS
4 #
5 #   This program is free software: you can redistribute it and/or modify
6 #   it under the terms of the GNU Affero General Public License as published by
7 #   the Free Software Foundation, either version 3 of the License, or
8 #   (at your option) any later version.
9 #
10 #   This program is distributed in the hope that it will be useful,
11 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #   GNU Affero General Public License for more details.
14 #
15 #   You should have received a copy of the GNU Affero General Public License
16 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #++
18 require "use_case"
19 require "tempfile"
20
21 SshKeyValidator = UseCase::Validator.define do
22   KEY_FORMAT = /^ssh\-[a-z0-9]{3,4} [a-z0-9\+=\/]+ .*$/ims.freeze
23   PRIVATE_KEY_FORMAT = /^-+.*PRIVATE.*-+$/ims.freeze
24
25   validate :valid_ssh_key
26   validates_presence_of :user_id, :key
27
28   def self.model_name
29     SshKey.model_name
30   end
31
32   def valid_ssh_key
33     if key =~ PRIVATE_KEY_FORMAT
34       errors.add(:key, I18n.t("ssh_key.private_key_validation_message")) and return
35     end
36
37     if key !~ KEY_FORMAT
38       invalid_format! and return
39     end
40
41     if !uniq?
42       errors.add(:key, I18n.t("ssh_key.unique_key_validation_message")) and return
43     end
44
45     # Only perform expensive check if otherwise valid
46     if errors.count == 0 && !valid_key_using_ssh_keygen?
47       errors.add(:key, "is not recognized as a valid public key")
48     end
49   rescue Encoding::CompatibilityError
50     invalid_format! and return
51   end
52
53   def valid_key_using_ssh_keygen?
54     temp_key = Tempfile.new("ssh_key_#{Time.now.to_i}")
55     temp_key.write(self.key)
56     temp_key.close
57     system("ssh-keygen -l -f #{temp_key.path} > /dev/null")
58     temp_key.delete
59     return $?.success?
60   end
61
62   def invalid_format!
63     errors.add(:key, I18n.t("ssh_key.key_format_validation_message"))
64   end
65 end