/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: 2012-06-17 22:07:02 UTC
  • mfrom: (237.7.154 trunk)
  • mto: This revision was merged to the branch mainline in revision 302.
  • Revision ID: teddy@recompile.se-20120617220702-oh6mr9nrx45ce968
MergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
    except ImportError:
89
89
        SO_BINDTODEVICE = None
90
90
 
91
 
version = "1.5.3"
 
91
version = "1.5.5"
92
92
stored_state_file = "clients.pickle"
93
93
 
94
94
logger = logging.getLogger()
151
151
    def __enter__(self):
152
152
        return self
153
153
    
154
 
    def __exit__ (self, exc_type, exc_value, traceback):
 
154
    def __exit__(self, exc_type, exc_value, traceback):
155
155
        self._cleanup()
156
156
        return False
157
157
    
1016
1016
        return xmlstring
1017
1017
 
1018
1018
 
1019
 
def datetime_to_dbus (dt, variant_level=0):
 
1019
def datetime_to_dbus(dt, variant_level=0):
1020
1020
    """Convert a UTC datetime.datetime() to a D-Bus type."""
1021
1021
    if dt is None:
1022
1022
        return dbus.String("", variant_level = variant_level)
1030
1030
    interface names according to the "alt_interface_names" mapping.
1031
1031
    Usage:
1032
1032
    
1033
 
    @alternate_dbus_names({"org.example.Interface":
1034
 
                               "net.example.AlternateInterface"})
 
1033
    @alternate_dbus_interfaces({"org.example.Interface":
 
1034
                                    "net.example.AlternateInterface"})
1035
1035
    class SampleDBusObject(dbus.service.Object):
1036
1036
        @dbus.service.method("org.example.Interface")
1037
1037
        def SampleDBusMethod():
1899
1899
        use_ipv6:       Boolean; to use IPv6 or not
1900
1900
    """
1901
1901
    def __init__(self, server_address, RequestHandlerClass,
1902
 
                 interface=None, use_ipv6=True):
 
1902
                 interface=None, use_ipv6=True, socketfd=None):
 
1903
        """If socketfd is set, use that file descriptor instead of
 
1904
        creating a new one with socket.socket().
 
1905
        """
1903
1906
        self.interface = interface
1904
1907
        if use_ipv6:
1905
1908
            self.address_family = socket.AF_INET6
 
1909
        if socketfd is not None:
 
1910
            # Save the file descriptor
 
1911
            self.socketfd = socketfd
 
1912
            # Save the original socket.socket() function
 
1913
            self.socket_socket = socket.socket
 
1914
            # To implement --socket, we monkey patch socket.socket.
 
1915
            # 
 
1916
            # (When socketserver.TCPServer is a new-style class, we
 
1917
            # could make self.socket into a property instead of monkey
 
1918
            # patching socket.socket.)
 
1919
            # 
 
1920
            # Create a one-time-only replacement for socket.socket()
 
1921
            @functools.wraps(socket.socket)
 
1922
            def socket_wrapper(*args, **kwargs):
 
1923
                # Restore original function so subsequent calls are
 
1924
                # not affected.
 
1925
                socket.socket = self.socket_socket
 
1926
                del self.socket_socket
 
1927
                # This time only, return a new socket object from the
 
1928
                # saved file descriptor.
 
1929
                return socket.fromfd(self.socketfd, *args, **kwargs)
 
1930
            # Replace socket.socket() function with wrapper
 
1931
            socket.socket = socket_wrapper
 
1932
        # The socketserver.TCPServer.__init__ will call
 
1933
        # socket.socket(), which might be our replacement,
 
1934
        # socket_wrapper(), if socketfd was set.
1906
1935
        socketserver.TCPServer.__init__(self, server_address,
1907
1936
                                        RequestHandlerClass)
 
1937
    
1908
1938
    def server_bind(self):
1909
1939
        """This overrides the normal server_bind() function
1910
1940
        to bind to an interface if one was specified, and also NOT to
