lib/omniauth-ldap/adaptor.rb in gitlab_omniauth-ldap-1.2.1 vs lib/omniauth-ldap/adaptor.rb in gitlab_omniauth-ldap-2.0.0

- old
+ new

@@ -11,23 +11,41 @@ class LdapError < StandardError; end class ConfigurationError < StandardError; end class AuthenticationError < StandardError; end class ConnectionError < StandardError; end - VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :bind_dn, :password, :try_sasl, :sasl_mechanisms, :uid, :base, :allow_anonymous, :filter] + VALID_ADAPTER_CONFIGURATION_KEYS = [ + :hosts, :host, :port, :encryption, :disable_verify_certificates, :bind_dn, :password, :try_sasl, + :sasl_mechanisms, :uid, :base, :allow_anonymous, :filter, :ca_file, :ssl_version, + # Deprecated + :method + ] + # A list of needed keys. Possible alternatives are specified using sub-lists. - MUST_HAVE_KEYS = [:host, :port, :method, [:uid, :filter], :base] + MUST_HAVE_KEYS = [ + :base, + [:encryption, :method], # :method is deprecated + [:hosts, :host], + [:hosts, :port], + [:uid, :filter] + ] - METHOD = { + ENCRYPTION_METHOD = { + :simple_tls => :simple_tls, + :start_tls => :start_tls, + :plain => nil, + + # Deprecated. This mapping aimed to be user-friendly, but only caused + # confusion. Better to pass-through the actual `Net::LDAP` encryption type. :ssl => :simple_tls, :tls => :start_tls, - :plain => nil, } attr_accessor :bind_dn, :password attr_reader :connection, :uid, :base, :auth, :filter + def self.validate(configuration={}) message = [] MUST_HAVE_KEYS.each do |names| names = [names].flatten missing_keys = names.select{|name| configuration[name].nil?} @@ -35,36 +53,36 @@ message << names.join(' or ') end end raise ArgumentError.new(message.join(",") +" MUST be provided") unless message.empty? end + def initialize(configuration={}) Adaptor.validate(configuration) @configuration = configuration.dup @configuration[:allow_anonymous] ||= false @logger = @configuration.delete(:logger) VALID_ADAPTER_CONFIGURATION_KEYS.each do |name| instance_variable_set("@#{name}", @configuration[name]) end - method = ensure_method(@method) config = { - :host => @host, - :port => @port, - :encryption => method, - :base => @base + base: @base, + hosts: @hosts, + host: @host, + port: @port, } - @bind_method = @try_sasl ? :sasl : (@allow_anonymous||!@bind_dn||!@password ? :anonymous : :simple) @auth = sasl_auths({:username => @bind_dn, :password => @password}).first if @bind_method == :sasl @auth ||= { :method => @bind_method, :username => @bind_dn, :password => @password } config[:auth] = @auth @connection = Net::LDAP.new(config) + @connection.encryption(encryption_options) end #:base => "dc=yourcompany, dc=com", # :filter => "(mail=#{user})", # :password => psw @@ -86,17 +104,49 @@ end result end private - def ensure_method(method) - method ||= "plain" - normalized_method = method.to_s.downcase.to_sym - return METHOD[normalized_method] if METHOD.has_key?(normalized_method) - available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ") + def encryption_options + translated_method = translate_method + + { + method: translated_method, + tls_options: tls_options(translated_method) + } + end + + def translate_method + method = @encryption || @method + method ||= "plain" + normalized_method = method.to_s.downcase.to_sym + + unless ENCRYPTION_METHOD.has_key?(normalized_method) + available_methods = ENCRYPTION_METHOD.keys.collect {|m| m.inspect}.join(", ") format = "%s is not one of the available connect methods: %s" raise ConfigurationError, format % [method.inspect, available_methods] + end + + ENCRYPTION_METHOD[normalized_method] + end + + def tls_options(translated_method) + return {} if translated_method == nil # (plain) + + tls_options = if @disable_verify_certificates + # 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 } + else + OpenSSL::SSL::SSLContext::DEFAULT_PARAMS + end + + tls_options[:ca_file] = @ca_file if @ca_file + tls_options[:ssl_version] = @ssl_version if @ssl_version + tls_options end def sasl_auths(options={}) auths = [] sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms