File Coverage

lib/Ubic/Credentials/OS/MacOSX.pm
Criterion Covered Total %
statement 18 135 13.3
branch 0 62 0.0
condition 0 9 0.0
subroutine 6 21 28.5
pod 11 11 100.0
total 35 238 14.7


line stmt bran cond sub pod time code
1             package Ubic::Credentials::OS::MacOSX;
2             $Ubic::Credentials::OS::MacOSX::VERSION = '1.60';
3 1     1   615 use strict;
  1         2  
  1         21  
4 1     1   3 use warnings;
  1         1  
  1         19  
5              
6 1     1   4 use parent qw(Ubic::Credentials);
  1         1  
  1         3  
7              
8             # ABSTRACT: MacOSX-specific credentials implementation
9              
10              
11 1     1   39 use List::MoreUtils qw(uniq);
  1         1  
  1         7  
12              
13 1     1   306 use Params::Validate qw(:all);
  1         2  
  1         123  
14 1     1   4 use Carp;
  1         1  
  1         959  
15              
16             sub new {
17 0     0 1   my $class = shift;
18 0           my $params = validate(@_, {
19             user => 0,
20             group => 0,
21             service => { optional => 1, isa => 'Ubic::Service' },
22             });
23              
24 0           my $self = {};
25 0 0         if (defined $params->{user}) {
    0          
26 0 0         if (defined $params->{service}) {
27 0           croak "Only one of 'user' and 'service' parameters should be specified";
28             }
29 0           $self->{user} = $params->{user};
30 0 0         $self->{group} = $params->{group} if defined $params->{group};
31 0 0         if (ref $self->{group}) {
32 0           $self->{group} = $self->{group}[0];
33             }
34             }
35             elsif (defined $params->{service}) {
36 0           $self->{user} = $params->{service}->user;
37 0           my @group = $params->{service}->group;
38 0 0         $self->{group} = $group[0] if @group;
39             }
40             else {
41 0           $self->{real_user_id} = $<;
42 0           $self->{effective_user_id} = $>;
43 0           ($self->{real_group_id}) = $( =~ /^(\d+)/;
44 0           ($self->{effective_group_id}) = $) =~ /^(\d+)/;
45             # TODO - derive user from real_user_id when user is not specified (or from effective_user_id?!)
46             }
47              
48 0           return bless $self => $class;
49             }
50              
51             sub user {
52 0     0 1   my $self = shift;
53 0 0         unless (defined $self->{user}) {
54 0           $self->{user} = getpwuid($>);
55             }
56 0           return $self->{user};
57             }
58              
59             sub group {
60 0     0 1   my $self = shift;
61 0 0         unless (defined $self->{group}) {
62 0           $self->_user2group;
63             }
64 0           return $self->{group};
65             }
66              
67             sub _user2uid {
68 0     0     my $self = shift;
69 0           my $user = $self->user;
70 0           my $id = scalar getpwnam($user);
71 0 0         unless (defined $id) {
72 0           croak "user $user not found";
73             }
74 0           return $id;
75             }
76              
77             sub real_user_id {
78 0     0 1   my $self = shift;
79 0 0         return $self->{real_user_id} if defined $self->{real_user_id};
80 0           return $self->_user2uid;
81             }
82              
83             sub effective_user_id {
84 0     0 1   my $self = shift;
85 0 0         return $self->{effective_user_id} if defined $self->{effective_user_id};
86 0           return $self->_user2uid;
87             }
88              
89             sub _group2gid {
90 0     0     my $self = shift;
91 0           my $group = $self->group;
92 0           my $gid = getgrnam($group);
93 0 0         unless (defined $gid) {
94 0           croak "group $group not found";
95             }
96 0           return $gid;
97             }
98              
99             sub real_group_id {
100 0     0 1   my $self = shift;
101 0 0         return $self->{real_group_id} if defined $self->{real_group_id};
102 0           return $self->_group2gid;
103             }
104              
105             sub effective_group_id {
106 0     0 1   my $self = shift;
107 0 0         return $self->{effective_group_id} if defined $self->{effective_group_id};
108 0           return $self->_group2gid;
109             }
110              
111             sub _user2group {
112 0     0     my $self = shift;
113 0           my $user = $self->user;
114 0 0         confess "user not defined" unless defined $user;
115              
116 0           my $main_group = getgrgid((getpwnam $user)[3]);
117 0           $self->{group} = $main_group;
118             }
119              
120             sub set_effective {
121 0     0 1   my $self = shift;
122              
123 0           my $current_creds = Ubic::Credentials->new;
124 0           my $euid = $current_creds->effective_user_id();
125 0           my ($egid) = $current_creds->effective_group_id();
126 0           $egid =~ s/^(\d+).*/$1/;
127              
128 0           my $current_user = getpwuid($euid);
129 0           my $current_group = getgrgid($egid);
130              
131 0           my $user = $self->user;
132 0           my ($group) = $self->group;
133              
134 0 0         if ($group ne $current_group) {
135 0           $self->{old_egid} = $);
136 0           my $new_gid = getgrnam($group);
137 0 0         unless (defined $new_gid) {
138 0           die "group $group not found";
139             }
140              
141             # AccessGuard don't need to handle supplementary groups correctly, so this is ok
142 0           $) = "$new_gid 0";
143 0           my ($current_gid) = $) =~ /^(\d+)/;
144 0 0         if ($current_gid != $new_gid) {
145 0           die "Failed to change group from $current_group to $group: $!";
146             }
147             }
148              
149 0 0         if ($user ne $current_user) {
150 0           $self->{old_euid} = $>;
151 0 0         if ($current_user ne 'root') {
152 0           die "Can't change user from $current_user to $user";
153             }
154 0           my $new_uid = getpwnam($user);
155 0 0         unless (defined $new_uid) {
156 0           die "user $user not found";
157             }
158 0           $> = $new_uid;
159 0 0         if ($> != $new_uid) {
160 0           die "Failed to change user from $current_user to $user: $!";
161             }
162             }
163             }
164              
165             sub _groups_equal {
166 0     0     my ($self, $g1, $g2) = @_;
167 0           my ($main1) = split / /, $g1;
168 0           my ($main2) = split / /, $g2;
169 0           return ($main1 == $main2);
170             }
171              
172              
173             sub reset_effective {
174 0     0 1   my $self = shift;
175              
176 0 0         if (defined $self->{old_euid}) {
177 0           $> = $self->{old_euid}; # return euid back to normal
178 0 0         if ($> != $self->{old_euid}) {
179 0           warn "Failed to restore euid from $> to $self->{old_euid}: $!";
180             }
181             }
182 0 0         if (defined $self->{old_egid}) {
183 0           $) = $self->{old_egid}; # return egid back to normal
184 0 0         if ($) != $self->{old_egid}) {
185 0           warn "Failed to restore egid from '$)' to '$self->{old_egid}': $!";
186             }
187             }
188             }
189              
190             sub eq {
191 0     0 1   my ($self, $other) = @_;
192 0 0 0       if (
      0        
      0        
193             $self->effective_user_id == $other->effective_user_id
194             and $self->real_user_id == $other->real_user_id
195             and $self->_groups_equal($self->effective_group_id, $other->effective_group_id)
196             and $self->_groups_equal($self->real_group_id, $other->real_group_id)
197             ) {
198 0           return 1;
199             }
200             else {
201 0           return;
202             }
203             }
204              
205             sub set {
206 0     0 1   my ($self) = @_;
207 0           my $effective_gid = $self->effective_group_id;
208 0           $) = $effective_gid;
209 0 0         unless ($self->_groups_equal($), $effective_gid)) {
210 0           die "Failed to set effective gid to $effective_gid: $!";
211             }
212 0           my $new_euid = $self->effective_user_id;
213 0           $> = $new_euid;
214 0 0         unless ($> == $new_euid) {
215 0           die "Failed to set effective uid to $new_euid: $!";
216             }
217 0           my $real_gid = $self->real_group_id;
218 0           $( = $real_gid;
219 0 0         unless ($self->_groups_equal($(, $real_gid)) {
220 0           die "Failed to set real gid to $real_gid: $!";
221             }
222 0           my $new_ruid = $self->real_user_id;
223 0           $< = $new_ruid;
224 0 0         unless ($< == $new_ruid) {
225 0           die "Failed to set real uid to $new_ruid: $!";
226             }
227             }
228              
229              
230             1;
231              
232             __END__