diff --git a/src/authm_mad/remotes/x509/x509_auth.rb b/src/authm_mad/remotes/x509/x509_auth.rb index 5e261745e7..4cdb0c7890 100644 --- a/src/authm_mad/remotes/x509/x509_auth.rb +++ b/src/authm_mad/remotes/x509/x509_auth.rb @@ -42,6 +42,14 @@ class OpenNebula::X509Auth :ca_dir => ETC_LOCATION + "/auth/certificates" } + def self.escape_dn(dn) + dn.gsub(/\s/) { |s| "\\"+s[0].ord.to_s(16) } + end + + def self.unescape_dn(dn) + dn.gsub(/\\[0-9a-f]{2}/) { |s| s[1,2].to_i(16).chr } + end + ########################################################################### # Initialize x509Auth object # @@ -81,7 +89,7 @@ class OpenNebula::X509Auth # Returns a valid password string to create a user using this auth driver. # In this case the dn of the user certificate. def password - @cert_chain[0].subject.to_s.delete("\s") + self.class.escape_dn(@cert_chain[0].subject.to_s) end # Generates a login token in the form: @@ -123,7 +131,8 @@ class OpenNebula::X509Auth # Some DN in the chain must match a DN in the password dn_ok = @cert_chain.each do |cert| - if pass.split('|').include?(cert.subject.to_s.delete("\s")) + if pass.split('|').include?( + self.class.escape_dn(cert.subject.to_s)) break true end end diff --git a/src/cli/one_helper/oneuser_helper.rb b/src/cli/one_helper/oneuser_helper.rb index 60e2143cb9..fbbdd21725 100644 --- a/src/cli/one_helper/oneuser_helper.rb +++ b/src/cli/one_helper/oneuser_helper.rb @@ -42,7 +42,8 @@ class OneUserHelper < OpenNebulaHelper::OneHelper end if options[:driver] == OpenNebula::User::X509_AUTH - password.delete!("\s") + require 'opennebula/x509_auth' + password = OpenNebula::X509Auth.escape_dn(password) end if options[:sha1] || options[:driver] == OpenNebula::User::CIPHER_AUTH diff --git a/src/cloud/common/CloudAuth.rb b/src/cloud/common/CloudAuth.rb index 89bca96587..ab6ddea5ef 100644 --- a/src/cloud/common/CloudAuth.rb +++ b/src/cloud/common/CloudAuth.rb @@ -134,9 +134,18 @@ class CloudAuth # password:: _String_ the password # [return] _Hash_ with the username def get_username(password) - xpath = "USER[contains(PASSWORD, \"#{password}\")]/NAME" + # Trying to match password with each + # of the pipe-separated DNs stored in USER/PASSWORD + @lock.synchronize do + @user_pool.each_with_xpath( + "USER[contains(PASSWORD, \"#{password}\")]") do |user| + STDERR.puts user.inspect + return user["NAME"] if user["AUTH_DRIVER"] == "x509" && + user["PASSWORD"].split('|').include?(password) + end + end - retrieve_from_userpool(xpath) + nil end private diff --git a/src/cloud/common/CloudAuth/X509CloudAuth.rb b/src/cloud/common/CloudAuth/X509CloudAuth.rb index e2f51873eb..cdae1f3893 100644 --- a/src/cloud/common/CloudAuth/X509CloudAuth.rb +++ b/src/cloud/common/CloudAuth/X509CloudAuth.rb @@ -14,6 +14,8 @@ # limitations under the License. # #--------------------------------------------------------------------------- # +require 'opennebula/x509_auth' + module X509CloudAuth def do_auth(env, params={}) # For https, the web service should be set to include the user cert in the environment. @@ -32,7 +34,8 @@ module X509CloudAuth end # Password should be DN with whitespace removed. - username = get_username(cert.subject.to_s.delete("\s")) + username = get_username( + OpenNebula::X509Auth.escape_dn(cert.subject.to_s)) return username if username diff --git a/src/oca/ruby/opennebula/pool.rb b/src/oca/ruby/opennebula/pool.rb index 616670730e..59b832e96c 100644 --- a/src/oca/ruby/opennebula/pool.rb +++ b/src/oca/ruby/opennebula/pool.rb @@ -22,6 +22,7 @@ module OpenNebula # and provides the basic functionality to handle the Pool elements class Pool < XMLPool include Enumerable + alias_method :each_with_xpath, :each protected #pool:: _String_ XML name of the root element