<commit_before>/*
 * Copyright (c) 2014, 2015 <NAME> <<EMAIL>>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * @file   main_greyd.c
 * @brief  Main function for the greyd daemon.
 * @author <NAME>
 * @date   2014
 */

#include <config.h>

#include <sys/types.h>
#include <sys/resource.h>

#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <signal.h>
#include <pwd.h>
#include <grp.h>
#include <poll.h>

#include "failures.h"
#include "greyd_config.h"
#include "constants.h"
#include "grey.h"
#include "sync.h"
#include "ip.h"
#include "utils.h"
#include "con.h"
#include "greyd.h"
#include "hash.h"
#include "log.h"
#include "config_parser.h"
#include "lexer_source.h"

#define PROG_NAME "greyd"

extern char *optarg;
extern int optind, opterr, optopt;

static void usage(void);
static int max_files(void);
static void destroy_blacklist(struct Hash_entry *entry);
static void shutdown_greyd(int sig);
static int start_fw_child(Config_T, int, int);

struct Greyd_state *Greyd_state = NULL;

static void
usage(void)
{
    fprintf(stderr,
        "usage: %s [-f config] [-45bdv] [-B maxblack] [-c maxcon] "
        "[-G passtime:greyexp:whiteexp]\n"
        "\t[-h hostname] [-l address] [-M address] [-n name] [-p port]\n"
        "\t[-S secs] [-s secs] [-L ipv6 address]\n"
        "[-w window] [-Y synctarget] [-y synclisten]\n",
        PROG_NAME);

    exit(1);
}

static void
shutdown_greyd(int sig)
{
    if(Greyd_state)
        Greyd_state->shutdown = 1;
}

static int
max_files(void)
{
    int max_files = CON_DEFAULT_MAX;

#ifdef __linux
    FILE *file_max = fopen("/proc/sys/fs/file-max", "r");
    if(file_max == NULL || fscanf(file_max, "%d", &max_files) == EOF)
        return max_files;
#endif

    if((max_files - MAX_FILES_THRESHOLD) < 10)
        errx(1, "max files is only %d, refusing to continue", max_files);
    else
        return (max_files - MAX_FILES_THRESHOLD);
}

static void
destroy_blacklist(struct Hash_entry *entry)
{
    if(entry && entry->v) {
        Blacklist_destroy((Blacklist_T *) &entry->v);
    }
}