1918
1948
                try:
1919
1949
                    self.socket.setsockopt(socket.SOL_SOCKET,
1920
1950
                                           SO_BINDTODEVICE,
1921
 
                                           str(self.interface
1922
 
                                               + '\0'))
 
1951
                                           str(self.interface + '\0'))
1923
1952
                except socket.error as error:
1924
1953
                    if error.errno == errno.EPERM:
1925
 
                        logger.error("No permission to"
1926
 
                                     " bind to interface %s",
1927
 
                                     self.interface)
 
1954
                        logger.error("No permission to bind to"
 
1955
                                     " interface %s", self.interface)
1928
1956
                    elif error.errno == errno.ENOPROTOOPT:
1929
1957
                        logger.error("SO_BINDTODEVICE not available;"
1930
1958
                                     " cannot bind to interface %s",
1931
1959
                                     self.interface)
1932
1960
                    elif error.errno == errno.ENODEV:
1933
 
                        logger.error("Interface %s does not"
1934
 
                                     " exist, cannot bind",
1935
 
                                     self.interface)
 
1961
                        logger.error("Interface %s does not exist,"
 
1962
                                     " cannot bind", self.interface)
1936
1963
                    else:
1937
1964
                        raise
1938
1965
        # Only bind(2) the socket if we really need to.
