3 # ssh_dump.pl - Script to suck data outta the database to be processed by ssh_create.pl
5 # Symlink attack fix Copyright (C) 2009 Sylvain Beucler / GPLv2+ / no warranty
9 ## Become this effective user (EUID/EGID) and perform this action.
11 ## This protect against symlink attacks; they are inevitable when
12 ## working in a directory owned by a local user. We could naively
13 ## check for the presence of symlinks, but then we'd still be
14 ## vulnerable to a symlink race attack.
16 ## We'll use set_e_uid/set_e_gid for efficiency and simplicity
17 ## (e.g. we can get the return value directly), which is enough for
18 ## opening files and similar basic operations. When calling external
19 ## programs, you should use fork&exec&setuid/setgid.
23 sub SudoEffectiveUser {
25 my $sub_unprivileged = $_[1];
27 my ($uid,$gid) = GetUserUidGid($user);
28 if ($uid eq "" or $gid eq "") {
29 print "Unknown user: $user\n";
33 my $old_GID = $GID; # save additional groups
35 $EGID = "$gid $gid"; # set egid and additional groups
37 warn "Cannot setegid($gid $gid): $!";
42 warn "Cannot seteuid($uid): $!";
46 # Perform the action under this effective user:
47 my $ret = &$sub_unprivileged();
50 undef($EUID); # restore euid==uid
51 $EGID = $old_GID; # restore egid==gid + additional groups
59 my ($name,$passwd,$uid,$gid,
60 $quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user);
64 require("/usr/share/gforge/lib/include.pl"); # Include all the predefined functions
67 my($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwnam("gforge");
75 $dbh->{AutoCommit} = 0;
77 # Dump the Table information
78 $query = "SELECT user_name,unix_uid,authorized_keys FROM users WHERE authorized_keys != '' AND status !='D'";
79 $c = $dbh->prepare($query);
81 while(my ($username, $unix_uid, $ssh_key) = $c->fetchrow()) {
82 $new_list = "$username:$unix_uid:$ssh_key\n";
83 push @ssh_array, $new_list;
89 my ($username, $ssh_keys, $ssh_dir);
91 if($verbose){print("\n\n Processing Users keys creation\n\n")};
92 while ($ln = pop(@ssh_array)) {
93 ($username, $uid, $ssh_key) = split(":", $ln);
95 $ssh_key =~ s/\#\#\#/\n/g;
96 $username =~ tr/[A-Z]/[a-z]/;
99 push @user_authorized_keys, $ssh_key . "\n";
100 push @user_authorized_keys, "\n# This file is automatically generated from your account settings.\n";
102 $ssh_dir = "$homedir_prefix/$username/.ssh";
104 if($verbose){print ("Processing $username\n")};
106 if (-d "$homedir_prefix/$username"){
107 chown $uid, $uid, ("$homedir_prefix/$username");
109 SudoEffectiveUser($username, sub {
111 mkdir $ssh_dir, 0755;
114 if($verbose){print("Writing authorized_keys for $username: ")};
116 if (write_array_file("$ssh_dir/authorized_keys", @user_authorized_keys)) {
117 warn "Problem writing authorized_keys for $username\n";
120 chmod 0644, "$ssh_dir/authorized_keys";
123 if($verbose){print ("Done\n")};
125 if($verbose){print ("Not yet done, waiting for home creation\n")};
128 undef @user_authorized_keys;
132 ### Phase 2: remove the files when needed
134 # Dump the Table information
135 $query = "SELECT user_name,unix_uid FROM users WHERE authorized_keys = '' OR authorized_keys IS NULL OR status = 'D'";
136 $c = $dbh->prepare($query);
138 while(my ($username, $unix_uid, $ssh_key) = $c->fetchrow()) {
139 $new_list = "$username:$unix_uid\n";
140 push @ssh_array, $new_list;
143 if($verbose){print("\n\n Processing Users keys deletion\n\n")};
144 while ($ln = pop(@ssh_array)) {
145 ($username, $uid) = split(":", $ln);
147 $username =~ tr/[A-Z]/[a-z]/;
150 $ssh_dir = "$homedir_prefix/$username/.ssh";
152 if($verbose){print ("Processing $username\n")};
155 if($verbose){print("Resetting authorized_keys for $username: ")};
157 SudoEffectiveUser($username, sub {
158 unlink("$ssh_dir/authorized_keys");
161 chown $uid, $uid, "$homedir_prefix/$username";
163 if($verbose){print ("Done\n")};