/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2009-02-13 08:00:47 UTC
  • mfrom: (237.2.78 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20090213080047-eibfmj4j2a9zt53d
Merge from trunk.  Notable changes:

 1. Server package now depends on "python-gobject".
 2. Permission fix for /lib64.
 3. Support for DEVICE setting from initramfs.conf, kernel parameters
    "ip=" and "mandos=connect".
 4. Fix for the bug where the server would stop responding, with a
    zombie checker process.
 5. Add support for disabling IPv6 in the server
 6. Fix for the bug which made the server, plugin-runner and
    mandos-client fail to change group ID.
 7. Add GnuTLS debugging to server debug output.
 8. Fix for the bug of the "--options-for" option of plugin-runner,
    where it would cut the value at the first colon character.
 9. Stop using sscanf() throughout, since it does not detect overflow.
10. Fix for the bug where plugin-runner would not go to the fallback
    if all plugins failed.
11. Fix for the bug where mandos-client would not clean up after a
    signal.
12. Added support for connecting to IPv4 addresses in mandos-client.
13. Added support for not using a specific network interface in
    mandos-client.
14. Kernel log level will be lowered by mandos-client while bringing
    up the network interface.
15. Add an option for the maximum time for mandos-client to wait for
    the network interface to come up.
16. Fix for the bug where mandos-client would not clean the temporary
    directory on some filesystems.

Show diffs side-by-side

added added

removed removed

Lines of Context:
114
114
    """
115
115
    def __init__(self, interface = avahi.IF_UNSPEC, name = None,
116
116
                 servicetype = None, port = None, TXT = None,
117
 
                 domain = "", host = "", max_renames = 32768):
 
117
                 domain = "", host = "", max_renames = 32768,
 
118
                 protocol = avahi.PROTO_UNSPEC):
118
119
        self.interface = interface
119
120
        self.name = name
120
121
        self.type = servicetype
124
125
        self.host = host
125
126
        self.rename_count = 0
126
127
        self.max_renames = max_renames
 
128
        self.protocol = protocol
127
129
    def rename(self):
128
130
        """Derived from the Avahi example code"""
129
131
        if self.rename_count >= self.max_renames:
158
160
                     service.name, service.type)
159
161
        group.AddService(
160
162
                self.interface,         # interface
161
 
                avahi.PROTO_INET6,      # protocol
 
163
                self.protocol,          # protocol
162
164
                dbus.UInt32(0),         # flags
163
165
                self.name, self.type,
164
166
                self.domain, self.host,
203
205
                     client lives.  %() expansions are done at
204
206
                     runtime with vars(self) as dict, so that for
205
207
                     instance %(name)s can be used in the command.
 
208
    current_checker_command: string; current running checker_command
206
209
    use_dbus: bool(); Whether to provide D-Bus interface and signals
207
210
    dbus_object_path: dbus.ObjectPath ; only set if self.use_dbus
208
211
    """
257
260
        self.disable_initiator_tag = None
258
261
        self.checker_callback_tag = None
259
262
        self.checker_command = config["checker"]
 
263
        self.current_checker_command = None
260
264
        self.last_connect = None
261
265
        # Only now, when this client is initialized, can it show up on
262
266
        # the D-Bus
377
381
        # checkers alone, the checker would have to take more time
378
382
        # than 'timeout' for the client to be declared invalid, which
379
383
        # is as it should be.
 
384
        
 
385
        # If a checker exists, make sure it is not a zombie
 
386
        if self.checker is not None:
 
387
            pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
 
388
            if pid:
 
389
                logger.warning("Checker was a zombie")
 
390
                gobject.source_remove(self.checker_callback_tag)
 
391
                self.checker_callback(pid, status,
 
392
                                      self.current_checker_command)
 
393
        # Start a new checker if needed
380
394
        if self.checker is None:
381
395
            try:
382
396
                # In case checker_command has exactly one % operator
392
406
                    logger.error(u'Could not format string "%s":'
393
407
                                 u' %s', self.checker_command, error)
394
408
                    return True # Try again later
 
409
                self.current_checker_command = command
395
410
            try:
396
411
                logger.info(u"Starting checker %r for %s",
397
412
                            command, self.name)
412
427
                                             (self.checker.pid,
413
428
                                              self.checker_callback,
414
429
                                              data=command))
 
430
                # The checker may have completed before the gobject
 
431
                # watch was added.  Check for this.
 
432
                pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
 
433
                if pid:
 
434
                    gobject.source_remove(self.checker_callback_tag)
 
435
                    self.checker_callback(pid, status, command)
415
436
            except OSError, error:
416
437
                logger.error(u"Failed to start subprocess: %s",
417
438
                             error)
732
753
 
733
754
class IPv6_TCPServer(SocketServer.ForkingMixIn,
734
755
                     SocketServer.TCPServer, object):
735
 
    """IPv6 TCP server.  Accepts 'None' as address and/or port.
 
756
    """IPv6-capable TCP server.  Accepts 'None' as address and/or port
