static int ip_acl_onload(noit_image_t *self) { int i, cnt; noit_conf_section_t *acl_c; ip_acl_module_id = noit_check_register_module("ip_acl"); if(ip_acl_module_id < 0) return -1; acl_c = noit_conf_get_sections(NULL, "/noit/acls//acl", &cnt); if(acl_c) { for(i=0; i<cnt; i++) { char *name; int j, rcnt, arcnt = 0; noit_conf_section_t *rule_c; if(noit_conf_get_string(acl_c[i], "@name", &name)) { rule_c = noit_conf_get_sections(acl_c[i], "rule", &rcnt); if(rule_c) { btrie *acl = calloc(1, sizeof(*acl)); for(j=0; j<rcnt; j++) { int mask = -1, rv; char dirstr[16] = "unspecified"; char *cp, target[256] = ""; union { struct in_addr addr4; struct in6_addr addr6; } a; noit_conf_get_stringbuf(rule_c[j], "self::node()", target, sizeof(target)); if(NULL != (cp = strchr(target, '/'))) { *cp++ = '\0'; mask = atoi(cp); } if(!noit_conf_get_stringbuf(rule_c[j], "@type", dirstr, sizeof(dirstr)) || (strcmp(dirstr, "deny") && strcmp(dirstr, "allow"))) { noitL(noit_error, "Unknown acl rule type \"%s\" in acl \"%s\"\n", dirstr, name); } else if(inet_pton(AF_INET, target, &a) == 1) { if(mask == -1) mask = 32; noit_add_route_ipv4(acl, &a.addr4, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR); arcnt++; } else if(inet_pton(AF_INET6, target, &a) == 1) { if(mask == -1) mask = 128; noit_add_route_ipv6(acl, &a.addr6, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR); arcnt++; } } noitL(noit_error, "ACL %s/%p -> %d/%d rules\n", name, acl, arcnt, rcnt); noit_hash_replace(&acls, name, strlen(name), acl, free, free_btrie); free(rule_c); } } } free(acl_c); } return 0; }
static int noit_console_filter_show(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { noit_conf_t_userdata_t *info; char xpath[1024]; xmlNodePtr fsnode; noit_conf_section_t *rules; int i, rulecnt; info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); snprintf(xpath, sizeof(xpath), "/%s", info->path); fsnode = noit_conf_get_section(NULL, xpath); if(!fsnode) { nc_printf(ncct, "internal error\n"); return -1; } rules = noit_conf_get_sections(fsnode, "rule", &rulecnt); for(i=0; i<rulecnt; i++) { char val[256]; val[0] = '\0'; noit_conf_get_stringbuf(rules[i], "@type", val, sizeof(val)); nc_printf(ncct, "Rule %d [%s]:\n", i+1, val); #define DUMP_ATTR(a) do { \ char *vstr; \ noit_conf_section_t ht; \ int cnt; \ ht = noit_conf_get_sections(rules[i], #a, &cnt); \ if(ht && cnt) { \ nc_printf(ncct, "\t%s: hash match of %d items\n", #a, cnt); \ } \ else if(noit_conf_get_string(rules[i], "@" #a, &vstr)) { \ nc_printf(ncct, "\t%s: /%s/\n", #a, val); \ free(vstr); \ } \ free(ht); \ } while(0) DUMP_ATTR(target); DUMP_ATTR(module); DUMP_ATTR(name); DUMP_ATTR(metric); } if(rules) free(rules); return 0; }
void noit_filter_compile_add(noit_conf_section_t setinfo) { noit_conf_section_t *rules; int j, fcnt; char filterset_name[256]; filterset_t *set; if(!noit_conf_get_stringbuf(setinfo, "@name", filterset_name, sizeof(filterset_name))) { noitL(noit_error, "filterset with no name, skipping as it cannot be referenced.\n"); return; } set = calloc(1, sizeof(*set)); set->ref_cnt = 1; set->name = strdup(filterset_name); rules = noit_conf_get_sections(setinfo, "rule", &fcnt); /* Here we will work through the list backwards pushing the rules on * the front of the list. That way we can simply walk them in order * for the application process. */ noitL(noit_debug, "Compiling filterset '%s'\n", set->name); for(j=fcnt-1; j>=0; j--) { filterrule_t *rule; char buffer[256]; if(!noit_conf_get_stringbuf(rules[j], "@type", buffer, sizeof(buffer)) || (strcmp(buffer, "accept") && strcmp(buffer, "allow") && strcmp(buffer, "deny"))) { noitL(noit_error, "rule must have type 'accept' or 'allow' or 'deny'\n"); continue; } noitL(noit_debug, "Prepending %s into %s\n", buffer, set->name); rule = calloc(1, sizeof(*rule)); rule->type = (!strcmp(buffer, "accept") || !strcmp(buffer, "allow")) ? NOIT_FILTER_ACCEPT : NOIT_FILTER_DENY; /* Compile our rules */ #define RULE_COMPILE(rname) do { \ char *longre = NULL; \ if(noit_conf_get_string(rules[j], "@" #rname, &longre)) { \ const char *error; \ int erroffset; \ rule->rname = pcre_compile(longre, 0, &error, &erroffset, NULL); \ if(!rule->rname) { \ noitL(noit_error, "set '%s' rule '%s: %s' compile failed: %s\n", \ set->name, #rname, longre, error ? error : "???"); \ } \ else { \ rule->rname##_e = pcre_study(rule->rname, 0, &error); \ } \ free(longre); \ } \ } while(0) RULE_COMPILE(target); RULE_COMPILE(module); RULE_COMPILE(name); RULE_COMPILE(metric); rule->next = set->rules; set->rules = rule; } free(rules); LOCKFS(); noit_hash_replace(filtersets, set->name, strlen(set->name), (void *)set, NULL, filterset_free); UNLOCKFS(); }
int main(int argc, char **argv) { int fd, lockfd = -1; char lockfile[PATH_MAX]; char user[32], group[32]; char *trace_dir = NULL; parse_clargs(argc, argv); noit_log_init(); noit_log_stream_add_stream(noit_debug, noit_stderr); noit_log_stream_add_stream(noit_error, noit_stderr); /* Next load the configs */ noit_conf_init(APPNAME); if(noit_conf_load(config_file) == -1) { fprintf(stderr, "Cannot load config: '%s'\n", config_file); exit(-1); } /* Reinitialize the logging system now that we have a config */ snprintf(user, sizeof(user), "%d", getuid()); snprintf(group, sizeof(group), "%d", getgid()); if(noit_security_usergroup(droptouser, droptogroup, noit_true)) { noitL(noit_stderr, "Failed to drop privileges, exiting.\n"); exit(-1); } noit_conf_log_init(APPNAME); cli_log_switches(); if(noit_security_usergroup(user, group, noit_true)) { noitL(noit_stderr, "Failed to regain privileges, exiting.\n"); exit(-1); } if(debug) noit_debug->enabled = 1; if(!glider) noit_conf_get_string(NULL, "/" APPNAME "/watchdog/@glider", &glider); noit_watchdog_glider(glider); noit_conf_get_string(NULL, "/" APPNAME "/watchdog/@tracedir", &trace_dir); if(trace_dir) noit_watchdog_glider_trace_dir(trace_dir); if(chdir("/") != 0) { fprintf(stderr, "cannot chdir(\"/\"): %s\n", strerror(errno)); exit(2); } noit_watchdog_prefork_init(); /* Acquire the lock so that we can throw an error if it doesn't work. * If we've started -D, we'll have the lock. * If not we will daemon and must reacquire the lock. */ lockfd = -1; lockfile[0] = '\0'; if(noit_conf_get_stringbuf(NULL, "/" APPNAME "/@lockfile", lockfile, sizeof(lockfile))) { if((lockfd = noit_lockfile_acquire(lockfile)) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } if(foreground) exit(child_main()); /* This isn't inherited across forks... */ if(lockfd >= 0) noit_lockfile_release(lockfd); fd = open("/dev/null", O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if(fork()) exit(0); setsid(); if(fork()) exit(0); /* Reacquire the lock */ if(*lockfile) { if(noit_lockfile_acquire(lockfile) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } return noit_watchdog_start_child("stratcond", child_main, 0); }
static int child_main() { char conf_str[1024]; /* Next (re)load the configs */ if(noit_conf_load(config_file) == -1) { fprintf(stderr, "Cannot load config: '%s'\n", config_file); exit(2); } noit_log_reopen_all(); /* Lastly, run through all other system inits */ if(!noit_conf_get_stringbuf(NULL, "/" APPNAME "/eventer/@implementation", conf_str, sizeof(conf_str))) { noitL(noit_stderr, "Cannot find '%s' in configuration\n", "/" APPNAME "/eventer/@implementation"); exit(2); } if(eventer_choose(conf_str) == -1) { noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str); exit(2); } if(configure_eventer() != 0) { noitL(noit_stderr, "Cannot configure eventer\n"); exit(2); } if(eventer_init() == -1) { noitL(noit_stderr, "Cannot init eventer %s\n", conf_str); exit(2); } /* rotation init requires, eventer_init() */ noit_conf_log_init_rotate(APPNAME, noit_false); noit_watchdog_child_eventer_heartbeat(); noit_console_init(APPNAME); noit_console_conf_init(); noit_http_rest_init(); stratcon_realtime_http_init(APPNAME); noit_capabilities_listener_init(); noit_listener_init(APPNAME); noit_module_init(); if(strict_module_load && noit_module_load_failures() > 0) { noitL(noit_stderr, "Failed to load some modules and -M given.\n"); exit(2); } if(stratcon_datastore_get_enabled()) stratcon_datastore_init(); /* Drop privileges */ if(chrootpath && noit_security_chroot(chrootpath)) { noitL(noit_stderr, "Failed to chroot(), exiting.\n"); exit(-1); } if(noit_security_usergroup(droptouser, droptogroup, noit_false)) { noitL(noit_stderr, "Failed to drop privileges, exiting.\n"); exit(-1); } stratcon_jlog_streamer_init(APPNAME); if(stratcon_iep_get_enabled()) stratcon_iep_init(); if(stratcon_datastore_get_enabled()) { /* Write our log out, and setup a watchdog to write it out on change. */ stratcon_datastore_saveconfig(NULL); noit_conf_coalesce_changes(10); /* 10 seconds of no changes before we write */ } else noit_conf_coalesce_changes(INT_MAX); noit_conf_watch_and_journal_watchdog(stratcon_datastore_saveconfig, NULL); eventer_loop(); return 0; }
void noit_http_rest_load_rules() { int ai, cnt = 0; noit_conf_section_t *acls; char path[256]; struct noit_rest_acl *newhead = NULL, *oldacls, *remove_acl; struct noit_rest_acl_rule *remove_rule; snprintf(path, sizeof(path), "//rest//acl"); acls = noit_conf_get_sections(NULL, path, &cnt); noitL(noit_debug, "Found %d acl stanzas\n", cnt); for(ai = cnt-1; ai>=0; ai--) { char tbuff[32]; struct noit_rest_acl *newacl; int ri, rcnt = 0; noit_boolean default_allow = noit_false; noit_conf_section_t *rules; newacl = calloc(1, sizeof(*newacl)); newacl->next = newhead; newhead = newacl; if(noit_conf_get_stringbuf(acls[ai], "@type", tbuff, sizeof(tbuff)) && !strcmp(tbuff, "allow")) newacl->allow = noit_true; #define compile_re(node, cont, name) do { \ char buff[256]; \ if(noit_conf_get_stringbuf(node, "@" #name, buff, sizeof(buff))) { \ const char *error; \ int erroffset; \ cont->name = pcre_compile(buff, 0, &error, &erroffset, NULL); \ } \ } while(0) newacl->allow = default_allow; compile_re(acls[ai], newacl, cn); compile_re(acls[ai], newacl, url); rules = noit_conf_get_sections(acls[ai], "rule", &rcnt); for(ri = rcnt - 1; ri >= 0; ri--) { struct noit_rest_acl_rule *newacl_rule; newacl_rule = calloc(1, sizeof(*newacl_rule)); newacl_rule->next = newacl->rules; newacl->rules = newacl_rule; if(noit_conf_get_stringbuf(rules[ri], "@type", tbuff, sizeof(tbuff)) && !strcmp(tbuff, "allow")) newacl_rule->allow = noit_true; compile_re(rules[ri], newacl_rule, cn); compile_re(rules[ri], newacl_rule, url); } free(rules); } free(acls); oldacls = global_rest_acls; global_rest_acls = newhead; while(oldacls) { remove_acl = oldacls->next; while(oldacls->rules) { remove_rule = oldacls->rules->next; if(oldacls->rules->cn) pcre_free(oldacls->rules->cn); if(oldacls->rules->url) pcre_free(oldacls->rules->url); free(oldacls->rules); oldacls->rules = remove_rule; } if(oldacls->cn) pcre_free(oldacls->cn); if(oldacls->url) pcre_free(oldacls->url); free(oldacls); oldacls = remove_acl; } }
void noit_listener_reconfig(const char *toplevel) { int i, cnt = 0; noit_conf_section_t *listener_configs; char path[256]; snprintf(path, sizeof(path), "/%s/listeners//listener", toplevel ? toplevel : "*"); listener_configs = noit_conf_get_sections(NULL, path, &cnt); noitL(noit_debug, "Found %d %s stanzas\n", cnt, path); for(i=0; i<cnt; i++) { char address[256]; char type[256]; unsigned short port; int portint; int backlog; eventer_func_t f; noit_boolean ssl; noit_hash_table *sslconfig, *config; if(!noit_conf_get_stringbuf(listener_configs[i], "ancestor-or-self::node()/@type", type, sizeof(type))) { noitL(noit_error, "No type specified in listener stanza %d\n", i+1); continue; } f = eventer_callback_for_name(type); if(!f) { noitL(noit_error, "Cannot find handler for listener type: '%s'\n", type); continue; } if(!noit_conf_get_stringbuf(listener_configs[i], "ancestor-or-self::node()/@address", address, sizeof(address))) { address[0] = '*'; address[1] = '\0'; } if(!noit_conf_get_int(listener_configs[i], "ancestor-or-self::node()/@port", &portint)) portint = 0; port = (unsigned short) portint; if(address[0] != '/' && (portint == 0 || (port != portint))) { /* UNIX sockets don't require a port (they'll ignore it if specified */ noitL(noit_error, "Invalid port [%d] specified in stanza %d\n", port, i+1); continue; } if(noit_listener_should_skip(address, port)) { if(port) noitL(noit_error, "Operator forced skipping listener %s:%d\n", address, port); else noitL(noit_error, "Operator forced skipping listener %s\n", address); continue; } if(!noit_conf_get_int(listener_configs[i], "ancestor-or-self::node()/@backlog", &backlog)) backlog = 5; if(!noit_conf_get_boolean(listener_configs[i], "ancestor-or-self::node()/@ssl", &ssl)) ssl = noit_false; sslconfig = ssl ? noit_conf_get_hash(listener_configs[i], "sslconfig") : NULL; config = noit_conf_get_hash(listener_configs[i], "config"); if(noit_listener(address, port, SOCK_STREAM, backlog, sslconfig, config, f, NULL) != 0) { noit_hash_destroy(config,free,free); free(config); } if(sslconfig) { /* A copy of this is made within noit_listener */ noit_hash_destroy(sslconfig,free,free); free(sslconfig); } } free(listener_configs); }
int noit_main(const char *appname, const char *config_filename, int debug, int foreground, const char *_glider, const char *drop_to_user, const char *drop_to_group, int (*passed_child_main)(void)) { int fd, lockfd, watchdog_timeout = 0; char conf_str[1024]; char lockfile[PATH_MAX]; char user[32], group[32]; char *trace_dir = NULL; char appscratch[1024]; char *glider = (char *)_glider; char *watchdog_timeout_str; /* First initialize logging, so we can log errors */ noit_log_init(); noit_log_stream_add_stream(noit_debug, noit_stderr); noit_log_stream_add_stream(noit_error, noit_stderr); /* Next load the configs */ noit_conf_init(appname); if(noit_conf_load(config_filename) == -1) { fprintf(stderr, "Cannot load config: '%s'\n", config_filename); exit(-1); } /* Reinitialize the logging system now that we have a config */ snprintf(user, sizeof(user), "%d", getuid()); snprintf(group, sizeof(group), "%d", getgid()); if(noit_security_usergroup(drop_to_user, drop_to_group, noit_true)) { noitL(noit_stderr, "Failed to drop privileges, exiting.\n"); exit(-1); } noit_conf_log_init(appname); cli_log_switches(); if(noit_security_usergroup(user, group, noit_true)) { noitL(noit_stderr, "Failed to regain privileges, exiting.\n"); exit(-1); } if(debug) noit_debug->enabled = 1; snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@glider", appname); if(!glider) noit_conf_get_string(NULL, appscratch, &glider); noit_watchdog_glider(glider); snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@tracedir", appname); noit_conf_get_string(NULL, appscratch, &trace_dir); if(trace_dir) noit_watchdog_glider_trace_dir(trace_dir); /* Lastly, run through all other system inits */ snprintf(appscratch, sizeof(appscratch), "/%s/eventer/@implementation", appname); if(!noit_conf_get_stringbuf(NULL, appscratch, conf_str, sizeof(conf_str))) { noitL(noit_stderr, "Cannot find '%s' in configuration\n", appscratch); exit(-1); } if(eventer_choose(conf_str) == -1) { noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str); exit(-1); } if(configure_eventer(appname) != 0) { noitL(noit_stderr, "Cannot configure eventer\n"); exit(-1); } noit_watchdog_prefork_init(); if(chdir("/") != 0) { noitL(noit_stderr, "Failed chdir(\"/\"): %s\n", strerror(errno)); exit(-1); } /* Acquire the lock so that we can throw an error if it doesn't work. * If we've started -D, we'll have the lock. * If not we will daemon and must reacquire the lock. */ lockfd = -1; lockfile[0] = '\0'; snprintf(appscratch, sizeof(appscratch), "/%s/@lockfile", appname); if(noit_conf_get_stringbuf(NULL, appscratch, lockfile, sizeof(lockfile))) { if((lockfd = noit_lockfile_acquire(lockfile)) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } if(foreground) return passed_child_main(); watchdog_timeout_str = getenv("WATCHDOG_TIMEOUT"); if(watchdog_timeout_str) { watchdog_timeout = atoi(watchdog_timeout_str); noitL(noit_error, "Setting watchdog timeout to %d\n", watchdog_timeout); } /* This isn't inherited across forks... */ if(lockfd >= 0) noit_lockfile_release(lockfd); fd = open("/dev/null", O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if(fork()) exit(0); setsid(); if(fork()) exit(0); /* Reacquire the lock */ if(*lockfile) { if(noit_lockfile_acquire(lockfile) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } signal(SIGHUP, SIG_IGN); return noit_watchdog_start_child("noitd", passed_child_main, watchdog_timeout); }