Guest User

Untitled

a guest
Nov 26th, 2018
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.33 KB | None | 0 0
  1. #this code borrowed pieces from activeldap and net-ldap
  2.  
  3. require 'rack'
  4. require 'net/ldap'
  5. require 'net/ntlm'
  6. require 'uri'
  7. require 'sasl'
  8. require 'kconv'
  9. module OmniAuth
  10. module LDAP
  11. class Adaptor
  12. class LdapError < StandardError; end
  13. class ConfigurationError < StandardError; end
  14. class AuthenticationError < StandardError; end
  15. class ConnectionError < StandardError; end
  16.  
  17. VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :bind_dn, :password, :try_sasl, :sasl_mechanisms, :uid, :base, :allow_anonymous, :dynamic_auth]
  18.  
  19. MUST_HAVE_KEYS = [:host, :port, :method, :uid, :base]
  20.  
  21. METHOD = {
  22. :ssl => :simple_tls,
  23. :tls => :start_tls,
  24. :plain => nil,
  25. }
  26.  
  27. attr_accessor :bind_dn, :password
  28. attr_reader :connection, :uid, :base, :auth
  29.  
  30. def initialize(configuration={})
  31. @configuration = configuration.dup
  32. @configuration[:allow_anonymous] ||= false
  33. @logger = @configuration.delete(:logger)
  34. message = []
  35. MUST_HAVE_KEYS.each do |name|
  36. message << name if configuration[name].nil?
  37. end
  38. raise ArgumentError.new(message.join(",") +" MUST be provided") unless message.empty?
  39. VALID_ADAPTER_CONFIGURATION_KEYS.each do |name|
  40. instance_variable_set("@#{name}", configuration[name])
  41. end
  42. method = ensure_method(@method)
  43. config = {
  44. :host => @host,
  45. :port => @port,
  46. :encryption => method,
  47. :base => @base
  48. }
  49. @uri = construct_uri(@host, @port, @method != :plain)
  50.  
  51. @bind_method = @try_sasl ? :sasl : (@allow_anonymous||!@bind_dn||!@password ? :anonymous : :simple)
  52.  
  53. @dynamic_auth = true if (@allow_anonymous == false && @bind_dn.nil? && @password.nil?)
  54.  
  55. @auth = sasl_auths({:username => @bind_dn, :password => @password}).first if @bind_method == :sasl
  56. @auth ||= { :method => @bind_method,
  57. :username => @bind_dn,
  58. :password => @password
  59. }
  60. config[:auth] = @auth
  61. @connection = Net::LDAP.new(config)
  62. end
  63.  
  64. #:base => "dc=yourcompany, dc=com",
  65. # :filter => "(mail=#{user})",
  66. # :password => psw
  67. def bind_as(args = {})
  68. result = false
  69. password = args[:password]
  70. method = args[:method] || @method
  71. password = password.call if password.respond_to?(:call)
  72. @connection.auth args[:username], password if @dynamic_auth
  73. @connection.open do |me|
  74. rs = me.search args
  75. if rs and rs.first and dn = rs.first.dn
  76. if method == 'sasl'
  77. result = rs.first if me.bind(sasl_auths({:username => dn, :password => password}).first)
  78. else
  79. result = rs.first if me.bind(:method => :simple, :username => dn,
  80. :password => password)
  81. end
  82. end
  83. end
  84. result
  85. end
  86.  
  87. private
  88. def ensure_method(method)
  89. method ||= "plain"
  90. normalized_method = method.to_s.downcase.to_sym
  91. return METHOD[normalized_method] if METHOD.has_key?(normalized_method)
  92.  
  93. available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
  94. format = "%s is not one of the available connect methods: %s"
  95. raise ConfigurationError, format % [method.inspect, available_methods]
  96. end
  97.  
  98. def sasl_auths(options={})
  99. auths = []
  100. sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms
  101. sasl_mechanisms.each do |mechanism|
  102. normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
  103. sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
  104. next unless respond_to?(sasl_bind_setup, true)
  105. initial_credential, challenge_response = send(sasl_bind_setup, options)
  106. auths << {
  107. :method => :sasl,
  108. :initial_credential => initial_credential,
  109. :mechanism => mechanism,
  110. :challenge_response => challenge_response
  111. }
  112. end
  113. auths
  114. end
  115.  
  116. def sasl_bind_setup_digest_md5(options)
  117. bind_dn = options[:username]
  118. initial_credential = ""
  119. challenge_response = Proc.new do |cred|
  120. pref = SASL::Preferences.new :digest_uri => "ldap/#{@host}", :username => bind_dn, :has_password? => true, :password => options[:password]
  121. sasl = SASL.new("DIGEST-MD5", pref)
  122. response = sasl.receive("challenge", cred)
  123. response[1]
  124. end
  125. [initial_credential, challenge_response]
  126. end
  127.  
  128. def sasl_bind_setup_gss_spnego(options)
  129. bind_dn = options[:username]
  130. psw = options[:password]
  131. raise LdapError.new( "invalid binding information" ) unless (bind_dn && psw)
  132.  
  133. nego = proc {|challenge|
  134. t2_msg = Net::NTLM::Message.parse( challenge )
  135. bind_dn, domain = bind_dn.split('\\').reverse
  136. t2_msg.target_name = Net::NTLM::encode_utf16le(domain) if domain
  137. t3_msg = t2_msg.response( {:user => bind_dn, :password => psw}, {:ntlmv2 => true} )
  138. t3_msg.serialize
  139. }
  140. [Net::NTLM::Message::Type1.new.serialize, nego]
  141. end
  142.  
  143. def construct_uri(host, port, ssl)
  144. protocol = ssl ? "ldaps" : "ldap"
  145. URI.parse("#{protocol}://#{host}:#{port}").to_s
  146. end
  147. end
  148. end
  149. end
Add Comment
Please, Sign In to add comment