#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef VERSION #define VERSION "1.0.0" #endif #define CRSD_LOG_NAME "crsd" #define CRSD_DEFAULT_PIDFILE "/var/run/crsd.pid" #define CRSD_DEFAULT_CFGFILE "/etc/crs/crsd.conf" #define CRSD_DEFAULT_FETCH_INTERVAL 120 #define CRSD_DEFAULT_FETCH_MARGIN 50 #define CRSD_DEFAULT_FETCH_TIMEOUT 60 #define CRSD_DEFAULT_CRL_MAX_SIZE 50000000ul #define CRSD_DEFAULT_CRL_STORAGE_MAX_SIZE 5000000000ul #define CRSD_DEFAULT_ROOTCERT_DIR "/etc/config/ike/ipsec.d/rootcerts" #define CRSD_DEFAULT_CACERT_DIR "/etc/config/ike/ipsec.d/cacerts" #define CRSD_DEFAULT_CERT_DIR "/etc/config/ike/ipsec.d/certs" #define CRSD_DEFAULT_OCSPCERT_DIR "/etc/config/ike/ipsec.d/ocspcerts" #define CRSD_DEFAULT_CRL_DIR "/etc/config/ike/ipsec.d/crls" #define CRSD_DEFAULT_KEY_DIR "/etc/config/ike/ipsec.d/private" #define CRSD_DEFAULT_P10_DIR "/etc/config/ike/ipsec.d/reqs" #define CRSD_DEFAULT_SECRETS_FILE "/etc/config/ike/ipsec.secrets" // Signal handlers static volatile int sigterm = 0; // Exit if 1 static void sighandler(int signo); static volatile int sighup = 0; // Re-read config file static void sighup_handler(int signo); static volatile int sigchld = 0; // Child execution is finished static void sigchld_handler(int signo); // Options and config file static void help(int status, const char *argv0); static struct options *opts_init(void); static void opts_free(struct options *opts); static int opts_parse(int argc, char *argv[], struct options *opts); static int opts_show(struct options *opts); static int config_parse(const char *cfgfile, struct options *opts); // Local syslog function bool_t verbose = BOOL_FALSE; bool_t silent = BOOL_FALSE; static void lsyslog(int priority, const char *format, ...) { va_list ap; if (silent) return; if (!verbose && (LOG_DEBUG == priority)) return; // Calculate buffer size va_start(ap, format); vsyslog(priority, format, ap); va_end(ap); } /** @brief Command line and config file options */ struct options { char *pidfile; char *cfgfile; char *unix_socket_path; bool_t cfgfile_userdefined; bool_t foreground; // Don't daemonize bool_t verbose; bool_t silent; bool_t check; int log_facility; char *uid_str; char *gid_str; uid_t uid; gid_t gid; long int fetch_interval; unsigned char fetch_margin; long int fetch_timeout; unsigned long int crl_max_size; unsigned long int crl_storage_max_size; char *rootcert_dir; char *cacert_dir; char *cert_dir; char *ocspcert_dir; char *crl_dir; char *key_dir; char *p10_dir; char *secrets_file; }; // Network static int create_listen_sock(const char *path, uid_t uid, gid_t gid); /** @brief Main function */ int main(int argc, char **argv) { int retval = -1; struct options *opts = NULL; int pidfd = -1; int logmask = 0; int logoptions = 0; // Event scheduler faux_sched_t *sched = NULL; // Network int listen_sock = -1; faux_pollfd_t *fds = NULL; // Signal vars struct sigaction sig_act = {}; sigset_t sig_set = {}; sigset_t orig_sig_set = {}; // Saved signal mask // Parse command line options opts = opts_init(); if (opts_parse(argc, argv, opts)) goto err; // Initialize syslog logoptions = LOG_CONS; if (opts->foreground) logoptions |= LOG_PERROR; openlog(CRSD_LOG_NAME, logoptions, opts->log_facility); if (!opts->verbose) { logmask = setlogmask(0); logmask = logmask & ~LOG_MASK(LOG_DEBUG); setlogmask(logmask); } // Parse config file lsyslog(LOG_DEBUG, "Parse config file: %s\n", opts->cfgfile); if (!access(opts->cfgfile, R_OK)) { if (config_parse(opts->cfgfile, opts)) goto err; } else if (opts->cfgfile_userdefined) { // User defined config must be found fprintf(stderr, "Error: Can't find config file %s\n", opts->cfgfile); goto err; } if (opts->check) { // Check only. Return 0 if config file is ok. retval = 0; goto err; } // DEBUG: Show options opts_show(opts); // Set crsp lib global var for debug if (opts->verbose) crsp_debug = 1; lsyslog(LOG_INFO, "Start daemon.\n"); // Fork the daemon if (!opts->foreground) { // Daemonize lsyslog(LOG_DEBUG, "Daemonize\n"); if (daemon(0, 0) < 0) { lsyslog(LOG_ERR, "Can't daemonize\n"); goto err; } // Write pidfile lsyslog(LOG_DEBUG, "Write PID file: %s\n", opts->pidfile); if ((pidfd = open(opts->pidfile, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { lsyslog(LOG_WARNING, "Can't open pidfile %s: %s\n", opts->pidfile, strerror(errno)); } else { char str[20]; snprintf(str, sizeof(str), "%u\n", getpid()); str[sizeof(str) - 1] = '\0'; if (write(pidfd, str, strlen(str)) < 0) lsyslog(LOG_WARNING, "Can't write to %s: %s\n", opts->pidfile, strerror(errno)); close(pidfd); } } // Network initialization lsyslog(LOG_DEBUG, "Create listen socket: %s\n", opts->unix_socket_path); listen_sock = create_listen_sock(opts->unix_socket_path, opts->uid, opts->gid); if (listen_sock < 0) goto err; // Change UID/GID if (opts->uid != getuid()) { lsyslog(LOG_DEBUG, "Change UID: %s\n", opts->uid_str ? opts->uid_str : ""); setfsuid(opts->uid); if (setresuid(opts->uid, opts->uid, opts->uid) < 0) { lsyslog(LOG_ERR, "Can't change user: %s", strerror(errno)); goto err; } } if (opts->gid != getgid()) { lsyslog(LOG_DEBUG, "Change GID: %s\n", opts->gid_str ? opts->gid_str : ""); if (setresgid(opts->gid, opts->gid, opts->gid) < 0 ) { lsyslog(LOG_ERR, "Can't change group: %s", strerror(errno)); goto err; } } // Set signal handler lsyslog(LOG_DEBUG, "Set signal handlers\n"); sigemptyset(&sig_set); sigaddset(&sig_set, SIGTERM); sigaddset(&sig_set, SIGINT); sigaddset(&sig_set, SIGQUIT); sig_act.sa_flags = 0; sig_act.sa_mask = sig_set; sig_act.sa_handler = &sighandler; sigaction(SIGTERM, &sig_act, NULL); sigaction(SIGINT, &sig_act, NULL); sigaction(SIGQUIT, &sig_act, NULL); // SIGHUP handler sigemptyset(&sig_set); sigaddset(&sig_set, SIGHUP); sig_act.sa_flags = 0; sig_act.sa_mask = sig_set; sig_act.sa_handler = &sighup_handler; sigaction(SIGHUP, &sig_act, NULL); // SIGCHLD handler sigemptyset(&sig_set); sigaddset(&sig_set, SIGCHLD); sig_act.sa_flags = 0; sig_act.sa_mask = sig_set; sig_act.sa_handler = &sigchld_handler; sigaction(SIGCHLD, &sig_act, NULL); // The struct pollfd vector for ppoll() fds = faux_pollfd_new(); if (!fds) { lsyslog(LOG_ERR, "Can't init pollfd vector"); goto err; } // Add listen socket to pollfds vector faux_pollfd_add(fds, listen_sock, POLLIN); // Block signals to prevent race conditions while loop and ppoll() // Catch signals while ppoll() only sigemptyset(&sig_set); sigaddset(&sig_set, SIGTERM); sigaddset(&sig_set, SIGINT); sigaddset(&sig_set, SIGQUIT); sigaddset(&sig_set, SIGHUP); sigaddset(&sig_set, SIGCHLD); sigprocmask(SIG_BLOCK, &sig_set, &orig_sig_set); // Main loop while (!sigterm) { int sn = 0; struct timespec *timeout = NULL; struct timespec next_interval = {}; faux_pollfd_iterator_t pollfd_iter; struct pollfd *pollfd = NULL; pid_t pid = -1; // Re-read config file on SIGHUP if (sighup) { if (access(opts->cfgfile, R_OK) == 0) { lsyslog(LOG_INFO, "Re-reading config file\n"); if (config_parse(opts->cfgfile, opts) < 0) lsyslog(LOG_ERR, "Error while config file parsing.\n"); reschedule_all(sched, cdp_db, opts->fetch_interval, opts->fetch_margin); } else if (opts->cfgfile_userdefined) { lsyslog(LOG_ERR, "Can't find config file.\n"); } sighup = 0; } // Non-blocking wait for all children while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { lsyslog(LOG_DEBUG, "Exit child process %d\n", pid); } sigchld = 0; // Find out timeout interval if (faux_sched_next_interval(sched, &next_interval) < 0) { timeout = NULL; } else { timeout = &next_interval; lsyslog(LOG_DEBUG, "Next interval: %ld\n", timeout->tv_sec); } // Wait for events sn = ppoll(faux_pollfd_vector(fds), faux_pollfd_len(fds), timeout, &orig_sig_set); if (sn < 0) { if ((EAGAIN == errno) || (EINTR == errno)) continue; lsyslog(LOG_ERR, "Error while select(): %s\n", strerror(errno)); break; } // Timeout (Scheduled event) if (0 == sn) { int id = 0; // Event idenftifier void *data = NULL; // Event data // Some scheduled events while(faux_sched_pop(sched, &id, &data) == 0) { cdp_t *cdp = (cdp_t *)data; download_args_t download_args = {}; // Now we have only one type of event - it's // a scheduled CRL downloading lsyslog(LOG_DEBUG, "sched: Update event for %s\n", cdp_uri(cdp)); download_args.cdp = cdp; download_args.opts = opts; fork_action(download_crl, (void *)&download_args); } continue; } // Get data via socket faux_pollfd_init_iterator(fds, &pollfd_iter); while ((pollfd = faux_pollfd_each_active(fds, &pollfd_iter))) { crsp_msg_t *req = NULL; crsp_msg_t *ack = NULL; faux_net_t *net = NULL; int fd = pollfd->fd; crsp_recv_e recv_status = CRSP_RECV_OK; // Listen socket if (fd == listen_sock) { int new_conn = -1; new_conn = accept(listen_sock, NULL, NULL); if (new_conn < 0) continue; faux_pollfd_add(fds, new_conn, POLLIN); lsyslog(LOG_DEBUG, "New connection %d\n", new_conn); continue; } // If it's not a listen socket then we have received // a message from client. net = faux_net_new(); faux_net_set_fd(net, fd); // Get message req = crsp_msg_recv(net, &recv_status); // Prepare empty answer structure ack = crsp_msg_new(); // Compose answer if (req) { msg_cb_f *handler = msg_handler[crsp_msg_get_cmd(req)]; crsp_msg_t *answer = NULL; // Callback function fills the answer by // real data if (handler) { msg_cb_args_t args = {}; args.cdp_db = cdp_db; args.sched = sched; args.opts = opts; args.credio = credio; args.net = net; answer = handler(req, ack, &args); if (!answer) { // Some local problem crsp_msg_set_cmd(ack, CRSP_CMD_ERROR); crsp_msg_set_status(ack, CRSP_STATUS_ERROR); } cdp_db_debug(cdp_db); // If there is no handler for this commnand just // return "unknown/unsupported command" message. } else { crsp_msg_set_cmd(ack, CRSP_CMD_ERROR); crsp_msg_set_status(ack, CRSP_STATUS_UNSUPPORTED); } // Some error while receiving } else { crsp_msg_set_cmd(ack, CRSP_CMD_ERROR); switch(recv_status) { case CRSP_RECV_OK: // Some system problem crsp_msg_set_status(ack, CRSP_STATUS_ERROR); break; default: // Classified problem // Now error codes of status is // equal to receive statuses. It can be // changed later. crsp_msg_set_status(ack, recv_status); break; } } // Send ACK crsp_msg_send(ack, net); crsp_msg_free(ack); crsp_msg_free(req); close(fd); faux_net_free(net); faux_pollfd_del_by_fd(fds, fd); lsyslog(LOG_DEBUG, "Close connection %d\n", fd); } } // Main loop end retval = 0; err: lsyslog(LOG_DEBUG, "Cleanup.\n"); sigprocmask(SIG_BLOCK, &orig_sig_set, NULL); faux_pollfd_free(fds); faux_sched_free(sched); // Close listen socket if (listen_sock >= 0) close(listen_sock); // Clean CDP database cdp_db_free(cdp_db); // Remove pidfile if (pidfd >= 0) { if (unlink(opts->pidfile) < 0) { lsyslog(LOG_ERR, "Can't remove pid-file %s: %s\n", opts->pidfile, strerror(errno)); } } // Crypto cleanup pgst_credio_free(&credio); pgst_cossl_free(&ossl); // Free command line options opts_free(opts); lsyslog(LOG_INFO, "Stop daemon.\n"); return retval; } /** @brief Create listen socket */ static int create_listen_sock(const char *path, uid_t uid, gid_t gid) { int sock = -1; int opt = 1; struct sockaddr_un laddr = {}; // mode_t mode = 0660; if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { lsyslog(LOG_ERR, "Cannot create socket: %s\n", strerror(errno)); goto error; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { lsyslog(LOG_ERR, "Can't set socket options: %s\n", strerror(errno)); goto error; } laddr.sun_family = AF_UNIX; strncpy(laddr.sun_path, path, USOCK_PATH_MAX); laddr.sun_path[USOCK_PATH_MAX - 1] = '\0'; unlink(path); if (bind(sock, (struct sockaddr *)&laddr, sizeof(laddr))) { lsyslog(LOG_ERR, "Can't bind socket: %s\n", strerror(errno)); goto err2; } if (uid != getuid() || gid != getgid()) { if (chown(path, uid, gid)) { lsyslog(LOG_ERR, "Can't chown socket: %s\n", strerror(errno)); goto err2; } } // if (chmod(path, mode)) { // lsyslog(LOG_ERR, "Can't chmod socket: %s\n", strerror(errno)); // goto err2; // } if (listen(sock, 64)) { lsyslog(LOG_ERR, "Can't listen socket: %s\n", strerror(errno)); goto err2; } return sock; err2: unlink(path); error: if (sock != -1) close(sock); return -1; } /** @brief Signal handler for temination signals (like SIGTERM, SIGINT, ...) */ static void sighandler(int signo) { sigterm = 1; signo = signo; // Happy compiler } /** @brief Re-read config file on SIGHUP */ static void sighup_handler(int signo) { sighup = 1; signo = signo; // Happy compiler } /** @brief Child was finished */ static void sigchld_handler(int signo) { sigchld = 1; signo = signo; // Happy compiler } /** @brief Initialize option structure by defaults */ static struct options *opts_init(void) { struct options *opts = NULL; opts = faux_zmalloc(sizeof(*opts)); assert(opts); // Initialize opts->pidfile = faux_str_dup(CRSD_DEFAULT_PIDFILE); opts->cfgfile = faux_str_dup(CRSD_DEFAULT_CFGFILE); opts->unix_socket_path = faux_str_dup(CRSD_DEFAULT_UNIX_SOCKET_PATH); opts->cfgfile_userdefined = BOOL_FALSE; opts->foreground = BOOL_FALSE; // Daemonize by default opts->verbose = BOOL_FALSE; opts->silent = BOOL_FALSE; opts->check = BOOL_FALSE; opts->log_facility = LOG_DAEMON; opts->uid = getuid(); opts->gid = getgid(); opts->uid_str = faux_sysdb_name_by_uid(opts->uid); opts->gid_str = faux_sysdb_name_by_gid(opts->gid); opts->fetch_interval = CRSD_DEFAULT_FETCH_INTERVAL; opts->fetch_margin = CRSD_DEFAULT_FETCH_MARGIN; opts->fetch_timeout = CRSD_DEFAULT_FETCH_TIMEOUT; opts->crl_max_size = CRSD_DEFAULT_CRL_MAX_SIZE; opts->crl_storage_max_size = CRSD_DEFAULT_CRL_STORAGE_MAX_SIZE; opts->rootcert_dir = faux_str_dup(CRSD_DEFAULT_ROOTCERT_DIR); opts->cacert_dir = faux_str_dup(CRSD_DEFAULT_CACERT_DIR); opts->cert_dir = faux_str_dup(CRSD_DEFAULT_CERT_DIR); opts->ocspcert_dir = faux_str_dup(CRSD_DEFAULT_OCSPCERT_DIR); opts->crl_dir = faux_str_dup(CRSD_DEFAULT_CRL_DIR); opts->key_dir = faux_str_dup(CRSD_DEFAULT_KEY_DIR); opts->p10_dir = faux_str_dup(CRSD_DEFAULT_P10_DIR); opts->secrets_file = faux_str_dup(CRSD_DEFAULT_SECRETS_FILE); return opts; } /** @brief Free options structure */ static void opts_free(struct options *opts) { faux_str_free(opts->pidfile); faux_str_free(opts->cfgfile); faux_str_free(opts->unix_socket_path); faux_str_free(opts->uid_str); faux_str_free(opts->gid_str); faux_str_free(opts->rootcert_dir); faux_str_free(opts->cacert_dir); faux_str_free(opts->cert_dir); faux_str_free(opts->ocspcert_dir); faux_str_free(opts->crl_dir); faux_str_free(opts->key_dir); faux_str_free(opts->p10_dir); faux_str_free(opts->secrets_file); faux_free(opts); } /** @brief Parse command line options */ static int opts_parse(int argc, char *argv[], struct options *opts) { static const char *shortopts = "hp:c:fl:vsk"; static const struct option longopts[] = { {"help", 0, NULL, 'h'}, {"pid", 1, NULL, 'p'}, {"conf", 1, NULL, 'c'}, {"foreground", 0, NULL, 'f'}, {"verbose", 0, NULL, 'v'}, {"silent", 0, NULL, 's'}, {"check", 0, NULL, 'k'}, {"facility", 1, NULL, 'l'}, {NULL, 0, NULL, 0} }; optind = 1; while(1) { int opt = 0; opt = getopt_long(argc, argv, shortopts, longopts, NULL); if (-1 == opt) break; switch (opt) { case 'p': faux_str_free(opts->pidfile); opts->pidfile = faux_str_dup(optarg); break; case 'c': faux_str_free(opts->cfgfile); opts->cfgfile = faux_str_dup(optarg); opts->cfgfile_userdefined = BOOL_TRUE; break; case 'f': opts->foreground = BOOL_TRUE; break; case 'v': opts->verbose = BOOL_TRUE; break; case 's': opts->silent = BOOL_TRUE; break; case 'k': opts->check = BOOL_TRUE; break; case 'l': if (faux_log_facility_id(optarg, &(opts->log_facility))) { fprintf(stderr, "Error: Illegal syslog facility %s.\n", optarg); _exit(-1); } break; case 'h': help(0, argv[0]); _exit(0); break; default: help(-1, argv[0]); _exit(-1); break; } } return 0; } /** @brief Print help message */ static void help(int status, const char *argv0) { const char *name = NULL; if (!argv0) return; // Find the basename name = strrchr(argv0, '/'); if (name) name++; else name = argv0; if (status != 0) { fprintf(stderr, "Try `%s -h' for more information.\n", name); } else { printf("Version : %s\n", VERSION); printf("Usage : %s [options]\n", name); printf("Certificate Revocation Service Daemon\n"); printf("Options :\n"); printf("\t-h, --help Print this help.\n"); printf("\t-f, --foreground Don't daemonize.\n"); printf("\t-v, --verbose Be verbose.\n"); printf("\t-s, --silent Be silent.\n"); printf("\t-k, --check Check config only and exit.\n"); printf("\t-p , --pid= File to save daemon's PID to (" CRSD_DEFAULT_PIDFILE ").\n"); printf("\t-c , --conf= Config file (" CRSD_DEFAULT_CFGFILE ").\n"); printf("\t-l, --facility Syslog facility (DAEMON).\n"); } } /** @brief Parse config file */ static int config_parse(const char *cfgfile, struct options *opts) { faux_ini_t *ini = NULL; const char *tmp = NULL; ini = faux_ini_new(); assert(ini); if (!ini) return -1; if (faux_ini_parse_file(ini, cfgfile)) { lsyslog(LOG_ERR, "Can't parse config file: %s\n", cfgfile); faux_ini_free(ini); return -1; } if ((tmp = faux_ini_find(ini, "UnixSocketPath"))) { faux_str_free(opts->unix_socket_path); opts->unix_socket_path = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "UID"))) { faux_str_free(opts->uid_str); opts->uid_str = faux_str_dup(tmp); if (faux_sysdb_uid_by_name(opts->uid_str, &opts->uid) < 0) { lsyslog(LOG_ERR, "Unknown user: %s\n", opts->uid_str); faux_ini_free(ini); return -1; // Unknown user } } if ((tmp = faux_ini_find(ini, "GID"))) { faux_str_free(opts->gid_str); opts->gid_str = faux_str_dup(tmp); if (faux_sysdb_gid_by_name(opts->gid_str, &opts->gid)) { lsyslog(LOG_ERR, "Unknown group: %s\n", opts->gid_str); faux_ini_free(ini); return -1; // Unknown group } } if ((tmp = faux_ini_find(ini, "FetchInterval"))) { if (faux_conv_atol(tmp, &opts->fetch_interval, 10) < 0) { lsyslog(LOG_ERR, "Illegal FetchInterval: %s\n", tmp); faux_ini_free(ini); return -1; } if (opts->fetch_interval < 0) { lsyslog(LOG_ERR, "FetchInterval can't be less than zero: %s\n", tmp); faux_ini_free(ini); return -1; } } if ((tmp = faux_ini_find(ini, "FetchMargin"))) { if (faux_conv_atouc(tmp, &opts->fetch_margin, 10) < 0) { lsyslog(LOG_ERR, "Illegal FetchMargin: %s\n", tmp); faux_ini_free(ini); return -1; } if (opts->fetch_margin > 100) { // Value in percents lsyslog(LOG_ERR, "FetchMargin (in percents) can't be greater than 100: %s\n", tmp); faux_ini_free(ini); return -1; } } if ((tmp = faux_ini_find(ini, "FetchTimeout"))) { if (faux_conv_atol(tmp, &opts->fetch_timeout, 10) < 0) { lsyslog(LOG_ERR, "Illegal FetchTimeout: %s\n", tmp); faux_ini_free(ini); return -1; } if (opts->fetch_timeout < 0) { lsyslog(LOG_ERR, "FetchTimeout can't be less than zero: %s\n", tmp); faux_ini_free(ini); return -1; } if (opts->fetch_timeout > opts->fetch_interval) { lsyslog(LOG_ERR, "FetchTimeout can't be greater than FetchInterval: %s\n", tmp); faux_ini_free(ini); return -1; } } if ((tmp = faux_ini_find(ini, "CRLMaxSize"))) { if (faux_conv_atoul(tmp, &opts->crl_max_size, 10) < 0) { lsyslog(LOG_ERR, "Illegal CRLMaxSize: %s\n", tmp); faux_ini_free(ini); return -1; } if (opts->crl_max_size > CRSD_DEFAULT_CRL_MAX_SIZE) { lsyslog(LOG_ERR, "CRLMaxSize can't be greater than %lu: %s\n", CRSD_DEFAULT_CRL_MAX_SIZE, tmp); faux_ini_free(ini); return -1; } } if ((tmp = faux_ini_find(ini, "CRLStorageMaxSize"))) { if (faux_conv_atoul(tmp, &opts->crl_storage_max_size, 10) < 0) { lsyslog(LOG_ERR, "Illegal CRLStorageMaxSize: %s\n", tmp); faux_ini_free(ini); return -1; } } if ((tmp = faux_ini_find(ini, "RootCertDir"))) { faux_str_free(opts->rootcert_dir); opts->rootcert_dir = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "CACertDir"))) { faux_str_free(opts->cacert_dir); opts->cacert_dir = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "CertDir"))) { faux_str_free(opts->cert_dir); opts->cert_dir = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "OCSPCertDir"))) { faux_str_free(opts->ocspcert_dir); opts->ocspcert_dir = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "CRLDir"))) { faux_str_free(opts->crl_dir); opts->crl_dir = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "KeyDir"))) { faux_str_free(opts->key_dir); opts->key_dir = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "P10Dir"))) { faux_str_free(opts->p10_dir); opts->p10_dir = faux_str_dup(tmp); } if ((tmp = faux_ini_find(ini, "SecretsFile"))) { faux_str_free(opts->secrets_file); opts->secrets_file = faux_str_dup(tmp); } faux_ini_free(ini); return 0; } /** @brief Show options. For debug purposes. */ static int opts_show(struct options *opts) { assert(opts); if (!opts) return -1; lsyslog(LOG_DEBUG, "opts: Foreground = %s\n", opts->foreground ? "true" : "false"); lsyslog(LOG_DEBUG, "opts: Verbose = %s\n", opts->verbose ? "true" : "false"); lsyslog(LOG_DEBUG, "opts: LogFacility = %s\n", faux_log_facility_str(opts->log_facility)); lsyslog(LOG_DEBUG, "opts: PIDPath = %s\n", opts->pidfile); lsyslog(LOG_DEBUG, "opts: ConfigPath = %s\n", opts->cfgfile); lsyslog(LOG_DEBUG, "opts: UnixSocketPath = %s\n", opts->unix_socket_path); lsyslog(LOG_DEBUG, "opts: UID = %s\n", opts->uid_str ? opts->uid_str : ""); lsyslog(LOG_DEBUG, "opts: GID = %s\n", opts->gid_str ? opts->gid_str : ""); lsyslog(LOG_DEBUG, "opts: FetchInterval = %ld sec\n", opts->fetch_interval); lsyslog(LOG_DEBUG, "opts: FetchMargin = %u %% \n", opts->fetch_margin); lsyslog(LOG_DEBUG, "opts: FetchTimeout = %ld sec\n", opts->fetch_timeout); lsyslog(LOG_DEBUG, "opts: CRLMaxSize = %ld bytes\n", opts->crl_max_size); lsyslog(LOG_DEBUG, "opts: CRLStorageMaxSize = %ld bytes\n", opts->crl_storage_max_size); lsyslog(LOG_DEBUG, "opts: RootCertDir = %s\n", opts->rootcert_dir); lsyslog(LOG_DEBUG, "opts: CACertDir = %s\n", opts->cacert_dir); lsyslog(LOG_DEBUG, "opts: CertDir = %s\n", opts->cert_dir); lsyslog(LOG_DEBUG, "opts: OCSPCertDir = %s\n", opts->ocspcert_dir); lsyslog(LOG_DEBUG, "opts: CRLDir = %s\n", opts->crl_dir); lsyslog(LOG_DEBUG, "opts: KeyDir = %s\n", opts->key_dir); lsyslog(LOG_DEBUG, "opts: P10Dir = %s\n", opts->p10_dir); lsyslog(LOG_DEBUG, "opts: SecretsFile = %s\n", opts->secrets_file); return 0; }