JFIFxxC      C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr#!/usr/bin/python3 # SPDX-License-Identifier: GPL-2.0-or-later # # Copyright (C) 2010-2016 Red Hat, Inc. # # Authors: # Thomas Woerner # # python fork magic derived from setroubleshoot # Copyright (C) 2006,2007,2008,2009 Red Hat, Inc. # Authors: # John Dennis # Dan Walsh import os import sys import dbus import argparse from firewall import config from firewall.functions import firewalld_is_active from firewall.core.logger import log, FileLog def parse_cmdline(): parser = argparse.ArgumentParser() parser.add_argument( "--debug", nargs="?", const=1, default=0, type=int, choices=range(1, log.DEBUG_MAX + 1), help="""Enable logging of debug messages. Additional argument in range 1..%s can be used to specify log level.""" % log.DEBUG_MAX, metavar="level", ) parser.add_argument( "--debug-gc", help="""Turn on garbage collector leak information. The collector runs every 10 seconds and if there are leaks, it prints information about the leaks.""", action="store_true", ) parser.add_argument( "--nofork", help="""Turn off daemon forking, run as a foreground process.""", action="store_true", ) parser.add_argument( "--nopid", help="""Disable writing pid file and don't check for existing server process.""", action="store_true", ) parser.add_argument( "--system-config", help="""Path to firewalld system configuration""", metavar="path", ) parser.add_argument( "--default-config", help="""Path to firewalld default configuration""", metavar="path", ) parser.add_argument( "--log-target", choices=["mixed", "syslog", "file", "console"], default="mixed", help="""Log target. mixed is a backward compatible mode logging to multiple targets. The modes syslog, file or console log to one target only.""", ) parser.add_argument( "--log-file", help="""Path to firewalld log file""", metavar="path" ) return parser.parse_args() def setup_logging(args): # Set up logging capabilities if config.FIREWALLD_LOGTARGET == "syslog": log.setFormat("%(label)s%(message)s") log.setInfoLogging("*", log.syslog) if args.debug: log.setDebugLogging("*", log.syslog) log.setInfoLogLevel(log.INFO_MAX) log.setDebugLogLevel(args.debug) elif config.FIREWALLD_LOGTARGET == "file": log.setDateFormat("%Y-%m-%d %H:%M:%S") log.setFormat("%(date)s %(label)s%(message)s") log_file = FileLog(config.FIREWALLD_LOGFILE, "a") try: log_file.open() except IOError as e: print("Failed to open log file '%s': %s", config.FIREWALLD_LOGFILE, str(e)) else: log.setInfoLogging("*", log_file) if args.debug: log.setDebugLogging("*", log_file) log.setInfoLogLevel(log.INFO_MAX) log.setDebugLogLevel(args.debug) elif config.FIREWALLD_LOGTARGET == "console": log.setDateFormat("%Y-%m-%d %H:%M:%S") log.setFormat("%(date)s %(label)s%(message)s") log.setInfoLogging("*", log.stdout) if args.debug: log.setDebugLogging("*", log.stdout) log.setInfoLogLevel(log.INFO_MAX) log.setDebugLogLevel(args.debug) else: log.setDateFormat("%Y-%m-%d %H:%M:%S") log.setFormat("%(date)s %(label)s%(message)s") log.setInfoLogging( "*", log.syslog, [log.FATAL, log.ERROR, log.WARNING, log.TRACEBACK], fmt="%(label)s%(message)s", ) log.setDebugLogLevel(log.NO_INFO) log.setDebugLogLevel(log.NO_DEBUG) if args.debug: log.setInfoLogLevel(log.INFO_MAX) log.setDebugLogLevel(args.debug) if args.nofork: log.addInfoLogging("*", log.stdout) log.addDebugLogging("*", log.stdout) log_file = FileLog(config.FIREWALLD_LOGFILE, "a") try: log_file.open() except IOError as e: log.error( "Failed to open log file '%s': %s", config.FIREWALLD_LOGFILE, str(e) ) else: log.addInfoLogging( "*", log_file, [log.FATAL, log.ERROR, log.WARNING, log.TRACEBACK] ) log.addDebugLogging("*", log_file) if args.debug: log.addInfoLogging("*", log_file) log.addDebugLogging("*", log_file) def startup(args): try: if not args.nofork: # do the UNIX double-fork magic, see Stevens' "Advanced # Programming in the UNIX Environment" for details (ISBN 0201563177) pid = os.fork() if pid > 0: # exit first parent sys.exit(0) # decouple from parent environment os.chdir("/") os.setsid() os.umask(os.umask(0o077) | 0o022) # Do not close the file descriptors here anymore # File descriptors are now closed in runProg before execve # Redirect the standard I/O file descriptors to /dev/null if hasattr(os, "devnull"): REDIRECT_TO = os.devnull else: REDIRECT_TO = "/dev/null" fd = os.open(REDIRECT_TO, os.O_RDWR) os.dup2(fd, 0) # standard input (0) os.dup2(fd, 1) # standard output (1) os.dup2(fd, 2) # standard error (2) if not args.nopid: # write the pid file with open(config.FIREWALLD_PIDFILE, "w") as f: f.write(str(os.getpid())) if not os.path.exists(config.FIREWALLD_TEMPDIR): os.mkdir(config.FIREWALLD_TEMPDIR, 0o750) # attempt to drop Linux capabilities to a minimal set: # - CAP_NET_ADMIN # - CAP_NET_RAW # - CAP_SYS_MODULE try: import capng capng.capng_clear(capng.CAPNG_SELECT_BOTH) if ( capng.capng_update( capng.CAPNG_ADD, capng.CAPNG_EFFECTIVE | capng.CAPNG_PERMITTED | capng.CAPNG_BOUNDING_SET, capng.CAP_NET_ADMIN, ) or capng.capng_update( capng.CAPNG_ADD, capng.CAPNG_EFFECTIVE | capng.CAPNG_PERMITTED | capng.CAPNG_BOUNDING_SET, capng.CAP_NET_RAW, ) or capng.capng_update( capng.CAPNG_ADD, capng.CAPNG_EFFECTIVE | capng.CAPNG_PERMITTED | capng.CAPNG_BOUNDING_SET, capng.CAP_SYS_MODULE, ) or capng.capng_apply(capng.CAPNG_SELECT_BOTH) ): log.info(log.INFO1, "libcap-ng failed to drop Linux capabilities.") else: log.info( log.INFO1, "Dropped Linux capabilities to NET_ADMIN, NET_RAW, SYS_MODULE.", ) except ImportError: pass if args.system_config: config.set_system_config_paths(args.system_config) if args.default_config: config.set_default_config_paths(args.default_config) # Start the server mainloop here from firewall.server import server server.run_server(args.debug_gc) # Clean up on exit if not args.nopid and os.path.exists(config.FIREWALLD_PIDFILE): os.remove(config.FIREWALLD_PIDFILE) except OSError as e: log.fatal("Fork #1 failed: %d (%s)" % (e.errno, e.strerror)) log.exception() if not args.nopid and os.path.exists(config.FIREWALLD_PIDFILE): os.remove(config.FIREWALLD_PIDFILE) sys.exit(1) except dbus.exceptions.DBusException as e: log.fatal(str(e)) log.exception() if not args.nopid and os.path.exists(config.FIREWALLD_PIDFILE): os.remove(config.FIREWALLD_PIDFILE) sys.exit(1) except IOError as e: log.fatal(str(e)) log.exception() if not args.nopid and os.path.exists(config.FIREWALLD_PIDFILE): os.remove(config.FIREWALLD_PIDFILE) sys.exit(1) def main(): # firewalld should only be run as the root user if os.getuid() != 0: print("You need to be root to run %s." % sys.argv[0]) sys.exit(-1) # Process the command-line arguments args = parse_cmdline() config.FIREWALLD_LOGTARGET = args.log_target if args.log_file: config.FIREWALLD_LOGFILE = args.log_file setup_logging(args) # Don't attempt to run two copies of firewalld simultaneously if not args.nopid and firewalld_is_active(): log.fatal("Not starting FirewallD, already running.") sys.exit(1) startup(args) sys.exit(0) if __name__ == "__main__": main()