678
653
def handle(self):
679
654
logger.info(u"TCP connection from: %s",
680
655
unicode(self.client_address))
681
logger.debug(u"Pipe: %d", self.server.pipe[1])
682
# Open IPC pipe to parent process
683
with closing(os.fdopen(self.server.pipe[1], "w", 1)) as ipc:
684
session = (gnutls.connection
685
.ClientSession(self.request,
689
line = self.request.makefile().readline()
690
logger.debug(u"Protocol version: %r", line)
692
if int(line.strip().split()[0]) > 1:
694
except (ValueError, IndexError, RuntimeError), error:
695
logger.error(u"Unknown protocol version: %s", error)
698
# Note: gnutls.connection.X509Credentials is really a
699
# generic GnuTLS certificate credentials object so long as
700
# no X.509 keys are added to it. Therefore, we can use it
701
# here despite using OpenPGP certificates.
703
#priority = ':'.join(("NONE", "+VERS-TLS1.1",
704
# "+AES-256-CBC", "+SHA1",
705
# "+COMP-NULL", "+CTYPE-OPENPGP",
707
# Use a fallback default, since this MUST be set.
708
priority = self.server.settings.get("priority", "NORMAL")
709
(gnutls.library.functions
710
.gnutls_priority_set_direct(session._c_object,
715
except gnutls.errors.GNUTLSError, error:
716
logger.warning(u"Handshake failed: %s", error)
717
# Do not run session.bye() here: the session is not
718
# established. Just abandon the request.
720
logger.debug(u"Handshake succeeded")
722
fpr = fingerprint(peer_certificate(session))
723
except (TypeError, gnutls.errors.GNUTLSError), error:
724
logger.warning(u"Bad certificate: %s", error)
727
logger.debug(u"Fingerprint: %s", fpr)
729
for c in self.server.clients:
730
if c.fingerprint == fpr:
734
logger.warning(u"Client not found for fingerprint: %s",
736
ipc.write("NOTFOUND %s\n" % fpr)
739
# Have to check if client.still_valid(), since it is
740
# possible that the client timed out while establishing
741
# the GnuTLS session.
742
if not client.still_valid():
743
logger.warning(u"Client %(name)s is invalid",
745
ipc.write("INVALID %s\n" % client.name)
748
ipc.write("SENDING %s\n" % client.name)
750
while sent_size < len(client.secret):
751
sent = session.send(client.secret[sent_size:])
752
logger.debug(u"Sent: %d, remaining: %d",
753
sent, len(client.secret)
754
- (sent_size + sent))
759
class ForkingMixInWithPipe(SocketServer.ForkingMixIn, object):
760
"""Like SocketServer.ForkingMixIn, but also pass a pipe.
761
Assumes a gobject.MainLoop event loop.
763
def process_request(self, request, client_address):
764
"""This overrides and wraps the original process_request().
765
This function creates a new pipe in self.pipe
767
self.pipe = os.pipe()
768
super(ForkingMixInWithPipe,
769
self).process_request(request, client_address)
770
os.close(self.pipe[1]) # close write end
771
# Call "handle_ipc" for both data and EOF events
772
gobject.io_add_watch(self.pipe[0],
773
gobject.IO_IN | gobject.IO_HUP,
775
def handle_ipc(source, condition):
776
"""Dummy function; override as necessary"""
781
class IPv6_TCPServer(ForkingMixInWithPipe,
656
session = (gnutls.connection
657
.ClientSession(self.request,
661
line = self.request.makefile().readline()
662
logger.debug(u"Protocol version: %r", line)
664
if int(line.strip().split()[0]) > 1:
666
except (ValueError, IndexError, RuntimeError), error:
667
logger.error(u"Unknown protocol version: %s", error)
670
# Note: gnutls.connection.X509Credentials is really a generic
671
# GnuTLS certificate credentials object so long as no X.509
672
# keys are added to it. Therefore, we can use it here despite
673
# using OpenPGP certificates.
675
#priority = ':'.join(("NONE", "+VERS-TLS1.1", "+AES-256-CBC",
676
# "+SHA1", "+COMP-NULL", "+CTYPE-OPENPGP",
678
# Use a fallback default, since this MUST be set.
679
priority = self.server.settings.get("priority", "NORMAL")
680
(gnutls.library.functions
681
.gnutls_priority_set_direct(session._c_object,
686
except gnutls.errors.GNUTLSError, error:
687
logger.warning(u"Handshake failed: %s", error)
688
# Do not run session.bye() here: the session is not
689
# established. Just abandon the request.
692
fpr = fingerprint(peer_certificate(session))
693
except (TypeError, gnutls.errors.GNUTLSError), error:
694
logger.warning(u"Bad certificate: %s", error)
697
logger.debug(u"Fingerprint: %s", fpr)
698
for c in self.server.clients:
699
if c.fingerprint == fpr:
703
logger.warning(u"Client not found for fingerprint: %s",
707
# Have to check if client.still_valid(), since it is possible
708
# that the client timed out while establishing the GnuTLS
710
if not client.still_valid():
711
logger.warning(u"Client %(name)s is invalid",
715
## This won't work here, since we're in a fork.
716
# client.bump_timeout()
718
while sent_size < len(client.secret):
719
sent = session.send(client.secret[sent_size:])
720
logger.debug(u"Sent: %d, remaining: %d",
721
sent, len(client.secret)
722
- (sent_size + sent))
727
class IPv6_TCPServer(SocketServer.ForkingMixIn,
782
728
SocketServer.TCPServer, object):
783
"""IPv6-capable TCP server. Accepts 'None' as address and/or port
729
"""IPv6 TCP server. Accepts 'None' as address and/or port.
785
731
settings: Server settings
786
732
clients: Set() of Client objects
843
782
return super(IPv6_TCPServer, self).server_activate()
844
783
def enable(self):
845
784
self.enabled = True
846
def handle_ipc(self, source, condition, file_objects={}):
847
logger.debug("Handling IPC: %r : %r", source, condition)
849
# Turn a file descriptor into a Python file object
850
if source not in file_objects:
851
file_objects[source] = os.fdopen(source, "r", 1)
853
# Read a line from the file object
854
cmdline = file_objects[source].readline()
855
if not cmdline: # Empty line means end of file
857
logger.debug("Closing: %r", source)
858
file_objects[source].close()
859
del file_objects[source]
861
# Stop calling this function
864
logger.debug("IPC command: %r\n" % cmdline)
866
# Parse and act on command
867
cmd, args = cmdline.split(None, 1)
868
if cmd == "NOTFOUND":
870
elif cmd == "INVALID":
872
elif cmd == "SENDING":
874
# client.checked_ok()
876
logger.error("Unknown IPC command: %r", cmdline)
878
# Keep calling this function
882
787
def string_to_delta(interval):
883
788
"""Parse a string and return a datetime.timedelta
885
790
>>> string_to_delta('7d')
886
791
datetime.timedelta(7)
887
792
>>> string_to_delta('60s')
1039
941
server_config.read(os.path.join(options.configdir, "mandos.conf"))
1040
942
# Convert the SafeConfigParser object to a dict
1041
943
server_settings = server_config.defaults()
1042
# Use the appropriate methods on the non-string config options
1043
server_settings["debug"] = server_config.getboolean("DEFAULT",
1045
server_settings["use_dbus"] = server_config.getboolean("DEFAULT",
1047
server_settings["use_ipv6"] = server_config.getboolean("DEFAULT",
1049
if server_settings["port"]:
1050
server_settings["port"] = server_config.getint("DEFAULT",
944
# Use getboolean on the boolean config options
945
server_settings["debug"] = (server_config.getboolean
946
("DEFAULT", "debug"))
947
server_settings["use_dbus"] = (server_config.getboolean
948
("DEFAULT", "use_dbus"))
1052
949
del server_config
1054
951
# Override the settings from the config file with command line
1055
952
# options, if set.
1056
953
for option in ("interface", "address", "port", "debug",
1057
954
"priority", "servicename", "configdir",
1058
"use_dbus", "use_ipv6"):
1059
956
value = getattr(options, option)
1060
957
if value is not None:
1061
958
server_settings[option] = value