Session or form-based authentication
Session vs. Basic authentication
Pros:- "real" logout button
- "nice" login screen
- user-based setuid/setgid wrapping is possible but not really fast (exception: with Speedy-CGI if available)
- two different URLs for WebDAV access and web interface with all consequences for setup effort, user support, security
- sessions can be attacked (CRSF, man-in-the-middle, ...)
- a matching authentication handler written in Perl
- additional session files on the server
Features
- form login customization
- domain based authentication support: let the user select a domain in login screen
- authentication handler for LDAP (simple bind authentication), Kerberos for SMB backend, Kerberos/AFS for AFS backend, Apache htpasswd files
- support for suid/setgid wrapped WebDAV and web interface access
Requirements
- follow the installation documentation
- some new Perl modules:
- CGI::Session (Debian/Ubuntu: apt install libcgi-session-perl)
- WWW::CSRF (Debian/Ubuntu: apt install libwww-csrf-perl)
- two configurations for Apache und WebDAV CGI:
- web interface needs a session setup
- WebDAV uses another Perl script
Setup recommendations
| Backend | ModPerl | setuid/setgid wrapper | Required CGI scripts/wrappers | Authentication handler |
|---|---|---|---|---|
| AFS | best performance | UID/GID not used | webdav.pl and session.pl | SessionAuthenticationHandler::AfsKerberosAuthHandler |
| SMB | best performance | UID/GID not used | webdav.pl and session.pl | SessionAuthenticationHandler::KerberosAuthHandler |
| DBB | best performance | UID/GID not used | webdav.pl and session.pl | SessionAuthenticationHandler::LdapBindAuthHandler SessionAuthenticationHandler::HtpasswdAuthHandler |
| FS / GFS / GIT / RCS | no effect on wrapped webdav.pl script but usable for session.pl and webdav-susession.pl | on user-based, group-based, or ACL-based file/folder access rights | session.pl, webdav-susession.pl, webdavwrapper, webdav.pl | SessionAuthenticationHandler::LdapBindAuthHandler SessionAuthenticationHandler::HtpasswdAuthHandler |
Setup
WebDAV CGI
The WebDAV and the web interface setup differ in two aspects:-
$VIRTUAL_BASE- you need two URLs, so the VIRTUAL_BASE differs -
%SESSION- only the web interface setup and wrapper scripts like session.pl and webdav-susession.pl for WebDAV access must have this
WebDAV setup:
/etc/webdav.conf:
... # set this only if you don't use domain based defaults (see defaults in %SESSION domain setup): $DOCUMENT_ROOT='/myuserpath/'; $BACKED = 'FS'; $VIRTUAL_BASE='/webdav/?'; # additional: disable web interface to prevent misuse: $FANCYINDEXING = 0; # and redirect the user to the right session login: $REDIRECT_TO = '/'; # to be sure we have no session setup for the WebDAV access: undef %SESSION; ...
Web interface setup:
/etc/webdav-session.conf:
## reuse webdav.conf because $INSTALL_BASE, $DOCUMENT_ROOT, $BACKEND, $DBI_... are the same:
## but if you use ModPerl, 'require' doesn't work
require '/etc/webdav.conf';
$FANCYINDEXING = 1;
$VIRTUAL_BASE = '/';
%SESSION = (
## keep it secret like a database password, because it will be used to protect the CSRF token:
secret => 'YOUR SECRET PASSWORD COMES HERE',
## if the session timeout is too short, the users cry, if it's to long, admin cries (security!):
## see manual of CGI::Session for more information
expire => '+10m',
## in seconds - normally, tokens a refreshed with a folder change,
## but a tokenmaxage is not a session timeout, so it should live longer:
tokenmaxage => 36000,
## the tokenname should not be changed unless you know you are doing (avoid clashes with form/post parameters):
tokenname => 'TOKEN',
## here comes the path to the session files
## (hint: setup a daily cronjob to remove old session files, e.g. find /tmp -name cgisess\* -mtime +1 -delete )
temp => '/tmp',
## logout_redir defines a URL to an alternate logout page
## (only for regular logout with logout button [query: ?logout=1])
## hint: with a multi domain setup it makes sense to redirect to the start path, e.g. logout_redir=>'/?logout=1',
# logout_redir => undef,
## a callback module that is called per request
# callback => qw( Helper::AdsSmbConfiguratorSessionAdapter ),
# callback_param => { debug=>1, nameserver=>['8.8.8.8'], memcached=>'127.0.0.1:11211', allowflag=>'webfiles' },
## post configuration file only loaded for logged-in users for every request
## (same content like webdav.conf but with access to $REMOTE_USER variable for special user-based setups)
# postconfig => '/etc/webdav-session-post.conf',
## setuid/setgid wrapper called from session.pl and webdav-susession.pl for logged-in users
## required for setuid/setgid setups
# wrapper => '/etc/webdavcgi/cgi-bin/webdavwrapper',
## okay, the domain based authentication:
domains => {
## this domain name should be readable for a user if you have more than one:
'mydomain' => {
## this is an example, because the TestAuthHandler knows only one user: testuser1 (password: testuser1)
## (see Authentication handler section for more)
authhandler => qw( SessionAuthenticationHandler::TestAuthHandler ),
## handler setup stuff (TestAuthHandler doesn't need it):
# config => { },
## this defaults overwrite some webdav.conf defaults:
# defaults => {
# DOCUMENT_ROOT => '/somewhereelse/',
# BACKEND => 'GFS',
# },
## domain based session timeout overwrites expire from %SESSION:
# expire => '+10m',
## a callback module that is called per request
# callback => qw( Helper::AdsSmbConfiguratorSessionAdapter ),
# callback_param => { debug=>1, nameserver=>['8.8.8.8'], memcached=>'127.0.0.1:11211', allowflag=>'webfiles' },
## post configuration file only loaded for logged-in users for every request
## after the session postconfig (see above)
## (same content like webdav.conf but with access to $REMOTE_USER variable for special user-based setups)
# postconfig => '/etc/webdav-session-mydomain-post.conf',
## this optional _order flag influences the domain selection sort order in the login form:
# _order => 1,
},
## if you have more domains and more than one auth handler for a domain you can do this:
'myseconddomain' => [
{
authhandler => qw ( SessionAuthenticationHandler::LdapBindAuthHandler ),
config => {
server => 'myldapserver.mydomain.test',
basedn => 'dc=mydomain,dc=test',
},
},
{
authhandler=> qw ( SessionAuthenticationHandler::LdapBindAuthHandler ),
config => {
server => 'mysecondldapserver.mydomain.test',
basedn => 'dc=mydomain,dc=test',
},
},
],
},
);
# ... and here maybe follows extension setup
Okay, now we need a logout button for the web interface, maybe like this one: /etc/webdavcgi/templates/simple/help.custom.tmpl:
<li class="logout-button" data-href="?logout=1"><div class="label">Logout</div></li>And if you want to customize the login screen, you should copy the login.tmpl to login.custom.tmpl and edit the custom template:
cp /etc/webdavcgi/templates/simple/login.tmpl /etc/webdavcgi/templates/simple/login.custom.tmpl
Apache
The Apache configuration depends on your needs:- with mod_perl or with a simple CGI call ...
- multiple domains need multiple WebDAV URLs,
or all domains are checked for a username and password (omit DOMAIN environment in rewrite rules for that)
## yes: session.pl handles WebDAV with Basic authentication:
ScriptAlias /_dav /etc/webdavcgi/cgi-bin/session.pl
ScriptAlias /_web /etc/webdavcgi/cgi-bin/webdav.pl
## or for setuid/setgid wrapping:
# ScriptAlias /_web /etc/webdavcgi/cgi-bin/webdav-susession.pl
## ModPerl:
# PerlRequire /etc/webdavcgi/helper/mod_perl_startup.pl
<Location /_>
Require all granted
## ModPerl:
# PerlOptions +SetupEnv
# PerlResponseHandler ModPerl::RegistryPrefork
# Options +ExecCGI
</Location>
## WebDAV acccess: it gets its own WEBDAVCONF but the the wrapper needs the web interface setup in SESSIONCONF;
## change E parameter like DOMAIN and REALM as you need;
## when all domains should be checked, omit the DOMAIN env
# the session.pl needs the session configuration, the webdav.conf,
# and the HTTP header 'Authorization' to handle Basic auth:
RewriteRule /webdav /_dav \
[PT,L,E=WEBDAVCONF:/etc/webdav.conf,E=SESSIONCONF:/etc/webdav-session.conf,E=DOMAIN:mydomain,E=REALM:WebDAV,E=AUTHHEADER:%{HTTP:Authorization},E=PERLLIB:/etc/webdavcgi/lib/perl]
## you see: WEBDAVCONF differs because this is for the web interface:
RewriteRule / /_web [PT,L,E=WEBDAVCONF:/etc/webdav-session.conf,E=PERLLIB:/etc/webdavcgi/lib/perl]
Authentication handler
LDAP
The LDAP authentication handler requires the Perl module Net::LDAP (Debian/Ubuntu:apt install libnet-ldap-perl).
The necessary distinguished name (dn) for LDAP bind authentication can be searched or given by a parameter (userdn).
# this is the default:
authhandler => qw( SessionAuthenticationHandler::LdapBindAuthHandler ),
config => {
server => 'localhost',
## security:
starttls => 1,
sslversion => 'tlsv1_2',
verify => 'required',
## faster than search:
userdn => undef, # usage: 'uid=%s,dc=localhost'
## for search:
basedn => 'dc=localhost',
filter => '(uid=%s)',
timelimit => 5,
sizelimit => 5,
scope => 'sub',
binddn => undef,
password => undef,
},
Kerberos
... used for ADS/SMB share access and requires Perl module Env::C (cpan install Env::C).
authhandler => qw( SessionAuthenticationHandler::KerberosAuthHandler ),
config => {
krb5_config => undef, # overwrites KRB5CCNAME environment (system default: /etc/krb5.conf)
ticketfilename => '/tmp/krb5cc_webdavcgi_%s',
ticketlifetime => 600, ## real ticket lifetime >= ticketlifetime >= expire
log => undef, # log severity: 1:error, 2:warn, 4:info, 8:debug, 15: all; combine severties: add
kinit => q{kinit '%s' 1>/dev/null 2>&1}, # %s is replaced by username
kdestroy => q{kdestroy 1>/dev/null 2>&1},
},
AFS
AFS authentication handles require Perl module AFS::PAG (Debian/Ubuntu:apt install libafs-pag-perl).
authhandler => qw( SessionAuthenticationHandler::AfsKerberosAuthHandler ),
config => {
## all options from Kerberos authentication handler and additionally:
aklog => 'aklog', # path to aklog binary
},
Apache htpasswd (file-based)
Requires Perl module Authen::Htpasswd (Debian/Ubuntu:apt install libauthen-htpasswd-perl)
authhandler => qw( SessionAuthenticationHandler::HtpasswdAuthHandler),
config => {
htpasswd => '/etc/apache2/users'; # path to user file managed with htpasswd command
},
Maintenance
- remove (daily) old session files:
find /tmp -name cgisess\* -mtime +1 -delete - remove (daily) old kerberos ticket files (only for AFS or SMB backend users):
find /tmp/ -name krb5cc_webdavcgi\* -mtime +1 -delete - check for WebDAV CGI updates: https://github.com/DanRohde/webdavcgi
Cluster
- You should synchronize the session files in a fail-over cluster (DRBD, rsync with inotify-tools, inotify-hookable).
- In an active-active cluster setup your load-balancer should use a "sticky session" policy.
Security
- WebDAV CGI uses POST and sometimes GET requests but all POST requests (includes login process) are protected by secure token (using WWW::CSRF and the Encrypted Token Pattern).
- The secure token changes every time a user change the folder and a token expires in a given time (default: 10 hours).
- The token is protected by a secret password that must be set by the administrator in the session setup.
- The session file on the server stores only the username. No password is stored by WebDAV CGI.
- The session expires in a given time (default: really short 10 minutes) and is bound to an IP address to prevent a abuse of a user session.
© ZE CMS, Humboldt-Universität zu Berlin | Written 2010-2017 by Daniel Rohde