diff --git a/src/authm_mad/remotes/ssh/ssh_auth.rb b/src/authm_mad/remotes/ssh/ssh_auth.rb index 85d38f313e..a0d2915be9 100644 --- a/src/authm_mad/remotes/ssh/ssh_auth.rb +++ b/src/authm_mad/remotes/ssh/ssh_auth.rb @@ -24,6 +24,8 @@ require 'fileutils' # as auth method is defined. It also holds some helper methods to be used # by oneauth command class SshAuth + PROXY_PATH = ENV['HOME']+'/.one/one_ssh' + attr_reader :public_key # Initialize SshAuth object @@ -64,33 +66,28 @@ class SshAuth # By default it is valid for 1 hour but it can be changed to any number # of seconds with expire parameter (in seconds) def login(user, expire=3600) + expire ||= 3600 + # Init proxy file path and creates ~/.one directory if needed - proxy_dir=ENV['HOME']+'/.one' - + proxy_dir = File.dirname(PROXY_PATH) + begin FileUtils.mkdir_p(proxy_dir) rescue Errno::EEXIST end - - proxy_path = proxy_dir + '/one_ssh' # Generate security token - time = Time.now.to_i + expire + time = Time.now.to_i + expire.to_i secret_plain = "#{user}:#{time}" secret_crypted = encrypt(secret_plain) proxy = "#{user}:ssh:#{secret_crypted}" - - file = File.open(proxy_path, "w") + file = File.open(PROXY_PATH, "w") file.write(proxy) - file.close - - # Help string - puts "export ONE_AUTH=#{ENV['HOME']}/.one/one_ssh" - + secret_crypted end @@ -99,7 +96,7 @@ class SshAuth begin token_plain = decrypt(token) _user, time = token_plain.split(':') - + if user == _user if Time.now.to_i >= time.to_i return "ssh proxy expired, login again to renew it" @@ -114,12 +111,13 @@ class SshAuth end end -private + private + ########################################################################### # Methods to handle ssh keys ########################################################################### # Encrypts data with the private key of the user and returns - # base 64 encoded output in a single line + # base 64 encoded output in a single line def encrypt(data) rsa=OpenSSL::PKey::RSA.new(@private_key) Base64::encode64(rsa.private_encrypt(data)).gsub!(/\n/, '').strip diff --git a/src/authm_mad/remotes/x509/x509_auth.rb b/src/authm_mad/remotes/x509/x509_auth.rb index 7b067f151f..7e04c00566 100644 --- a/src/authm_mad/remotes/x509/x509_auth.rb +++ b/src/authm_mad/remotes/x509/x509_auth.rb @@ -22,6 +22,9 @@ require 'fileutils' # as auth method is defined. It also holds some helper methods to be used # by oneauth command class X509Auth + PROXY_PATH = ENV['HOME']+'/.one/one_x509' + + attr_reader :dn # Initialize x509Auth object # @@ -42,7 +45,7 @@ class X509Auth if @options[:key] @key = OpenSSL::PKey::RSA.new(@options[:key]) - end + end end ########################################################################### @@ -53,50 +56,45 @@ class X509Auth # By default it is valid for 1 hour but it can be changed to any number # of seconds with expire parameter (in seconds) def login(user, expire=3600) + expire ||= 3600 + # Init proxy file path and creates ~/.one directory if needed # Set instance variables - proxy_dir=ENV['HOME']+'/.one' - + proxy_dir = File.dirname(PROXY_PATH) + begin FileUtils.mkdir_p(proxy_dir) rescue Errno::EEXIST end - - one_proxy_path = proxy_dir + '/one_x509' #Create the x509 proxy time = Time.now.to_i+expire - + text_to_sign = "#{user}:#{@dn}:#{time}" signed_text = encrypt(text_to_sign) - token = "#{signed_text}:#{@cert.to_pem}" + token = "#{signed_text}:#{@cert.to_pem}" token64 = Base64::encode64(token).strip.delete!("\n") proxy="#{user}:x509:#{token64}" - file = File.open(one_proxy_path, "w") - + file = File.open(PROXY_PATH, "w") file.write(proxy) - file.close - - # Help string - puts "export ONE_AUTH=#{ENV['HOME']}/.one/one_x509" - + token64 end - + ########################################################################### # Server side ########################################################################### # auth method for auth_mad - def authenticate(user, pass, token) + def authenticate(user, pass, token) begin validate plain = decrypt(token) - + _user, subject, time_expire = plain.split(':') if (user != _user) @@ -112,22 +110,22 @@ class X509Auth return e.message end end - + private ########################################################################### # Methods to encrpyt/decrypt keys ########################################################################### # Encrypts data with the private key of the user and returns - # base 64 encoded output in a single line + # base 64 encoded output in a single line def encrypt(data) return nil if !@key Base64::encode64(@key.private_encrypt(data)).delete!("\n").strip end # Decrypts base 64 encoded data with pub_key (public key) - def decrypt(data) + def decrypt(data) @cert.public_key.public_decrypt(Base64::decode64(data)) - end + end ########################################################################### # Validate the user certificate @@ -138,10 +136,10 @@ private # Check start time and end time of certificate if @cert.not_before > now || @cert.not_after < now - raise failed + "Certificate not valid. Current time is " + + raise failed + "Certificate not valid. Current time is " + now.localtime.to_s + "." end - + # Check the rest of the certificate chain if specified if !@options[:ca_dir] return @@ -149,24 +147,24 @@ private begin signee = @cert - + begin ca_hash = signee.issuer.hash.to_s(16) ca_path = @options[:ca_dir] + '/' + ca_hash + '.0' ca_cert = OpenSSL::X509::Certificate.new(File.read(ca_path)) - - if !((signee.issuer.to_s == ca_cert.subject.to_s) && + + if !((signee.issuer.to_s == ca_cert.subject.to_s) && (signee.verify(ca_cert.public_key))) - raise failed + signee.subject.to_s + " with issuer " + - signee.issuer.to_s + " was not verified by " + + raise failed + signee.subject.to_s + " with issuer " + + signee.issuer.to_s + " was not verified by " + ca.subject.to_s + "." end signee = ca_cert end while ca_cert.subject.to_s != ca_cert.issuer.to_s rescue - raise + raise end end end diff --git a/src/authm_mad/remotes/x509_proxy/x509_proxy_auth.rb b/src/authm_mad/remotes/x509_proxy/x509_proxy_auth.rb index 8653788588..2ed8b386b4 100644 --- a/src/authm_mad/remotes/x509_proxy/x509_proxy_auth.rb +++ b/src/authm_mad/remotes/x509_proxy/x509_proxy_auth.rb @@ -18,19 +18,20 @@ require 'openssl' require 'base64' require 'fileutils' -# Authentication class based on x509 proxy certificate. +# Authentication class based on x509 proxy certificate. class X509ProxyAuth + PROXY_PATH = ENV['HOME']+'/.one/one_x509_proxy' # Initialize x509ProxyAuth object # # @param [Hash] default options for path - # @option options [String] :proxy ($X509_PROXY_CERT) + # @option options [String] :proxy ($X509_PROXY_CERT) # proxy cert for the user - # @option options [String] :proxy_cert (nil) + # @option options [String] :proxy_cert (nil) # public cert of a user proxy - # @option options [String] :user_cert (nil) + # @option options [String] :user_cert (nil) # user cert, used to generate the proxy - # @option options [String] :ca_dir (/etc/grid-security/certificates) + # @option options [String] :ca_dir (/etc/grid-security/certificates) # trusted CA directory. If nil it will not be used to verify # certificates def initialize(options={}) @@ -53,33 +54,33 @@ class X509ProxyAuth proxy_cert_txt = rc[0] user_cert_txt = rc[1] - + rc = proxy.match(/-+BEGIN RSA PRIVATE KEY-+\n([^-]*)\n-+END RSA PRIVATE KEY-+/) proxy_key_txt = rc[1] end - + if !proxy_cert_txt || !user_cert_txt raise "Can not get user or proxy certificates" end - + @proxy_cert = OpenSSL::X509::Certificate.new(proxy_cert_txt) @user_cert = OpenSSL::X509::Certificate.new(user_cert_txt) @dn = @user_cert.subject.to_s - + if proxy_ket_txt @poxy_key = OpenSSL::PKey::RSA.new(proxy_key_txt) end # Load configuration file #@auth_conf_path = ETC_LOCATION+'/auth/auth.conf' - + #if File.readable?(@auth_conf_path) # config = File.read(@auth_conf_path) # config = YAML::load(config_data) # @options.merge!(config) - #end + #end end ########################################################################### @@ -90,47 +91,45 @@ class X509ProxyAuth def login(user) # Init proxy file path and creates ~/.one directory if needed # Set instance variables - proxy_dir=ENV['HOME']+'/.one' - + proxy_dir=File.dirname(PROXY_PATH) + begin FileUtils.mkdir_p(proxy_dir) rescue Errno::EEXIST end - - one_proxy_path = proxy_dir + '/one_x509_proxy' - + #Generate token for authentication text_to_sign = "#{user}:#{@dn}" signed_text = encrypt(text_to_sign) - token = "#{signed_text}:#{@proxy_cert.to_pem}:#{@user_cert.to_pem}" + token = "#{signed_text}:#{@proxy_cert.to_pem}:#{@user_cert.to_pem}" token64 = Base64::encode64(token).strip.delete!("\n") proxy="#{user}:grid:#{token64}" - file = File.open(one_proxy_path, "w") + file = File.open(PROXY_PATH, "w") file.write(proxy) - + file.close - + # Help string - puts "export ONE_AUTH=#{ENV['HOME']}/.one/one_grid" - + puts "export ONE_AUTH=#{ENV['HOME']}/.one/one_x509_proxy" + token64 end - + ########################################################################### # Server side ########################################################################### # auth method for auth_mad - def authenticate(user, pass, token) + def authenticate(user, pass, token) begin validate_chain plain = decrypt(token) - + _user, subject = plain.split(':') if (user != _user) @@ -149,14 +148,14 @@ private # Methods to encrpyt/decrypt keys ########################################################################### # Encrypts data with the private key of the user and returns - # base 64 encoded output in a single line + # base 64 encoded output in a single line def encrypt(data) return nil if !@proxy_key Base64::encode64(@proxy_key.private_encrypt(data)).delete!("\n").strip end # Decrypts base 64 encoded data with pub_key (public key) - def decrypt(data) + def decrypt(data) @proxy_cert.public_key.public_decrypt(Base64::decode64(data)) end @@ -169,22 +168,22 @@ private # Check start time and end time of proxy if @proxy_cert.not_before > now || @proxy_cert.not_after < now - raise failed + "Certificate not valid. Current time is " + + raise failed + "Certificate not valid. Current time is " + now.localtime.to_s + "." end - + # Check that the issuer of the proxy is the same user as in the user certificate if @proxy_cert.issuer.to_s != @user_cert.subject.to_s - raise failed + "Proxy with issuer " + @proxy_cert.issuer.to_s + + raise failed + "Proxy with issuer " + @proxy_cert.issuer.to_s + " does not match user " + @dn end - + # Check that the user signed the proxy if !@proxy_cert.verify(@user_cert.public_key) - raise "Proxy with subject " + @proxy_cert.subject.to_s + + raise "Proxy with subject " + @proxy_cert.subject.to_s + " was not verified by " + @dn + "." end - + # Check the rest of the certificate chain if specified if !@options[:ca_dir] return @@ -192,24 +191,24 @@ private begin signee = @user_cert - + begin ca_hash = signee.issuer.hash.to_s(16) ca_path = @options[:ca_dir] + '/' + ca_hash + '.0' ca_cert = OpenSSL::X509::Certificate.new(File.read(ca_path)) - - if !((signee.issuer.to_s == ca_cert.subject.to_s) && + + if !((signee.issuer.to_s == ca_cert.subject.to_s) && (signee.verify(ca_cert.public_key))) - raise failed + signee.subject.to_s + " with issuer " + - signee.issuer.to_s + " was not verified by " + + raise failed + signee.subject.to_s + " with issuer " + + signee.issuer.to_s + " was not verified by " + ca.subject.to_s + "." end signee = ca_cert end while ca_cert.subject.to_s != ca_cert.issuer.to_s rescue - raise + raise end end end