Project

General

Profile

Patch #3358 » advanced_ldap_auth_1.2.1.diff

LDAP authentication patch for 1.2.1 - Anonymous, 2011-08-12 02:01

View differences:

app/views/ldap_auth_sources/_form.rhtml (working copy)
9 9
<%= text_field 'auth_source', 'host'  %></p>
10 10

  
11 11
<p><label for="auth_source_port"><%=l(:field_port)%> <span class="required">*</span></label>
12
<%= text_field 'auth_source', 'port', :size => 6 %> <%= check_box 'auth_source', 'tls'  %> LDAPS</p>
12
<%= text_field 'auth_source', 'port', :size => 6 %>
13
<%= check_box 'auth_source', 'tls' %> LDAPS
14
<%= check_box 'auth_source', 'starttls' %> START_TLS</p>
15

  
16
<p><label for="auth_source_protocol_version"><%=l(:field_protocol_version)%></label>
17
<%= select 'auth_source', 'protocol_version', [2, 3] %></p>
13 18

  
14 19
<p><label for="auth_source_account"><%=l(:field_account)%></label>
15
<%= text_field 'auth_source', 'account'  %></p>
20
<%= text_field 'auth_source', 'account' %></p>
16 21

  
17 22
<p><label for="auth_source_account_password"><%=l(:field_password)%></label>
18 23
<%= password_field 'auth_source', 'account_password', :name => 'ignore',
......
20 25
                                           :onfocus => "this.value=''; this.name='auth_source[account_password]';",
21 26
                                           :onchange => "this.name='auth_source[account_password]';" %></p>
22 27

  
28
<p><label for="auth_source_require_cert"><%=l(:field_require_cert)%></label>
29
<%= select 'auth_source', 'require_cert', [ [l(:field_require_cert_never), 0],
30
                                            [l(:field_require_cert_hard), 1],
31
                                            [l(:field_require_cert_demand), 2],
32
                                            [l(:field_require_cert_allow), 3],
33
                                            [l(:field_require_cert_try), 4] ] %></p>
34

  
23 35
<p><label for="auth_source_base_dn"><%=l(:field_base_dn)%> <span class="required">*</span></label>
24 36
<%= text_field 'auth_source', 'base_dn', :size => 60 %></p>
25 37

  
38
<p><label for="auth_source_filter"><%=l(:field_filter)%></label><%= text_field 'auth_source', 'filter' %></p>
39

  
40
<p><label for="auth_source_dereference"><%=l(:field_dereference)%></label>
41
<%= select 'auth_source', 'dereference', [ [l(:field_dereference_never), 0],
42
                                         [l(:field_dereference_searching), 1],
43
                                         [l(:field_dereference_finding), 2],
44
                                         [l(:field_dereference_always), 3] ] %></p>
45

  
26 46
<p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
27 47
<%= check_box 'auth_source', 'onthefly_register' %></p>
28 48
</div>
app/models/auth_source_ldap.rb (working copy)
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17
# Modified by Daniel Marczisovszky (marczi@dev-labs.com) 
18
# to allow dereferencing aliases, START_TLS
17 19

  
18
require 'net/ldap'
20
require 'ldap'
19 21
require 'iconv'
20 22

  
21 23
class AuthSourceLdap < AuthSource 
22 24
  validates_presence_of :host, :port, :attr_login
23 25
  validates_length_of :name, :host, :maximum => 60, :allow_nil => true
24
  validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_nil => true
26
  validates_length_of :account, :base_dn, :filter, :maximum => 255, :allow_nil => true
25 27
  validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
26
  validates_numericality_of :port, :only_integer => true
27
  
28
  validates_numericality_of :port, :protocol_version, :only_integer => true
29
    
28 30
  before_validation :strip_ldap_attributes
29 31
  
30 32
  def after_initialize
31 33
    self.port = 389 if self.port == 0
34
    self.protocol_version = 3 if self.protocol_version == 0
32 35
  end
33 36
  
34 37
  def authenticate(login, password)
......
39 42
      logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
40 43
      return attrs.except(:dn)
41 44
    end
42
  rescue  Net::LDAP::LdapError => text
43
    raise "LdapError: " + text
