Object
This class encapsulates all operations done by clients on a user’s private keys. In practice, the client should never need a reference to a private key; instead, they grab a list of “identities” (public keys) that are available from the KeyManager, and then use the KeyManager to do various private key operations using those identities.
The KeyManager also uses the Agent class to encapsulate the ssh-agent. Thus, from a client’s perspective it is completely hidden whether an identity comes from the ssh-agent or from a file on disk.
Create a new KeyManager. By default, the manager will use the ssh-agent (if it is running).
# File lib/net/ssh/authentication/key_manager.rb, line 41 41: def initialize(logger, options={}) 42: self.logger = logger 43: @key_files = [] 44: @key_data = [] 45: @use_agent = true 46: @known_identities = {} 47: @agent = nil 48: @options = options 49: end
Add the given key_file to the list of key files that will be used.
# File lib/net/ssh/authentication/key_manager.rb, line 63 63: def add(key_file) 64: key_files.push(File.expand_path(key_file)).uniq! 65: self 66: end
Add the given key_file to the list of keys that will be used.
# File lib/net/ssh/authentication/key_manager.rb, line 69 69: def add_key_data(key_data_) 70: key_data.push(key_data_).uniq! 71: self 72: end
Returns an Agent instance to use for communicating with an SSH agent process. Returns nil if use of an SSH agent has been disabled, or if the agent is otherwise not available.
# File lib/net/ssh/authentication/key_manager.rb, line 176 176: def agent 177: return unless use_agent? 178: @agent ||= Agent.connect(logger) 179: rescue AgentNotAvailable 180: @use_agent = false 181: nil 182: end
Clear all knowledge of any loaded user keys. This also clears the list of default identity files that are to be loaded, thus making it appropriate to use if a client wishes to NOT use the default identity files.
# File lib/net/ssh/authentication/key_manager.rb, line 55 55: def clear! 56: key_files.clear 57: key_data.clear 58: known_identities.clear 59: self 60: end
Iterates over all available identities (public keys) known to this manager. As it finds one, it will then yield it to the caller. The origin of the identities may be from files on disk or from an ssh-agent. Note that identities from an ssh-agent are always listed first in the array, with other identities coming after.
If key manager was created with :keys_only option, any identity from ssh-agent will be ignored unless it present in key_files or key_data.
# File lib/net/ssh/authentication/key_manager.rb, line 97 97: def each_identity 98: prepared_identities = prepare_identities_from_files + prepare_identities_from_data 99: 100: user_identities = load_identities(prepared_identities, false) 101: 102: if agent 103: agent.identities.each do |key| 104: corresponding_user_identity = user_identities.detect { |identity| 105: identity[:public_key] && identity[:public_key].to_pem == key.to_pem 106: } 107: user_identities.delete(corresponding_user_identity) if corresponding_user_identity 108: 109: if !options[:keys_only] || corresponding_user_identity 110: known_identities[key] = { :from => :agent } 111: yield key 112: end 113: end 114: end 115: 116: user_identities = load_identities(user_identities, true) 117: 118: user_identities.each do |identity| 119: key = identity.delete(:public_key) 120: known_identities[key] = identity 121: yield key 122: end 123: 124: self 125: end
This is used as a hint to the KeyManager indicating that the agent connection is no longer needed. Any other open resources may be closed at this time.
Calling this does NOT indicate that the KeyManager will no longer be used. Identities may still be requested and operations done on loaded identities, in which case, the agent will be automatically reconnected. This method simply allows the client connection to be closed when it will not be used in the immediate future.
# File lib/net/ssh/authentication/key_manager.rb, line 83 83: def finish 84: @agent.close if @agent 85: @agent = nil 86: end
Sign the given data, using the corresponding private key of the given identity. If the identity was originally obtained from an ssh-agent, then the ssh-agent will be used to sign the data, otherwise the private key for the identity will be loaded from disk (if it hasn’t been loaded already) and will then be used to sign the data.
Regardless of the identity’s origin or who does the signing, this will always return the signature in an SSH2-specified “signature blob” format.
# File lib/net/ssh/authentication/key_manager.rb, line 136 136: def sign(identity, data) 137: info = known_identities[identity] or raise KeyManagerError, "the given identity is unknown to the key manager" 138: 139: if info[:key].nil? && info[:from] == :file 140: begin 141: info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase], true) 142: rescue Exception, OpenSSL::OpenSSLError => e 143: raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})" 144: end 145: end 146: 147: if info[:key] 148: return Net::SSH::Buffer.from(:string, identity.ssh_type, 149: :string, info[:key].ssh_do_sign(data.to_s)).to_s 150: end 151: 152: if info[:from] == :agent 153: raise KeyManagerError, "the agent is no longer available" unless agent 154: return agent.sign(identity, data.to_s) 155: end 156: 157: raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})" 158: end
Toggles whether the ssh-agent will be used or not. If true, an attempt will be made to use the ssh-agent. If false, any existing connection to an agent is closed and the agent will not be used.
# File lib/net/ssh/authentication/key_manager.rb, line 168 168: def use_agent=(use_agent) 169: finish if !use_agent 170: @use_agent = use_agent 171: end
Load prepared identities. Private key decryption errors ignored if passphrase was not prompted.
# File lib/net/ssh/authentication/key_manager.rb, line 206 206: def load_identities(identities, ask_passphrase) 207: identities.map do |identity| 208: begin 209: case identity[:load_from] 210: when :pubkey_file 211: key = KeyFactory.load_public_key(identity[:file] + ".pub") 212: { :public_key => key, :from => :file, :file => identity[:file] } 213: when :privkey_file 214: private_key = KeyFactory.load_private_key(identity[:file], options[:passphrase], ask_passphrase) 215: key = private_key.send(:public_key) 216: { :public_key => key, :from => :file, :file => identity[:file], :key => private_key } 217: when :data 218: private_key = KeyFactory.load_data_private_key(identity[:data], options[:passphrase], ask_passphrase) 219: key = private_key.send(:public_key) 220: { :public_key => key, :from => :key_data, :data => identity[:data], :key => private_key } 221: else 222: identity 223: end 224: 225: rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError => e 226: if ask_passphrase 227: process_identity_loading_error(identity, e) 228: nil 229: else 230: identity 231: end 232: rescue Exception => e 233: process_identity_loading_error(identity, e) 234: nil 235: end 236: end.compact 237: end
Prepared identities from user key_data, preserving their order and sources.
# File lib/net/ssh/authentication/key_manager.rb, line 199 199: def prepare_identities_from_data 200: key_data.map do |data| 201: { :load_from => :data, :data => data } 202: end 203: end
Prepares identities from user key_files for loading, preserving their order and sources.
# File lib/net/ssh/authentication/key_manager.rb, line 187 187: def prepare_identities_from_files 188: key_files.map do |file| 189: public_key_file = file + ".pub" 190: if File.readable?(public_key_file) 191: { :load_from => :pubkey_file, :file => file } 192: elsif File.readable?(file) 193: { :load_from => :privkey_file, :file => file } 194: end 195: end.compact 196: end
# File lib/net/ssh/authentication/key_manager.rb, line 239 239: def process_identity_loading_error(identity, e) 240: case identity[:load_from] 241: when :pubkey_file 242: error { "could not load public key file `#{identity[:file]}': #{e.class} (#{e.message})" } 243: when :privkey_file 244: error { "could not load private key file `#{identity[:file]}': #{e.class} (#{e.message})" } 245: else 246: raise e 247: end 248: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.