1968
1995
    """
1969
1996
    def __init__(self, server_address, RequestHandlerClass,
1970
1997
                 interface=None, use_ipv6=True, clients=None,
1971
 
                 gnutls_priority=None, use_dbus=True):
 
1998
                 gnutls_priority=None, use_dbus=True, socketfd=None):
1972
1999
        self.enabled = False
1973
2000
        self.clients = clients
1974
2001
        if self.clients is None:
1978
2005
        IPv6_TCPServer.__init__(self, server_address,
1979
2006
                                RequestHandlerClass,
1980
2007
                                interface = interface,
1981
 
                                use_ipv6 = use_ipv6)
 
2008
                                use_ipv6 = use_ipv6,
 
2009
                                socketfd = socketfd)
1982
2010
    def server_activate(self):
1983
2011
        if self.enabled:
1984
2012
            return socketserver.TCPServer.server_activate(self)
2165
2193
    parser.add_argument("--no-restore", action="store_false",
2166
2194
                        dest="restore", help="Do not restore stored"
2167
2195
                        " state")
 
2196
    parser.add_argument("--socket", type=int,
 
2197
                        help="Specify a file descriptor to a network"
 
2198
                        " socket to use instead of creating one")
2168
2199
    parser.add_argument("--statedir", metavar="DIR",
2169
2200
                        help="Directory to save/restore state in")
 
2201
    parser.add_argument("--foreground", action="store_true",
 
2202
                        help="Run in foreground")
2170
2203
    
2171
2204
    options = parser.parse_args()
2172
2205
    
2187
2220
                        "use_ipv6": "True",
2188
2221
                        "debuglevel": "",
2189
2222
                        "restore": "True",
2190
 
                        "statedir": "/var/lib/mandos"
 
2223
                        "socket": "",
 
2224
                        "statedir": "/var/lib/mandos",
 
2225
                        "foreground": "False",
2191
2226
                        }
2192
2227
    
2193
2228
    # Parse config file for server-global settings
2198
2233
    # Convert the SafeConfigParser object to a dict
2199
2234
    server_settings = server_config.defaults()
2200
2235
    # Use the appropriate methods on the non-string config options
2201
 
    for option in ("debug", "use_dbus", "use_ipv6"):
 
2236
    for option in ("debug", "use_dbus", "use_ipv6", "foreground"):
2202
2237
        server_settings[option] = server_config.getboolean("DEFAULT",
2203
2238
                                                           option)
2204
2239
    if server_settings["port"]:
2205
2240
        server_settings["port"] = server_config.getint("DEFAULT",
2206
2241
                                                       "port")
 
2242
    if server_settings["socket"]:
 
2243
        server_settings["socket"] = server_config.getint("DEFAULT",
 
2244
                                                         "socket")
 
2245
        # Later, stdin will, and stdout and stderr might, be dup'ed
 
2246
        # over with an opened os.devnull.  But we don't want this to
 
2247
        # happen with a supplied network socket.
 
2248
        if 0 <= server_settings["socket"] <= 2:
 
2249
            server_settings["socket"] = os.dup(server_settings
 
2250
                                               ["socket"])
2207
2251
    del server_config
2208
2252
    
2209
2253
    # Override the settings from the config file with command line
2211
2255
    for option in ("interface", "address", "port", "debug",
2212
2256
                   "priority", "servicename", "configdir",
2213
2257
                   "use_dbus", "use_ipv6", "debuglevel", "restore",
2214
 
                   "statedir"):
 
2258
                   "statedir", "socket", "foreground"):
2215
2259
        value = getattr(options, option)
2216
2260
        if value is not None:
2217
2261
            server_settings[option] = value
2220
2264
    for option in server_settings.keys():
2221
2265
        if type(server_settings[option]) is str:
2222
2266
            server_settings[option] = unicode(server_settings[option])
 
2267
    # Debug implies foreground
 
2268
    if server_settings["debug"]:
 
2269
        server_settings["foreground"] = True
2223
2270
    # Now we have our good server settings in "server_settings"
2224
2271
    
2225
2272
    ##################################################################
2231
2278
    use_ipv6 = server_settings["use_ipv6"]
2232
2279
    stored_state_path = os.path.join(server_settings["statedir"],
2233
2280
                                     stored_state_file)
 
2281
    foreground = server_settings["foreground"]
2234
2282
    
2235
2283
    if debug:
2236
2284
        initlogger(debug, logging.DEBUG)
2265
2313
                              use_ipv6=use_ipv6,
2266
2314
                              gnutls_priority=
2267
2315
                              server_settings["priority"],
2268
 
                              use_dbus=use_dbus)
2269
 
    if not debug:
 
2316
                              use_dbus=use_dbus,
 
2317
                              socketfd=(server_settings["socket"]
 
2318
                                        or None))
 
2319
    if not foreground:
2270
2320
        pidfilename = "/var/run/mandos.pid"
 
2321
        pidfile = None
2271
2322
        try:
2272
2323
            pidfile = open(pidfilename, "w")
2273
2324
        except IOError as e:
2312
2363
            os.close(null)
2313
2364
    
2314
2365
    # Need to fork before connecting to D-Bus
2315
 
    if not debug:
 
2366
    if not foreground:
2316
2367
        # Close all input and output, do double fork, etc.
2317
2368
        daemon()
2318
2369
    
 
2370
    # multiprocessing will use threads, so before we use gobject we
 
2371
    # need to inform gobject that threads will be used.
2319
2372
    gobject.threads_init()
2320
2373
    
2321
2374
    global main_loop
2449
2502
    if not tcp_server.clients:
2450
2503
        logger.warning("No clients defined")
2451
2504
    
2452
 
    if not debug:
2453
 
        try:
2454
 
            with pidfile:
2455
 
                pid = os.getpid()
2456
 
                pidfile.write(str(pid) + "\n".encode("utf-8"))
2457
 
            del pidfile
2458
 
        except IOError:
2459
 
            logger.error("Could not write to file %r with PID %d",
2460
 
                         pidfilename, pid)
2461
 
        except NameError:
2462
 
            # "pidfile" was never created
2463
 
            pass
 
2505
    if not foreground:
 
2506
        if pidfile is not None:
 
2507
            try:
 
2508
                with pidfile:
 
2509
                    pid = os.getpid()
 
2510
                    pidfile.write(str(pid) + "\n".encode("utf-8"))
 
2511
            except IOError:
 
2512
                logger.error("Could not write to file %r with PID %d",
 
2513
                             pidfilename, pid)
 
2514
        del pidfile
2464
2515
        del pidfilename
2465
2516
    
2466
2517
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())