196
265
.replace(b"\n", b"\\n")
197
266
.replace(b"\0", b"\\x00"))
200
269
def encrypt(self, data, password):
201
270
passphrase = self.password_encode(password)
202
271
with tempfile.NamedTemporaryFile(
203
272
dir=self.tempdir) as passfile:
204
273
passfile.write(passphrase)
206
proc = subprocess.Popen(['gpg', '--symmetric',
275
proc = subprocess.Popen([self.gpg, '--symmetric',
207
276
'--passphrase-file',
209
278
+ self.gnupgargs,
210
stdin = subprocess.PIPE,
211
stdout = subprocess.PIPE,
212
stderr = subprocess.PIPE)
213
ciphertext, err = proc.communicate(input = data)
279
stdin=subprocess.PIPE,
280
stdout=subprocess.PIPE,
281
stderr=subprocess.PIPE)
282
ciphertext, err = proc.communicate(input=data)
214
283
if proc.returncode != 0:
215
284
raise PGPError(err)
216
285
return ciphertext
218
287
def decrypt(self, data, password):
219
288
passphrase = self.password_encode(password)
220
289
with tempfile.NamedTemporaryFile(
221
dir = self.tempdir) as passfile:
290
dir=self.tempdir) as passfile:
222
291
passfile.write(passphrase)
224
proc = subprocess.Popen(['gpg', '--decrypt',
293
proc = subprocess.Popen([self.gpg, '--decrypt',
225
294
'--passphrase-file',
227
296
+ self.gnupgargs,
228
stdin = subprocess.PIPE,
229
stdout = subprocess.PIPE,
230
stderr = subprocess.PIPE)
231
decrypted_plaintext, err = proc.communicate(input = data)
297
stdin=subprocess.PIPE,
298
stdout=subprocess.PIPE,
299
stderr=subprocess.PIPE)
300
decrypted_plaintext, err = proc.communicate(input=data)
232
301
if proc.returncode != 0:
233
302
raise PGPError(err)
234
303
return decrypted_plaintext
306
# Pretend that we have an Avahi module
308
"""This isn't so much a class as it is a module-like namespace."""
309
IF_UNSPEC = -1 # avahi-common/address.h
310
PROTO_UNSPEC = -1 # avahi-common/address.h
311
PROTO_INET = 0 # avahi-common/address.h
312
PROTO_INET6 = 1 # avahi-common/address.h
313
DBUS_NAME = "org.freedesktop.Avahi"
314
DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + ".EntryGroup"
315
DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
316
DBUS_PATH_SERVER = "/"
319
def string_array_to_txt_array(t):
320
return dbus.Array((dbus.ByteArray(s.encode("utf-8"))
321
for s in t), signature="ay")
322
ENTRY_GROUP_ESTABLISHED = 2 # avahi-common/defs.h
323
ENTRY_GROUP_COLLISION = 3 # avahi-common/defs.h
324
ENTRY_GROUP_FAILURE = 4 # avahi-common/defs.h
325
SERVER_INVALID = 0 # avahi-common/defs.h
326
SERVER_REGISTERING = 1 # avahi-common/defs.h
327
SERVER_RUNNING = 2 # avahi-common/defs.h
328
SERVER_COLLISION = 3 # avahi-common/defs.h
329
SERVER_FAILURE = 4 # avahi-common/defs.h
237
332
class AvahiError(Exception):
238
333
def __init__(self, value, *args, **kwargs):
239
334
self.value = value
429
524
class AvahiServiceToSyslog(AvahiService):
430
525
def rename(self, *args, **kwargs):
431
526
"""Add the new name to the syslog messages"""
432
ret = AvahiService.rename(self, *args, **kwargs)
527
ret = super(AvahiServiceToSyslog, self).rename(*args,
433
529
syslogger.setFormatter(logging.Formatter(
434
530
'Mandos ({}) [%(process)d]: %(levelname)s: %(message)s'
435
531
.format(self.name)))
535
# Pretend that we have a GnuTLS module
537
"""This isn't so much a class as it is a module-like namespace."""
539
library = ctypes.util.find_library("gnutls")
541
library = ctypes.util.find_library("gnutls-deb0")
542
_library = ctypes.cdll.LoadLibrary(library)
545
# Unless otherwise indicated, the constants and types below are
546
# all from the gnutls/gnutls.h C header file.
557
E_NO_CERTIFICATE_FOUND = -49
562
KEYID_USE_SHA256 = 1 # gnutls/x509.h
563
OPENPGP_FMT_RAW = 0 # gnutls/openpgp.h
566
class session_int(ctypes.Structure):
568
session_t = ctypes.POINTER(session_int)
570
class certificate_credentials_st(ctypes.Structure):
572
certificate_credentials_t = ctypes.POINTER(
573
certificate_credentials_st)
574
certificate_type_t = ctypes.c_int
576
class datum_t(ctypes.Structure):
577
_fields_ = [('data', ctypes.POINTER(ctypes.c_ubyte)),
578
('size', ctypes.c_uint)]
580
class openpgp_crt_int(ctypes.Structure):
582
openpgp_crt_t = ctypes.POINTER(openpgp_crt_int)
583
openpgp_crt_fmt_t = ctypes.c_int # gnutls/openpgp.h
584
log_func = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p)
585
credentials_type_t = ctypes.c_int
586
transport_ptr_t = ctypes.c_void_p
587
close_request_t = ctypes.c_int
590
class Error(Exception):
591
def __init__(self, message=None, code=None, args=()):
592
# Default usage is by a message string, but if a return
593
# code is passed, convert it to a string with
596
if message is None and code is not None:
597
message = gnutls.strerror(code)
598
return super(gnutls.Error, self).__init__(
601
class CertificateSecurityError(Error):
607
self._c_object = gnutls.certificate_credentials_t()
608
gnutls.certificate_allocate_credentials(
609
ctypes.byref(self._c_object))
610
self.type = gnutls.CRD_CERTIFICATE
613
gnutls.certificate_free_credentials(self._c_object)
616
def __init__(self, socket, credentials=None):
617
self._c_object = gnutls.session_t()
618
gnutls_flags = gnutls.CLIENT
619
if gnutls.check_version(b"3.5.6"):
620
gnutls_flags |= gnutls.NO_TICKETS
622
gnutls_flags |= gnutls.ENABLE_RAWPK
623
gnutls.init(ctypes.byref(self._c_object), gnutls_flags)
625
gnutls.set_default_priority(self._c_object)
626
gnutls.transport_set_ptr(self._c_object, socket.fileno())
627
gnutls.handshake_set_private_extensions(self._c_object,
630
if credentials is None:
631
credentials = gnutls.Credentials()
632
gnutls.credentials_set(self._c_object, credentials.type,
633
ctypes.cast(credentials._c_object,
635
self.credentials = credentials
638
gnutls.deinit(self._c_object)
641
return gnutls.handshake(self._c_object)
643
def send(self, data):
647
data_len -= gnutls.record_send(self._c_object,
652
return gnutls.bye(self._c_object, gnutls.SHUT_RDWR)
654
# Error handling functions
655
def _error_code(result):
656
"""A function to raise exceptions on errors, suitable
657
for the 'restype' attribute on ctypes functions"""
660
if result == gnutls.E_NO_CERTIFICATE_FOUND:
661
raise gnutls.CertificateSecurityError(code=result)
662
raise gnutls.Error(code=result)
664
def _retry_on_error(result, func, arguments):
665
"""A function to retry on some errors, suitable
666
for the 'errcheck' attribute on ctypes functions"""
668
if result not in (gnutls.E_INTERRUPTED, gnutls.E_AGAIN):
669
return _error_code(result)
670
result = func(*arguments)
673
# Unless otherwise indicated, the function declarations below are
674
# all from the gnutls/gnutls.h C header file.
677
priority_set_direct = _library.gnutls_priority_set_direct
678
priority_set_direct.argtypes = [session_t, ctypes.c_char_p,
679
ctypes.POINTER(ctypes.c_char_p)]
680
priority_set_direct.restype = _error_code
682
init = _library.gnutls_init
683
init.argtypes = [ctypes.POINTER(session_t), ctypes.c_int]
684
init.restype = _error_code
686
set_default_priority = _library.gnutls_set_default_priority
687
set_default_priority.argtypes = [session_t]
688
set_default_priority.restype = _error_code
690
record_send = _library.gnutls_record_send
691
record_send.argtypes = [session_t, ctypes.c_void_p,
693
record_send.restype = ctypes.c_ssize_t
694
record_send.errcheck = _retry_on_error
696
certificate_allocate_credentials = (
697
_library.gnutls_certificate_allocate_credentials)
698
certificate_allocate_credentials.argtypes = [
699
ctypes.POINTER(certificate_credentials_t)]
700
certificate_allocate_credentials.restype = _error_code
702
certificate_free_credentials = (
703
_library.gnutls_certificate_free_credentials)
704
certificate_free_credentials.argtypes = [
705
certificate_credentials_t]
706
certificate_free_credentials.restype = None
708
handshake_set_private_extensions = (
709
_library.gnutls_handshake_set_private_extensions)
710
handshake_set_private_extensions.argtypes = [session_t,
712
handshake_set_private_extensions.restype = None
714
credentials_set = _library.gnutls_credentials_set
715
credentials_set.argtypes = [session_t, credentials_type_t,
717
credentials_set.restype = _error_code
719
strerror = _library.gnutls_strerror
720
strerror.argtypes = [ctypes.c_int]
721
strerror.restype = ctypes.c_char_p
723
certificate_type_get = _library.gnutls_certificate_type_get
724
certificate_type_get.argtypes = [session_t]
725
certificate_type_get.restype = _error_code
727
certificate_get_peers = _library.gnutls_certificate_get_peers
728
certificate_get_peers.argtypes = [session_t,
729
ctypes.POINTER(ctypes.c_uint)]
730
certificate_get_peers.restype = ctypes.POINTER(datum_t)
732
global_set_log_level = _library.gnutls_global_set_log_level
733
global_set_log_level.argtypes = [ctypes.c_int]
734
global_set_log_level.restype = None
736
global_set_log_function = _library.gnutls_global_set_log_function
737
global_set_log_function.argtypes = [log_func]
738
global_set_log_function.restype = None
740
deinit = _library.gnutls_deinit
741
deinit.argtypes = [session_t]
742
deinit.restype = None
744
handshake = _library.gnutls_handshake
745
handshake.argtypes = [session_t]
746
handshake.restype = _error_code
747
handshake.errcheck = _retry_on_error
749
transport_set_ptr = _library.gnutls_transport_set_ptr
750
transport_set_ptr.argtypes = [session_t, transport_ptr_t]
751
transport_set_ptr.restype = None
753
bye = _library.gnutls_bye
754
bye.argtypes = [session_t, close_request_t]
755
bye.restype = _error_code
756
bye.errcheck = _retry_on_error
758
check_version = _library.gnutls_check_version
759
check_version.argtypes = [ctypes.c_char_p]
760
check_version.restype = ctypes.c_char_p
762
_need_version = b"3.3.0"
763
if check_version(_need_version) is None:
764
raise self.Error("Needs GnuTLS {} or later"
765
.format(_need_version))
767
_tls_rawpk_version = b"3.6.6"
768
has_rawpk = bool(check_version(_tls_rawpk_version))
772
class pubkey_st(ctypes.Structure):
774
pubkey_t = ctypes.POINTER(pubkey_st)
776
x509_crt_fmt_t = ctypes.c_int
778
# All the function declarations below are from
780
pubkey_init = _library.gnutls_pubkey_init
781
pubkey_init.argtypes = [ctypes.POINTER(pubkey_t)]
782
pubkey_init.restype = _error_code
784
pubkey_import = _library.gnutls_pubkey_import
785
pubkey_import.argtypes = [pubkey_t, ctypes.POINTER(datum_t),
787
pubkey_import.restype = _error_code
789
pubkey_get_key_id = _library.gnutls_pubkey_get_key_id
790
pubkey_get_key_id.argtypes = [pubkey_t, ctypes.c_int,
791
ctypes.POINTER(ctypes.c_ubyte),
792
ctypes.POINTER(ctypes.c_size_t)]
793
pubkey_get_key_id.restype = _error_code
795
pubkey_deinit = _library.gnutls_pubkey_deinit
796
pubkey_deinit.argtypes = [pubkey_t]
797
pubkey_deinit.restype = None
799
# All the function declarations below are from
802
openpgp_crt_init = _library.gnutls_openpgp_crt_init
803
openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
804
openpgp_crt_init.restype = _error_code
806
openpgp_crt_import = _library.gnutls_openpgp_crt_import
807
openpgp_crt_import.argtypes = [openpgp_crt_t,
808
ctypes.POINTER(datum_t),
810
openpgp_crt_import.restype = _error_code
812
openpgp_crt_verify_self = \
813
_library.gnutls_openpgp_crt_verify_self
814
openpgp_crt_verify_self.argtypes = [
817
ctypes.POINTER(ctypes.c_uint),
819
openpgp_crt_verify_self.restype = _error_code
821
openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
822
openpgp_crt_deinit.argtypes = [openpgp_crt_t]
823
openpgp_crt_deinit.restype = None
825
openpgp_crt_get_fingerprint = (
826
_library.gnutls_openpgp_crt_get_fingerprint)
827
openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
831
openpgp_crt_get_fingerprint.restype = _error_code
833
if check_version(b"3.6.4"):
834
certificate_type_get2 = _library.gnutls_certificate_type_get2
835
certificate_type_get2.argtypes = [session_t, ctypes.c_int]
836
certificate_type_get2.restype = _error_code
838
# Remove non-public functions
839
del _error_code, _retry_on_error
438
842
def call_pipe(connection, # : multiprocessing.Connection
439
843
func, *args, **kwargs):
440
844
"""This function is meant to be called by multiprocessing.Process
442
846
This function runs func(*args, **kwargs), and writes the resulting
443
847
return value on the provided multiprocessing.Connection.
445
849
connection.send(func(*args, **kwargs))
446
850
connection.close()
448
class Client(object):
449
854
"""A representation of a client host served by this server.
452
857
approved: bool(); 'None' if not yet approved/disapproved
453
858
approval_delay: datetime.timedelta(); Time to wait for approval
454
859
approval_duration: datetime.timedelta(); Duration of one approval
455
checker: subprocess.Popen(); a running checker process used
456
to see if the client lives.
457
'None' if no process is running.
458
checker_callback_tag: a gobject event source tag, or None
860
checker: multiprocessing.Process(); a running checker process used
861
to see if the client lives. 'None' if no process is
863
checker_callback_tag: a GLib event source tag, or None
459
864
checker_command: string; External command which is run to check
460
865
if client lives. %() expansions are done at
461
866
runtime with vars(self) as dict, so that for
462
867
instance %(name)s can be used in the command.
463
checker_initiator_tag: a gobject event source tag, or None
868
checker_initiator_tag: a GLib event source tag, or None
464
869
created: datetime.datetime(); (UTC) object creation
465
870
client_structure: Object describing what attributes a client has
466
871
and is used for storing the client at exit
467
872
current_checker_command: string; current running checker_command
468
disable_initiator_tag: a gobject event source tag, or None
873
disable_initiator_tag: a GLib event source tag, or None
470
875
fingerprint: string (40 or 32 hexadecimal digits); used to
471
uniquely identify the client
876
uniquely identify an OpenPGP client
877
key_id: string (64 hexadecimal digits); used to uniquely identify
878
a client using raw public keys
472
879
host: string; available for use by the checker command
473
880
interval: datetime.timedelta(); How often to start a new checker
474
881
last_approval_request: datetime.datetime(); (UTC) or None
1991
2405
delay -= time2 - time
1994
while sent_size < len(client.secret):
1996
sent = session.send(client.secret[sent_size:])
1997
except gnutls.errors.GNUTLSError as error:
1998
logger.warning("gnutls send failed",
2001
logger.debug("Sent: %d, remaining: %d", sent,
2002
len(client.secret) - (sent_size
2408
session.send(client.secret)
2409
except gnutls.Error as error:
2410
logger.warning("gnutls send failed",
2006
2414
logger.info("Sending secret to %s", client.name)
2007
2415
# bump the timeout using extended_timeout
2008
2416
client.bump_timeout(client.extended_timeout)
2009
2417
if self.server.use_dbus:
2010
2418
# Emit D-Bus signal
2011
2419
client.GotSecret()
2014
2422
if approval_required:
2015
2423
client.approvals_pending -= 1
2018
except gnutls.errors.GNUTLSError as error:
2426
except gnutls.Error as error:
2019
2427
logger.warning("GnuTLS bye failed",
2020
2428
exc_info=error)
2023
2431
def peer_certificate(session):
2024
"Return the peer's OpenPGP certificate as a bytestring"
2025
# If not an OpenPGP certificate...
2026
if (gnutls.library.functions.gnutls_certificate_type_get(
2028
!= gnutls.library.constants.GNUTLS_CRT_OPENPGP):
2029
# ...do the normal thing
2030
return session.peer_certificate
2432
"Return the peer's certificate as a bytestring"
2434
cert_type = gnutls.certificate_type_get2(session._c_object,
2436
except AttributeError:
2437
cert_type = gnutls.certificate_type_get(session._c_object)
2438
if gnutls.has_rawpk:
2439
valid_cert_types = frozenset((gnutls.CRT_RAWPK,))
2441
valid_cert_types = frozenset((gnutls.CRT_OPENPGP,))
2442
# If not a valid certificate type...
2443
if cert_type not in valid_cert_types:
2444
logger.info("Cert type %r not in %r", cert_type,
2446
# ...return invalid data
2031
2448
list_size = ctypes.c_uint(1)
2032
cert_list = (gnutls.library.functions
2033
.gnutls_certificate_get_peers
2449
cert_list = (gnutls.certificate_get_peers
2034
2450
(session._c_object, ctypes.byref(list_size)))
2035
2451
if not bool(cert_list) and list_size.value != 0:
2036
raise gnutls.errors.GNUTLSError("error getting peer"
2452
raise gnutls.Error("error getting peer certificate")
2038
2453
if list_size.value == 0:
2040
2455
cert = cert_list[0]
2041
2456
return ctypes.string_at(cert.data, cert.size)
2459
def key_id(certificate):
2460
"Convert a certificate bytestring to a hexdigit key ID"
2461
# New GnuTLS "datum" with the public key
2462
datum = gnutls.datum_t(
2463
ctypes.cast(ctypes.c_char_p(certificate),
2464
ctypes.POINTER(ctypes.c_ubyte)),
2465
ctypes.c_uint(len(certificate)))
2466
# XXX all these need to be created in the gnutls "module"
2467
# New empty GnuTLS certificate
2468
pubkey = gnutls.pubkey_t()
2469
gnutls.pubkey_init(ctypes.byref(pubkey))
2470
# Import the raw public key into the certificate
2471
gnutls.pubkey_import(pubkey,
2472
ctypes.byref(datum),
2473
gnutls.X509_FMT_DER)
2474
# New buffer for the key ID
2475
buf = ctypes.create_string_buffer(32)
2476
buf_len = ctypes.c_size_t(len(buf))
2477
# Get the key ID from the raw public key into the buffer
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))
2484
# Deinit the certificate
2485
gnutls.pubkey_deinit(pubkey)
2487
# Convert the buffer to a Python bytestring
2488
key_id = ctypes.string_at(buf, buf_len.value)
2489
# Convert the bytestring to hexadecimal notation
2490
hex_key_id = binascii.hexlify(key_id).upper()
2044
2494
def fingerprint(openpgp):
2045
2495
"Convert an OpenPGP bytestring to a hexdigit fingerprint"
2046
2496
# New GnuTLS "datum" with the OpenPGP public key
2047
datum = gnutls.library.types.gnutls_datum_t(
2497
datum = gnutls.datum_t(
2048
2498
ctypes.cast(ctypes.c_char_p(openpgp),
2049
2499
ctypes.POINTER(ctypes.c_ubyte)),
2050
2500
ctypes.c_uint(len(openpgp)))
2051
2501
# New empty GnuTLS certificate
2052
crt = gnutls.library.types.gnutls_openpgp_crt_t()
2053
gnutls.library.functions.gnutls_openpgp_crt_init(
2502
crt = gnutls.openpgp_crt_t()
2503
gnutls.openpgp_crt_init(ctypes.byref(crt))
2055
2504
# Import the OpenPGP public key into the certificate
2056
gnutls.library.functions.gnutls_openpgp_crt_import(
2057
crt, ctypes.byref(datum),
2058
gnutls.library.constants.GNUTLS_OPENPGP_FMT_RAW)
2505
gnutls.openpgp_crt_import(crt, ctypes.byref(datum),
2506
gnutls.OPENPGP_FMT_RAW)
2059
2507
# Verify the self signature in the key
2060
2508
crtverify = ctypes.c_uint()
2061
gnutls.library.functions.gnutls_openpgp_crt_verify_self(
2062
crt, 0, ctypes.byref(crtverify))
2509
gnutls.openpgp_crt_verify_self(crt, 0,
2510
ctypes.byref(crtverify))
2063
2511
if crtverify.value != 0:
2064
gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
2065
raise gnutls.errors.CertificateSecurityError(
2512
gnutls.openpgp_crt_deinit(crt)
2513
raise gnutls.CertificateSecurityError(code
2067
2515
# New buffer for the fingerprint
2068
2516
buf = ctypes.create_string_buffer(20)
2069
2517
buf_len = ctypes.c_size_t()
2070
2518
# Get the fingerprint from the certificate into the buffer
2071
gnutls.library.functions.gnutls_openpgp_crt_get_fingerprint(
2072
crt, ctypes.byref(buf), ctypes.byref(buf_len))
2519
gnutls.openpgp_crt_get_fingerprint(crt, ctypes.byref(buf),
2520
ctypes.byref(buf_len))
2073
2521
# Deinit the certificate
2074
gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
2522
gnutls.openpgp_crt_deinit(crt)
2075
2523
# Convert the buffer to a Python bytestring
2076
2524
fpr = ctypes.string_at(buf, buf_len.value)
2077
2525
# Convert the bytestring to hexadecimal notation
2165
2614
# socket_wrapper(), if socketfd was set.
2166
2615
socketserver.TCPServer.__init__(self, server_address,
2167
2616
RequestHandlerClass)
2169
2618
def server_bind(self):
2170
2619
"""This overrides the normal server_bind() function
2171
2620
to bind to an interface if one was specified, and also NOT to
2172
2621
bind to an address or port if they were not specified."""
2622
global SO_BINDTODEVICE
2173
2623
if self.interface is not None:
2174
2624
if SO_BINDTODEVICE is None:
2175
logger.error("SO_BINDTODEVICE does not exist;"
2176
" cannot bind to interface %s",
2180
self.socket.setsockopt(
2181
socket.SOL_SOCKET, SO_BINDTODEVICE,
2182
(self.interface + "\0").encode("utf-8"))
2183
except socket.error as error:
2184
if error.errno == errno.EPERM:
2185
logger.error("No permission to bind to"
2186
" interface %s", self.interface)
2187
elif error.errno == errno.ENOPROTOOPT:
2188
logger.error("SO_BINDTODEVICE not available;"
2189
" cannot bind to interface %s",
2191
elif error.errno == errno.ENODEV:
2192
logger.error("Interface %s does not exist,"
2193
" cannot bind", self.interface)
2625
# Fall back to a hard-coded value which seems to be
2627
logger.warning("SO_BINDTODEVICE not found, trying 25")
2628
SO_BINDTODEVICE = 25
2630
self.socket.setsockopt(
2631
socket.SOL_SOCKET, SO_BINDTODEVICE,
2632
(self.interface + "\0").encode("utf-8"))
2633
except socket.error as error:
2634
if error.errno == errno.EPERM:
2635
logger.error("No permission to bind to"
2636
" interface %s", self.interface)
2637
elif error.errno == errno.ENOPROTOOPT:
2638
logger.error("SO_BINDTODEVICE not available;"
2639
" cannot bind to interface %s",
2641
elif error.errno == errno.ENODEV:
2642
logger.error("Interface %s does not exist,"
2643
" cannot bind", self.interface)
2196
2646
# Only bind(2) the socket if we really need to.
2197
2647
if self.server_address[0] or self.server_address[1]:
2648
if self.server_address[1]:
2649
self.allow_reuse_address = True
2198
2650
if not self.server_address[0]:
2199
2651
if self.address_family == socket.AF_INET6:
2200
any_address = "::" # in6addr_any
2652
any_address = "::" # in6addr_any
2202
any_address = "0.0.0.0" # INADDR_ANY
2654
any_address = "0.0.0.0" # INADDR_ANY
2203
2655
self.server_address = (any_address,
2204
2656
self.server_address[1])
2205
2657
elif not self.server_address[1]:
2239
2691
self.gnutls_priority = gnutls_priority
2240
2692
IPv6_TCPServer.__init__(self, server_address,
2241
2693
RequestHandlerClass,
2242
interface = interface,
2243
use_ipv6 = use_ipv6,
2244
socketfd = socketfd)
2694
interface=interface,
2246
2698
def server_activate(self):
2247
2699
if self.enabled:
2248
2700
return socketserver.TCPServer.server_activate(self)
2250
2702
def enable(self):
2251
2703
self.enabled = True
2253
2705
def add_pipe(self, parent_pipe, proc):
2254
2706
# Call "handle_ipc" for both data and EOF events
2255
gobject.io_add_watch(
2256
parent_pipe.fileno(),
2257
gobject.IO_IN | gobject.IO_HUP,
2708
GLib.IOChannel.unix_new(parent_pipe.fileno()),
2709
GLib.PRIORITY_DEFAULT, GLib.IO_IN | GLib.IO_HUP,
2258
2710
functools.partial(self.handle_ipc,
2259
parent_pipe = parent_pipe,
2711
parent_pipe=parent_pipe,
2262
2714
def handle_ipc(self, source, condition,
2263
2715
parent_pipe=None,
2265
2717
client_object=None):
2266
2718
# error, or the other end of multiprocessing.Pipe has closed
2267
if condition & (gobject.IO_ERR | gobject.IO_HUP):
2719
if condition & (GLib.IO_ERR | GLib.IO_HUP):
2268
2720
# Wait for other process to exit
2272
2724
# Read a request from the child
2273
2725
request = parent_pipe.recv()
2274
2726
command = request[0]
2276
2728
if command == 'init':
2278
address = request[2]
2280
for c in self.clients.itervalues():
2281
if c.fingerprint == fpr:
2729
key_id = request[1].decode("ascii")
2730
fpr = request[2].decode("ascii")
2731
address = request[3]
2733
for c in self.clients.values():
2734
if key_id == ("E3B0C44298FC1C149AFBF4C8996FB924"
2735
"27AE41E4649B934CA495991B7852B855"):
2737
if key_id and c.key_id == key_id:
2740
if fpr and c.fingerprint == fpr:
2285
logger.info("Client not found for fingerprint: %s, ad"
2286
"dress: %s", fpr, address)
2744
logger.info("Client not found for key ID: %s, address"
2745
": %s", key_id or fpr, address)
2287
2746
if self.use_dbus:
2288
2747
# Emit D-Bus signal
2289
mandos_dbus_service.ClientNotFound(fpr,
2748
mandos_dbus_service.ClientNotFound(key_id or fpr,
2291
2750
parent_pipe.send(False)
2294
gobject.io_add_watch(
2295
parent_pipe.fileno(),
2296
gobject.IO_IN | gobject.IO_HUP,
2754
GLib.IOChannel.unix_new(parent_pipe.fileno()),
2755
GLib.PRIORITY_DEFAULT, GLib.IO_IN | GLib.IO_HUP,
2297
2756
functools.partial(self.handle_ipc,
2298
parent_pipe = parent_pipe,
2300
client_object = client))
2757
parent_pipe=parent_pipe,
2759
client_object=client))
2301
2760
parent_pipe.send(True)
2302
2761
# remove the old hook in favor of the new above hook on
2750
3221
protocol = avahi.PROTO_INET6 if use_ipv6 else avahi.PROTO_INET
2751
3222
service = AvahiServiceToSyslog(
2752
name = server_settings["servicename"],
2753
servicetype = "_mandos._tcp",
2754
protocol = protocol,
3223
name=server_settings["servicename"],
3224
servicetype="_mandos._tcp",
2756
3227
if server_settings["interface"]:
2757
3228
service.interface = if_nametoindex(
2758
3229
server_settings["interface"].encode("utf-8"))
2760
3231
global multiprocessing_manager
2761
3232
multiprocessing_manager = multiprocessing.Manager()
2763
3234
client_class = Client
2765
client_class = functools.partial(ClientDBus, bus = bus)
3236
client_class = functools.partial(ClientDBus, bus=bus)
2767
3238
client_settings = Client.config_parser(client_config)
2768
3239
old_client_settings = {}
2769
3240
clients_data = {}
2771
3242
# This is used to redirect stdout and stderr for checker processes
2773
wnull = open(os.devnull, "w") # A writable /dev/null
3244
wnull = open(os.devnull, "w") # A writable /dev/null
2774
3245
# Only used if server is running in foreground but not in debug
2776
3247
if debug or not foreground:
2779
3250
# Get client data and settings from last running state.
2780
3251
if server_settings["restore"]:
2782
3253
with open(stored_state_path, "rb") as stored_state:
2783
clients_data, old_client_settings = pickle.load(
3254
if sys.version_info.major == 2:
3255
clients_data, old_client_settings = pickle.load(
3258
bytes_clients_data, bytes_old_client_settings = (
3259
pickle.load(stored_state, encoding="bytes"))
3260
# Fix bytes to strings
3263
clients_data = {(key.decode("utf-8")
3264
if isinstance(key, bytes)
3267
bytes_clients_data.items()}
3268
del bytes_clients_data
3269
for key in clients_data:
3270
value = {(k.decode("utf-8")
3271
if isinstance(k, bytes) else k): v
3273
clients_data[key].items()}
3274
clients_data[key] = value
3276
value["client_structure"] = [
3278
if isinstance(s, bytes)
3280
value["client_structure"]]
3281
# .name, .host, and .checker_command
3282
for k in ("name", "host", "checker_command"):
3283
if isinstance(value[k], bytes):
3284
value[k] = value[k].decode("utf-8")
3285
if "key_id" not in value:
3286
value["key_id"] = ""
3287
elif "fingerprint" not in value:
3288
value["fingerprint"] = ""
3289
# old_client_settings
3291
old_client_settings = {
3292
(key.decode("utf-8")
3293
if isinstance(key, bytes)
3296
bytes_old_client_settings.items()}
3297
del bytes_old_client_settings
3298
# .host and .checker_command
3299
for value in old_client_settings.values():
3300
for attribute in ("host", "checker_command"):
3301
if isinstance(value[attribute], bytes):
3302
value[attribute] = (value[attribute]
2785
3304
os.remove(stored_state_path)
2786
3305
except IOError as e:
2787
3306
if e.errno == errno.ENOENT: