From 70758769356cc99ba0121f530b77a7c06920c5b4 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Fri, 5 Jul 2013 02:56:52 -0700 Subject: [PATCH] Support user removal User.pm now supports a remove function that removes the user from all the user's groups and then from the passwd file itself. Additionally, User.pm can store an authentication type when generating an authentication code so that an authentication generated for removing a user cannot be used to update a user and vice versa. edituser.cgi now recognizes only the correct authentication type when updating a user. A web interface to the delete user functionality is not provided with these changes. --- Girocco/User.pm | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++------ cgi/edituser.cgi | 2 +- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/Girocco/User.pm b/Girocco/User.pm index 7a7ab4c..4264c89 100644 --- a/Girocco/User.pm +++ b/Girocco/User.pm @@ -7,6 +7,7 @@ use Digest::MD5 qw(md5); use Girocco::Config; use Girocco::CGI; +use Girocco::Project; use Girocco::Util; use Girocco::SSHUtil; @@ -42,6 +43,12 @@ sub _gen_uuid { @md5); } +sub _remove_ssh_leftovers { + my $self = shift; + system "rm -f '$Girocco::Config::chroot/etc/sshkeys/$self->{name}'"; + system "rm -f '$Girocco::Config::chroot/etc/sshcerts/${Girocco::Config::nickname}_$self->{name}'_user_*.pem"; +} + sub _passwd_add { my $self = shift; my (undef, undef, $gid) = getgrnam($Girocco::Config::owning_group||''); @@ -51,6 +58,7 @@ sub _passwd_add { my $email_uuid = join ',', $self->{email}, $self->{uuid}; filedb_atomic_append(jailed_file('/etc/passwd'), join(':', $self->{name}, 'x', '\i', $owngroupid, $email_uuid, '/', '/bin/git-shell-verify')); + $self->_remove_ssh_leftovers; } sub _passwd_update { @@ -74,6 +82,16 @@ sub _passwd_update { ); } +sub _passwd_remove { + my $self = shift; + $self->_remove_ssh_leftovers; + filedb_atomic_edit(jailed_file('/etc/passwd'), + sub { + $self->{name} ne (split /:/)[0] and return $_; + } + ); +} + sub _sshkey_path { my $self = shift; '/etc/sshkeys/'.$self->{name}; @@ -84,18 +102,20 @@ sub _sshkey_load { open F, "<".jailed_file($self->_sshkey_path) or die "sshkey load failed: $!"; my @keys = (); my $auth = ''; + my $authtype = ''; while () { chomp; if (/^ssh-(?:dss|rsa) /) { push @keys, $_; - } elsif (/^# REPOAUTH ([0-9a-f]+) (\d+)/) { - my $expire = $2; - $auth = $1 unless (time >= $expire); + } elsif (/^# ([A-Z]+)AUTH ([0-9a-f]+) (\d+)/) { + my $expire = $3; + $auth = $2 unless (time >= $expire); + $authtype = $1 if $auth; } } close F; my $keys = join("\n", @keys); chomp $keys; - ($keys, $auth); + ($keys, $auth, $authtype); } sub _trimkeys { @@ -114,7 +134,8 @@ sub _sshkey_save { open F, ">".jailed_file($self->_sshkey_path) or die "sshkey failed: $!"; if (defined($self->{auth}) && $self->{auth}) { my $expire = time + 24 * 3600; - print F "# REPOAUTH $self->{auth} $expire\n"; + my $typestr = $self->{authtype} ? uc($self->{authtype}) : 'REPO'; + print F "# ${typestr}AUTH $self->{auth} $expire\n"; } print F $self->{keys}."\n"; close F; @@ -156,7 +177,7 @@ sub load { my $email_uuid; (undef, $self->{uid}, undef, $email_uuid) = @_; - ($self->{keys}, $self->{auth}) = $self->_sshkey_load; + ($self->{keys}, $self->{auth}, $self->{authtype}) = $self->_sshkey_load; ($self->{email}, $self->{uuid}) = split ',', $email_uuid; close F; @@ -182,7 +203,7 @@ sub load_by_uid { my $email_uuid; (undef, undef, $self->{uid}, undef, $email_uuid) = @_; - ($self->{keys}, $self->{auth}) = $self->_sshkey_load; + ($self->{keys}, $self->{auth}, $self->{authtype}) = $self->_sshkey_load; ($self->{email}, $self->{uuid}) = split ',', $email_uuid; close F; @@ -287,7 +308,10 @@ sub keys_html_list { sub gen_auth { my $self = shift; + my ($type) = @_; + $type = 'REPO' unless $type =~ /^[A-Z]+$/; + $self->{authtype} = $type; $self->{auth} = sha1_hex(time . $$ . rand() . $self->{keys}); $self->_sshkey_save; $self->{auth}; @@ -297,6 +321,23 @@ sub del_auth { my $self = shift; delete $self->{auth}; + delete $self->{authtype}; +} + +sub get_projects { + my $self = shift; + + return @{$self->{projects}} if defined($self->{projects}); + my @projects = filedb_atomic_grep(jailed_file('/etc/group'), + sub { + $_ = $_[0]; + chomp; + my ($group, $users) = (split /:/)[0,3]; + $group if $users && $users =~ /(^|,)\Q$self->{name}\E(,|$)/; + } + ); + $self->{projects} = \@projects; + @{$self->{projects}}; } sub conjure { @@ -306,6 +347,19 @@ sub conjure { $self->_sshkey_save; } +sub remove { + my $self = shift; + + foreach ($self->get_projects) { + if (Girocco::Project::does_exist($_)) { + my $project = Girocco::Project->load($_); + $project->update if $project->remove_user($self->{name}); + } + } + + $self->_passwd_remove; +} + ### static methods sub valid_name { diff --git a/cgi/edituser.cgi b/cgi/edituser.cgi index 2544637..2be52f5 100755 --- a/cgi/edituser.cgi +++ b/cgi/edituser.cgi @@ -87,7 +87,7 @@ EOT _auth_form($name, "'Login'"); exit; } else { - $user->{auth} or do { + $user->{auth} && $user->{authtype} ne 'DEL' or do { print "There currently isn't any authorization code filed under your account. Please generate one."; exit; }; -- 2.11.4.GIT