diff --git a/lib/authlogic_x509/session.rb b/lib/authlogic_x509/session.rb index eae8e19..599c8e4 100644 --- a/lib/authlogic_x509/session.rb +++ b/lib/authlogic_x509/session.rb @@ -1,5 +1,3 @@ -require 'openssl' - module AuthlogicX509 module Session # Add a simple openid_identifier attribute and some validations for the field. @@ -12,23 +10,23 @@ def self.included(klass) module Config # Once X509 authentication has succeeded we need to find the user in the database. By default this just calls the - # find_with_x509_login method provided by ActiveRecord. If you have a more advanced set up and need to find users + # find_by_x509_subject_dn method provided by ActiveRecord. If you have a more advanced set up and need to find users # differently specify your own method and define your logic in there. # # For example, if you allow users to store multiple x509 subject DNs with their account, you might do something like: # # class User < ActiveRecord::Base - # def self.find_with_x509_login(login_hash) - # first(:conditions => ["#{X509Login.table_name}.subject_dn = ? and #{X509Login.table_name}.issuer_dn = ?", login_hash[:subject_dn], login_hash[:issuer_dn]], :join => :x509_logins) + # def self.find_by_x509_subject_dn(login) + # first(:conditions => ["#{X509Login.table_name}.login = ?", login], :join => :x509_logins) # end # end # - # * Default: :find_with_x509_login + # * Default: :find_by_x509_subject_dn # * Accepts: Symbol - def find_with_x509_login_method(value = nil) - rw_config(:find_with_x509_login_method, value, :find_with_x509_login) + def find_by_x509_login_method(value = nil) + rw_config(:find_by_x509_login_method, value, :find_by_x509_login) end - alias_method :find_with_x509_login_method=, :find_with_x509_login_method + alias_method :find_by_x509_login_method=, :find_by_x509_login_method end @@ -36,74 +34,68 @@ module Methods def self.included(klass) klass.class_eval do attr_accessor :x509_login - attr_accessor :x509_subject_dn attr_accessor :x509_issuer_dn - attr_accessor :x509_client_cert + attr_accessor :x509_subject_dn validate :validate_by_x509, :if => :authenticating_with_x509? end end - - # Hooks into credentials so that you can pass an :x509_login key. - def credentials - if authenticating_with_x509? - details = {} - details[:x509_subject_dn] = self.x509_subject_dn - details[:x509_issuer_dn] = self.x509_issuer_dn - details - else - super - end - end + # Hooks into credentials so that you can pass an :x509_login key. def credentials=(value) super values = value.is_a?(Array) ? value : [value] hash = values.first.is_a?(Hash) ? values.first.with_indifferent_access : nil if !hash.nil? self.x509_login = hash[:x509_login] if hash.key?(:x509_login) - self.x509_client_cert = hash[:x509_client_cert] if hash.key?(:x509_client_cert) end end - + private def authenticating_with_x509? - x509_login + attempted_record.nil? && errors.empty? && x509_login end def validate_by_x509 - parse_x509_login - if self.x509_subject_dn || self.x509_issuer_dn - self.attempted_record = search_for_record(find_with_x509_login_method, {:subject_dn=>x509_subject_dn,:issuer_dn=>x509_issuer_dn}) - errors.add(:x509_login, I18n.t('error_messages.x509_login_user_not_found', :default => "does not exist")) if attempted_record.blank? + + if controller.local_request? + self.x509_subject_dn = "/CN=Local Request" + self.x509_issuer_dn = "/CN=Local Issuer" + elsif controller.request.env['SSL_CLIENT_S_DN'] =~ /CN/ + self.x509_subject_dn = controller.request.env['SSL_CLIENT_S_DN'] + self.x509_issuer_dn = controller.request.env['SSL_CLIENT_I_DN'] + elsif controller.request.env['REDIRECT_SSL_CLIENT_S_DN'] =~ /CN/ + self.x509_subject_dn = controller.request.env['REDIRECT_SSL_CLIENT_S_DN'] + self.x509_issuer_dn = controller.request.env['REDIRECT_SSL_CLIENT_I_DN'] + elsif controller.request.env['HTTP_REDIRECT_SSL_CLIENT_S_DN'] =~ /CN/ + self.x509_subject_dn = controller.request.env['HTTP_REDIRECT_SSL_CLIENT_S_DN'] + self.x509_issuer_dn = controller.request.env['HTTP_REDIRECT_SSL_CLIENT_I_DN'] + end + + if self.x509_subject_dn && self.x509_issuer_dn + controller.logger.info "start" + self.attempted_record = klass.send(find_by_x509_login_method, x509_subject_dn, x509_issuer_dn) + controller.logger.info "stop" + errors.add(:x509_login, I18n.t('error_messages.x509_login_not_found', :default => "does not exist")) if attempted_record.blank? else - errors.add_to_base("User not found") + errors.add_to_base("Subject DN not found") end end - def find_with_x509_login_method - self.class.find_with_x509_login_method + def find_by_x509_login_method + self.class.find_by_x509_login_method end - def parse_x509_login - get_subject_dn - get_issuer_dn - end - - def get_subject_dn - if controller.local_request? - self.x509_subject_dn = "/CN=Local Request" - elsif cert = OpenSSL::X509::Certificate.new(x509_client_cert) - self.x509_subject_dn = cert.subject.to_s - end - end - - def get_issuer_dn - if controller.local_request? - self.x509_issuer_dn = "/CN=Local Request Issuer" - elsif cert = OpenSSL::X509::Certificate.new(x509_client_cert) - self.x509_issuer_dn = cert.issuer.to_s - end - end + def x509_subject_dn + self.class.x509_subject_dn + end + + def x509_issuer_dn + self.class.x509_issuer_dn + end + + def x509_login + self.class.x509_login + end end end end \ No newline at end of file