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
This commit is contained in:
Yann 2016-11-24 20:29:09 +01:00
parent 9d5bb760e5
commit d4afe13f05
5 changed files with 59 additions and 40 deletions

View File

@ -15,3 +15,4 @@ requires 'Filesys::DfPortable';
requires 'Switch'; requires 'Switch';
requires 'Data::Entropy'; requires 'Data::Entropy';
requires 'Net::LDAP'; requires 'Net::LDAP';
requires 'Apache::Htpasswd';

22
lib/Lufi.pm Normal file → Executable file
View File

@ -4,6 +4,7 @@ use Mojo::Base 'Mojolicious';
use LufiDB; use LufiDB;
use Data::Entropy qw(entropy_source); use Data::Entropy qw(entropy_source);
use Net::LDAP; use Net::LDAP;
use Apache::Htpasswd;
$ENV{MOJO_MAX_WEBSOCKET_SIZE} = 100485760; # 10 * 1024 * 1024 = 10MiB $ENV{MOJO_MAX_WEBSOCKET_SIZE} = 100485760; # 10 * 1024 * 1024 = 10MiB
@ -61,6 +62,9 @@ sub startup {
# Debug # Debug
$self->plugin('DebugDumperHelper'); $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) # Authentication (if configured)
$self->plugin('authentication' => $self->plugin('authentication' =>
{ {
@ -74,6 +78,7 @@ sub startup {
validate_user => sub { validate_user => sub {
my ($c, $username, $password, $extradata) = @_; my ($c, $username, $password, $extradata) = @_;
if (defined($c->config('ldap'))) {
my $ldap = Net::LDAP->new($c->config->{ldap}->{uri}); my $ldap = Net::LDAP->new($c->config->{ldap}->{uri});
my $mesg = $ldap->bind($c->config->{ldap}->{bind_user}.$c->config->{ldap}->{bind_dn}, my $mesg = $ldap->bind($c->config->{ldap}->{bind_user}.$c->config->{ldap}->{bind_dn},
password => $c->config->{ldap}->{bind_pwd} password => $c->config->{ldap}->{bind_pwd}
@ -103,12 +108,21 @@ sub startup {
} }
$c->app->log->info("[LDAP authentication successful] login: $username, IP: ".$c->ip); $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);
}
return $username; 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')); $self->app->sessions->default_expiration($self->config('session_duration'));
} }
@ -238,14 +252,14 @@ sub startup {
# Page for files uploading # Page for files uploading
$r->get('/' => sub { $r->get('/' => sub {
my $c = shift; 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'); $c->render(template => 'index');
} else { } else {
$c->redirect_to('login'); $c->redirect_to('login');
} }
})->name('index'); })->name('index');
if (defined $self->config('ldap')) { if (defined $self->config('ldap') || defined $self->config('htpasswd')) {
# Login page # Login page
$r->get('/login' => sub { $r->get('/login' => sub {
my $c = shift; my $c = shift;
@ -291,7 +305,7 @@ sub startup {
# List of files (use localstorage, so the server know nothing about files) # List of files (use localstorage, so the server know nothing about files)
$r->get('/files' => sub { $r->get('/files' => sub {
my $c = shift; 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'); $c->render(template => 'files');
} else { } else {
$c->redirect_to('login'); $c->redirect_to('login');

View File

@ -13,7 +13,7 @@ use Filesys::DfPortable;
sub upload { sub upload {
my $c = shift; 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->inactivity_timeout(30000000);
$c->app->log->debug('Client connected'); $c->app->log->debug('Client connected');
@ -97,7 +97,7 @@ sub upload {
} }
my $creator = $c->ip; 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; $creator = 'User: '.$c->current_user.', IP: '.$creator;
} }
$f = Lufi::File->new( $f = Lufi::File->new(
@ -303,7 +303,7 @@ sub get_counter {
my $short = $c->param('short'); my $short = $c->param('short');
my $token = $c->param('token'); 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); my @records = LufiDB::Files->select('WHERE short = ?', $short);
if (scalar(@records)) { if (scalar(@records)) {
if ($records[0]->mod_token eq $token) { if ($records[0]->mod_token eq $token) {
@ -352,7 +352,7 @@ sub delete {
my $short = $c->param('short'); my $short = $c->param('short');
my $token = $c->param('token'); 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)); my @records = LufiDB::Files->select('WHERE short = ? AND mod_token = ?', ($short, $token));
if (scalar(@records)) { if (scalar(@records)) {
my $f = Lufi::File->new(record => $records[0]); my $f = Lufi::File->new(record => $records[0]);

4
lufi.conf.template Normal file → Executable file
View File

@ -132,6 +132,10 @@
# user_filter => '!(uid=ldap_user)' # 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 # if you've set ldap above, the session will last `session_duration` seconds before
# the user needs to reauthenticate # the user needs to reauthenticate
# optional, default is 3600 # optional, default is 3600

View File

@ -31,26 +31,26 @@
<a href="<%= url_for('/') %>" class="brand-logo">&nbsp;<img src="<%= url_for('/img/lufi-min.png') %>" alt="logo"> Lufi</a> <a href="<%= url_for('/') %>" class="brand-logo">&nbsp;<img src="<%= url_for('/img/lufi-min.png') %>" alt="logo"> Lufi</a>
<a href="#" data-activates="mobile-demo" class="button-collapse"><i class="mdi-navigation-menu"></i></a> <a href="#" data-activates="mobile-demo" class="button-collapse"><i class="mdi-navigation-menu"></i></a>
<ul id="nav-mobile" class="right hide-on-med-and-down"> <ul id="nav-mobile" class="right hide-on-med-and-down">
% if (!defined(config('ldap')) || is_user_authenticated()) { % if ((!defined(config('ldap')) && !defined(config('htpasswd'))) || is_user_authenticated()) {
<li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li> <li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li>
<li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li> <li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li>
% } else { % } else {
<li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li> <li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
% } % }
<li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li> <li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li>
% if (defined(config('ldap')) && is_user_authenticated()) { % if ((defined(config('ldap')) || defined(config('htpasswd'))) && is_user_authenticated()) {
<li><a href="<%= url_for('/logout') %>"><%= l('Logout') %></a></li> <li><a href="<%= url_for('/logout') %>"><%= l('Logout') %></a></li>
% } % }
</ul> </ul>
<ul id="mobile-demo" class="side-nav"> <ul id="mobile-demo" class="side-nav">
% if (!defined(config('ldap')) || is_user_authenticated()) { % if ((!defined(config('ldap')) && !defined(config('htpasswd'))) || is_user_authenticated()) {
<li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li> <li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li>
<li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li> <li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li>
% } else { % } else {
<li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li> <li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
% } % }
<li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li> <li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li>
% if (defined(config('ldap')) && is_user_authenticated()) { % if ((defined(config('ldap')) || defined(config('htpasswd'))) && is_user_authenticated()) {
<li><a href="<%= url_for('/logout') %>"><%= l('Logout') %></a></li> <li><a href="<%= url_for('/logout') %>"><%= l('Logout') %></a></li>
% } % }
</ul> </ul>