lib/chaltron/ldap/connection.rb in chaltron-1.0.10 vs lib/chaltron/ldap/connection.rb in chaltron-1.1.0

- old
+ new

@@ -2,10 +2,16 @@ require 'chaltron/ldap/person' module Chaltron module LDAP class Connection + NET_LDAP_ENCRYPTION_METHOD = { + simple_tls: :simple_tls, + start_tls: :start_tls, + plain: nil + }.freeze + attr_reader :ldap def initialize(params = {}) @ldap = Net::LDAP.new(adapter_options) end @@ -14,11 +20,13 @@ filter = Net::LDAP::Filter.eq(uid, login) ldap.bind_as(base: base, filter: filter, password: password) end def find_by_uid(id) - find_user(uid: id) + opts = {} + opts[uid.to_sym] = id + ret = find_user(opts) end def find_user(*args) find_users(*args).first end @@ -45,74 +53,125 @@ options = { base: args[:dn], scope: Net::LDAP::SearchScope_BaseObject } else - filters = [] - fields.each do |field| - filters << Net::LDAP::Filter.eq(field, args[field]) + filters = fields.map do |field| + f = translate_field(field) + Net::LDAP::Filter.eq(f, args[field]) if f end options = { base: base, filter: filters.inject { |sum, n| Net::LDAP::Filter.join(sum, n) } } end + options.merge!(size: limit) unless limit.nil? + ldap_search(options).map do |entry| + Chaltron::LDAP::Person.new(entry, uid) if entry.respond_to? uid + end.compact + end -# if config.user_filter.present? -# user_filter = Net::LDAP::Filter.construct(config.user_filter) + def find_groups_by_member(entry) + options = { + base: Chaltron.ldap_group_base || base, + filter: Chaltron.ldap_group_member_filter.call(entry) + } + ldap_search(options) + end -# options[:filter] = if options[:filter] -# Net::LDAP::Filter.join(options[:filter], user_filter) -# else -# user_filter -# end -# end - - options.merge!(size: limit) if limit.present? - - entries = ldap_search(options).select do |entry| - entry.respond_to? uid - end - - entries.map do |entry| - Chaltron::LDAP::Person.new(entry, uid) - end + def update_attributes(dn, args) + ldap.modify dn: dn, operations: args.map { |k,v| [:replace, k, v] } end private def options Devise.omniauth_configs[:ldap].options end + def translate_field field + return uid if field.to_sym == :uid + return Chaltron.ldap_field_mappings[field.to_sym] unless Chaltron.ldap_field_mappings[field.to_sym].nil? + field + end + def adapter_options - { + opts = { host: options[:host], port: options[:port], - encryption: encryption, + encryption: encryption_options, verbose: true - }.tap do |options| - options.merge!(auth_options) if has_auth? - end + } + opts.merge!(auth_options) if has_auth? + opts end def base options[:base] end def uid options[:uid] end - def encryption - case options[:method].to_s - when 'ssl' - :simple_tls - when 'tls' - :start_tls - else - nil + def encryption_options + method = translate_method + return unless method + { + method: method, + tls_options: tls_options + } + end + + def translate_method + NET_LDAP_ENCRYPTION_METHOD[options[:encryption]&.to_sym] + end + + def tls_options + return @tls_options if defined?(@tls_options) + + method = translate_method + return unless method + + opts = if options[:verify_certificates] && method != 'plain' + # Dup so we don't accidentally overwrite the constant + OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.dup + else + # It is important to explicitly set verify_mode for two reasons: + # 1. The behavior of OpenSSL is undefined when verify_mode is not set. + # 2. The net-ldap gem implementation verifies the certificate hostname + # unless verify_mode is set to VERIFY_NONE. + { verify_mode: OpenSSL::SSL::VERIFY_NONE } + end + + opts.merge!(custom_tls_options) + + @tls_options = opts + end + + def custom_tls_options + return {} unless options['tls_options'] + + # Dup so we don't overwrite the original value + custom_options = options['tls_options'].dup.delete_if { |_, value| value.nil? || value.blank? } + custom_options.symbolize_keys! + + if custom_options[:cert] + begin + custom_options[:cert] = OpenSSL::X509::Certificate.new(custom_options[:cert]) + rescue OpenSSL::X509::CertificateError => e + Rails.logger.error "LDAP TLS Options 'cert' is invalid for provider #{provider}: #{e.message}" + end end + + if custom_options[:key] + begin + custom_options[:key] = OpenSSL::PKey.read(custom_options[:key]) + rescue OpenSSL::PKey::PKeyError => e + Rails.logger.error "LDAP TLS Options 'key' is invalid for provider #{provider}: #{e.message}" + end + end + custom_options end def auth_options { auth: {