File Coverage

blib/lib/Unix/SetUser.pm
Criterion Covered Total %
statement 63 110 57.2
branch 24 56 42.8
condition 4 9 44.4
subroutine 8 9 88.8
pod 1 1 100.0
total 100 185 54.0


line stmt bran cond sub pod time code
1             # $Id$
2              
3             package Unix::SetUser;
4              
5 10     10   6636 use warnings;
  10         11  
  10         330  
6 10     10   50 use strict;
  10         19  
  10         210  
7 10     10   40 use Carp;
  10         65  
  10         613  
8 10     10   55 use Unix::SavedIDs 0.004002;
  10         212  
  10         544  
9 10     10   42 use Data::Dumper;
  10         20  
  10         637  
10              
11             #warn "\@INC = ".join(" ",@INC)."\n";
12             #warn "\%INC = ".Dumper(\%INC)."\n";
13              
14             our $verbose = 0;
15              
16             my $warncount = 0;
17              
18             BEGIN {
19 10     10   52 use Exporter ();
  10         20  
  10         943  
20 10     10   20 our ($VERSION,@ISA,@EXPORT);
21 10         98 @ISA = qw(Exporter);
22 10         39 @EXPORT = qw(set_user);
23 10         10797 $VERSION = 0.004003;
24             }
25              
26             sub set_user {
27             ## Figure Out IDs to Set
28 8     8 1 12021640 my($user,$group,@sup_groups) = @_;
29 8         217 my($uid,$gid,%sup_gids);
30 8         815 my $is_int = qr/^(\d+)$/o;
31 8 100       382 if ( !defined($user) ) {
32 1         663 croak "set_user() called with no arguments";
33             }
34             # get uids
35 7 100       520 if ( $user =~ $is_int ) {
36 1         193 $uid = $1;
37             }
38             else {
39             # get numeric uid if given non-numeric user name
40 6         2532 $uid = getpwnam($user);
41 6 100       93 if ( !defined($uid) ) {
42 1         1092 croak "User '$user' does not exist";
43             }
44 5 50       397 if ( $uid !~ $is_int ) {
45 0         0 croak "User id for '$user' is not an int. "
46             ."This shouldn't ever happen";
47             }
48 5         269 $uid = $1;
49             }
50             # get primary gid
51 6 100 100     182 if ( defined($group) && $group =~ $is_int ) {
52 1         12 $gid = $1;
53 1 50       135 if ( !getgrgid($gid) ) {
54 1         1016 croak "Primary group id '$gid' does not exist\n";
55             }
56             }
57             else {
58             # use user's primary group if no primary group specified
59 5 100       122 if ( !defined($group) ) {
60 4         810 $gid = (getpwuid($uid))[3];
61 4 100       70 if ( !defined($gid)) {
62 1         738 croak "Failed to get primary group ID for uid '$uid'";
63             }
64             }
65             else {
66             # get gid from group name
67 1         121 $gid = getgrnam($group);
68 1 50       9 if ( !defined($gid) ) {
69 1         1109 croak "Primary group '$group' does not exist";
70             }
71              
72             }
73 3 50       74 if ( $gid !~ $is_int ) {
74 0         0 croak "Primary group ID for '$user' is not an int. "
75             ."This shouldn't ever happen";
76             }
77             }
78             # get supplemental groups
79 3         22 my @dont_exist;
80 3         66 foreach my $sup_group (@sup_groups) {
81 3         8 my $sup_gid;
82 3 100       21 if ( !defined($sup_group) ) {
83 1         605 croak "Supplemental group list contains 'undef'";
84             }
85             # if ints, make sure they exist
86 2 100       28 if ( $sup_group =~ $is_int ) {
87 1         14 $sup_gid = $1;
88 1 50 33     41 if ( $sup_gid == $gid || defined($sup_gids{$sup_gid})) {
89             # remove duplicates
90 0         0 next;
91             }
92 1 50       114 if ( !getgrgid($sup_gid) ) {
93 1         7 push(@dont_exist,$sup_group);
94 1         14 next;
95             }
96             }
97             # if not ints, convert text usernames to ints which tests existance
98             else {
99 1         61 $sup_gid = getgrnam($sup_group);
100 1 50       5 if ( !defined($sup_gid) ) {
101 1         12 push(@dont_exist,$sup_group);
102 1         9 next;
103             }
104 0 0       0 if ( $sup_gid !~ $is_int ) {
105 0         0 croak "Supplemental group id for group '$sup_group' is "
106             ."not an int. This shouldn't ever happen";
107             }
108 0 0 0     0 if ( $sup_gid == $gid || defined($sup_gids{$sup_gid}) ) {
109             # duplicate
110 0         0 next;
111             }
112             }
113 0         0 $sup_gids{$sup_gid} = 1;
114             }
115 2 50       25 if ( @dont_exist ) {
116 2         1592 croak "Specified supplemental group(s) '".join("', '",@dont_exist)
117             ."' do(es) not exist(s)";
118             }
119              
120             ## Set Ids
121              
122             # set gid, egid and sgid
123 0           setresgid($gid,$gid,$gid);
124             # set egid & supplimental gids
125 0           my $egid_string = $gid;
126 0 0         if ( keys(%sup_gids) == 0 ) { # $) lists primary group twice
127 0           $egid_string .= ' '.$gid; # if it's your only group
128             }
129             else {
130 0           $egid_string .= ' '.join(' ',sort(keys(%sup_gids)));
131             }
132 0           $) = $egid_string;
133             # set uid,euid & suid
134             #_warn_ids();
135             #warn "-- Setting uid,euid & suid setresuid($uid,$uid,$uid)\n";
136 0           setresuid($uid,$uid,$uid);
137             #_warn_ids();
138              
139             ## Make sure everything worked
140 0           my @errs = ();
141             # make sure uid change worked
142 0 0         if ( $< != $uid ) {
143 0           push(@errs,"Failed to set uid: uid = '$<', not '$uid'");
144             }
145             # make sure set euid worked
146 0 0         if ( $> != $uid ) {
147 0           push(@errs,"Failed to set euid: euid = '$>', not '$uid'");
148             }
149             # make sure saved uid got set correctly
150 0           my $suid = (getresuid())[2];
151 0 0         if ( $suid != $uid ) {
152 0           push(@errs,'Failed to set saved uid: saved uid = '.$suid
153             .' not '.$uid);
154             }
155             #warn "about to check rgid\n";
156             #_warn_ids();
157             # make sure rgid is correct
158 0 0         if ( $( !~ /^(\d+)/o ) {
159 0           croak "GID is not an int!??!";
160             }
161 0           my $now_gid = $1;
162 0 0         if ( $now_gid != $gid ) {
163 0           croak "Failed to set gid: gid is '$now_gid' not '$gid'\n";
164             }
165             # make sure set egid & supplimental gids worked
166 0 0         if ( $) ne $egid_string ) {
167             # Order doesn't matter, so split, sort and rejoin to test.
168 0           my $now = join(' ',sort(split(' ',$))));
169 0           my $want = join(' ',sort(split(' ',$egid_string)));
170 0 0         if ( $now ne $want ) {
171 0           push(@errs,"Failed to set egid: egid = '$)', not '$egid_string'");
172             }
173             }
174             # make sure sgid got set correctly
175 0           my $sgid = (getresgid())[2];
176 0 0         if ( $sgid != $gid ) {
177 0           push(@errs,'Failed to set saved gid: saved gid = '.$sgid
178             .' not '.$gid);
179             }
180 0 0         if ( @errs ) {
181 0           croak join("\n",@errs);
182             }
183             #_warn_ids();
184 0           return undef;
185             }
186              
187             sub _warn_ids {
188 0     0     $warncount++;
189 0           warn "count = $warncount\n";
190 0           warn "\$< = '$<'\n";
191 0           warn "\$> = '$>'\n";
192 0           warn "\$( = '$('\n";
193 0           warn "\$) = '$)'\n";
194 0           warn "geresuid = ".join(',',getresuid())."\n";
195 0           warn "geresgid = ".join(',',getresuid())."\n";
196             }
197              
198             1; # Magic true value required at end of module
199             __END__