line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Protocol::DBus::Authn::Mechanism::EXTERNAL; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
2193
|
use strict; |
|
1
|
|
|
|
|
10
|
|
|
1
|
|
|
|
|
70
|
|
4
|
1
|
|
|
1
|
|
8
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
125
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
7
|
use parent 'Protocol::DBus::Authn::Mechanism'; |
|
1
|
|
|
|
|
10
|
|
|
1
|
|
|
|
|
42
|
|
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
83
|
use Protocol::DBus::Socket (); |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
515
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
0
|
50
|
sub INITIAL_RESPONSE { unpack 'H*', $> } |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# The reference server implementation does a number of things to try to |
13
|
|
|
|
|
|
|
# fetch the peer credentials. See dbus/dbus-sysdeps-unix.c. |
14
|
|
|
|
|
|
|
sub must_send_initial { |
15
|
2
|
|
|
2
|
0
|
6
|
my ($self) = @_; |
16
|
|
|
|
|
|
|
|
17
|
2
|
100
|
|
|
|
9
|
if (!defined $self->{'_must_send_initial'}) { |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# On Linux this module doesn’t need to make any special |
20
|
|
|
|
|
|
|
# effort to send credentials because the server will request them on |
21
|
|
|
|
|
|
|
# its own, and SO_PASSCRED works independently of the client anyway. |
22
|
|
|
|
|
|
|
# (Although Linux only sends the real credentials, we’ll send the |
23
|
|
|
|
|
|
|
# EUID in the AUTH line.) |
24
|
|
|
|
|
|
|
# |
25
|
|
|
|
|
|
|
# As it happens, though, the reference implementation uses |
26
|
|
|
|
|
|
|
# SO_PEERCRED on Linux anyway, as well as OpenBSD. It also |
27
|
|
|
|
|
|
|
# tries LOCAL_PEEREID for NetBSD, getpeerucred() for Solaris, |
28
|
|
|
|
|
|
|
# and getpeereid() as a fallback. Only FreeBSD & DragonflyBSD |
29
|
|
|
|
|
|
|
# appear to be expected to send SCM_CREDS directly, even though |
30
|
|
|
|
|
|
|
# those OSes do have LOCAL_PEERCRED which should work. |
31
|
|
|
|
|
|
|
# |
32
|
1
|
|
|
|
|
2
|
my $can_skip_msghdr = eval { my $v = Socket::SO_PEERCRED(); 1 }; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
33
|
1
|
|
33
|
|
|
5
|
$can_skip_msghdr ||= eval { my $v = Socket::LOCAL_PEEREID(); 1 }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# macOS can’t send SCM_CREDS, despite that the constants |
36
|
|
|
|
|
|
|
# are defined. |
37
|
1
|
|
33
|
|
|
3
|
$can_skip_msghdr ||= ($^O eq 'darwin'); |
38
|
|
|
|
|
|
|
|
39
|
1
|
|
|
|
|
3
|
$self->{'_must_send_initial'} = !$can_skip_msghdr; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
2
|
|
|
|
|
13
|
return $self->{'_must_send_initial'}; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub send_initial { |
46
|
0
|
|
|
0
|
0
|
|
my ($self, $s) = @_; |
47
|
|
|
|
|
|
|
|
48
|
0
|
0
|
|
|
|
|
eval { require Socket::MsgHdr; 1 } or do { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
49
|
0
|
|
|
|
|
|
die "Socket::MsgHdr appears to be needed for EXTERNAL authn but failed to load: $@"; |
50
|
|
|
|
|
|
|
}; |
51
|
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
|
my $msg = Socket::MsgHdr->new( buf => "\0" ); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# The kernel should fill in the payload. |
55
|
0
|
|
|
|
|
|
$msg->cmsghdr( Socket::SOL_SOCKET(), Socket::SCM_CREDS(), "\0" x 64 ); |
56
|
|
|
|
|
|
|
|
57
|
0
|
|
|
|
|
|
local $!; |
58
|
0
|
|
|
|
|
|
my $ok = Protocol::DBus::Socket::sendmsg_nosignal($s, $msg, 0); |
59
|
|
|
|
|
|
|
|
60
|
0
|
0
|
0
|
|
|
|
if (!$ok && !$!{'EAGAIN'}) { |
61
|
0
|
|
|
|
|
|
die "sendmsg($s): $!"; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
0
|
|
|
|
|
|
return $ok; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
1; |