Commit | Line | Data |
---|---|---|
c9983bc7 | 1 | #!/usr/bin/perl |
2 | use warnings; | |
3 | use strict; | |
dd7a3814 | 4 | |
cb80809a JH |
5 | sub supplemental_groups { |
6 | my $user=shift; | |
7 | ||
8 | my @list; | |
9 | while (my @fields=getgrent()) { | |
10 | if (grep { $_ eq $user } split(' ', $fields[3])) { | |
11 | push @list, $fields[2]; | |
12 | } | |
13 | } | |
14 | ||
15 | return @list; | |
16 | } | |
17 | ||
5807f1de JH |
18 | sub samelists { |
19 | my %a=map { $_ => 1 } split(' ', shift()); | |
20 | my %b=map { $_ => 1 } split(' ', shift()); | |
21 | ||
22 | foreach my $i (keys %b) { | |
23 | if (! exists $a{$i}) { | |
24 | return 0; | |
25 | } | |
26 | } | |
27 | foreach my $i (keys %a) { | |
28 | if (! exists $b{$i}) { | |
29 | return 0; | |
30 | } | |
31 | } | |
32 | return 1; | |
33 | } | |
34 | ||
c9983bc7 | 35 | sub processline { |
36 | my $user=shift; | |
37 | my $setup=shift; | |
38 | ||
39 | if (! getpwnam("$user")) { | |
40 | print STDERR "warning: user $user does not exist\n"; | |
41 | return | |
42 | } | |
43 | if (! -f "$setup") { | |
44 | print STDERR "warning: $setup does not exist, skipping\n"; | |
45 | return; | |
46 | } | |
47 | print "Processing $setup as user $user ...\n"; | |
48 | # su is not used because it passes arguments through the shell, | |
49 | # which is not safe for untrusted setup file names. | |
50 | defined(my $pid = fork) or die "Can’t fork: $!"; | |
51 | if (! $pid) { | |
52 | my ($uuid, $ugid) = (getpwnam($user))[2, 3]; | |
20ac7c1b | 53 | my $grouplist=join(" ", $ugid, sort {$a <=> $b} $ugid, supplemental_groups($user)); |
5807f1de | 54 | if (! samelists(($)=$grouplist), $grouplist)) { |
20ac7c1b | 55 | die "failed to set egid $grouplist (got back $))"; |
cb80809a | 56 | } |
c9983bc7 | 57 | $(=$ugid; |
c9983bc7 | 58 | $<=$uuid; |
f947f8c4 | 59 | $>=$uuid; |
cb80809a | 60 | if ($< != $uuid || $> != $uuid || $( != $ugid) { |
c9983bc7 | 61 | die "failed to drop permissions to $user"; |
62 | } | |
1e1e1f50 JH |
63 | %ENV=( |
64 | PATH => $ENV{PATH}, | |
65 | HOME => (getpwnam($user))[7], | |
66 | ); | |
c9983bc7 | 67 | exec("ikiwiki", "-setup", $setup, @ARGV); |
68 | die "failed to run ikiwiki: $!"; | |
69 | } | |
70 | waitpid($pid,0); | |
71 | if ($?) { | |
72 | print STDERR "Processing $setup as user $user failed with code $?\n"; | |
73 | } | |
74 | } | |
c20c4066 | 75 | |
c9983bc7 | 76 | sub processlist { |
77 | my $file=shift; | |
78 | my $forceuser=shift; | |
dd7a3814 | 79 | |
c9983bc7 | 80 | my $list; |
81 | open ($list, "<$file") || die "$file: $!"; | |
82 | while (<$list>) { | |
83 | chomp; | |
84 | s/^\s+//; | |
85 | s/\s+$//; | |
86 | next if /^#/ || ! length; | |
87 | ||
88 | if (/^([^\s]+)\s+([^\s]+)$/) { | |
89 | my $user=$1; | |
90 | my $setup=$2; | |
91 | if (defined $forceuser && $forceuser ne $user) { | |
92 | print STDERR "warning: in $file line $., attempt to set user to $user, but user forced to $forceuser. Skipping\n"; | |
93 | } | |
94 | processline($user, $setup); | |
95 | } | |
96 | elsif (/^([^\s]+)$/) { | |
97 | my $user=$1; | |
98 | my $home=(getpwnam($user))[7]; | |
99 | if (defined $home && -d $home) { | |
100 | my $dotfile="$home/.ikiwiki/wikilist"; | |
101 | if (-e $dotfile) { | |
102 | processlist($dotfile, $user); | |
103 | } | |
104 | } | |
105 | } | |
106 | } | |
107 | close $list; | |
108 | } | |
109 | ||
110 | my $wikilist="/etc/ikiwiki/wikilist"; | |
111 | ||
112 | if (-e $wikilist) { | |
113 | processlist($wikilist); | |
dd7a3814 | 114 | } |
115 |