From efbaff9b9a79995911fdbaaa3311288d283b5b12 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Mon, 18 Feb 2013 17:51:39 +0100 Subject: [PATCH 1/5] feature #1741: escape spaces instead of deleting them in x509 auth --- src/authm_mad/remotes/x509/x509_auth.rb | 13 +++++++++++-- src/cli/one_helper/oneuser_helper.rb | 3 ++- 2 files changed, 13 insertions(+), 3 deletions(-) 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 From 7b9c6561ea8f03ba379f9792358facf0cb90df5f Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Mon, 18 Feb 2013 17:52:17 +0100 Subject: [PATCH 2/5] feature #1741: test every dn in x509 authentication This patch was provided by Boris Parak <256254@mail.muni.cz> in http://dev.opennebula.org/issues/1741 Minor cosmetic changes --- src/cloud/common/CloudAuth.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/cloud/common/CloudAuth.rb b/src/cloud/common/CloudAuth.rb index 89bca96587..fdec369d75 100644 --- a/src/cloud/common/CloudAuth.rb +++ b/src/cloud/common/CloudAuth.rb @@ -134,9 +134,21 @@ class CloudAuth # password:: _String_ the password # [return] _Hash_ with the username def get_username(password) - xpath = "USER[contains(PASSWORD, \"#{password}\")]/NAME" + xpath = "USER[PASSWORD=\"#{password}\"]/NAME" + username = retrieve_from_userpool(xpath) - retrieve_from_userpool(xpath) + # No exact match, trying to match password with each + # of the pipe-separated DNs stored in USER/PASSWORD + if username.nil? + @lock.synchronize do + @user_pool.each do |user| + return user["NAME"] if user["AUTH_DRIVER"] == "x509" && + user["PASSWORD"].split('|').include?(password) + end + end + end + + username end private From 02cd738d8f2319db9515997c30befd50ab2f40cf Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Fri, 22 Feb 2013 16:59:46 +0100 Subject: [PATCH 3/5] feature #1741: escape dn in X509CloudAuth.rb --- src/cloud/common/CloudAuth/X509CloudAuth.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 From 60e0a6f2e750ed1fe4984972987a37fc279b45d2 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Fri, 22 Feb 2013 17:01:19 +0100 Subject: [PATCH 4/5] feature #1741: add method each_with_xpath to object pools --- src/oca/ruby/opennebula/pool.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/src/oca/ruby/opennebula/pool.rb b/src/oca/ruby/opennebula/pool.rb index 1ff18c1abd..10921d720b 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 From b5feaadda45d8d9537f01b473eb5eddc1df3baba Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Fri, 22 Feb 2013 17:05:29 +0100 Subject: [PATCH 5/5] feature #1741: filter possible user matches using xpath --- src/cloud/common/CloudAuth.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/cloud/common/CloudAuth.rb b/src/cloud/common/CloudAuth.rb index fdec369d75..ab6ddea5ef 100644 --- a/src/cloud/common/CloudAuth.rb +++ b/src/cloud/common/CloudAuth.rb @@ -134,21 +134,18 @@ class CloudAuth # password:: _String_ the password # [return] _Hash_ with the username def get_username(password) - xpath = "USER[PASSWORD=\"#{password}\"]/NAME" - username = retrieve_from_userpool(xpath) - - # No exact match, trying to match password with each + # Trying to match password with each # of the pipe-separated DNs stored in USER/PASSWORD - if username.nil? - @lock.synchronize do - @user_pool.each do |user| - return user["NAME"] if user["AUTH_DRIVER"] == "x509" && - user["PASSWORD"].split('|').include?(password) - end + @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 - username + nil end private