45
#  rescue  Net::LDAP::LdapError => text
46
#    raise "LdapError: " + text
47
  rescue  LDAP::Error => text
48
    raise "LDAP Auth Error: " + text
44 49
  end
45 50

  
46 51
  # test the connection to the LDAP
47 52
  def test_connection
48 53
    ldap_con = initialize_ldap_con(self.account, self.account_password)
49
    ldap_con.open { }
50
  rescue  Net::LDAP::LdapError => text
51
    raise "LdapError: " + text
54
  rescue  LDAP::Error => text
55
    raise "LDAP Error: " + text
56
#    ldap_con.open { }
57
#  rescue  Net::LDAP::LdapError => text
58
#    raise "LdapError: " + text
52 59
  end
53 60
 
54 61
  def auth_method_name
......
64 71
  end
65 72
  
66 73
  def initialize_ldap_con(ldap_user, ldap_password)
67
    options = { :host => self.host,
68
                :port => self.port,
69
                :encryption => (self.tls ? :simple_tls : nil)
70
              }
71
    options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
72
    Net::LDAP.new options
74
#    options = { :host => self.host,
75
#                :port => self.port,
76
#                :encryption => (self.tls ? :simple_tls : nil)
77
#              }
78
#    options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
79
#    Net::LDAP.new options
80
    logger.debug "Connecting to #{self.host}:#{self.port}, tls=#{self.tls}" if logger && logger.debug?
81
    if self.tls
82
      conn = LDAP::SSLConn.new(self.host, self.port, self.starttls)
83
    else
84
      conn = LDAP::Conn.new(self.host, self.port)
85
    end
86
    logger.debug "Dereference set option" if logger && logger.debug?
87
    conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, self.protocol_version)
88
    conn.set_option(LDAP::LDAP_OPT_DEREF, self.dereference)
89
    if self.tls && self.starttls
90
      logger.debug "Certificate set option" if logger && logger.debug?
91
      conn.set_option(LDAP::LDAP_OPT_X_TLS_REQUIRE_CERT, self.require_cert)
92
    end
93

  
94
    logger.debug "Trying to bind" if logger && logger.debug?
95
    if !ldap_user.blank? || !ldap_password.blank? then
96
      logger.debug "Bind as user #{ldap_user}" if logger && logger.debug?
97
      conn.bind(ldap_user, ldap_password)
98
    else
99
      logger.debug "Anonymous bind" if logger && logger.debug?
100
      conn.bind
101
    end
102
  rescue LDAP::Error => text
103
    logger.debug "LDAP Connect Error: #{$!}" if logger && logger.debug?
104
    raise
73 105
  end
74 106

  
75 107
  def get_user_attributes_from_ldap_entry(entry)
......
95 127
  # Check if a DN (user record) authenticates with the password
96 128
  def authenticate_dn(dn, password)
97 129
    if dn.present? && password.present?
98
      initialize_ldap_con(dn, password).bind
130
      begin
131
        logger.debug "Trying to login as #{dn}" if logger && logger.debug?
132
        initialize_ldap_con(dn, password)
133
      rescue LDAP::Error => bindError
134
        logger.debug "Login failed: #{bindError}" if logger && logger.debug?
135
        return nil
136
      end
137
#      initialize_ldap_con(dn, password).bind
99 138
    end
100 139
  end
101 140

  
102 141
  # Get the user's dn and any attributes for them, given their login
103 142
  def get_user_dn(login)
104
    ldap_con = initialize_ldap_con(self.account, self.account_password)
105
    login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) 
106
    object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) 
143
#    ldap_con = initialize_ldap_con(self.account, self.account_password)
144
#    login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) 
145
#    object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) 
107 146
    attrs = {}
108 147
    
109
    ldap_con.search( :base => self.base_dn, 
110
                     :filter => object_filter & login_filter, 
111
                     :attributes=> search_attributes) do |entry|
148

  
149
    # Ticket #1913 by Adi Kriegisch (adi@cg.tuwien.ac.at)
150
    if self.account.include? "$login" then
151
      logger.debug "LDAP-Auth with User login" if logger && logger.debug?
152
      ldap_con = initialize_ldap_con(self.account.sub("$login", encode(login)), password)
