From dbdaff9421e2b6142a0d280f3ef0da7e71a491f5 Mon Sep 17 00:00:00 2001 From: Yann Date: Thu, 24 Nov 2016 20:29:09 +0100 Subject: [PATCH] Add htpasswd file support for user authentication Fixes based on merge request discussion by Luc Didry: https://framagit.org/luc/lufi/merge_requests/7 Coding style --- cpanfile | 1 + lib/Lufi.pm | 78 +++++++++++-------- lib/Lufi/Controller/Files.pm | 8 +- lufi.conf.template | 4 + .../default/templates/layouts/default.html.ep | 8 +- 5 files changed, 59 insertions(+), 40 deletions(-) mode change 100644 => 100755 lib/Lufi.pm mode change 100644 => 100755 lufi.conf.template diff --git a/cpanfile b/cpanfile index 358d0d4..3502780 100644 --- a/cpanfile +++ b/cpanfile @@ -16,3 +16,4 @@ requires 'Switch'; requires 'Data::Entropy'; requires 'Net::LDAP'; requires 'Crypt::SaltedHash'; +requires 'Apache::Htpasswd'; diff --git a/lib/Lufi.pm b/lib/Lufi.pm old mode 100644 new mode 100755 index 5374754..d53e842 --- a/lib/Lufi.pm +++ b/lib/Lufi.pm @@ -4,6 +4,7 @@ use Mojo::Base 'Mojolicious'; use LufiDB; use Data::Entropy qw(entropy_source); use Net::LDAP; +use Apache::Htpasswd; $ENV{MOJO_MAX_WEBSOCKET_SIZE} = 100485760; # 10 * 1024 * 1024 = 10MiB @@ -62,6 +63,9 @@ sub startup { # Debug $self->plugin('DebugDumperHelper'); + # Check htpasswd file existence + die 'Unable to read '.$self->config('htpasswd') if (defined($self->config('htpasswd')) && !-r $self->config('htpasswd')); + # Authentication (if configured) $self->plugin('authentication' => { @@ -75,41 +79,51 @@ sub startup { validate_user => sub { my ($c, $username, $password, $extradata) = @_; - my $ldap = Net::LDAP->new($c->config->{ldap}->{uri}); - my $mesg = $ldap->bind($c->config->{ldap}->{bind_user}.$c->config->{ldap}->{bind_dn}, - password => $c->config->{ldap}->{bind_pwd} - ); - - $mesg->code && die $mesg->error; - - $mesg = $ldap->search( - base => $c->config->{ldap}->{user_tree}, - filter => "(&(uid=$username)".$c->config->{ldap}->{user_filter}.")" - ); - - if ($mesg->code) { - $c->app->log->error($mesg->error); - return undef; + if (defined($c->config('ldap'))) { + my $ldap = Net::LDAP->new($c->config->{ldap}->{uri}); + my $mesg = $ldap->bind($c->config->{ldap}->{bind_user}.$c->config->{ldap}->{bind_dn}, + password => $c->config->{ldap}->{bind_pwd} + ); + + $mesg->code && die $mesg->error; + + $mesg = $ldap->search( + base => $c->config->{ldap}->{user_tree}, + filter => "(&(uid=$username)".$c->config->{ldap}->{user_filter}.")" + ); + + if ($mesg->code) { + $c->app->log->error($mesg->error); + return undef; + } + + # Now we know that the user exists + $mesg = $ldap->bind('uid='.$username.$c->config->{ldap}->{bind_dn}, + password => $password + ); + + if ($mesg->code) { + $c->app->log->info("[LDAP authentication failed] login: $username, IP: ".$c->ip); + $c->app->log->error("[LDAP authentication failed] ".$mesg->error); + return undef; + } + + $c->app->log->info("[LDAP authentication successful] login: $username, IP: ".$c->ip); + } elsif (defined($c->config('htpasswd'))) { + my $htpasswd = new Apache::Htpasswd({passwdFile => $c->config->{htpasswd}, + ReadOnly => 1} + ); + if (!$htpasswd->htCheckPassword($username, $password)) { + return undef; + } + $c->app->log->info("[Simple authentication successful] login: $username, IP: ".$c->ip); } - # Now we know that the user exists - $mesg = $ldap->bind('uid='.$username.$c->config->{ldap}->{bind_dn}, - password => $password - ); - - if ($mesg->code) { - $c->app->log->info("[LDAP authentication failed] login: $username, IP: ".$c->ip); - $c->app->log->error("[LDAP authentication failed] ".$mesg->error); - return undef; - } - - $c->app->log->info("[LDAP authentication successful] login: $username, IP: ".$c->ip); - return $username; } } ); - if (defined($self->config('ldap'))) { + if (defined($self->config('ldap')) || defined($self->config('htpasswd'))) { $self->app->sessions->default_expiration($self->config('session_duration')); } @@ -249,14 +263,14 @@ sub startup { # Page for files uploading $r->get('/' => sub { my $c = shift; - if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) { $c->render(template => 'index'); } else { $c->redirect_to('login'); } })->name('index'); - if (defined $self->config('ldap')) { + if (defined $self->config('ldap') || defined $self->config('htpasswd')) { # Login page $r->get('/login' => sub { my $c = shift; @@ -302,7 +316,7 @@ sub startup { # List of files (use localstorage, so the server know nothing about files) $r->get('/files' => sub { my $c = shift; - if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) { $c->render(template => 'files'); } else { $c->redirect_to('login'); diff --git a/lib/Lufi/Controller/Files.pm b/lib/Lufi/Controller/Files.pm index b25bca6..614693b 100644 --- a/lib/Lufi/Controller/Files.pm +++ b/lib/Lufi/Controller/Files.pm @@ -14,7 +14,7 @@ use Crypt::SaltedHash; sub upload { my $c = shift; - if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) { $c->inactivity_timeout(30000000); $c->app->log->debug('Client connected'); @@ -109,7 +109,7 @@ sub upload { } my $creator = $c->ip; - if (defined($c->config('ldap'))) { + if (defined($c->config('ldap')) || defined($c->config('htpasswd'))) { $creator = 'User: '.$c->current_user.', IP: '.$creator; } $f = Lufi::File->new( @@ -329,7 +329,7 @@ sub get_counter { my $short = $c->param('short'); my $token = $c->param('token'); - if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) { my @records = LufiDB::Files->select('WHERE short = ?', $short); if (scalar(@records)) { if ($records[0]->mod_token eq $token) { @@ -378,7 +378,7 @@ sub delete { my $short = $c->param('short'); my $token = $c->param('token'); - if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) { my @records = LufiDB::Files->select('WHERE short = ? AND mod_token = ?', ($short, $token)); if (scalar(@records)) { my $f = Lufi::File->new(record => $records[0]); diff --git a/lufi.conf.template b/lufi.conf.template old mode 100644 new mode 100755 index 33aefac..56bda8f --- a/lufi.conf.template +++ b/lufi.conf.template @@ -132,6 +132,10 @@ # user_filter => '!(uid=ldap_user)' #}, + # set `htpasswd` if you want to use an htpasswd file instead of ldap + # see 'man htpasswd' to know how to create such file + #htpasswd => 'lufi.passwd', + # if you've set ldap above, the session will last `session_duration` seconds before # the user needs to reauthenticate # optional, default is 3600 diff --git a/themes/default/templates/layouts/default.html.ep b/themes/default/templates/layouts/default.html.ep index 67b7ddc..faf03be 100644 --- a/themes/default/templates/layouts/default.html.ep +++ b/themes/default/templates/layouts/default.html.ep @@ -31,26 +31,26 @@