11
11
# "AvahiService" class, and some lines in "main".
13
13
# Everything else is
14
# Copyright © 2008-2019 Teddy Hogeborn
15
# Copyright © 2008-2019 Björn Påhlsson
14
# Copyright © 2008-2020 Teddy Hogeborn
15
# Copyright © 2008-2020 Björn Påhlsson
17
17
# This file is part of Mandos.
92
94
if sys.version_info.major == 2:
93
95
__metaclass__ = type
98
# Add collections.abc.Callable if it does not exist
100
collections.abc.Callable
101
except AttributeError:
103
Callable = collections.Callable
104
collections.abc = abc
107
# Add shlex.quote if it does not exist
110
except AttributeError:
111
shlex.quote = re.escape
95
113
# Show warnings by default
96
114
if not sys.warnoptions:
123
141
SO_BINDTODEVICE = None
125
if sys.version_info.major == 2:
128
143
if sys.version_info < (3, 2):
129
144
configparser.Configparser = configparser.SafeConfigParser
132
147
stored_state_file = "clients.pickle"
134
149
logger = logging.getLogger()
509
524
class AvahiServiceToSyslog(AvahiService):
510
525
def rename(self, *args, **kwargs):
511
526
"""Add the new name to the syslog messages"""
512
ret = super(AvahiServiceToSyslog, self).rename(*args, **kwargs)
527
ret = super(AvahiServiceToSyslog, self).rename(*args,
513
529
syslogger.setFormatter(logging.Formatter(
514
530
'Mandos ({}) [%(process)d]: %(levelname)s: %(message)s'
515
531
.format(self.name)))
760
776
x509_crt_fmt_t = ctypes.c_int
762
# All the function declarations below are from gnutls/abstract.h
778
# All the function declarations below are from
763
780
pubkey_init = _library.gnutls_pubkey_init
764
781
pubkey_init.argtypes = [ctypes.POINTER(pubkey_t)]
765
782
pubkey_init.restype = _error_code
779
796
pubkey_deinit.argtypes = [pubkey_t]
780
797
pubkey_deinit.restype = None
782
# All the function declarations below are from gnutls/openpgp.h
799
# All the function declarations below are from
784
802
openpgp_crt_init = _library.gnutls_openpgp_crt_init
785
803
openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
791
809
openpgp_crt_fmt_t]
792
810
openpgp_crt_import.restype = _error_code
794
openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
795
openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
796
ctypes.POINTER(ctypes.c_uint)]
812
openpgp_crt_verify_self = \
813
_library.gnutls_openpgp_crt_verify_self
814
openpgp_crt_verify_self.argtypes = [
817
ctypes.POINTER(ctypes.c_uint),
797
819
openpgp_crt_verify_self.restype = _error_code
799
821
openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
1037
1059
if self.checker_initiator_tag is not None:
1038
1060
GLib.source_remove(self.checker_initiator_tag)
1039
1061
self.checker_initiator_tag = GLib.timeout_add(
1040
int(self.interval.total_seconds() * 1000),
1062
random.randrange(int(self.interval.total_seconds() * 1000
1041
1064
self.start_checker)
1042
1065
# Schedule a disable() when 'timeout' has passed
1043
1066
if self.disable_initiator_tag is not None:
1117
1141
if self.checker is None:
1118
1142
# Escape attributes for the shell
1119
1143
escaped_attrs = {
1120
attr: re.escape(str(getattr(self, attr)))
1144
attr: shlex.quote(str(getattr(self, attr)))
1121
1145
for attr in self.runtime_expansions}
1123
1147
command = self.checker_command % escaped_attrs
1412
1436
raise ValueError("Byte arrays not supported for non-"
1413
1437
"'ay' signature {!r}"
1414
1438
.format(prop._dbus_signature))
1415
value = dbus.ByteArray(b''.join(chr(byte)
1439
value = dbus.ByteArray(bytes(value))
1419
1442
@dbus.service.method(dbus.PROPERTIES_IFACE,
2452
2475
buf = ctypes.create_string_buffer(32)
2453
2476
buf_len = ctypes.c_size_t(len(buf))
2454
2477
# Get the key ID from the raw public key into the buffer
2455
gnutls.pubkey_get_key_id(pubkey,
2456
gnutls.KEYID_USE_SHA256,
2457
ctypes.cast(ctypes.byref(buf),
2458
ctypes.POINTER(ctypes.c_ubyte)),
2459
ctypes.byref(buf_len))
2478
gnutls.pubkey_get_key_id(
2480
gnutls.KEYID_USE_SHA256,
2481
ctypes.cast(ctypes.byref(buf),
2482
ctypes.POINTER(ctypes.c_ubyte)),
2483
ctypes.byref(buf_len))
2460
2484
# Deinit the certificate
2461
2485
gnutls.pubkey_deinit(pubkey)
2707
2731
address = request[3]
2709
2733
for c in self.clients.values():
2710
if key_id == "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855":
2734
if key_id == ("E3B0C44298FC1C149AFBF4C8996FB924"
2735
"27AE41E4649B934CA495991B7852B855"):
2712
2737
if key_id and c.key_id == key_id:
2765
2790
def rfc3339_duration_to_delta(duration):
2766
2791
"""Parse an RFC 3339 "duration" and return a datetime.timedelta
2768
>>> rfc3339_duration_to_delta("P7D")
2769
datetime.timedelta(7)
2770
>>> rfc3339_duration_to_delta("PT60S")
2771
datetime.timedelta(0, 60)
2772
>>> rfc3339_duration_to_delta("PT60M")
2773
datetime.timedelta(0, 3600)
2774
>>> rfc3339_duration_to_delta("PT24H")
2775
datetime.timedelta(1)
2776
>>> rfc3339_duration_to_delta("P1W")
2777
datetime.timedelta(7)
2778
>>> rfc3339_duration_to_delta("PT5M30S")
2779
datetime.timedelta(0, 330)
2780
>>> rfc3339_duration_to_delta("P1DT3M20S")
2781
datetime.timedelta(1, 200)
2793
>>> timedelta = datetime.timedelta
2794
>>> rfc3339_duration_to_delta("P7D") == timedelta(7)
2796
>>> rfc3339_duration_to_delta("PT60S") == timedelta(0, 60)
2798
>>> rfc3339_duration_to_delta("PT60M") == timedelta(0, 3600)
2800
>>> rfc3339_duration_to_delta("PT24H") == timedelta(1)
2802
>>> rfc3339_duration_to_delta("P1W") == timedelta(7)
2804
>>> rfc3339_duration_to_delta("PT5M30S") == timedelta(0, 330)
2806
>>> rfc3339_duration_to_delta("P1DT3M20S") == timedelta(1, 200)
2784
2811
# Parsing an RFC 3339 duration with regular expressions is not
2864
2891
def string_to_delta(interval):
2865
2892
"""Parse a string and return a datetime.timedelta
2867
>>> string_to_delta('7d')
2868
datetime.timedelta(7)
2869
>>> string_to_delta('60s')
2870
datetime.timedelta(0, 60)
2871
>>> string_to_delta('60m')
2872
datetime.timedelta(0, 3600)
2873
>>> string_to_delta('24h')
2874
datetime.timedelta(1)
2875
>>> string_to_delta('1w')
2876
datetime.timedelta(7)
2877
>>> string_to_delta('5m 30s')
2878
datetime.timedelta(0, 330)
2894
>>> string_to_delta('7d') == datetime.timedelta(7)
2896
>>> string_to_delta('60s') == datetime.timedelta(0, 60)
2898
>>> string_to_delta('60m') == datetime.timedelta(0, 3600)
2900
>>> string_to_delta('24h') == datetime.timedelta(1)
2902
>>> string_to_delta('1w') == datetime.timedelta(7)
2904
>>> string_to_delta('5m 30s') == datetime.timedelta(0, 330)
3251
3278
if isinstance(s, bytes)
3252
3279
else s) for s in
3253
3280
value["client_structure"]]
3255
for k in ("name", "host"):
3281
# .name, .host, and .checker_command
3282
for k in ("name", "host", "checker_command"):
3256
3283
if isinstance(value[k], bytes):
3257
3284
value[k] = value[k].decode("utf-8")
3258
3285
if "key_id" not in value:
3268
3295
for key, value in
3269
3296
bytes_old_client_settings.items()}
3270
3297
del bytes_old_client_settings
3298
# .host and .checker_command
3272
3299
for value in old_client_settings.values():
3273
if isinstance(value["host"], bytes):
3274
value["host"] = (value["host"]
3300
for attribute in ("host", "checker_command"):
3301
if isinstance(value[attribute], bytes):
3302
value[attribute] = (value[attribute]
3276
3304
os.remove(stored_state_path)
3277
3305
except IOError as e:
3278
3306
if e.errno == errno.ENOENT: