34
34
from __future__ import (division, absolute_import, print_function,
38
from future_builtins import *
37
from future_builtins import *
43
40
import SocketServer as socketserver
121
119
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__,
140
122
def initlogger(debug, level=logging.WARNING):
141
123
"""init logger and add loglevel"""
174
156
output = subprocess.check_output(["gpgconf"])
175
157
for line in output.splitlines():
176
name, text, path = line.split(b":")
158
name, text, path = line.split(":")
177
159
if name == "gpg":
256
238
raise PGPError(err)
257
239
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
284
242
class AvahiError(Exception):
285
243
def __init__(self, value, *args, **kwargs):
490
448
_library = ctypes.cdll.LoadLibrary(
491
449
ctypes.util.find_library("gnutls"))
492
_need_version = b"3.3.0"
450
_need_version = "3.3.0"
493
451
def __init__(self):
494
452
# Need to use class name "GnuTLS" here, since this method is
495
453
# called before the assignment to the "gnutls" global variable
836
794
client["fingerprint"] = (section["fingerprint"].upper()
837
795
.replace(" ", ""))
838
796
if "secret" in section:
839
client["secret"] = codecs.decode(section["secret"]
797
client["secret"] = section["secret"].decode("base64")
842
798
elif "secfile" in section:
843
799
with open(os.path.expanduser(os.path.expandvars
844
800
(section["secfile"])),
897
853
self.changedstate = multiprocessing_manager.Condition(
898
854
multiprocessing_manager.Lock())
899
855
self.client_structure = [attr
900
for attr in self.__dict__.keys()
856
for attr in self.__dict__.iterkeys()
901
857
if not attr.startswith("_")]
902
858
self.client_structure.append("client_structure")
1551
1507
interface_names.add(alt_interface)
1552
1508
# Is this a D-Bus signal?
1553
1509
if getattr(attribute, "_dbus_is_signal", False):
1554
# Extract the original non-method undecorated
1555
# function by black magic
1556
1510
if sys.version_info.major == 2:
1511
# Extract the original non-method undecorated
1512
# function by black magic
1557
1513
nonmethod_func = (dict(
1558
1514
zip(attribute.func_code.co_freevars,
1559
1515
attribute.__closure__))
1560
1516
["func"].cell_contents)
1562
nonmethod_func = (dict(
1563
zip(attribute.__code__.co_freevars,
1564
attribute.__closure__))
1565
["func"].cell_contents)
1518
nonmethod_func = attribute
1566
1519
# Create a new, but exactly alike, function
1567
1520
# object, and decorate it to be a new D-Bus signal
1568
1521
# with the alternate D-Bus interface name
1569
new_function = copy_function(nonmethod_func)
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__)
1570
1536
new_function = (dbus.service.signal(
1572
1538
attribute._dbus_signature)(new_function))
1612
1578
attribute._dbus_in_signature,
1613
1579
attribute._dbus_out_signature)
1614
(copy_function(attribute)))
1580
(types.FunctionType(attribute.func_code,
1581
attribute.func_globals,
1582
attribute.func_name,
1583
attribute.func_defaults,
1584
attribute.func_closure)))
1615
1585
# Copy annotations, if any
1617
1587
attr[attrname]._dbus_annotations = dict(
1629
1599
attribute._dbus_access,
1630
1600
attribute._dbus_get_args_options
1631
1601
["byte_arrays"])
1632
(copy_function(attribute)))
1602
(types.FunctionType(
1603
attribute.func_code,
1604
attribute.func_globals,
1605
attribute.func_name,
1606
attribute.func_defaults,
1607
attribute.func_closure)))
1633
1608
# Copy annotations, if any
1635
1610
attr[attrname]._dbus_annotations = dict(
1644
1619
# to the class.
1645
1620
attr[attrname] = (
1646
1621
dbus_interface_annotations(alt_interface)
1647
(copy_function(attribute)))
1622
(types.FunctionType(attribute.func_code,
1623
attribute.func_globals,
1624
attribute.func_name,
1625
attribute.func_defaults,
1626
attribute.func_closure)))
1649
1628
# Deprecate all alternate interfaces
1650
1629
iname="_AlternateDBusNames_interface_annotation{}"
1663
1642
if interface_names:
1664
1643
# Replace the class with a new subclass of it with
1665
1644
# methods, signals, etc. as created above.
1666
if sys.version_info.major == 2:
1667
cls = type(b"{}Alternate".format(cls.__name__),
1670
cls = type("{}Alternate".format(cls.__name__),
1645
cls = type(b"{}Alternate".format(cls.__name__),
3052
3027
if server_settings["restore"]:
3054
3029
with open(stored_state_path, "rb") as stored_state:
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
for key in clients_data:
3070
value = { (k.decode("utf-8")
3071
if isinstance(k, bytes) else k): v
3073
clients_data[key].items() }
3074
clients_data[key] = value
3076
value["client_structure"] = [
3078
if isinstance(s, bytes)
3080
value["client_structure"] ]
3082
for k in ("name", "host"):
3083
if isinstance(value[k], bytes):
3084
value[k] = value[k].decode("utf-8")
3085
## old_client_settings
3087
old_client_settings = {
3088
(key.decode("utf-8")
3089
if isinstance(key, bytes)
3092
bytes_old_client_settings.items() }
3094
for value in old_client_settings.values():
3095
value["host"] = value["host"].decode("utf-8")
3030
clients_data, old_client_settings = pickle.load(
3096
3032
os.remove(stored_state_path)
3097
3033
except IOError as e:
3098
3034
if e.errno == errno.ENOENT:
3248
3184
return dbus.Dictionary(
3249
3185
{ c.dbus_object_path: c.GetAll(
3250
3186
"se.recompile.Mandos.Client")
3251
for c in tcp_server.clients.values() },
3187
for c in tcp_server.clients.itervalues() },
3252
3188
signature="oa{sv}")
3254
3190
@dbus.service.method(_interface, in_signature="o")
3255
3191
def RemoveClient(self, object_path):
3257
for c in tcp_server.clients.values():
3193
for c in tcp_server.clients.itervalues():
3258
3194
if c.dbus_object_path == object_path:
3259
3195
del tcp_server.clients[c.name]
3260
3196
c.remove_from_connection()
3320
3256
# removed/edited, old secret will thus be unrecovable.
3322
3258
with PGPEngine() as pgp:
3323
for client in tcp_server.clients.values():
3259
for client in tcp_server.clients.itervalues():
3324
3260
key = client_settings[client.name]["secret"]
3325
3261
client.encrypted_secret = pgp.encrypt(client.secret,
3350
3286
prefix='clients-',
3351
3287
dir=os.path.dirname(stored_state_path),
3352
3288
delete=False) as stored_state:
3353
pickle.dump((clients, client_settings), stored_state,
3289
pickle.dump((clients, client_settings), stored_state)
3355
3290
tempname = stored_state.name
3356
3291
os.rename(tempname, stored_state_path)
3357
3292
except (IOError, OSError) as e: