From 1488d536c3994a7dca9f4e92ac654d8c24a45367 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 21 Aug 2011 01:55:00 +0200 Subject: [PATCH] feature #754: Validate X509 expiration times. Support for trusted CA's --- src/authm_mad/remotes/x509/x509_auth.rb | 58 +++++++++++++++++-- .../remotes/x509_proxy/x509_proxy_auth.rb | 8 +-- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/authm_mad/remotes/x509/x509_auth.rb b/src/authm_mad/remotes/x509/x509_auth.rb index 7ac30b71d3..7b067f151f 100644 --- a/src/authm_mad/remotes/x509/x509_auth.rb +++ b/src/authm_mad/remotes/x509/x509_auth.rb @@ -27,11 +27,14 @@ class X509Auth # # @param [Hash] default options for path # @option options [String] :cert public cert for the user - # @option options [String] :key private key for the user + # @option options [String] :key private key for the user. Needed + # to use login method + # @option options [String] :ca_dir directory of trusted CA's. Optional. def initialize(options={}) @options={ - :cert => nil, - :key => nil + :cert => nil, + :key => nil, + :ca_dir => nil }.merge!(options) @cert = OpenSSL::X509::Certificate.new(@options[:cert]) @@ -90,6 +93,8 @@ class X509Auth # auth method for auth_mad def authenticate(user, pass, token) begin + validate + plain = decrypt(token) _user, subject, time_expire = plain.split(':') @@ -103,8 +108,8 @@ class X509Auth end return true - rescue - return "Can not decrypt security token" + rescue => e + return e.message end end @@ -123,4 +128,45 @@ private def decrypt(data) @cert.public_key.public_decrypt(Base64::decode64(data)) end -end + + ########################################################################### + # Validate the user certificate + ########################################################################### + def validate + now = Time.now + failed = "Could not validate user credentials: " + + # 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 " + + now.localtime.to_s + "." + end + + # Check the rest of the certificate chain if specified + if !@options[:ca_dir] + return + end + + 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) && + (signee.verify(ca_cert.public_key))) + 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 + 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 9a6522420c..ca2d3bfa9d 100644 --- a/src/authm_mad/remotes/x509_proxy/x509_proxy_auth.rb +++ b/src/authm_mad/remotes/x509_proxy/x509_proxy_auth.rb @@ -163,15 +163,15 @@ private end ########################################################################### - # Validates the the certificate chain + # Validates the certificate chain ########################################################################### def validate_chain now = Time.now - failed = "Could not validate user credentials. " + failed = "Could not validate user credentials: " # Check start time and end time of proxy if @proxy_cert.not_before > now || @proxy_cert.not_after < now - raise failed + "Certfacete not valid. Current time is " + + raise failed + "Certificate not valid. Current time is " + now.localtime.to_s + "." end @@ -213,7 +213,5 @@ private rescue raise end - - end end end