736
757
    Attributes:
737
758
        settings:       Server settings
738
759
        clients:        Set() of Client objects
746
767
        if "clients" in kwargs:
747
768
            self.clients = kwargs["clients"]
748
769
            del kwargs["clients"]
 
770
        if "use_ipv6" in kwargs:
 
771
            if not kwargs["use_ipv6"]:
 
772
                self.address_family = socket.AF_INET
 
773
            del kwargs["use_ipv6"]
749
774
        self.enabled = False
750
775
        super(IPv6_TCPServer, self).__init__(*args, **kwargs)
751
776
    def server_bind(self):
769
794
        # Only bind(2) the socket if we really need to.
770
795
        if self.server_address[0] or self.server_address[1]:
771
796
            if not self.server_address[0]:
772
 
                in6addr_any = "::"
773
 
                self.server_address = (in6addr_any,
 
797
                if self.address_family == socket.AF_INET6:
 
798
                    any_address = "::" # in6addr_any
 
799
                else:
 
800
                    any_address = socket.INADDR_ANY
 
801
                self.server_address = (any_address,
774
802
                                       self.server_address[1])
775
803
            elif not self.server_address[1]:
776
804
                self.server_address = (self.server_address[0],
921
949
                      " files")
922
950
    parser.add_option("--no-dbus", action="store_false",
923
951
                      dest="use_dbus",
924
 
                      help="Do not provide D-Bus system bus"
925
 
                      " interface")
 
952
                      help=optparse.SUPPRESS_HELP) # XXX: Not done yet
 
953
    parser.add_option("--no-ipv6", action="store_false",
 
954
                      dest="use_ipv6", help="Do not use IPv6")
926
955
    options = parser.parse_args()[0]
927
956
    
928
957
    if options.check:
939
968
                        "SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP",
940
969
                        "servicename": "Mandos",
941
970
                        "use_dbus": "True",
 
971
                        "use_ipv6": "True",
942
972
                        }
943
973
    
944
974
    # Parse config file for server-global settings
952
982
                                                        "debug")
953
983
    server_settings["use_dbus"] = server_config.getboolean("DEFAULT",
954
984
                                                           "use_dbus")
 
985
    server_settings["use_ipv6"] = server_config.getboolean("DEFAULT",
 
986
                                                           "use_ipv6")
955
987
    if server_settings["port"]:
956
988
        server_settings["port"] = server_config.getint("DEFAULT",
957
989
                                                       "port")
961
993
    # options, if set.
962
994
    for option in ("interface", "address", "port", "debug",
963
995
                   "priority", "servicename", "configdir",
964
 
                   "use_dbus"):
 
996
                   "use_dbus", "use_ipv6"):
965
997
        value = getattr(options, option)
966
998
        if value is not None:
967
999
            server_settings[option] = value
971
1003
    # For convenience
972
1004
    debug = server_settings["debug"]
973
1005
    use_dbus = server_settings["use_dbus"]
 
1006
    use_dbus = False            # XXX: Not done yet
 
1007
    use_ipv6 = server_settings["use_ipv6"]
974
1008
    
975
1009
    if not debug:
976
1010
        syslogger.setLevel(logging.WARNING)
997
1031
                                 server_settings["port"]),
998
1032
                                TCP_handler,
999
1033
                                settings=server_settings,
1000
 
                                clients=clients)
 
1034
                                clients=clients, use_ipv6=use_ipv6)
1001
1035
    pidfilename = "/var/run/mandos.pid"
1002
1036
    try:
1003
1037
        pidfile = open(pidfilename, "w")
1039
1073
         .gnutls_global_set_log_function(debug_gnutls))
1040
1074
    
1041
1075
    global service
 
1076
    protocol = avahi.PROTO_INET6 if use_ipv6 else avahi.PROTO_INET
1042
1077
    service = AvahiService(name = server_settings["servicename"],
1043
 
                           servicetype = "_mandos._tcp", )
 
1078
                           servicetype = "_mandos._tcp",
 
1079
                           protocol = protocol)
1044
1080
    if server_settings["interface"]:
1045
1081
        service.interface = (if_nametoindex
1046
1082
                             (server_settings["interface"]))
1173
1209
    
1174
1210
    # Find out what port we got
1175
1211
    service.port = tcp_server.socket.getsockname()[1]
1176
 
    logger.info(u"Now listening on address %r, port %d, flowinfo %d,"
1177
 
                u" scope_id %d" % tcp_server.socket.getsockname())
 
1212
    if use_ipv6:
 
1213
        logger.info(u"Now listening on address %r, port %d,"
 
1214
                    " flowinfo %d, scope_id %d"
 
1215
                    % tcp_server.socket.getsockname())
 
1216
    else:                       # IPv4
 
1217
        logger.info(u"Now listening on address %r, port %d"
 
1218
                    % tcp_server.socket.getsockname())
1178
1219
    
1179
1220
    #service.interface = tcp_server.socket.getsockname()[3]
1180
1221