Example #1
0
static void init_digest_cache(fko_srv_options_t *opts)
{
    int     rp_cache_count;

#if AFL_FUZZING
    if(opts->afl_fuzzing)
        return;
#endif

    if(strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
    {
        rp_cache_count = replay_cache_init(opts);

        if(rp_cache_count < 0)
        {
            log_msg(LOG_WARNING,
                "Error opening digest cache file. Incoming digests will not be remembered."
            );
            /* Destination points to heap memory, and is guaranteed to be
             * at least two bytes large via validate_options(),
             * DEF_ENABLE_DIGEST_PERSISTENCE, and set_config_entry()
            */
            strlcpy(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "N", 2);
        }

        if(opts->verbose)
            log_msg(LOG_ERR,
                "Using Digest Cache: '%s' (entry count = %i)",
#if USE_FILE_CACHE
                opts->config[CONF_DIGEST_FILE], rp_cache_count
#else
                opts->config[CONF_DIGEST_DB_FILE], rp_cache_count
#endif
            );
    }
    return;
}
Example #2
0
int
main(int argc, char **argv)
{
    int                 res, last_sig, rp_cache_count;
    char               *locale;
    pid_t               old_pid;

    fko_srv_options_t   opts;

    while(1)
    {
        /* Handle command line
        */
        config_init(&opts, argc, argv);

        /* Process any options that do their thing and exit. */

        /* Kill the currently running fwknopd?
        */
        if(opts.kill == 1)
        {
            old_pid = get_running_pid(&opts);

            if(old_pid > 0)
            {
                res = kill(old_pid, SIGTERM);
                if(res == 0)
                {
                    fprintf(stderr, "Killed fwknopd (pid=%i)\n", old_pid);
                    exit(EXIT_SUCCESS);
                }
                else
                {
                    perror("Unable to kill fwknop: ");
                    exit(EXIT_FAILURE);
                }
            }
            else
            {
                fprintf(stderr, "No running fwknopd detected.\n");
                exit(EXIT_FAILURE);
            }
        }

        /* Status of the currently running fwknopd?
        */
        if(opts.status == 1)
        {
            old_pid = write_pid_file(&opts);

            if(old_pid > 0)
                fprintf(stderr, "Detected fwknopd is running (pid=%i).\n", old_pid);
            else
                fprintf(stderr, "No running fwknopd detected.\n");

            exit(EXIT_SUCCESS);
        }

        /* Restart the currently running fwknopd?
        */
        if(opts.restart == 1 || opts.status == 1)
        {
            old_pid = get_running_pid(&opts);

            if(old_pid > 0)
            {
                res = kill(old_pid, SIGHUP);
                if(res == 0)
                {
                    fprintf(stderr, "Sent restart signal to fwknopd (pid=%i)\n", old_pid);
                    exit(EXIT_SUCCESS);
                }
                else
                {
                    perror("Unable to send signal to fwknop: ");
                    exit(EXIT_FAILURE);
                }
            }
            else
            {
                fprintf(stderr, "No running fwknopd detected.\n");
                exit(EXIT_FAILURE);
            }
        }

        /* Initialize logging.
        */
        init_logging(&opts);

#if HAVE_LOCALE_H 
        /* Set the locale if specified. 
        */ 
        if(opts.config[CONF_LOCALE] != NULL
          && strncasecmp(opts.config[CONF_LOCALE], "NONE", 4) != 0) 
        { 
            locale = setlocale(LC_ALL, opts.config[CONF_LOCALE]); 
 
            if(locale == NULL) 
            { 
                log_msg(LOG_ERR, 
                    "WARNING: Unable to set locale to '%s'.", 
                    opts.config[CONF_LOCALE] 
                ); 
            } 
            else 
            { 
                if(opts.verbose) 
                    log_msg(LOG_INFO, 
                        "Locale set to '%s'.", opts.config[CONF_LOCALE] 
                    ); 
            } 
        } 
#endif 

        /* Make sure we have a valid run dir and path leading to digest file
         * in case it configured to be somewhere other than the run dir.
        */
        check_dir_path((const char *)opts.config[CONF_FWKNOP_RUN_DIR], "Run", 0);
#if USE_FILE_CACHE
        check_dir_path((const char *)opts.config[CONF_DIGEST_FILE], "Run", 1);
#else
        check_dir_path((const char *)opts.config[CONF_DIGEST_DB_FILE], "Run", 1);
#endif

        /* Process the access.conf file.
        */
        parse_access_file(&opts);

        /* Show config (including access.conf vars) and exit dump config was
         * wanted.
        */
        if(opts.dump_config == 1)
        {
            dump_config(&opts);
            dump_access_list(&opts);
            exit(EXIT_SUCCESS);
        }

        /* Initialize the firewall rules handler based on the fwknopd.conf
         * file, but (for iptables firewalls) don't flush any rules or create
         * any chains yet.  This allows us to dump the current firewall rules
         * via fw_rules_dump() in --fw-list mode before changing around any rules
         * of an existing fwknopd process.
        */
        fw_config_init(&opts);

        if(opts.fw_list == 1)
        {
            fw_dump_rules(&opts);
            exit(EXIT_SUCCESS);
        }

        /* If we are a new process (just being started), proceed with normal
         * start-up.  Otherwise, we are here as a result of a signal sent to an
         * existing process and we want to restart.
        */
        if(get_running_pid(&opts) != getpid())
        {
            /* If foreground mode is not set, the fork off and become a daemon.
            * Otherwise, attempt to get the pid file lock and go on.
            */
            if(opts.foreground == 0)
            {
                daemonize_process(&opts);
            }
            else
            {
                old_pid = write_pid_file(&opts);
                if(old_pid > 0)
                {
                    fprintf(stderr,
                        "* An instance of fwknopd is already running: (PID=%i).\n", old_pid
                    );

                    exit(EXIT_FAILURE);
                }
                else if(old_pid < 0)
                {
                    fprintf(stderr, "* PID file error. The lock may not be effective.\n");
                }
            }

            log_msg(LOG_INFO, "Starting %s", MY_NAME);
        }
        else
        {
            log_msg(LOG_INFO, "Re-starting %s", MY_NAME);
        }

        if(opts.verbose > 1 && opts.foreground)
        {
            dump_config(&opts);
            dump_access_list(&opts);
        }

        /* Initialize the digest cache for replay attack detection (either
         * with dbm support or with the default simple cache file strategy)
         * if so configured.
        */
        if(strncasecmp(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
        {
            rp_cache_count = replay_cache_init(&opts);

            if(rp_cache_count < 0)
            {
                log_msg(LOG_WARNING,
                    "Error opening digest cache file. Incoming digests will not be remembered."
                );
                strlcpy(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "N", 2);
            }

            if(opts.verbose)
                log_msg(LOG_ERR,
                    "Using Digest Cache: '%s' (entry count = %i)",
#if USE_FILE_CACHE
                    opts.config[CONF_DIGEST_FILE], rp_cache_count
#else
                    opts.config[CONF_DIGEST_DB_FILE], rp_cache_count
#endif
                );
        }

        /* Prepare the firewall - i.e. flush any old rules and (for iptables)
         * create fwknop chains.
        */
        fw_initialize(&opts);

        /* If the TCP server option was set, fire it up here.
        */
        if(strncasecmp(opts.config[CONF_ENABLE_TCP_SERVER], "Y", 1) == 0)
        {
            if(atoi(opts.config[CONF_TCPSERV_PORT]) <= 0
              || atoi(opts.config[CONF_TCPSERV_PORT]) >  65535)
            {
                log_msg(LOG_WARNING,
                    "WARNING: ENABLE_TCP_SERVER is set, but TCPSERV_PORT is not valid. TCP server not started!"
                );
            }
            else
            {
                run_tcp_server(&opts);
            }
        }

        /* Intiate pcap capture mode...
        */
        pcap_capture(&opts);

        if(got_signal) {
            last_sig   = got_signal;
            got_signal = 0;

            if(got_sighup)
            {
                log_msg(LOG_WARNING, "Got SIGHUP.  Re-reading configs.");
                free_configs(&opts);
                kill(opts.tcp_server_pid, SIGTERM);
                usleep(1000000);
                got_sighup = 0;
            }
            else if(got_sigint)
            {
                log_msg(LOG_WARNING, "Got SIGINT.  Exiting...");
                got_sigint = 0;
                break;
            }
            else if(got_sigterm)
            {
                log_msg(LOG_WARNING, "Got SIGTERM.  Exiting...");
                got_sigterm = 0;
                break;
            }
            else
            {
                log_msg(LOG_WARNING,
                    "Got signal %i. No defined action but to exit.", last_sig);
                break;
            }
        }
        else if (opts.packet_ctr_limit > 0
            && opts.packet_ctr >= opts.packet_ctr_limit)
        {
            log_msg(LOG_INFO,
                "Packet count limit (%d) reached.  Exiting...",
                opts.packet_ctr_limit);
            break;
        }
        else    /* got_signal was not set (should be if we are here) */
        {
            log_msg(LOG_WARNING,
                "Capture ended without signal.  Exiting...");
            break;
        }
    }

    log_msg(LOG_INFO, "Shutting Down fwknopd.");

    /* Kill the TCP server (if we have one running).
    */
    if(opts.tcp_server_pid > 0)
    {
        log_msg(LOG_INFO, "Killing the TCP server (pid=%i)",
            opts.tcp_server_pid);

        kill(opts.tcp_server_pid, SIGTERM);

        /* --DSS XXX: This seems to be necessary if the tcp server
         *            was restarted by this program.  We need to
         *            investigate and fix this. For now, this works
         *            (it is kludgy, but does no harm afaik).
        */
        kill(opts.tcp_server_pid, SIGKILL);
    }

    /* Other cleanup.
    */
    fw_cleanup();
    free_logging();

#if USE_FILE_CACHE
    free_replay_list(&opts);
#endif

    free_configs(&opts);

    return(0);
}