34
34
from __future__ import (division, absolute_import, print_function,
37
from future_builtins import *
38
from future_builtins import *
40
43
import SocketServer as socketserver
119
121
return interface_index
124
def copy_function(func):
125
"""Make a copy of a function"""
126
if sys.version_info.major == 2:
127
return types.FunctionType(func.func_code,
133
return types.FunctionType(func.__code__,
122
140
def initlogger(debug, level=logging.WARNING):
123
141
"""init logger and add loglevel"""
156
174
output = subprocess.check_output(["gpgconf"])
157
175
for line in output.splitlines():
158
name, text, path = line.split(":")
176
name, text, path = line.split(b":")
159
177
if name == "gpg":
238
256
raise PGPError(err)
239
257
return decrypted_plaintext
259
# Pretend that we have an Avahi module
261
"""This isn't so much a class as it is a module-like namespace.
262
It is instantiated once, and simulates having an Avahi module."""
263
IF_UNSPEC = -1 # avahi-common/address.h
264
PROTO_UNSPEC = -1 # avahi-common/address.h
265
PROTO_INET = 0 # avahi-common/address.h
266
PROTO_INET6 = 1 # avahi-common/address.h
267
DBUS_NAME = "org.freedesktop.Avahi"
268
DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + ".EntryGroup"
269
DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
270
DBUS_PATH_SERVER = "/"
271
def string_array_to_txt_array(self, t):
272
return dbus.Array((dbus.ByteArray(s.encode("utf-8"))
273
for s in t), signature="ay")
274
ENTRY_GROUP_ESTABLISHED = 2 # avahi-common/defs.h
275
ENTRY_GROUP_COLLISION = 3 # avahi-common/defs.h
276
ENTRY_GROUP_FAILURE = 4 # avahi-common/defs.h
277
SERVER_INVALID = 0 # avahi-common/defs.h
278
SERVER_REGISTERING = 1 # avahi-common/defs.h
279
SERVER_RUNNING = 2 # avahi-common/defs.h
280
SERVER_COLLISION = 3 # avahi-common/defs.h
281
SERVER_FAILURE = 4 # avahi-common/defs.h
242
284
class AvahiError(Exception):
243
285
def __init__(self, value, *args, **kwargs):
448
490
_library = ctypes.cdll.LoadLibrary(
449
491
ctypes.util.find_library("gnutls"))
450
_need_version = "3.3.0"
492
_need_version = b"3.3.0"
451
493
def __init__(self):
452
494
# Need to use class name "GnuTLS" here, since this method is
453
495
# called before the assignment to the "gnutls" global variable
487
529
openpgp_crt_t = ctypes.POINTER(openpgp_crt_int)
488
530
openpgp_crt_fmt_t = ctypes.c_int # gnutls/openpgp.h
489
531
log_func = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p)
490
credentials_type_t = ctypes.c_int #
532
credentials_type_t = ctypes.c_int
491
533
transport_ptr_t = ctypes.c_void_p
492
534
close_request_t = ctypes.c_int
794
836
client["fingerprint"] = (section["fingerprint"].upper()
795
837
.replace(" ", ""))
796
838
if "secret" in section:
797
client["secret"] = section["secret"].decode("base64")
839
client["secret"] = codecs.decode(section["secret"]
798
842
elif "secfile" in section:
799
843
with open(os.path.expanduser(os.path.expandvars
800
844
(section["secfile"])),
853
897
self.changedstate = multiprocessing_manager.Condition(
854
898
multiprocessing_manager.Lock())
855
899
self.client_structure = [attr
856
for attr in self.__dict__.iterkeys()
900
for attr in self.__dict__.keys()
857
901
if not attr.startswith("_")]
858
902
self.client_structure.append("client_structure")
1507
1551
interface_names.add(alt_interface)
1508
1552
# Is this a D-Bus signal?
1509
1553
if getattr(attribute, "_dbus_is_signal", False):
1554
# Extract the original non-method undecorated
1555
# function by black magic
1510
1556
if sys.version_info.major == 2:
1511
# Extract the original non-method undecorated
1512
# function by black magic
1513
1557
nonmethod_func = (dict(
1514
1558
zip(attribute.func_code.co_freevars,
1515
1559
attribute.__closure__))
1516
1560
["func"].cell_contents)
1518
nonmethod_func = attribute
1562
nonmethod_func = (dict(
1563
zip(attribute.__code__.co_freevars,
1564
attribute.__closure__))
1565
["func"].cell_contents)
1519
1566
# Create a new, but exactly alike, function
1520
1567
# object, and decorate it to be a new D-Bus signal
1521
1568
# with the alternate D-Bus interface name
1522
if sys.version_info.major == 2:
1523
new_function = types.FunctionType(
1524
nonmethod_func.func_code,
1525
nonmethod_func.func_globals,
1526
nonmethod_func.func_name,
1527
nonmethod_func.func_defaults,
1528
nonmethod_func.func_closure)
1530
new_function = types.FunctionType(
1531
nonmethod_func.__code__,
1532
nonmethod_func.__globals__,
1533
nonmethod_func.__name__,
1534
nonmethod_func.__defaults__,
1535
nonmethod_func.__closure__)
1569
new_function = copy_function(nonmethod_func)
1536
1570
new_function = (dbus.service.signal(
1538
1572
attribute._dbus_signature)(new_function))
1578
1612
attribute._dbus_in_signature,
1579
1613
attribute._dbus_out_signature)
1580
(types.FunctionType(attribute.func_code,
1581
attribute.func_globals,
1582
attribute.func_name,
1583
attribute.func_defaults,
1584
attribute.func_closure)))
1614
(copy_function(attribute)))
1585
1615
# Copy annotations, if any
1587
1617
attr[attrname]._dbus_annotations = dict(
1599
1629
attribute._dbus_access,
1600
1630
attribute._dbus_get_args_options
1601
1631
["byte_arrays"])
1602
(types.FunctionType(
1603
attribute.func_code,
1604
attribute.func_globals,
1605
attribute.func_name,
1606
attribute.func_defaults,
1607
attribute.func_closure)))
1632
(copy_function(attribute)))
1608
1633
# Copy annotations, if any
1610
1635
attr[attrname]._dbus_annotations = dict(
1619
1644
# to the class.
1620
1645
attr[attrname] = (
1621
1646
dbus_interface_annotations(alt_interface)
1622
(types.FunctionType(attribute.func_code,
1623
attribute.func_globals,
1624
attribute.func_name,
1625
attribute.func_defaults,
1626
attribute.func_closure)))
1647
(copy_function(attribute)))
1628
1649
# Deprecate all alternate interfaces
1629
1650
iname="_AlternateDBusNames_interface_annotation{}"
1642
1663
if interface_names:
1643
1664
# Replace the class with a new subclass of it with
1644
1665
# methods, signals, etc. as created above.
1645
cls = type(b"{}Alternate".format(cls.__name__),
1666
if sys.version_info.major == 2:
1667
cls = type(b"{}Alternate".format(cls.__name__),
1670
cls = type("{}Alternate".format(cls.__name__),
2966
logger.debug("Did setuid/setgid to {}:{}".format(uid,
2940
2968
except OSError as error:
2969
logger.warning("Failed to setuid/setgid to {}:{}: {}"
2970
.format(uid, gid, os.strerror(error.errno)))
2941
2971
if error.errno != errno.EPERM:
3022
3052
if server_settings["restore"]:
3024
3054
with open(stored_state_path, "rb") as stored_state:
3025
clients_data, old_client_settings = pickle.load(
3055
if sys.version_info.major == 2:
3056
clients_data, old_client_settings = pickle.load(
3059
bytes_clients_data, bytes_old_client_settings = (
3060
pickle.load(stored_state, encoding = "bytes"))
3061
### Fix bytes to strings
3064
clients_data = { (key.decode("utf-8")
3065
if isinstance(key, bytes)
3068
bytes_clients_data.items() }
3069
del bytes_clients_data
3070
for key in clients_data:
3071
value = { (k.decode("utf-8")
3072
if isinstance(k, bytes) else k): v
3074
clients_data[key].items() }
3075
clients_data[key] = value
3077
value["client_structure"] = [
3079
if isinstance(s, bytes)
3081
value["client_structure"] ]
3083
for k in ("name", "host"):
3084
if isinstance(value[k], bytes):
3085
value[k] = value[k].decode("utf-8")
3086
## old_client_settings
3088
old_client_settings = {
3089
(key.decode("utf-8")
3090
if isinstance(key, bytes)
3093
bytes_old_client_settings.items() }
3094
del bytes_old_client_settings
3096
for value in old_client_settings.values():
3097
if isinstance(value["host"], bytes):
3098
value["host"] = (value["host"]
3027
3100
os.remove(stored_state_path)
3028
3101
except IOError as e:
3029
3102
if e.errno == errno.ENOENT:
3179
3252
return dbus.Dictionary(
3180
3253
{ c.dbus_object_path: c.GetAll(
3181
3254
"se.recompile.Mandos.Client")
3182
for c in tcp_server.clients.itervalues() },
3255
for c in tcp_server.clients.values() },
3183
3256
signature="oa{sv}")
3185
3258
@dbus.service.method(_interface, in_signature="o")
3186
3259
def RemoveClient(self, object_path):
3188
for c in tcp_server.clients.itervalues():
3261
for c in tcp_server.clients.values():
3189
3262
if c.dbus_object_path == object_path:
3190
3263
del tcp_server.clients[c.name]
3191
3264
c.remove_from_connection()
3251
3324
# removed/edited, old secret will thus be unrecovable.
3253
3326
with PGPEngine() as pgp:
3254
for client in tcp_server.clients.itervalues():
3327
for client in tcp_server.clients.values():
3255
3328
key = client_settings[client.name]["secret"]
3256
3329
client.encrypted_secret = pgp.encrypt(client.secret,
3281
3354
prefix='clients-',
3282
3355
dir=os.path.dirname(stored_state_path),
3283
3356
delete=False) as stored_state:
3284
pickle.dump((clients, client_settings), stored_state)
3357
pickle.dump((clients, client_settings), stored_state,
3285
3359
tempname = stored_state.name
3286
3360
os.rename(tempname, stored_state_path)
3287
3361
except (IOError, OSError) as e: