This is a multi-part message in MIME format. --------------1.9.1 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit
--- INSTALL | 3 ++ README | 4 +- conf/settings-default.yml | 4 +- conf/settings-ldap.yml | 20 +++++++++ lib/coquelicot/auth/ldap.rb | 68 ++++++++++++++++++++++++++++++ po/coquelicot.pot | 6 ++- po/de/coquelicot.po | 6 ++- po/fr/coquelicot.po | 6 ++- public/javascripts/coquelicot.auth.ldap.js | 45 ++++++++++++++++++++ spec/coquelicot_spec.rb | 18 ++++++++ views/auth/ldap.haml | 24 +++++++++++ 11 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 conf/settings-ldap.yml create mode 100644 lib/coquelicot/auth/ldap.rb create mode 100644 public/javascripts/coquelicot.auth.ldap.js create mode 100644 views/auth/ldap.haml
--------------1.9.1 Content-Type: text/x-patch; name="0001-Add-LDAP-authentication-with-uid-lookup.patch" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="0001-Add-LDAP-authentication-with-uid-lookup.patch"
diff --git a/INSTALL b/INSTALL index 2e571b3..ebd826b 100644 --- a/INSTALL +++ b/INSTALL @@ -134,6 +134,9 @@ Further settings example: * `conf/settings-imap.yml`: necessary configuration for the "imap" authentication mechanism.
+ * `conf/settings-ldap.yml`: necessary configuration for the "ldap" + authentication mechanism. + You can copy one of these examples to `conf/settings.yml` and adjust them according to your environment.
diff --git a/README b/README index 7571d3b..3533d63 100644 --- a/README +++ b/README @@ -21,12 +21,14 @@ Features
In order to prevent random Internet users to eat bandwidth and disk space, Coquelicot limits upload to authenticated users. - It currently ships with two authentication mechanisms: + It currently ships with three authentication mechanisms:
- "simplepass": uploading users need to provide a global, pre-shared, password; - "imap": users will need to provide a login and a password, that are used to authenticate against an existing IMAP server. + - "ldap": users will need to provide a uid and a password, + that are used to authenticate against an existing LDAP server.
It is possible to integrate more authentication mechanisms by implementing a single method, some JavaScript, and a partial template diff --git a/conf/settings-default.yml b/conf/settings-default.yml index 8077fa9..ebb2012 100644 --- a/conf/settings-default.yml +++ b/conf/settings-default.yml @@ -110,8 +110,8 @@ show_exceptions: false
# Authentication method # -# Please have look at `conf/settings-simplepass.yml` and -# `conf/settings-imap.yml` for more details. +# Please have a look at `conf/settings-simplepass.yml`, +# `conf/settings-imap.yml` and `conf/settings-ldap.yml` for more details. # # The default password is 'test'. authentication_method: diff --git a/conf/settings-ldap.yml b/conf/settings-ldap.yml new file mode 100644 index 0000000..6151bf7 --- /dev/null +++ b/conf/settings-ldap.yml @@ -0,0 +1,20 @@ +# Settings for the LDAP authentication method +# ------------------------------------------- +# +# When using the LDAP authentication method users will be +# asked for a login and a password. Those credentials will +# be tested against the given LDAP server. +# +# Connections to the LDAP server are made using SSL/TLS. + +authentication_method: + name: ldap + + # Hostname of the authenticating LDAP server + ldap_server: "ldap.example.com" + + # Port of the authenticating LDAP server + ldap_port: 636 + + # Search base of the authenticating LDAP server + ldap_base: "dc=example,dc=com" diff --git a/lib/coquelicot/auth/ldap.rb b/lib/coquelicot/auth/ldap.rb new file mode 100644 index 0000000..fee3783 --- /dev/null +++ b/lib/coquelicot/auth/ldap.rb @@ -0,0 +1,68 @@ +# -*- coding: UTF-8 -*- +# Coquelicot: "one-click" file sharing with a focus on users' privacy. +# Copyright © 2012-2013 potager.org jardiniers@potager.org +# © 2011 mh / immerda.ch mh+coquelicot@immerda.ch +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +# TODO: set array of multiple ldap servers in settings and loop over them to +# find first matching UID to connect as + +# TODO: add commented code showing how to direct login by full username, +# without lookup + +# TODO: add commented code showing how to use starttls as an option instead of +# dedicated SSL port, too + +# NB: :simple_tls ensures all communication is encrypted, but it doesn't +# verify the server-certificate. A method which does *both* doesn't +# seem to exist in Net::LDAP yet... + +require 'net/ldap' +module Coquelicot + module Auth + class LdapAuthenticator < AbstractAuthenticator + def authenticate(params) + if params[:ldap_user].empty? or params[:ldap_password].empty? + raise Coquelicot::Auth::Error.new( + 'Disallowing empty uid/password - might "auth" anonymous user on server') + end + # connect anonymously & lookup user to do authenticated bind_as() next + ldap = Net::LDAP.new( :host => settings.ldap_server, + :port => settings.ldap_port, + :base => settings.ldap_base, + :encryption => :simple_tls, + :auth => { :method => :anonymous } ) + result = ldap.bind_as( :base => settings.ldap_base, + :filter => "(uid=" + params[:ldap_user] + ")", + :password => params[:ldap_password] ) + if not(result) + raise Coquelicot::Auth::Error.new( + 'Failed authentication to LDAP server') + end + true + rescue Errno::ECONNREFUSED + raise Coquelicot::Auth::Error.new( + 'Unable to connect to LDAP server') + rescue NoMethodError => ex + if [ :ldap_server, :ldap_port, :ldap_base ].include? ex.name + raise Coquelicot::Auth::Error.new( + "Missing '#{ex.name}' attribute in configuration.") + else + raise + end + end + end + end +end diff --git a/po/coquelicot.pot b/po/coquelicot.pot index 503dd26..cf1fadc 100644 --- a/po/coquelicot.pot +++ b/po/coquelicot.pot @@ -49,7 +49,11 @@ msgstr "" msgid "E-mail User:" msgstr ""
-#: views/auth/imap.haml:23 views/enter_file_key.haml:22 +#: views/auth/ldap.haml:20 +msgid "LDAP User:" +msgstr "" + +#: views/auth/imap.haml:23 views/auth/ldap.haml:23 views/enter_file_key.haml:22 msgid "Password:" msgstr ""
diff --git a/po/de/coquelicot.po b/po/de/coquelicot.po index c0b45ed..ce9e739 100644 --- a/po/de/coquelicot.po +++ b/po/de/coquelicot.po @@ -48,7 +48,11 @@ msgstr "Upload Passwort:" msgid "E-mail User:" msgstr "Email User:"
-#: views/auth/imap.haml:23 views/enter_file_key.haml:22 +#: views/auth/ldap.haml:20 +msgid "LDAP User:" +msgstr "LDAP User:" + +#: views/auth/imap.haml:23 views/auth/ldap.haml:23 views/enter_file_key.haml:22 msgid "Password:" msgstr "Passwort:"
diff --git a/po/fr/coquelicot.po b/po/fr/coquelicot.po index c5230c3..9e8e9e0 100644 --- a/po/fr/coquelicot.po +++ b/po/fr/coquelicot.po @@ -48,7 +48,11 @@ msgstr "Mot de passe pour envoyer :" msgid "E-mail User:" msgstr "Compte email :"
-#: views/auth/imap.haml:23 views/enter_file_key.haml:22 +#: views/auth/ldap.haml:20 +msgid "LDAP User:" +msgstr "Compte LDAP :" + +#: views/auth/imap.haml:23 views/auth/ldap.haml:23 views/enter_file_key.haml:22 msgid "Password:" msgstr "Mot de passe :"
diff --git a/public/javascripts/coquelicot.auth.ldap.js b/public/javascripts/coquelicot.auth.ldap.js new file mode 100644 index 0000000..eca3928 --- /dev/null +++ b/public/javascripts/coquelicot.auth.ldap.js @@ -0,0 +1,45 @@ +/* + * Coquelicot: "one-click" file sharing with a focus on users' privacy. + * Copyright © 2012-2013 potager.org jardiniers@potager.org + * © 2011 mh / immerda.ch mh+coquelicot@immerda.ch + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +var authentication = { + getData: function() { + return { + ldap_user: $('#ldap_user').val(), + ldap_password: $('#ldap_password').val() + }; + }, + focus: function() { + $('#ldap_user').focus(); + }, + handleReject: function() { + $('#ldap_user').val(''); + $('#ldap_password').val(''); + }, +}; + +$(document).ready(function() { + $('#ldap-auth-submit').remove(); + var submit = $('<input type="submit" />'); + submit.attr('value', 'Login'); + submit.attr('id', 'ldap-auth-submit'); + $('#upload-authentication').append( + $('<div class="field" />').append( + $('<div class="submit" />').append( + submit))); +}); diff --git a/spec/coquelicot_spec.rb b/spec/coquelicot_spec.rb index 226ab87..9022aff 100644 --- a/spec/coquelicot_spec.rb +++ b/spec/coquelicot_spec.rb @@ -341,4 +341,22 @@ PART last_response.should be_ok end end + + context "when using 'ldap' authentication mechanism" do + before(:each) do + app.set :authentication_method, :name => 'ldap', + :ldap_server => 'example.org', + :ldap_port => 636 + end + + it "should try to login to the LDAP server when using AJAX" do + imap = stub('Net::LDAP').as_null_object + imap.should_receive(:login).with('user', 'password') + Net::LDAP.should_receive(:new).with('example.org', 636, "dc=example, dc=com", :simple_tls, { :method => :anonymous }).and_return(ldap) + request "/authenticate", :method => "POST", :xhr => true, + :params => { :ldap_user => 'user', + :ldap_password => 'password' } + last_response.should be_ok + end + end end diff --git a/views/auth/ldap.haml b/views/auth/ldap.haml new file mode 100644 index 0000000..202b158 --- /dev/null +++ b/views/auth/ldap.haml @@ -0,0 +1,24 @@ +-# -*- coding: UTF-8 -*- +-# Coquelicot: "one-click" file sharing with a focus on users' privacy. +-# Copyright © 2012-2013 potager.org jardiniers@potager.org +-# © 2011 mh / immerda.ch mh+coquelicot@immerda.ch +-# +-# This program is free software: you can redistribute it and/or modify +-# it under the terms of the GNU Affero General Public License as +-# published by the Free Software Foundation, either version 3 of the +-# License, or (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU Affero General Public License for more details. +-# +-# You should have received a copy of the GNU Affero General Public License +-# along with this program. If not, see http://www.gnu.org/licenses/. + +.field + %label{ :for => 'ldap_user' } LDAP User: + %input.input{ :type => 'text', :id => 'ldap_user', :name => 'ldap_user' } +.field + %label{ :for => 'ldap_password' } Password: + %input.input{ :type => 'password', :id => 'ldap_password', :name => 'ldap_password' }
--------------1.9.1--