HEX
Server: Apache
System: Linux vmi2872685.contaboserver.net 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64
User: computingcore (1007)
PHP: 8.3.28
Disabled: NONE
Upload Files
File: //sbin/firewalld
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2010-2016 Red Hat, Inc.
#
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# python fork magic derived from setroubleshoot
# Copyright (C) 2006,2007,2008,2009 Red Hat, Inc.
# Authors:
#   John Dennis <jdennis@redhat.com>
#   Dan Walsh <dwalsh@redhat.com>

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()