Commit 44cf6703 authored by Felix Schäfer's avatar Felix Schäfer

Merge pull request #142 from elm/custom-ldap-filter

[#388] Custom LDAP filter
parents b135162c 48737b0c
......@@ -21,6 +21,7 @@ class AuthSourceLdap < AuthSource
validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_nil => true
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
validates_numericality_of :port, :only_integer => true
validate :custom_filter_should_be_valid_ldap_filter_syntax
before_validation :strip_ldap_attributes
......@@ -101,10 +102,17 @@ class AuthSourceLdap < AuthSource
ldap_con = initialize_ldap_con(self.account, self.account_password)
login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
custom_ldap_filter = custom_filter_to_ldap
if custom_ldap_filter.present?
search_filters = object_filter & login_filter & custom_ldap_filter
else
search_filters = object_filter & login_filter
end
attrs = {}
ldap_con.search( :base => self.base_dn,
:filter => object_filter & login_filter,
:filter => search_filters,
:attributes=> search_attributes) do |entry|
if onthefly_register?
......@@ -119,6 +127,27 @@ class AuthSourceLdap < AuthSource
attrs
end
def custom_filter_to_ldap
return nil unless custom_filter.present?
begin
return Net::LDAP::Filter.construct(custom_filter)
rescue Net::LDAP::LdapError # Filter syntax error
logger.debug "LDAP custom filter syntax error for: #{custom_filter}" if logger && logger.debug?
return nil
end
end
def custom_filter_should_be_valid_ldap_filter_syntax
return true unless custom_filter.present?
begin
return Net::LDAP::Filter.construct(custom_filter)
rescue Net::LDAP::LdapError # Filter syntax error
errors.add(:custom_filter, :invalid)
end
end
def self.get_attr(entry, attr_name)
if !attr_name.blank?
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
......
......@@ -25,6 +25,9 @@
<p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
<%= check_box 'auth_source', 'onthefly_register' %></p>
<p><label for="auth_source_custom_filter"><%=l(:field_custom_filter)%></label>
<%= text_field 'auth_source', 'custom_filter', :size => 60 %></p>
</div>
<fieldset class="box"><legend><%=l(:label_attribute_plural)%></legend>
......
......@@ -307,6 +307,7 @@ en:
field_text: Text field
field_visible: Visible
field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"
field_custom_filter: Custom LDAP filter
setting_app_title: Application title
setting_app_subtitle: Application subtitle
......
class AddCustomFilterToAuthSources < ActiveRecord::Migration
def self.up
add_column :auth_sources, :custom_filter, :string
end
def self.down
remove_column :auth_sources, :custom_filter
end
end
# This is a configuration for a new database to test the ldap plugin.
# It is assumed that you have a ldap server up and running. Do not
# use this file on a new openldap installation.
# Database settings
dn: olcDatabase=hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: hdb
olcSuffix: dc=redmine,dc=org
# WARNING: Do not use a directory that already contains a ldap database.
# Each database has to be stored in a seperate directory. The directory
# /var/lib/ldap is the default directory on Debian.
olcDbDirectory: /var/lib/ldap/redmine
olcRootDN: cn=Manager,dc=redmine,dc=org
olcRootPW: secret
olcDbConfig: set_cachesize 0 2097152 0
olcDbConfig: set_lk_max_objects 1500
olcDbConfig: set_lk_max_locks 1500
olcDbConfig: set_lk_max_lockers 1500
olcDbIndex: objectClass eq
olcLastMod: TRUE
olcDbCheckpoint: 512 30
olcAccess: to attrs=userPassword by dn="cn=Manager,dc=redmine,dc=org" write by anonymous auth by self write by * none
olcAccess: to attrs=shadowLastChange by self write by * read
olcAccess: to dn.base="" by * read
olcAccess: to * by dn="cn=Manager,dc=redmine,dc=org" write by * read
......@@ -4,39 +4,11 @@ objectClass: dcObject
objectClass: organization
o: redmine.org
dc: redmine
structuralObjectClass: organization
entryUUID: 886f5fca-0a87-102e-8d06-67c361d9bd2d
creatorsName:
createTimestamp: 20090721211642Z
entryCSN: 20090721211642.955188Z#000000#000#000000
modifiersName:
modifyTimestamp: 20090721211642Z
dn: cn=admin,dc=redmine,dc=org
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e2NyeXB0fWlWTU9DcUt6WWxXRDI=
structuralObjectClass: organizationalRole
entryUUID: 88704e44-0a87-102e-8d07-67c361d9bd2d
creatorsName:
createTimestamp: 20090721211642Z
entryCSN: 20090721211642.961418Z#000000#000#000000
modifiersName:
modifyTimestamp: 20090721211642Z
dn: ou=Person,dc=redmine,dc=org
ou: Person
objectClass: top
objectClass: organizationalUnit
structuralObjectClass: organizationalUnit
entryUUID: d39dd388-0c84-102e-82fa-dff86c63a7d6
creatorsName: cn=admin,dc=redmine,dc=org
createTimestamp: 20090724100222Z
entryCSN: 20090724100222.924226Z#000000#000#000000
modifiersName: cn=admin,dc=redmine,dc=org
modifyTimestamp: 20090724100222Z
dn: uid=example1,ou=Person,dc=redmine,dc=org
objectClass: posixAccount
......@@ -48,16 +20,9 @@ sn: One
uid: example1
homeDirectory: /home/example1
cn: Example One
structuralObjectClass: inetOrgPerson
entryUUID: 285d304e-0c8a-102e-82fc-dff86c63a7d6
creatorsName: cn=admin,dc=redmine,dc=org
createTimestamp: 20090724104032Z
uidNumber: 0
mail: example1@redmine.org
userPassword:: e1NIQX1mRXFOQ2NvM1lxOWg1WlVnbEQzQ1pKVDRsQnM9
entryCSN: 20090724105945.375801Z#000000#000#000000
modifiersName: cn=admin,dc=redmine,dc=org
modifyTimestamp: 20090724105945Z
dn: uid=edavis,ou=Person,dc=redmine,dc=org
objectClass: posixAccount
......@@ -68,15 +33,8 @@ givenName: Eric
sn: Davis
uid: edavis
mail: edavis@littlestreamsoftware.com
structuralObjectClass: inetOrgPerson
entryUUID: 9c5f0502-0c8b-102e-82fe-dff86c63a7d6
creatorsName: cn=admin,dc=redmine,dc=org
createTimestamp: 20090724105056Z
homeDirectory: /home/edavis
cn: Eric Davis
uidNumber: 0
userPassword:: e1NIQX1mRXFOQ2NvM1lxOWg1WlVnbEQzQ1pKVDRsQnM9
entryCSN: 20090724105937.734480Z#000000#000#000000
modifiersName: cn=admin,dc=redmine,dc=org
modifyTimestamp: 20090724105937Z
......@@ -31,6 +31,20 @@ class AuthSourceLdapTest < ActiveSupport::TestCase
assert_equal 'givenName', a.reload.attr_firstname
end
context "validations" do
should "validate that custom_filter is a valid LDAP filter" do
@auth = AuthSourceLdap.new(:name => 'Validation', :host => 'localhost', :port => 389, :attr_login => 'login')
@auth.custom_filter = "(& (homeDirectory=*) (sn=O*" # Missing ((
assert @auth.invalid?
assert_equal "is invalid", @auth.errors.on(:custom_filter)
@auth.custom_filter = "(& (homeDirectory=*) (sn=O*))"
assert @auth.valid?
assert_equal nil, @auth.errors.on(:custom_filter)
end
end
if ldap_configured?
context '#authenticate' do
setup do
......@@ -69,6 +83,32 @@ class AuthSourceLdapTest < ActiveSupport::TestCase
end
end
context "using a valid custom filter" do
setup do
@auth.update_attributes(:custom_filter => "(& (homeDirectory=*) (sn=O*))")
end
should "find a user who authenticates and matches the custom filter" do
assert_not_nil @auth.authenticate('example1', '123456')
end
should "be nil for users who don't match the custom filter" do
assert_nil @auth.authenticate('edavis', '123456')
end
end
context "using an invalid custom filter" do
setup do
# missing )) at the end
@auth.update_attributes(:custom_filter => "(& (homeDirectory=*) (sn=O*")
end
should "skip the custom filter" do
assert_not_nil @auth.authenticate('example1', '123456')
assert_not_nil @auth.authenticate('edavis', '123456')
end
end
end
else
puts '(Test LDAP server not configured)'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment