int configuration(struct app_parent *app_p, const char *configfile, char **policy_file, char **syslog_ident, int *syslog_flags, int *syslog_facility) { unsigned int i, j; struct tq_listener_s *p_listener = NULL; struct tq_service_s *p_service = NULL; char *buf = NULL; cfg_t *cfg; cfg_t *syslog_sec; unsigned n_listener, n_services; int ret; static cfg_opt_t syslog_opts[] = { CFG_STR("ident", NULL, CFGF_NONE), CFG_INT_CB("facility", NONE, CFGF_NONE, &cb_syslog_facility), CFG_INT_LIST_CB("options", NULL, CFGF_NONE, &cb_syslog_options), CFG_END() }; static cfg_opt_t service_opts[] = { CFG_INT_CB("type", NONE, CFGF_NONE, &cb_service_type), CFG_STR("uri", 0, CFGF_NONE), CFG_INT("threads", 4, CFGF_NONE), CFG_END() }; static cfg_opt_t listener_opts[] = { CFG_STR("bindaddress", 0, CFGF_NONE), CFG_INT("port", 9001, CFGF_NONE), CFG_INT("backlog", 1024, CFGF_NONE), CFG_STR("cert", 0, CFGF_NONE), CFG_STR("key", 0, CFGF_NONE), CFG_STR("cafile", 0, CFGF_NONE), CFG_STR("capath", 0, CFGF_NONE), CFG_STR("crlpath", 0, CFGF_NONE), CFG_STR("password", 0, CFGF_NONE), CFG_STR("cipherlist", 0, CFGF_NONE), CFG_INT_CB("clientauth", NONE, CFGF_NONE, &cb_answer), CFG_INT_CB("rfc3820", NONE, CFGF_NONE, &cb_answer), CFG_STR("whitelist", 0, CFGF_NONE), CFG_STR("blacklist", 0, CFGF_NONE), CFG_SEC("service", service_opts, CFGF_MULTI), CFG_END() }; cfg_opt_t opts[] = { CFG_INT_CB("debug", NONE, CFGF_NONE, &cb_answer), CFG_STR("policyfile", 0, CFGF_NONE), CFG_SEC("syslog", syslog_opts, CFGF_NONE), CFG_SEC("listener", listener_opts, CFGF_MULTI), CFG_END() }; cfg = cfg_init(opts, CFGF_NOCASE); /* set a validating callback function for bookmark sections */ /* cfg_set_validate_func(cfg, "bookmark", &cb_validate_bookmark); */ ret = cfg_parse(cfg, configfile); if (ret == CFG_FILE_ERROR) { fprintf(stderr, "Error: could not open or read the configuration file " "\"%s\".\n", configfile); return GA_BAD; } else if (ret == CFG_PARSE_ERROR) { fprintf(stderr, "Error: parse error in the configuration file " "\"%s\".\n", configfile); return GA_BAD; } /* Generic */ app_p->debug = cfg_getint(cfg, "debug"); if (app_p->debug == MAYBE || app_p->debug == OPTIONAL) { printf("Overriding debug setting to 'yes'\n"); app_p->debug = YES; } else if (app_p->debug == YES) { printf("= Service running in DEBUG mode =\n"); } /* XACML Rules file */ *policy_file = strdup(cfg_getstr(cfg, "policyfile")); if (*policy_file == NULL) { fprintf(stderr, "Error: no \"policyfile\" set in the configuration file\n"); return GA_BAD; } else { if (app_p->verbose) { printf("Using XACML Policy file: \"%s\"\n", *policy_file); } } /* Syslog */ syslog_sec = cfg_getsec(cfg, "syslog"); if (syslog_sec == NULL) { fprintf(stderr, "Error: no \"syslog\" section found in the " "configuration file \"%s\"\n", configfile); } else { *syslog_ident = strdup(cfg_getstr(syslog_sec, "ident")); *syslog_facility = cfg_getint(syslog_sec, "facility"); if (app_p->debug == YES) { printf("found syslog\n"); printf(" ident = %s\n", cfg_getstr(syslog_sec, "ident")); printf(" facility = %ld\n", cfg_getint(syslog_sec, "facility")); printf("BUG\n"); for (i = 0; i < cfg_size(syslog_sec, "options"); i++) { printf("options[%d] == %ld\n", i, cfg_getnint(syslog_sec, "options", i)); } printf("BUG\n"); } /* Hardwired the settings */ *syslog_flags = LOG_PID|LOG_NDELAY; if (app_p->verbose > 1) { *syslog_flags |= LOG_PERROR; } } /* Listeners */ n_listener = cfg_size(cfg, "listener"); if (app_p->verbose) { printf("%d configured listeners:\n", n_listener); } for (i = 0; i < n_listener; i++) { cfg_t *ls = cfg_getnsec(cfg, "listener", i); if (ls == NULL) { goto cleanup; } p_listener = malloc(sizeof(struct tq_listener_s)); if (p_listener == NULL) { fprintf(stderr, "Error: memory allocation problem, couldn't allocate %lu bytes\n", sizeof(struct tq_listener_s)); goto cleanup; } memset(p_listener, 0, sizeof(struct tq_listener_s)); TAILQ_INIT(&(p_listener->services_head)); /* Settings */ STRDUP_OR_GOTO_CLEANUP(p_listener->bindip, cfg_getstr(ls, "bindaddress")); p_listener->port = (short)cfg_getint(ls, "port"); p_listener->backlog = (short)cfg_getint(ls, "backlog"); STRDUP_OR_GOTO_CLEANUP(p_listener->cert, cfg_getstr(ls, "cert")); STRDUP_OR_GOTO_CLEANUP(p_listener->key, cfg_getstr(ls, "key")); STRDUP_OR_GOTO_CLEANUP(p_listener->cafile, cfg_getstr(ls, "cafile")); STRDUP_OR_GOTO_CLEANUP(p_listener->capath, cfg_getstr(ls, "capath")); STRDUP_OR_GOTO_CLEANUP(p_listener->crlpath, cfg_getstr(ls, "crlpath")); STRDUP_OR_GOTO_CLEANUP(p_listener->cipherlist, cfg_getstr(ls, "cipherlist") ? cfg_getstr(ls, "cipherlist") : "HIGH"); STRDUP_OR_GOTO_CLEANUP(p_listener->cert_password, cfg_getstr(ls, "password")); STRDUP_OR_GOTO_CLEANUP(p_listener->whitelist_path, cfg_getstr(ls, "whitelist")); STRDUP_OR_GOTO_CLEANUP(p_listener->blacklist_path, cfg_getstr(ls, "blacklist")); p_listener->clientauth = (short)cfg_getint(ls, "clientauth"); p_listener->rfc3820 = (short)cfg_getint(ls, "rfc3820"); /* Normalizer */ if (p_listener->clientauth == MAYBE) p_listener->clientauth = OPTIONAL; if (p_listener->rfc3820 == MAYBE || p_listener->rfc3820 == OPTIONAL) p_listener->rfc3820 = YES; /* Create evhtp_ssl_cfg_t */ if (create_evhtp_ssl_cfg_from_tq_listener(p_listener) == GA_BAD) { goto cleanup; } /* Services per listener */ n_services = cfg_size(ls, "service"); if (app_p->verbose) { printf(" %d\n", n_services); } for (j = 0; j < n_services; j++) { cfg_t *serv = cfg_getnsec(ls, "service", j); if (serv == NULL) { goto cleanup; } p_service = malloc(sizeof(struct tq_service_s)); if (p_service == NULL) { fprintf(stderr, "Error: memory allocation problem, couldn't allocate %lu bytes\n", sizeof(struct tq_service_s)); goto cleanup; } memset(p_service, 0, sizeof(struct tq_service_s)); p_service->parent_listener = p_listener; /* Thread count override in Debug mode - max is 1 worker thread */ if (app_p->debug == YES) { p_service->thread_cnt = 1; } else { p_service->thread_cnt = (short)cfg_getint(serv, "threads"); } p_service->ltype = cfg_getint(serv, "type"); p_service->uri = cfg_getstr(serv, "uri"); if (p_service->uri && p_service->uri[0] == '/') { p_service->uri = strdup(p_service->uri); } else { buf = malloc(strlen(p_service->uri) + 2); if (buf == NULL) { goto cleanup; } snprintf(buf, strlen(p_service->uri) + 2, "/%s", p_service->uri); p_service->uri = buf; } if (app_p->verbose) { printf(" uri = %s\n", p_service->uri); printf(" type = %s\n", p_service->ltype == PDP ? "PDP" : p_service->ltype == PAP ? "PAP" : p_service->ltype == PEP ? "PEP" : "unknown"); } TAILQ_INSERT_TAIL(&(p_listener->services_head), p_service, next); } TAILQ_INSERT_TAIL(&(app_p->listener_head), p_listener, next); } cfg_free(cfg); return GA_GOOD; cleanup: cfg_free(cfg); return GA_BAD; }
int main(int argc, char **argv) { unsigned int i; cfg_t *cfg; unsigned n; int ret; cfg_opt_t proxy_opts[] = { CFG_INT("type", 0, CFGF_NONE), CFG_STR("host", 0, CFGF_NONE), CFG_STR_LIST("exclude", "{localhost, .localnet}", CFGF_NONE), CFG_INT("port", 21, CFGF_NONE), CFG_END() }; cfg_opt_t bookmark_opts[] = { CFG_STR("machine", 0, CFGF_NONE), CFG_INT("port", 21, CFGF_NONE), CFG_STR("login", 0, CFGF_NONE), CFG_STR("password", 0, CFGF_NONE), CFG_STR("directory", 0, CFGF_NONE), CFG_BOOL("passive-mode", cfg_false, CFGF_NONE), CFG_SEC("proxy", proxy_opts, CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { CFG_INT("backlog", 42, CFGF_NONE), CFG_STR("probe-device", "eth2", CFGF_NONE), CFG_SEC("bookmark", bookmark_opts, CFGF_MULTI | CFGF_TITLE), CFG_FLOAT_LIST("delays", "{3.567e2, 0.2, -47.11}", CFGF_NONE), CFG_FUNC("func", &cb_func), CFG_INT_CB("ask-quit", 3, CFGF_NONE, &cb_verify_ask), CFG_INT_LIST_CB("ask-quit-array", "{maybe, yes, no}", CFGF_NONE, &cb_verify_ask), CFG_FUNC("include", &cfg_include), CFG_END() }; #ifndef _WIN32 /* for some reason, MS Visual C++ chokes on this (?) */ printf("Using %s\n\n", confuse_copyright); #endif cfg = cfg_init(opts, CFGF_NOCASE); /* set a validating callback function for bookmark sections */ cfg_set_validate_func(cfg, "bookmark", &cb_validate_bookmark); ret = cfg_parse(cfg, argc > 1 ? argv[1] : "test.conf"); printf("ret == %d\n", ret); if(ret == CFG_FILE_ERROR) { perror("test.conf"); return 1; } else if(ret == CFG_PARSE_ERROR) { fprintf(stderr, "parse error\n"); return 2; } printf("backlog == %ld\n", cfg_getint(cfg, "backlog")); printf("probe device is %s\n", cfg_getstr(cfg, "probe-device")); cfg_setstr(cfg, "probe-device", "lo"); printf("probe device is %s\n", cfg_getstr(cfg, "probe-device")); n = cfg_size(cfg, "bookmark"); printf("%d configured bookmarks:\n", n); for(i = 0; i < n; i++) { cfg_t *pxy; cfg_t *bm = cfg_getnsec(cfg, "bookmark", i); printf(" bookmark #%u (%s):\n", i+1, cfg_title(bm)); printf(" machine = %s\n", cfg_getstr(bm, "machine")); printf(" port = %d\n", (int)cfg_getint(bm, "port")); printf(" login = %s\n", cfg_getstr(bm, "login")); printf(" passive-mode = %s\n", cfg_getbool(bm, "passive-mode") ? "true" : "false"); printf(" directory = %s\n", cfg_getstr(bm, "directory")); printf(" password = %s\n", cfg_getstr(bm, "password")); pxy = cfg_getsec(bm, "proxy"); if(pxy) { int j, m; if(cfg_getstr(pxy, "host") == 0) { printf(" no proxy host is set, setting it to 'localhost'...\n"); /* For sections without CFGF_MULTI flag set, there is * also an extended syntax to get an option in a * subsection: */ cfg_setstr(bm, "proxy|host", "localhost"); } printf(" proxy host is %s\n", cfg_getstr(pxy, "host")); printf(" proxy type is %ld\n", cfg_getint(pxy, "type")); printf(" proxy port is %ld\n", cfg_getint(pxy, "port")); m = cfg_size(pxy, "exclude"); printf(" got %d hosts to exclude from proxying:\n", m); for(j = 0; j < m; j++) { printf(" exclude %s\n", cfg_getnstr(pxy, "exclude", j)); } } else printf(" no proxy settings configured\n"); } printf("delays are (%d):\n", cfg_size(cfg, "delays")); for(i = 0; i < cfg_size(cfg, "delays"); i++) printf(" %G\n", cfg_getnfloat(cfg, "delays", i)); printf("ask-quit == %ld\n", cfg_getint(cfg, "ask-quit")); /* Using cfg_setint(), the integer value for the option ask-quit * is not verified by the value parsing callback. * * cfg_setint(cfg, "ask-quit", 4); printf("ask-quit == %ld\n", cfg_getint(cfg, "ask-quit")); */ /* The following commented line will generate a failed assertion * and abort, since the option "foo" is not declared * * printf("foo == %ld\n", cfg_getint(cfg, "foo")); */ cfg_addlist(cfg, "ask-quit-array", 2, 1, 2); for(i = 0; i < cfg_size(cfg, "ask-quit-array"); i++) printf("ask-quit-array[%d] == %ld\n", i, cfg_getnint(cfg, "ask-quit-array", i)); /* print the parsed values to another file */ { FILE *fp = fopen("test.conf.out", "w"); cfg_set_print_func(cfg, "func", print_func); cfg_set_print_func(cfg, "ask-quit", print_ask); cfg_set_print_func(cfg, "ask-quit-array", print_ask); cfg_print(cfg, fp); fclose(fp); } cfg_free(cfg); return 0; }