I have just finished getting LDAP authentication working with Coquelicot (modelled very closely on the existing IMAP code), and would love to share it back to the project, but am not sure exactly where and how. I doubt I have access to interact with the repo in any way other than cloning from it, and I doubt you would want me to email a huge patch to the mailing list? Should I upload my repo to github or somewhere public like that, for you to pull from? Or can I send you a pull request somewhere?
Rowan Thorpe:
I have just finished getting LDAP authentication working with Coquelicot (modelled very closely on the existing IMAP code), and would love to share it back to the project, but am not sure exactly where and how. I doubt I have access to interact with the repo in any way other than cloning from it, and I doubt you would want me to email a huge patch to the mailing list? Should I upload my repo to github or somewhere public like that, for you to pull from? Or can I send you a pull request somewhere?
I would gladly accept a patch or a pull request sent to this mailing list. :) Thanks for your interest in Coquelicot!
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--
From fa4f5811de85273daa8b1d8f3bb347a9e5f3b73a Mon Sep 17 00:00:00 2001
Message-Id: fa4f5811de85273daa8b1d8f3bb347a9e5f3b73a.1396427308.git.rowan@rowanthorpe.com In-Reply-To: 01dd956a5ffbc0cdeffbcc62fc190695baa049f2.1396340195.git.rowan@rowanthorpe.com References: 01dd956a5ffbc0cdeffbcc62fc190695baa049f2.1396340195.git.rowan@rowanthorpe.com From: Rowan Thorpe rowan@rowanthorpe.com Date: Wed, 2 Apr 2014 11:25:25 +0300 Subject: [PATCH] Change a couple of wrongly copied vars in coquelicot_spec To: coquelicot@potager.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------1.9.1"
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
--- spec/coquelicot_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--------------1.9.1 Content-Type: text/x-patch; name="0001-Change-a-couple-of-wrongly-copied-vars-in-coquelicot.patch" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="0001-Change-a-couple-of-wrongly-copied-vars-in-coquelicot.patch"
diff --git a/spec/coquelicot_spec.rb b/spec/coquelicot_spec.rb index 9022aff..a92abaf 100644 --- a/spec/coquelicot_spec.rb +++ b/spec/coquelicot_spec.rb @@ -350,8 +350,8 @@ PART 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') + ldap = stub('Net::LDAP').as_null_object + ldap.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',
--------------1.9.1--
Hi again,
I squashed it to a single commit, which is below (can be applied in git, as it is "git format-patch" output). You may wish to add in the docs that the underlying ldap module doesn't validate server certs yet - I just added it as an in-code comment. Also, the copyright notices will need bumping to 2014 :-)
=====
From f0a89e471d6387ead50bcb5e5246595e0d88a439 Mon Sep 17 00:00:00 2001
Message-Id: f0a89e471d6387ead50bcb5e5246595e0d88a439.1396437566.git.rowan@rowanthorpe.com In-Reply-To: 20140402102720.GA22057@loar References: 20140402102720.GA22057@loar From: Rowan Thorpe rowan@rowanthorpe.com Date: Mon, 31 Mar 2014 20:01:56 +0300 Subject: [PATCH] Add LDAP authentication (with uid lookup) To: coquelicot@potager.org
--- 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
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..a92abaf 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 + ldap = stub('Net::LDAP').as_null_object + ldap.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' }
Hi!
Rowan Thorpe:
I squashed it to a single commit, which is below (can be applied in git, as it is "git format-patch" output). You may wish to add in the docs that the underlying ldap module doesn't validate server certs yet - I just added it as an in-code comment. Also, the copyright notices will need bumping to 2014 :-)
I'm finally getting to your patch. I have a couple of changes in the way, but I just wanted to highlight one thing:
result = ldap.bind_as( :base => settings.ldap_base,
:filter => "(uid=" + params[:ldap_user] + ")",
:password => params[:ldap_password] )
This code puts a user controlled string directly into the filter. Bad idea. Net::Ldap::Filter provides an `escape` method which is made for these occasions.
On 16:51 Tue 06 May 2014, Lunar wrote:
..[snip]..
result = ldap.bind_as( :base => settings.ldap_base,
:filter => "(uid=" + params[:ldap_user] + ")",
:password => params[:ldap_password] )
This code puts a user controlled string directly into the filter. Bad idea. Net::Ldap::Filter provides an `escape` method which is made for these occasions.
Wow, how did I miss that(!) Even being a relative non-ruby developor is not much of an excuse... Thanks for spotting it, and reminding me of the dangers of late-night coding in unfamiliar languages ;-)
I guess I'll go and drop some tables now - https://xkcd.com/327/