1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
import os.path
import sys
from os import remove, chmod, access, R_OK
from shutil import copyfile
from hashlib import sha512
from twisted.logger import Logger
from leap.bitmask.vpn import _config
from leap.bitmask.system import IS_LINUX, IS_MAC, IS_SNAP
from leap.bitmask.util import STANDALONE
log = Logger()
if IS_LINUX:
from leap.bitmask.vpn.constants import BITMASK_ROOT_SYSTEM
from leap.bitmask.vpn.constants import BITMASK_ROOT_LOCAL
from leap.bitmask.vpn.constants import BITMASK_ROOT_SNAP
from leap.bitmask.vpn.constants import OPENVPN_SYSTEM
from leap.bitmask.vpn.constants import OPENVPN_LOCAL
from leap.bitmask.vpn.constants import OPENVPN_SNAP
from leap.bitmask.vpn.constants import POLKIT_SYSTEM
from leap.bitmask.vpn.constants import POLKIT_LOCAL
from leap.bitmask.vpn.constants import POLKIT_SNAP
from leap.bitmask.vpn.privilege import is_pkexec_in_system
from leap.bitmask.vpn.privilege import LinuxPolicyChecker
def install():
print('installing bitmask helpers...')
helper_from = _config.get_bitmask_helper_path()
polkit_from = _config.get_bitmask_polkit_policy_path()
openvpn_from = _config.get_bitmask_openvpn_path()
sbin = '/usr/local/sbin'
if not os.path.isdir(sbin):
os.makedirs(sbin)
copyfile(helper_from, BITMASK_ROOT_LOCAL)
chmod(BITMASK_ROOT_LOCAL, 0744)
copyfile(polkit_from, POLKIT_LOCAL)
if STANDALONE:
copyfile(openvpn_from, OPENVPN_LOCAL)
chmod(OPENVPN_LOCAL, 0744)
def uninstall():
remove(BITMASK_ROOT_LOCAL)
remove(POLKIT_LOCAL)
remove(OPENVPN_LOCAL)
def privcheck(timeout=5):
has_pkexec = is_pkexec_in_system()
running = LinuxPolicyChecker.is_up()
if not running:
try:
LinuxPolicyChecker.get_usable_pkexec(timeout=timeout)
running = LinuxPolicyChecker.is_up()
except Exception:
running = False
result = has_pkexec and running
log.debug('Privilege check: %s' % result)
return result
def check():
pkexec = is_pkexec_in_system()
helper = _check_helper()
polkit = _check_polkit_file_exist()
openvpn = _check_openvpn()
if not pkexec:
log.error('No pkexec in system!')
if not helper:
log.error('No bitmask-root in system!')
if not polkit:
log.error('No polkit file in system!')
if not openvpn:
log.error('No openvpn in system!')
result = all([pkexec, helper, polkit, openvpn])
if result is True:
log.debug('All checks passed')
return result
def _check_helper():
log.debug('Checking whether helper exists')
helper_path = _config.get_bitmask_helper_path()
if not _exists_and_can_read(helper_path):
log.debug('Cannot read helpers')
return True
if IS_SNAP:
if os.path.isfile(BITMASK_ROOT_SNAP):
return True
log.error('Cannot find bitmask-root in snap')
return False
helper_path_digest = digest(helper_path)
if (_exists_and_can_read(BITMASK_ROOT_SYSTEM) and
helper_path_digest == digest(BITMASK_ROOT_SYSTEM)):
log.debug('Global bitmask-root: %s'
% os.path.isfile(BITMASK_ROOT_SYSTEM))
return True
if (_exists_and_can_read(BITMASK_ROOT_LOCAL) and
helper_path_digest == digest(BITMASK_ROOT_LOCAL)):
log.debug('Local bitmask-root: %s'
% os.path.isfile(BITMASK_ROOT_LOCAL))
return True
log.debug('No valid bitmask-root found')
return False
def _check_openvpn():
if IS_SNAP:
return os.path.exists(OPENVPN_SNAP)
if os.path.exists(OPENVPN_SYSTEM):
return True
openvpn_path = _config.get_bitmask_openvpn_path()
if openvpn_path is None:
# If Bitmask does not provide any openvpn binary
# (we are not in a bundle: either running from debian packages, git
# or pip) reporting an error on check will trigger an attempt to
# install helpers that can not be successful.
# XXX: we need a better way to flag errors that can not be solved
# by installing helpers
return True
openvpn_path_digest = digest(openvpn_path)
if (_exists_and_can_read(OPENVPN_LOCAL) and
openvpn_path_digest == digest(OPENVPN_LOCAL)):
return True
return False
def _check_polkit_file_exist():
"""
We are just checking if there is any policy file installed not
if it's valid or if it's the correct one that will be used.
If LOCAL: we use /usr/local/sbin/bitmask-root
If SYSTEM: we use /usr/sbin/bitmask-root, and
if SNAP: we use /snap/bin/riseup-vpn.bitmask-root
"""
return (os.path.exists(POLKIT_LOCAL) or
os.path.exists(POLKIT_SYSTEM) or
os.path.exists(POLKIT_SNAP))
def _exists_and_can_read(file_path):
return access(file_path, R_OK)
elif IS_MAC:
def check():
# XXX check if bitmask-helper is running
return True
def privcheck(timeout=5):
return True
def digest(path):
with open(path, 'r') as f:
s = f.read()
return sha512(s).digest()
def main():
if sys.argv[-1] == 'install':
install()
if sys.argv[-1] == 'uninstall':
uninstall()
if __name__ == "__main__":
main()
|