# HG changeset patch # User Matthias Förste # Date 1311059292 -7200 # Node ID fee44892ca1ee3063328041ad43bae22d39fca92 # Parent e0e126b7f06dc81f5fa394e14f5b1e1ff0e24c4f# Parent a459cc790ed0e20e3465b23e6d99ffdd3c34bdd4 merged diff -r e0e126b7f06d -r fee44892ca1e .hgignore --- a/.hgignore Wed Jul 13 13:41:08 2011 +0200 +++ b/.hgignore Tue Jul 19 09:08:12 2011 +0200 @@ -1,6 +1,6 @@ syntax regexp: ^TODO$ -^dav-htpasswd.conf$ +^ius-dav-htpasswd.conf$ ^_build ^Build$ diff -r e0e126b7f06d -r fee44892ca1e Build.PL --- a/Build.PL Wed Jul 13 13:41:08 2011 +0200 +++ b/Build.PL Tue Jul 19 09:08:12 2011 +0200 @@ -4,7 +4,7 @@ my $builder = Module::Build->subclass( class => 'My::Module::Build', - code => <<'___CODE', + code => <<'___CODE', use strict; use warnings; use File::Temp; @@ -18,32 +18,44 @@ defined $provides{$_} ? $provides{$_} : 'lib' . lc $d . '-perl' => $self->requires->{$_} == 0 ? '' : ' (>= ' . $self->requires->{$_} . ')' } keys %{$self->requires} ), - 'at' => '' ); my $c = new File::Temp or die "Can't tempfile"; print $c "Package: libius-dav-htpasswd-perl-deps\n"; print $c 'Depends: ', join ', ', map { "$_$deps{$_}" } keys %deps; system('equivs-build', $c->filename); } + sub ACTION_install { + my $self = shift; + my $h = ($self->install_path('cgi-bin') =~ m|^(.*)/cgi-bin$|)[0] ; + my $u = my $g = ($h =~ m|/([^/]+)$|)[0]; + system(qw(chown -R), "$u:$g", $h) == 0 + or die "Can't 'chown -R $u:$g $h': $!"; + { no warnings 'qw'; + system(qw(chmod -R go=,-st), $h) == 0 + or die "Can't 'chmod -R go=,-st $h"; + } + $self->SUPER::ACTION_install; + } ___CODE ); -my $build = $builder->new -( - module_name => 'Ius::Dav::Htpasswd', - license => 'gpl', +my $build = $builder->new( + module_name => 'Ius::Dav::Htpasswd', + license => 'gpl', create_license => 1, - requires => { + requires => { 'Apache::Htpasswd' => 0, - 'AppConfig' => 0, - 'File::Path' => 0, - 'POSIX' => 0, + 'AppConfig' => 0, + 'File::Path' => 0, + 'POSIX' => 0, 'String::MkPasswd' => 0 }, - script_files => [glob 'bin/*'], - cgi_files => { map { /\.(bak|orig)$/ ? () : ($_ => $_) } glob 'cgi-bin/admin/*' } + script_files => [ glob 'bin/*' ], + cgi_files => + { map { /\.(bak|orig)$/ ? () : ( $_ => $_ ) } glob 'cgi-bin/*' } ); $build->add_build_element('cgi'); $build->install_path( - 'cgi-bin' => $build->original_prefix($build->installdirs) . '/lib/cgi-bin'); + 'cgi-bin' => $build->original_prefix( $build->installdirs ) + . '/lib/ius-dav-htpasswd/cgi-bin' ); $build->create_build_script; diff -r e0e126b7f06d -r fee44892ca1e README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Tue Jul 19 09:08:12 2011 +0200 @@ -0,0 +1,31 @@ +Installation (on debian): + + * install dependencies + # perl ./Build.PL && ./Build equivs + # dpkg -i libius-dav-htpasswd-perl-deps_*_all.deb + # aptitude install + # aptitude install apache2-mpm-itk sudo + + * preinst + # mkdir -p $PREFIX/lib/ius-dav-htpasswd + # useradd -d $PREFIX/lib/ius-dav-htpasswd -m -r -U -s /bin/true ius-dav-htpasswd + # passwd -l ius-dav-htpasswd + + * installation + + # perl ./Build.PL && ./Build test && ./Build install + + # visudo + + [...] + + ius-dav-htpasswd debian-lenny = (root) NOPASSWD: $PREFIX/bin/ius-dav-htuseradd, $PREFIX/bin/ius-dav-htuserdel + + [...] + + # $EDITOR /etc/apache2/sites-available/ius-dav-htpasswd # see ssl-vhost-apache-example.conf + # htpasswd [-c] $PREFIX/etc/ius-dav-htpasswd/htpasswd.admin ius-dav-htpasswd-admin + # htpasswd -c $PREFIX/etc/ius-dav-htpasswd/htpasswd.dav ius-dav-htpasswd-master # when using a master user + + # ln -s /usr/local/bin/ius-dav-htuserexpiry /etc/cron.daily/ + diff -r e0e126b7f06d -r fee44892ca1e bin/dav-htuseradd --- a/bin/dav-htuseradd Wed Jul 13 13:41:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#!/usr/bin/perl - -# Copyright (C) 2011 Matthias Förste -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Matthias Förste - -use strict; -use warnings; - -use Ius::Dav::Htpasswd qw(mkpasswd readconfig useradd usage); - -use Getopt::Long; -use Pod::Usage; - -my ($user, $expiry, $pass); - -GetOptions( - 'u|user=s' => \$user, - 'e|expiry=i' => \$expiry, - 'h|help' => sub { usage(-exit => 0, -verbose => 1) }, - 'm|man' => sub { - usage( - -exit => 0, - - # "system('perldoc -V &>/dev/null')" appears shorter, but may not - # do what you expect ( it still returns 0 on debian squeeze with - # dash as system shell even if cannot find the command in $PATH) - -noperldoc => system('perldoc -V >/dev/null 2>&1'), - -verbose => 2 - ); - }, -) and defined $user or usage; - -$pass = useradd readconfig, $user, mkpasswd, $expiry; -print "[$pass]\n"; diff -r e0e126b7f06d -r fee44892ca1e bin/dav-htuserdel --- a/bin/dav-htuserdel Wed Jul 13 13:41:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -#!/usr/bin/perl - -# Copyright (C) 2011 Matthias Förste -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Matthias Förste - -use strict; -use warnings; - -use Getopt::Long; -use Ius::Dav::Htpasswd qw(readconfig userdel usage); - -my $user; - -GetOptions( - 'u|user=s' => \$user, - "h|help" => sub { usage( -verbose => 0, -exitval => 0 ) }, - "m|man" => sub { - usage( - -verbose => 2, - -exitval => 0, - -noperldoc => ( `perldoc -V 2>/dev/null`, $? != 0 )[-1] - ); - }, -) and defined $user or usage(); - -exit userdel readconfig, $user; diff -r e0e126b7f06d -r fee44892ca1e bin/ius-dav-htuseradd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/ius-dav-htuseradd Tue Jul 19 09:08:12 2011 +0200 @@ -0,0 +1,50 @@ +#!/usr/bin/perl + +# Copyright (C) 2011 Matthias Förste +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Matthias Förste + +use strict; +use warnings; + +use Ius::Dav::Htpasswd qw(mkpasswd readconfig useradd usage); + +use Getopt::Long; +use Pod::Usage; + +my ( $user, $expiry, $pass ); + +GetOptions( + 'u|user=s' => \$user, + 'e|expiry=i' => \$expiry, + 'h|help' => sub { usage( -exit => 0, -verbose => 1 ) }, + 'm|man' => sub { + usage( + -exit => 0, + + # "system('perldoc -V &>/dev/null')" appears shorter, but may not + # do what you expect ( it still returns 0 on debian squeeze with + # dash as system shell even if cannot find the command in $PATH) + -noperldoc => system('perldoc -V >/dev/null 2>&1'), + -verbose => 2 + ); + }, + ) + and defined $user + or usage; + +$pass = useradd readconfig, $user, mkpasswd, $expiry; +print "$pass\n"; diff -r e0e126b7f06d -r fee44892ca1e bin/ius-dav-htuserdel --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/ius-dav-htuserdel Tue Jul 19 09:08:12 2011 +0200 @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +# Copyright (C) 2011 Matthias Förste +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Matthias Förste + +use strict; +use warnings; + +use Getopt::Long; +use Ius::Dav::Htpasswd qw(readconfig userdel usage); + +my $user; + +GetOptions( + 'u|user=s' => \$user, + "h|help" => sub { usage( -verbose => 0, -exitval => 0 ) }, + "m|man" => sub { + usage( + -verbose => 2, + -exitval => 0, + -noperldoc => ( `perldoc -V 2>/dev/null`, $? != 0 )[-1] + ); + }, + ) + and defined $user + or usage(); + +exit userdel readconfig, $user; diff -r e0e126b7f06d -r fee44892ca1e bin/ius-dav-htuserexpiry --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/ius-dav-htuserexpiry Tue Jul 19 09:08:12 2011 +0200 @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +# Copyright (C) 2011 Matthias Förste +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Matthias Förste + +use strict; +use warnings; + +use Ius::Dav::Htpasswd qw(readconfig userexpiry usage); + +use Getopt::Long; +use Pod::Usage; + +GetOptions( + 'h|help' => sub { usage( -exit => 0, -verbose => 1 ) }, + 'm|man' => sub { + usage( + -exit => 0, + + # "system('perldoc -V &>/dev/null')" appears shorter, but may not + # do what you expect ( it still returns 0 on debian squeeze with + # dash as system shell even if cannot find the command in $PATH) + -noperldoc => system('perldoc -V >/dev/null 2>&1'), + -verbose => 2 + ); + }, +) or usage; + +exit userexpiry readconfig; diff -r e0e126b7f06d -r fee44892ca1e cgi-bin/admin/dav-htuseradd.cgi --- a/cgi-bin/admin/dav-htuseradd.cgi Wed Jul 13 13:41:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -#!/usr/bin/perl - -# Copyright (C) 2011 Matthias Förste -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Matthias Förste - -use warnings; - -# Using CGI::Fast will result in an Internal Server Error because we are -# restarting apache when everything else works -# use CGI::Fast; -use CGI; -use Ius::Dav::Htpasswd qw(mkpasswd readconfig useradd); - -my $q = new CGI; - - print $q->header(-charset => 'UTF-8'); - print $q->start_html( - -title => $0, - -bgcolor => "white", - ); - - my ($user, $pass, $expiry) = ( - $q->param('user'), - $q->param('pass'), - $q->param('expiry') - ); - - unless (defined $user or defined $pass or defined $expiry) { - - print $q->start_form, - 'New User' => $q->textfield('user'), - 'Password' => $q->password_field('pass'), - 'Expiry' => $q->textfield('expiry'), - $q->submit, - $q->end_form; - - } else { - - my @cmd = (qw(sudo dav-htuseradd -u), $user); - push @cmd, '-e', $expiry if defined $expiry and $expiry ne ''; - - if (my $pass = qx(@cmd)) { - chomp $pass; - print $q->p($pass); - } else { - print $q->p('Something went wrong'); - } - - } - - print $q->end_html; diff -r e0e126b7f06d -r fee44892ca1e cgi-bin/ius-dav-htuseradd.cgi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cgi-bin/ius-dav-htuseradd.cgi Tue Jul 19 09:08:12 2011 +0200 @@ -0,0 +1,105 @@ +#!/usr/bin/perl + +# Copyright (C) 2011 Matthias Förste +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Matthias Förste + +use warnings; + +# Using CGI::Fast will result in an Internal Server Error because we are +# restarting apache when everything else works +# use CGI::Fast; +use CGI; +use Ius::Dav::Htpasswd qw(mkpasswd readconfig useradd); + +my $css = <header( -charset => 'UTF-8' ); +print $q->start_html( + -title => $0, + -style => { -code => $css }, + -onload => q{document.forms['passwd'].elements['user'].focus();} + ), + $q->h3( { -id => 'header' }, 'Befristete WebDAV Zugänge einrichten' ), + $q->hr; + +my $p; +$p->{$_} = $q->param($_) for qw(user expiry add del); + +print $q->start_form( -id => 'passwd' ), + $q->table( + $q->Tr( $q->td('Nutzername'), $q->td( $q->textfield('user') ) ), + $q->Tr( + $q->td('Gültigkeitsdauer in Tagen (default: 1)'), + $q->td( $q->textfield('expiry') ) + ), + $q->Tr( + $q->td( $q->submit( { -name => 'add', -value => 'Anlegen' } ) ), + $q->td( $q->submit( { -name => 'del', -value => 'Löschen' } ) ) + ) + ), + $q->end_form; + +my $doit = 0; + +my $conf = readconfig or die "Can't readconfig"; + +if ( defined $p->{add} and $p->{add} ne '' ) { + + print $q->hr; + my @cmd = ( qw(sudo ius-dav-htuseradd -u), $p->{user} ); + push @cmd, '-e', $p->{expiry} + if defined $p->{expiry} and $p->{expiry} ne ''; + + if ( my $pass = qx(@cmd) ) { + + my $url = "$conf->{dav_base_remote}/$p->{user}"; + + chomp $pass; + + print $q->table( + $q->Tr( + $q->td('Url:'), $q->td( $q->a( { -href => $url }, $url ) ) + ), + $q->Tr( $q->td('Passwort:'), $q->td($pass) ) + ); + + } + else { + print $q->p('Something went wrong'); + } + +} +elsif ( defined $p->{del} and $p->{del} ne '' ) { + + my @cmd = ( qw(sudo ius-dav-htuserdel -u), $p->{user} ); + print $q->hr, $q->p('Something went wrong') if system @cmd; + +} + +print $q->hr, $q->end_html; diff -r e0e126b7f06d -r fee44892ca1e dav-htpasswd.conf.ex --- a/dav-htpasswd.conf.ex Wed Jul 13 13:41:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -expiry = 1 # expire user after this many days per default -expiry_min = 1 # don't accept arguments less than expiry_min to the --expiry option -expiry_max = 56 # don't accept arguments greater than expiry_max to the --expiry option - -dav_base = /srv/dav # user directories will be placed below dav_base -htpasswd = /etc/apache2/htpasswd # where to place/look for the htpasswd -conf_d = /etc/apache2/dav.d # where to place/look for configuration snippets - -www_user = www-data # webserver user -www_group = www-data # webserver group - -master_user = david # master user with access to all directories (optional) diff -r e0e126b7f06d -r fee44892ca1e ius-dav-htpasswd.conf.ex --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ius-dav-htpasswd.conf.ex Tue Jul 19 09:08:12 2011 +0200 @@ -0,0 +1,33 @@ +# expire user after this many days per default +expiry = 1 + +# don't accept arguments less than expiry_min to the --expiry option +expiry_min = 1 + +# don't accept arguments greater than expiry_max to the --expiry option +expiry_max = 56 + + +# user directories will be placed below dav_base_local +dav_base_local = /srv/ius-dav + +# the username will be prefixed with dav_base_remote when displaying the uri +# for the directory of a newly created user (you can omit the trailing slash) +dav_base_remote = https://hostname/ + +# where to place/look for the htpasswd; note that we may want a different +# htpasswd file in the same directory to limit access to the admin cgi script +htpasswd = /usr/local/etc/ius-dav-htpasswd/htpasswd.dav + +# where to place/look for configuration snippets +conf_d = /usr/local/etc/ius-dav-htpasswd/apache.d + + +# webserver user +www_user = www-data + +# webserver group +www_group = www-data + +# master user with access to all directories (optional) +master_user = davius diff -r e0e126b7f06d -r fee44892ca1e lib/Ius/Dav/Htpasswd.pm --- a/lib/Ius/Dav/Htpasswd.pm Wed Jul 13 13:41:08 2011 +0200 +++ b/lib/Ius/Dav/Htpasswd.pm Tue Jul 19 09:08:12 2011 +0200 @@ -32,14 +32,14 @@ BEGIN { - our ($VERSION, @ISA, @EXPORT_OK); + our ( $VERSION, @ISA, @EXPORT_OK ); use Exporter; # set the version for version checking $VERSION = 0.1; - @ISA = qw(Exporter); - @EXPORT_OK = qw(readconfig mkpasswd useradd userdel usage); + @ISA = qw(Exporter); + @EXPORT_OK = qw(readconfig mkpasswd useradd userdel userexpiry usage); } sub usage { @@ -47,37 +47,43 @@ use Pod::Usage; use Pod::Find qw(pod_where); - pod2usage( -input => pod_where({-inc => 1}, __PACKAGE__), @_ ); + pod2usage( -input => pod_where( { -inc => 1 }, __PACKAGE__ ), @_ ); } sub readconfig { - my $conf = new AppConfig(qw( - expiry=i - expiry_min=i - expiry_max=i - dav_base=s - htpasswd=s - conf_d=s - www_user=s - www_group=s - master_user=s) + my $conf = new AppConfig( + qw( + expiry=i + expiry_min=i + expiry_max=i + dav_base_local=s + dav_base_remote=s + htpasswd=s + conf_d=s + www_user=s + www_group=s + master_user=s) ) or die 'Failed to read config!'; - $conf->file($_) for grep -e, map "$_/dav-htpasswd.conf", qw(/etc /usr/local/etc ~ .); + $conf->file($_) + for grep -e, map "$_/ius-dav-htpasswd.conf", + qw(/etc/ius-dav-htpasswd /usr/local/etc/ius-dav-htpasswd ~/.ius-dav-htpasswd ./ius-dav-htpasswd); return { $conf->varlist('.') }; } sub validate { - my ($conf, $user, $expiry) = @_; + my ( $conf, $user, $expiry ) = @_; - return unless $user =~ /^[[:alpha:]_]+$/; + return unless $user =~ /^[[:alpha:]_]+$/; - if (defined $expiry) { + if ( defined $expiry ) { return unless $expiry =~ /^[0-9]+$/; - return unless $expiry >= $conf->{expiry_min} and $expiry <= $conf->{expiry_max}; + return + unless $expiry >= $conf->{expiry_min} + and $expiry <= $conf->{expiry_max}; } return 1; @@ -86,41 +92,42 @@ sub useradd { - my ($conf, $user, $pass, $expiry) = @_; + my ( $conf, $user, $pass, $expiry ) = @_; - for (qw(expiry expiry_min expiry_max dav_base htpasswd conf_d www_user www_group)) { + for ( + qw(expiry expiry_min expiry_max dav_base_local htpasswd conf_d www_user www_group) + ) + { die "Can't determine '$_' - please check configuration" - unless defined $conf->{$_}; + unless defined $conf->{$_}; } $expiry = $conf->{expiry} unless defined $expiry and $expiry ne ''; die 'Invalid input' unless validate $conf, $user, $expiry; - my $at_cmd = "at now + " . 24 * 60 * $expiry . " minutes"; - open AT, "|$at_cmd" - or die "Can't open AT, '|$at_cmd': $!"; - print AT "dav-htuserdel"; - close AT; - - my $user_dir = "$conf->{dav_base}/$user"; + my $user_dir = "$conf->{dav_base_local}/$user"; mkdir "$user_dir" or die "Can't mkdir '$user_dir': $!"; - my ($www_user, $www_group) = @{$conf}{qw(www_user www_group)}; - my $www_uid = getpwnam $www_user or die "Can't getpwnam '$www_user'"; + my ( $www_user, $www_group ) = @{$conf}{qw(www_user www_group)}; + my $www_uid = getpwnam $www_user or die "Can't getpwnam '$www_user'"; my $www_gid = getgrnam $www_group or die "Can't getgrnam '$www_group'"; - chown $www_uid, $www_gid, "$user_dir" or die "Can't chown, '$www_uid', '$www_gid', '$user_dir': $!"; + chown $www_uid, $www_gid, "$user_dir" + or die "Can't chown, '$www_uid', '$www_gid', '$user_dir': $!"; my $htpasswd_file = $conf->{htpasswd}; - unless (-e $htpasswd_file ) { + unless ( -e $htpasswd_file ) { open H, '>>', $htpasswd_file or die "Can't create '$htpasswd_file': $!"; close H; } + my $htpasswd = new Apache::Htpasswd $htpasswd_file; - $htpasswd->htpasswd($user, $pass) - or die $htpasswd->error; + $htpasswd->htpasswd( $user, $pass ) + or die $htpasswd->error; + $htpasswd->writeInfo( $user, time + 24 * 60 * 60 * $expiry ) + or die $htpasswd->error; my $master_user = $conf->{master_user}; - my $conf_file = "$conf->{conf_d}/$user.conf"; + my $conf_file = "$conf->{conf_d}/$user.conf"; open C, '>', $conf_file or die "Can't open '$conf_file': $!"; print C < @@ -137,7 +144,7 @@ close C; 0 == system qw(apache2ctl graceful) - or die "Can't 'apache2ctl graceful'!"; + or die "Can't 'apache2ctl graceful'!"; return $pass; @@ -147,36 +154,65 @@ sub userdel { - my ($conf, $user) = @_; + my ( $conf, $user ) = @_; - my $rc; + my $rc = 0; - for (qw(dav_base htpasswd conf_d)) { + for (qw(dav_base_local htpasswd conf_d)) { die "Can't determine '$_' - please check configuration" - unless defined $conf->{$_}; + unless defined $conf->{$_}; } # avoid 'Found = in conditional, should be ==' warnings no warnings qw(syntax); - my $user_dir = "$conf->{dav_base}/$user"; + my $user_dir = "$conf->{dav_base_local}/$user"; my $err; - rmtree($user_dir, error => $err) - or $rc = -1 and defined $err and warn "Errors occurred during rmtree '$user_dir': ", @{$err}; + rmtree( $user_dir, error => $err ) + or $rc = -1 + and defined $err + and warn "Errors occurred during rmtree '$user_dir': ", @{$err}; my $htpasswd_file = $conf->{htpasswd}; - my $htpasswd = new Apache::Htpasswd $htpasswd_file; + my $htpasswd = new Apache::Htpasswd $htpasswd_file; $htpasswd->htDelete($user) - or $rc = -1 and warn "Can't htdelete '$user': ", $htpasswd->error; + or $rc = -1 and warn "Can't htdelete '$user': ", $htpasswd->error; my $conf_file = "$conf->{conf_d}/$user.conf"; unlink $conf_file - or $rc = -1 and warn "Can't unlink '$conf_file': $!"; - - # maybe TODO: remove at job if it still exists (record job# during # - # 'useradd'?) + or $rc = -1 and warn "Can't unlink '$conf_file': $!"; 0 == system qw(apache2ctl graceful) - or $rc =-1 and warn "Can't 'apache2ctl graceful'!"; + or $rc = -1 and warn "Can't 'apache2ctl graceful'!"; + + return $rc; + +} + +sub userexpiry { + + my ($conf) = @_; + + for (qw(htpasswd)) { + die "Can't determine '$_' - please check configuration" + unless defined $conf->{$_}; + } + + my $htpasswd_file = $conf->{htpasswd}; + my $htpasswd = new Apache::Htpasswd $htpasswd_file; + my @users = $htpasswd->fetchUsers + or die "Can't fetch htuser list: ", $htpasswd->error; + my $now = time; + + for my $u (@users) { + if ( my $e = $htpasswd->fetchInfo($u) ) { + userdel( $conf, $u ) + or warn "Can't 'userdel $conf, $u'\n" + if $now >= $e; + } + else { + warn "Can't get expiry for '$u': ", $htpasswd->error, "\n"; + } + } } @@ -188,47 +224,53 @@ =head1 NAME -dav-useradd +ius-dav-useradd -dav-useradd.cgi +ius-dav-useradd.cgi -dav-userdel +ius-dav-userdel -Ius::Dav::Htpasswd - Add dav users to htpasswd and remove them automatically -after expiration or manually. +ius-dav-userexpiry + +Ius::Dav::Htpasswd - Add dav users to htpasswd and remove them after +expiration. =head1 SYNOPSIS -dav-useradd -u|--user user - [-e|--expiry expiry] +ius-dav-useradd + -u|--user user + [-e|--expiry expiry] -dav-userdel -u|--user user +ius-dav-userdel + -u|--user user + +ius-dav-userexpiry common options - - -m|--man - -h|--help + [-m|--man] + [-h|--help] =head1 DESCRIPTION -=head2 dav-useradd +=head2 ius-dav-useradd -Add an at job to remove the user later. Make a directory for the user. Chown -that directory to the webserver user and group. Add the user to an htpasswd -file. Place a config snippet for the users directory inside a directory (which -is included from the apache config). Reload apache (or maybe restart is -required). +Make a directory for the user. Chown that directory to the webserver user and +group. Add the user to an htpasswd file. Add expiry information to that +htpasswd file. Place a config snippet for the users directory inside a +directory (which is included from the apache config). Reload apache. -=head2 dav-useradd.cgi +=head2 ius-dav-useradd.cgi -Is supposed to do the same as dav-useradd. +This is a CGI Wrapper around ius-dav-useradd. -=head2 dav-userdel +=head2 ius-dav-userdel Removes the directory of the user. Removes the user from the htpasswd file. -Removes the config snippet for the users directory. Removes the at job that is -supposed to remove the user if it still exists. Reload apache (or maybe restart -is required). +Removes the config snippet for the users directory. Reload apache. + +=head2 ius-dav-userexpiry + +Check the htpasswd file and run deletion for any expired users found. =head1 OPTIONS @@ -262,7 +304,8 @@ =head1 REQUIRES -at from the 'at' job scheduler package. Several perl modules (should be installed automatically). +Several perl modules (should be installed automatically). Some kind of cron +daemon to run the user expiry is recommended. =head1 AUTHOR diff -r e0e126b7f06d -r fee44892ca1e ssl-vhost-apache-example.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ssl-vhost-apache-example.conf Tue Jul 19 09:08:12 2011 +0200 @@ -0,0 +1,62 @@ +# replace $PREFIX (usually with /usr or /usr/local) + +# note that you will need a wildcard certificate if you want namebased virtual +# hosts + ssl + + + DocumentRoot "$PREFIX/lib/ius-dav-htpasswd/cgi-bin" + AssignUserId "ius-dav-htpasswd" "ius-dav-htpasswd" + + ServerAdmin webmaster@localhost + ServerName ius-dav-htpasswd.domain.tld + + ErrorLog /var/log/apache2/error.log + LogLevel warn + CustomLog /var/log/apache2/ius-dav-htpasswd.domain.tld/ssl_access.log combined + + SSLEngine on + SSLCertificateFile /etc/ssl/certs/wildcard-certificate.pem + SSLCertificateKeyFile /etc/ssl/private/key-for-wildcard-certificate.pem + + # SSL Protocol Adjustments: + # The safe and default but still SSL/TLS standard compliant shutdown + # approach is that mod_ssl sends the close notify alert but doesn't wait for + # the close notify alert from client. When you need a different shutdown + # approach you can use one of the following variables: + # o ssl-unclean-shutdown: + # This forces an unclean shutdown when the connection is closed, i.e. no + # SSL close notify alert is send or allowed to received. This violates + # the SSL/TLS standard but is needed for some brain-dead browsers. Use + # this when you receive I/O errors because of the standard approach where + # mod_ssl sends the close notify alert. + # o ssl-accurate-shutdown: + # This forces an accurate shutdown when the connection is closed, i.e. a + # SSL close notify alert is send and mod_ssl waits for the close notify + # alert of the client. This is 100% SSL/TLS standard compliant, but in + # practice often causes hanging connections with brain-dead browsers. Use + # this only for browsers where you know that their SSL implementation + # works correctly. + # Notice: Most problems of broken clients are also related to the HTTP + # keep-alive facility, so you usually additionally want to disable + # keep-alive for those clients, too. Use variable "nokeepalive" for this. + # Similarly, one has to force some clients to use HTTP/1.0 to workaround + # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and + # "force-response-1.0" for this. + BrowserMatch ".*MSIE.*" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + + # local cgi scripts + + Order Deny,Allow + Deny from all + Allow from 127.0.0.0/8 + AuthType "Basic" + AuthName "ius-dav-htpasswd" + AuthUserFile "/path/to/ius-dav-admin-htpasswd" + Require valid-user + SetHandler cgi-script + + + +