static int
start_fw_child(Config_T config, int in_fd, int out_fd)
{
    FW_handle_T fw_handle;
    FILE *out;
    Lexer_source_T source;
    Lexer_T lexer;
    Config_parser_T parser;
    Config_T message;
    struct passwd *main_pw;
    char *main_user, *chroot_dir;
    int ret;
    struct sigaction sa;

    memset(&sa, 0, sizeof(sa));
    sigfillset(&sa.sa_mask);
    sa.sa_handler = shutdown_greyd;
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);

    /* Setup the firewall handle before dropping privileges. */
    if((fw_handle = FW_open(config)) == NULL)
        i_critical("could not obtain firewall handle");

    main_user = Config_get_str(config, "user", NULL, GREYD_MAIN_USER);
    if((main_pw = getpwnam(main_user)) == NULL)
        errx(1, "no such user %s", main_user);

    if(Config_get_int(config, "chroot", NULL, GREYD_CHROOT)) {
        chroot_dir = Config_get_str(config, "chroot_dir", NULL,
                                    GREYD_CHROOT_DIR);
        if(chroot(chroot_dir) == -1)
            i_critical("cannot chroot to %s", chroot_dir);
    }

    if(main_pw && Config_get_int(config, "drop_privs", NULL, 1)) {
        if(setgroups(1, &main_pw->pw_gid)
           || setresgid(main_pw->pw_gid, main_pw->pw_gid, main_pw->pw_gid)
           || setresuid(main_pw->pw_uid, main_pw->pw_uid, main_pw->pw_uid))
        {
            i_critical("failed to drop privileges: %s", strerror(errno));
        }
    }

    if((out = fdopen(out_fd, "w")) == NULL)
        i_critical("fdopen: %s", strerror(errno));

    source = Lexer_source_create_from_fd(in_fd);
    lexer = Config_lexer_create(source);
    parser = Config_parser_create(lexer);

    for(;;) {
        if(Greyd_state->shutdown) {
            i_info("stopping firewall process");
            goto cleanup;
        }

        message = Config_create();
        ret = Config_parser_start(parser, message);
        switch(ret) {
        case CONFIG_PARSER_OK:
            Greyd_process_fw_message(message, fw_handle, out);<commit_msg>added conditional compilation for chrooting firewall process with pf driver<commit_after>/*
 * Copyright (c) 2014, 2015 <NAME> <<EMAIL>>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * @file   main_greyd.c
 * @brief  Main function for the greyd daemon.
 * @author <NAME>
 * @date   2014
 */

#include <config.h>

#include <sys/types.h>
#include <sys/resource.h>

#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <signal.h>
#include <pwd.h>
#include <grp.h>
#include <poll.h>

#include "failures.h"
#include "greyd_config.h"
#include "constants.h"
#include "grey.h"
#include "sync.h"
#include "ip.h"
#include "utils.h"
#include "con.h"
#include "greyd.h"
#include "hash.h"
#include "log.h"
#include "config_parser.h"
#include "lexer_source.h"

#define PROG_NAME "greyd"

extern char *optarg;
extern int optind, opterr, optopt;

static void usage(void);
static int max_files(void);
static void destroy_blacklist(struct Hash_entry *entry);
static void shutdown_greyd(int sig);
static int start_fw_child(Config_T, int, int);

struct Greyd_state *Greyd_state = NULL;

static void
usage(void)
{
    fprintf(stderr,
        "usage: %s [-f config] [-45bdv] [-B maxblack] [-c maxcon] "
        "[-G passtime:greyexp:whiteexp]\n"
        "\t[-h hostname] [-l address] [-M address] [-n name] [-p port]\n"
        "\t[-S secs] [-s secs] [-L ipv6 address]\n"
        "[-w window] [-Y synctarget] [-y synclisten]\n",
        PROG_NAME);

    exit(1);
}

static void
shutdown_greyd(int sig)
{
    if(Greyd_state)
        Greyd_state->shutdown = 1;
}

static int
max_files(void)
{
    int max_files = CON_DEFAULT_MAX;

#ifdef __linux
    FILE *file_max = fopen("/proc/sys/fs/file-max", "r");
    if(file_max == NULL || fscanf(file_max, "%d", &max_files) == EOF)
        return max_files;
#endif

    if((max_files - MAX_FILES_THRESHOLD) < 10)
        errx(1, "max files is only %d, refusing to continue", max_files);
    else
        return (max_files - MAX_FILES_THRESHOLD);
}

static void
destroy_blacklist(struct Hash_entry *entry)
{
    if(entry && entry->v) {
        Blacklist_destroy((Blacklist_T *) &entry->v);
    }
}

static int
start_fw_child(Config_T config, int in_fd, int out_fd)
{
    FW_handle_T fw_handle;
    FILE *out;
    Lexer_source_T source;
    Lexer_T lexer;
    Config_parser_T parser;
    Config_T message;
    struct passwd *main_pw;
    char *main_user, *chroot_dir;
    int ret;
    struct sigaction sa;

    memset(&sa, 0, sizeof(sa));
    sigfillset(&sa.sa_mask);
    sa.sa_handler = shutdown_greyd;
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);

    /* Setup the firewall handle before dropping privileges. */
    if((fw_handle = FW_open(config)) == NULL)
        i_critical("could not obtain firewall handle");

    main_user = Config_get_str(config, "user", NULL, GREYD_MAIN_USER);
    if((main_pw = getpwnam(main_user)) == NULL)
        errx(1, "no such user %s", main_user);

#ifndef WITH_PF
    if(Config_get_int(config, "chroot", NULL, GREYD_CHROOT)) {
        chroot_dir = Config_get_str(config, "chroot_dir", NULL,
                                    GREYD_CHROOT_DIR);
        if(chroot(chroot_dir) == -1)
            i_critical("cannot chroot to %s", chroot_dir);
    }
#endif

    if(main_pw && Config_get_int(config, "drop_privs", NULL, 1)) {
        if(setgroups(1, &main_pw->pw_gid)
           || setresgid(main_pw->pw_gid, main_pw->pw_gid, main_pw->pw_gid)
           || setresuid(main_pw->pw_uid, main_pw->pw_uid, main_pw->pw_uid))
        {
            i_critical("failed to drop privileges: %s", strerror(errno));
        }
    }

    if((out = fdopen(out_fd, "w")) == NULL)
        i_critical("fdopen: %s", strerror(errno));

    source = Lexer_source_create_from_fd(in_fd);
    lexer = Config_lexer_create(source);
    parser = Config_parser_create(lexer);

    for(;;) {
        if(Greyd_state->shutdown) {
            i_info("stopping firewall process");
            goto cleanup;
        }

        message = Config_create();
        ret = Config_parser_start(parser, message);
        switch(ret) {
        case CONFIG_PARSER_OK:
            Greyd_process_fw_message(message, fw_handle, out);
{'fraction_non_alphanumeric': 0.12841998990408884, 'fraction_numerical': 0.005047955577990914, 'mean_word_length': 3.3238760366652116, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4464861', 'n_tokens_mistral': 3592, 'n_tokens_neox': 3440, 'n_words': 925}