324
319
# Emit D-Bus signal
325
320
self.PropertyChanged(dbus.String(u"checker_running"),
326
321
dbus.Boolean(False, variant_level=1))
327
if os.WIFEXITED(condition):
328
exitstatus = os.WEXITSTATUS(condition)
330
logger.info(u"Checker for %(name)s succeeded",
334
logger.info(u"Checker for %(name)s failed",
322
if (os.WIFEXITED(condition)
323
and (os.WEXITSTATUS(condition) == 0)):
324
logger.info(u"Checker for %(name)s succeeded",
336
326
if self.use_dbus:
337
327
# Emit D-Bus signal
338
self.CheckerCompleted(dbus.Int16(exitstatus),
339
dbus.Int64(condition),
328
self.CheckerCompleted(dbus.Boolean(True),
329
dbus.UInt16(condition),
340
330
dbus.String(command))
332
elif not os.WIFEXITED(condition):
342
333
logger.warning(u"Checker for %(name)s crashed?",
344
335
if self.use_dbus:
345
336
# Emit D-Bus signal
346
self.CheckerCompleted(dbus.Int16(-1),
347
dbus.Int64(condition),
337
self.CheckerCompleted(dbus.Boolean(False),
338
dbus.UInt16(condition),
339
dbus.String(command))
341
logger.info(u"Checker for %(name)s failed",
345
self.CheckerCompleted(dbus.Boolean(False),
346
dbus.UInt16(condition),
348
347
dbus.String(command))
350
def checked_ok(self):
349
def bump_timeout(self):
351
350
"""Bump up the timeout for this client.
352
351
This should only be called when the client has been seen,
656
649
def handle(self):
657
650
logger.info(u"TCP connection from: %s",
658
651
unicode(self.client_address))
659
logger.debug(u"Pipe: %d", self.server.pipe[1])
660
# Open IPC pipe to parent process
661
with closing(os.fdopen(self.server.pipe[1], "w", 1)) as ipc:
662
session = (gnutls.connection
663
.ClientSession(self.request,
667
line = self.request.makefile().readline()
668
logger.debug(u"Protocol version: %r", line)
670
if int(line.strip().split()[0]) > 1:
672
except (ValueError, IndexError, RuntimeError), error:
673
logger.error(u"Unknown protocol version: %s", error)
676
# Note: gnutls.connection.X509Credentials is really a
677
# generic GnuTLS certificate credentials object so long as
678
# no X.509 keys are added to it. Therefore, we can use it
679
# here despite using OpenPGP certificates.
681
#priority = ':'.join(("NONE", "+VERS-TLS1.1",
682
# "+AES-256-CBC", "+SHA1",
683
# "+COMP-NULL", "+CTYPE-OPENPGP",
685
# Use a fallback default, since this MUST be set.
686
priority = self.server.settings.get("priority", "NORMAL")
687
(gnutls.library.functions
688
.gnutls_priority_set_direct(session._c_object,
693
except gnutls.errors.GNUTLSError, error:
694
logger.warning(u"Handshake failed: %s", error)
695
# Do not run session.bye() here: the session is not
696
# established. Just abandon the request.
698
logger.debug(u"Handshake succeeded")
700
fpr = fingerprint(peer_certificate(session))
701
except (TypeError, gnutls.errors.GNUTLSError), error:
702
logger.warning(u"Bad certificate: %s", error)
705
logger.debug(u"Fingerprint: %s", fpr)
706
for c in self.server.clients:
707
if c.fingerprint == fpr:
711
logger.warning(u"Client not found for fingerprint: %s",
713
ipc.write("NOTFOUND %s\n" % fpr)
716
# Have to check if client.still_valid(), since it is
717
# possible that the client timed out while establishing
718
# the GnuTLS session.
719
if not client.still_valid():
720
logger.warning(u"Client %(name)s is invalid",
722
ipc.write("INVALID %s\n" % client.name)
725
ipc.write("SENDING %s\n" % client.name)
726
## This won't work here, since we're in a fork.
727
# client.checked_ok()
729
while sent_size < len(client.secret):
730
sent = session.send(client.secret[sent_size:])
731
logger.debug(u"Sent: %d, remaining: %d",
732
sent, len(client.secret)
733
- (sent_size + sent))
738
class ForkingMixInWithPipe(SocketServer.ForkingMixIn, object):
739
"""Like SocketServer.ForkingMixIn, but also pass a pipe.
740
Assumes a gobject.MainLoop event loop.
742
def process_request(self, request, client_address):
743
"""This overrides and wraps the original process_request().
744
This function creates a new pipe in self.pipe
746
self.pipe = os.pipe()
747
super(ForkingMixInWithPipe,
748
self).process_request(request, client_address)
749
os.close(self.pipe[1]) # close write end
750
# Call "handle_ipc" for both data and EOF events
751
gobject.io_add_watch(self.pipe[0],
752
gobject.IO_IN | gobject.IO_HUP,
754
def handle_ipc(source, condition):
755
"""Dummy function; override as necessary"""
760
class IPv6_TCPServer(ForkingMixInWithPipe,
652
session = (gnutls.connection
653
.ClientSession(self.request,
657
line = self.request.makefile().readline()
658
logger.debug(u"Protocol version: %r", line)
660
if int(line.strip().split()[0]) > 1:
662
except (ValueError, IndexError, RuntimeError), error:
663
logger.error(u"Unknown protocol version: %s", error)
666
# Note: gnutls.connection.X509Credentials is really a generic
667
# GnuTLS certificate credentials object so long as no X.509
668
# keys are added to it. Therefore, we can use it here despite
669
# using OpenPGP certificates.
671
#priority = ':'.join(("NONE", "+VERS-TLS1.1", "+AES-256-CBC",
672
# "+SHA1", "+COMP-NULL", "+CTYPE-OPENPGP",
674
# Use a fallback default, since this MUST be set.
675
priority = self.server.settings.get("priority", "NORMAL")
676
(gnutls.library.functions
677
.gnutls_priority_set_direct(session._c_object,
682
except gnutls.errors.GNUTLSError, error:
683
logger.warning(u"Handshake failed: %s", error)
684
# Do not run session.bye() here: the session is not
685
# established. Just abandon the request.
688
fpr = fingerprint(peer_certificate(session))
689
except (TypeError, gnutls.errors.GNUTLSError), error:
690
logger.warning(u"Bad certificate: %s", error)
693
logger.debug(u"Fingerprint: %s", fpr)
694
for c in self.server.clients:
695
if c.fingerprint == fpr:
699
logger.warning(u"Client not found for fingerprint: %s",
703
# Have to check if client.still_valid(), since it is possible
704
# that the client timed out while establishing the GnuTLS
706
if not client.still_valid():
707
logger.warning(u"Client %(name)s is invalid",
711
## This won't work here, since we're in a fork.
712
# client.bump_timeout()
714
while sent_size < len(client.secret):
715
sent = session.send(client.secret[sent_size:])
716
logger.debug(u"Sent: %d, remaining: %d",
717
sent, len(client.secret)
718
- (sent_size + sent))
723
class IPv6_TCPServer(SocketServer.ForkingMixIn,
761
724
SocketServer.TCPServer, object):
762
725
"""IPv6 TCP server. Accepts 'None' as address and/or port.
815
778
return super(IPv6_TCPServer, self).server_activate()
816
779
def enable(self):
817
780
self.enabled = True
818
def handle_ipc(self, source, condition, file_objects={}):
819
logger.debug("Handling IPC: %r : %r", source, condition)
821
# Turn a file descriptor into a Python file object
822
if source not in file_objects:
823
file_objects[source] = os.fdopen(source, "r", 1)
825
# Read a line from the file object
826
cmdline = file_objects[source].readline()
827
if not cmdline: # Empty line means end of file
829
logger.debug("Closing: %r", source)
830
file_objects[source].close()
831
del file_objects[source]
833
# Stop calling this function
836
logger.debug("IPC command: %r\n" % cmdline)
838
# Parse and act on command
839
cmd, args = cmdline.split(None, 1)
840
if cmd == "NOTFOUND":
842
elif cmd == "INVALID":
844
elif cmd == "SENDING":
847
logger.error("Unknown IPC command: %r", cmdline)
849
# Keep calling this function
853
783
def string_to_delta(interval):
1164
1098
class MandosServer(dbus.service.Object):
1165
1099
"""A D-Bus proxy object"""
1166
1100
def __init__(self):
1167
dbus.service.Object.__init__(self, bus, "/")
1168
_interface = u"se.bsnet.fukt.Mandos"
1101
dbus.service.Object.__init__(self, bus,
1103
_interface = u"org.mandos_system.Mandos"
1170
1105
@dbus.service.signal(_interface, signature="oa{sv}")
1171
1106
def ClientAdded(self, objpath, properties):
1175
@dbus.service.signal(_interface, signature="os")
1176
def ClientRemoved(self, objpath, name):
1110
@dbus.service.signal(_interface, signature="o")
1111
def ClientRemoved(self, objpath):
1180
1115
@dbus.service.method(_interface, out_signature="ao")
1181
1116
def GetAllClients(self):
1183
1117
return dbus.Array(c.dbus_object_path for c in clients)
1185
1119
@dbus.service.method(_interface, out_signature="a{oa{sv}}")
1186
1120
def GetAllClientsWithProperties(self):
1188
1121
return dbus.Dictionary(
1189
1122
((c.dbus_object_path, c.GetAllProperties())
1190
1123
for c in clients),
1191
1124
signature="oa{sv}")
1193
1126
@dbus.service.method(_interface, in_signature="o")
1194
1127
def RemoveClient(self, object_path):
1196
1128
for c in clients:
1197
1129
if c.dbus_object_path == object_path:
1198
1130
clients.remove(c)