153
    else
154
      logger.debug "LDAP-Auth with Admin User" if logger && logger.debug?
155
      ldap_con = initialize_ldap_con(self.account, self.account_password)
156
    end
157

  
158
    if self.filter.empty?
159
      filter = self.attr_login + "=" + encode(login)
160
    else
161
      filter = self.filter.gsub("$login", encode(login))
162
    end
163
      
164
      
165
#    ldap_con.search( :base => self.base_dn, 
166
#                     :filter => object_filter & login_filter, 
167
#                     :attributes=> search_attributes) do |entry|
168
    logger.debug "Search in DN: #{self.base_dn} with filter: #{filter}" if logger && logger.debug?
169
    ldap_con.search( self.base_dn, LDAP::LDAP_SCOPE_SUBTREE, filter,
170
                     (onthefly_register? ? ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail] : ['dn'])) { |entry|
112 171

  
113 172
      if onthefly_register?
114 173
        attrs = get_user_attributes_from_ldap_entry(entry)
......
117 176
      end
118 177

  
119 178
      logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
120
    end
179
#    end
180
     }
121 181

  
122 182
    attrs
123 183
  end
......
127 187
      entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
128 188
    end
129 189
  end
190

  
191
  def encode(value)
192
    value = value.gsub("\\", "\\\\5c")
193
    value = value.gsub("*", "\\\\2a")
194
    value = value.gsub("(", "\\\\28")
195
    value = value.gsub(")", "\\\\29")
196
    value = value.gsub("\000", "\\\\00")
197
  end
130 198
end
db/migrate/20110812010830_add_auth_sources_filter_deref_advtls.rb (revision 0)
1
class AddAuthSourcesFilterDerefAdvtls < ActiveRecord::Migration
2
  def self.up
3
    add_column :auth_sources, :starttls, :boolean, :default => false, :null => false
4
    add_column :auth_sources, :filter, :string
5
    add_column :auth_sources, :dereference, :integer
6
    add_column :auth_sources, :require_cert, :integer
7
    add_column :auth_sources, :protocol_version, :integer, :default => 3, :null => false
8
  end
9

  
10
  def self.down
11
    remove_column :auth_sources, :starttls
12
    remove_column :auth_sources, :filter
13
    remove_column :auth_sources, :dereference
14
    remove_column :auth_sources, :require_cert
15
    remove_column :auth_sources, :protocol_version
16
  end
17
end
config/locales/de.yml (working copy)
281 281
  field_port: Port
282 282
  field_account: Konto
283 283
  field_base_dn: Base DN
284
  field_protocol_version: Protokol Version
285
  field_filter: Filter
286
  field_dereference: LDAP Aliase dereferenzieren
287
  field_dereference_never: Nie (standard)
288
  field_dereference_searching: Beim suchen
289
  field_dereference_finding: Beim finden
290
  field_dereference_always: Immer
291
  field_require_cert: Zertifikat verlangen
292
  field_require_cert_never: Nie
293
  field_require_cert_hard: Hart
294
  field_require_cert_demand: Anfordern
295
  field_require_cert_allow: Erlauben
296
  field_require_cert_try: Versuchen
284 297
  field_attr_login: Mitgliedsname-Attribut
285 298
  field_attr_firstname: Vorname-Attribut
286 299
  field_attr_lastname: Name-Attribut
config/locales/en.yml (working copy)
265 265
  field_port: Port
266 266
  field_account: Account
267 267
  field_base_dn: Base DN
268
  field_protocol_version: Protocol version
269
  field_filter: Filter
270
  field_dereference: Dereference LDAP aliases
271
  field_dereference_never: Never (default)
272
  field_dereference_searching: Searching
273
  field_dereference_finding: Finding
274
  field_dereference_always: Always
275
  field_require_cert: Require certificate
276
  field_require_cert_never: Never
277
  field_require_cert_hard: Hard
278
  field_require_cert_demand: Demand
279
  field_require_cert_allow: Allow
280
  field_require_cert_try: Try
268 281
  field_attr_login: Login attribute
269 282
  field_attr_firstname: Firstname attribute
270 283
  field_attr_lastname: Lastname attribute
(5-5/9)