static void reload_handler(struct mbuf *mb) { bool dbg = force_debug; struct conf *lconf; struct pl opt; int err; (void)mb; err = conf_alloc(&lconf, configfile); if (err) { restund_error("error loading configuration: %s: %m\n", configfile, err); return; } conf = mem_deref(conf); conf = lconf; if (!conf_get(conf, "debug", &opt) && !pl_strcasecmp(&opt, "yes")) dbg = true; restund_log_enable_debug(dbg); restund_info("configuration reloaded from %s (debug%s)\n", configfile, dbg ? " enabled" : " disabled"); }
static int reload_from_client_confs(struct cstat **clist, struct conf *conf) { struct cstat *c; static struct conf *cconf=NULL; if(!cconf && !(cconf=conf_alloc())) goto error; for(c=*clist; c; c=c->next) { // Look at the client conf files to see if they have changed, // and reload bits and pieces if they have. struct stat statp; if(!c->conffile) continue; if(stat(c->conffile, &statp) || !S_ISREG(statp.st_mode)) { cstat_remove(clist, &c); continue; } if(statp.st_mtime==c->conf_mtime) { // conf file has not changed - no need to do anything. continue; } c->conf_mtime=statp.st_mtime; conf_free_content(cconf); if(!(cconf->cname=strdup_w(c->name, __func__))) goto error; if(conf_set_client_global(conf, cconf) || conf_load(c->conffile, cconf, 0)) { cstat_remove(clist, &c); continue; } if(set_cstat_from_conf(c, cconf)) goto error; } return 0; error: conf_free(cconf); cconf=NULL; return -1; }
/** * Allocate configuration from a buffer * * @param confp Configuration object to be allocated * @param buf Buffer containing configuration * @param sz Size of configuration buffer * * @return 0 if success, otherwise errorcode */ int conf_alloc_buf(struct conf **confp, const uint8_t *buf, size_t sz) { struct conf *conf; int err; err = conf_alloc(&conf, NULL); if (err) return err; err = mbuf_write_mem(conf->mb, buf, sz); if (err) mem_deref(conf); else *confp = conf; return err; }
static int run_status_server(int *rfd, int *cfd, int status_rfd, const char *conffile) { int ret=-1; struct conf *conf=NULL; close_fd(rfd); // Reload global config, in case things have changed. This means that // the server does not need to be restarted for most conf changes. if(!(conf=conf_alloc())) goto end; conf_init(conf); if(conf_load(conffile, conf, 1)) goto end; ret=status_server(cfd, status_rfd, conf); close_fd(cfd); end: logp("exit status server\n"); conf_free(conf); return ret; }
/** * Configure the system with default settings * * @return 0 if success, otherwise errorcode */ int conf_configure(void) { char path[FS_PATH_MAX], file[FS_PATH_MAX]; int err; #if defined (WIN32) dbg_init(DBG_INFO, DBG_NONE); #endif err = conf_path_get(path, sizeof(path)); if (err) { warning("conf: could not get config path: %m\n", err); return err; } if (re_snprintf(file, sizeof(file), "%s/config", path) < 0) return ENOMEM; if (!conf_fileexist(file)) { (void)fs_mkdir(path, 0700); err = config_write_template(file, conf_config()); if (err) goto out; } conf_obj = mem_deref(conf_obj); err = conf_alloc(&conf_obj, file); if (err) goto out; err = config_parse_conf(conf_config(), conf_obj); if (err) goto out; out: return err; }
int main (int argc, char *argv[]) { int ret=1; int option=0; int daemon=1; int forking=1; int strip=0; struct lock *lock=NULL; struct conf *conf=NULL; int forceoverwrite=0; enum action act=ACTION_LIST; const char *backup=NULL; const char *restoreprefix=NULL; const char *regex=NULL; const char *browsefile=NULL; const char *browsedir=NULL; const char *conffile=get_conf_path(); const char *orig_client=NULL; // The orig_client is the original client that the normal client // would like to restore from. #ifndef HAVE_WIN32 const char *sclient=NULL; // Status monitor client to view. int generate_ca_only=0; #endif int vss_restore=1; int json=0; init_log(argv[0]); while((option=getopt(argc, argv, "a:b:c:C:d:ghfFil:nr:s:vxjz:?"))!=-1) { switch(option) { case 'a': if(parse_action(&act, optarg)) goto end; break; case 'b': backup=optarg; break; case 'c': conffile=optarg; break; case 'C': orig_client=optarg; #ifndef HAVE_WIN32 sclient=optarg; #endif break; case 'd': restoreprefix=optarg; // for restores browsedir=optarg; // for lists break; case 'f': forceoverwrite=1; break; case 'F': daemon=0; break; case 'g': #ifndef HAVE_WIN32 generate_ca_only=1; #endif break; case 'i': cmd_print_all(); ret=0; goto end; case 'l': logp("-l <logfile> option obsoleted\n"); break; case 'n': forking=0; break; case 'r': regex=optarg; break; case 's': strip=atoi(optarg); break; case 'v': printf("%s-%s\n", progname(), VERSION); ret=0; goto end; case 'x': vss_restore=0; break; case 'j': json=1; break; case 'z': browsefile=optarg; break; case 'h': case '?': default: usage(); goto end; } } if(optind<argc) { usage(); goto end; } if(!(conf=conf_alloc())) goto end; if(reload(conf, conffile, 1 /* first time */, 0 /* no oldmax_children setting */, 0 /* no oldmax_status_children setting */, json)) goto end; if((act==ACTION_RESTORE || act==ACTION_VERIFY) && !backup) { logp("No backup specified. Using the most recent.\n"); backup="0"; } if(act==ACTION_DELETE && !backup) { logp("No backup specified for deletion.\n"); goto end; } if(conf->mode==MODE_CLIENT) { if(orig_client && *orig_client) { if(!(conf->orig_client=strdup(orig_client))) { log_out_of_memory(__func__); goto end; } } } if(conf->mode==MODE_SERVER && (act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT || act==ACTION_CHAMP_CHOOSER)) { // These server modes need to run without getting the lock. } else { if(!(lock=lock_alloc_and_init(conf->lockfile))) goto end; lock_get(lock); switch(lock->status) { case GET_LOCK_GOT: break; case GET_LOCK_NOT_GOT: logp("Could not get lockfile.\n"); logp("Another process is probably running,\n"); goto end; case GET_LOCK_ERROR: default: logp("Could not get lockfile.\n"); logp("Maybe you do not have permissions to write to %s.\n", conf->lockfile); goto end; } } conf->overwrite=forceoverwrite; conf->strip=strip; conf->forking=forking; conf->daemon=daemon; if(replace_conf_str(backup, &conf->backup) || replace_conf_str(restoreprefix, &conf->restoreprefix) || replace_conf_str(regex, &conf->regex) || replace_conf_str(browsefile, &conf->browsefile) || replace_conf_str(browsedir, &conf->browsedir)) goto end; if(conf->mode==MODE_SERVER) { #ifdef HAVE_WIN32 logp("Sorry, server mode is not implemented for Windows.\n"); #else if(act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT) { // We are running on the server machine, being a client // of the burp server, getting status information. ret=status_client_ncurses(conf, act, sclient); } else if(act==ACTION_CHAMP_CHOOSER) { // We are running on the server machine, wanting to // be a standalone champion chooser process. if(!sclient || !*sclient) { logp("No client name specified for standalone champion chooser process.\n"); logp("Try using the '-C' option.\n"); ret=1; } else ret=champ_chooser_server_standalone(conf, sclient); } else ret=server(conf, conffile, lock, generate_ca_only); #endif } else { logp("before client\n"); ret=client(conf, act, vss_restore, json); logp("after client\n"); } end: lock_release(lock); lock_free(&lock); conf_free(conf); return ret; }
int main(int argc, char *argv[]) { bool daemon = true; int err = 0; struct pl opt; (void)sys_coredump_set(true); #ifdef HAVE_GETOPT for (;;) { const int c = getopt(argc, argv, "dhnf:"); if (0 > c) break; switch (c) { case 'd': force_debug = true; restund_log_enable_debug(true); break; case 'f': configfile = optarg; break; case 'n': daemon = false; break; case '?': err = EINVAL; /*@fallthrough@*/ case 'h': usage(); return err; } } #else (void)argc; (void)argv; #endif restund_cmd_subscribe(&cmd_reload); err = fd_setsize(4096); if (err) { restund_warning("fd_setsize error: %m\n", err); goto out; } err = libre_init(); if (err) { restund_error("re init failed: %m\n", err); goto out; } /* configuration file */ err = conf_alloc(&conf, configfile); if (err) { restund_error("error loading configuration: %s: %m\n", configfile, err); goto out; } /* debug config */ if (!conf_get(conf, "debug", &opt) && !pl_strcasecmp(&opt, "yes")) restund_log_enable_debug(true); /* udp */ err = restund_udp_init(); if (err) goto out; /* tcp */ err = restund_tcp_init(); if (err) goto out; /* daemon config */ if (!conf_get(conf, "daemon", &opt) && !pl_strcasecmp(&opt, "no")) daemon = false; /* module config */ if (conf_get(conf, "module_path", &opt)) pl_set_str(&opt, "."); err = conf_apply(conf, "module", module_handler, &opt); if (err) goto out; /* daemon */ if (daemon) { err = sys_daemon(); if (err) { restund_error("daemon error: %m\n", err); goto out; } restund_log_enable_stderr(false); } /* database */ err = restund_db_init(); if (err) { restund_warning("database error: %m\n", err); goto out; } restund_info("stun server ready\n"); /* main loop */ err = re_main(signal_handler); out: restund_db_close(); mod_close(); restund_udp_close(); restund_tcp_close(); conf = mem_deref(conf); libre_close(); restund_cmd_unsubscribe(&cmd_reload); /* check for memory leaks */ tmr_debug(); mem_debug(); return err; }
static int run_child(int *rfd, int *cfd, SSL_CTX *ctx, const char *conffile, int forking) { int ret=-1; int ca_ret=0; SSL *ssl=NULL; BIO *sbio=NULL; struct conf *conf=NULL; struct conf *cconf=NULL; struct cntr *cntr=NULL; struct async *as=NULL; struct asfd *asfd=NULL; if(!(conf=conf_alloc()) || !(cconf=conf_alloc())) goto end; if(forking) close_fd(rfd); // Reload global config, in case things have changed. This means that // the server does not need to be restarted for most conf changes. conf_init(conf); conf_init(cconf); if(conf_load(conffile, conf, 1)) goto end; // Hack to keep forking turned off if it was specified as off on the // command line. if(!forking) conf->forking=0; if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE)) || !(ssl=SSL_new(ctx))) { logp("There was a problem joining ssl to the socket\n"); goto end; } SSL_set_bio(ssl, sbio, sbio); /* Do not try to check peer certificate straight away. Clients can send a certificate signing request when they have no certificate. */ SSL_set_verify(ssl, SSL_VERIFY_PEER /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, 0); if(SSL_accept(ssl)<=0) { char buf[256]=""; ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); logp("SSL_accept: %s\n", buf); goto end; } if(!(as=async_alloc()) || !(asfd=asfd_alloc()) || as->init(as, 0) || asfd->init(asfd, "main socket", as, *cfd, ssl, conf)) goto end; as->asfd_add(as, asfd); if(authorise_server(asfd, conf, cconf) || !cconf->cname || !*(cconf->cname)) { // Add an annoying delay in case they are tempted to // try repeatedly. log_and_send(asfd, "unable to authorise on server"); sleep(1); goto end; } // Set up counters. Have to wait until here to get cname. if(!(cntr=cntr_alloc()) || cntr_init(cntr, cconf->cname)) goto end; conf->cntr=cntr; cconf->cntr=cntr; /* At this point, the client might want to get a new certificate signed. Clients on 1.3.2 or newer can do this. */ if((ca_ret=ca_server_maybe_sign_client_cert(asfd, conf, cconf))<0) { logp("Error signing client certificate request for %s\n", cconf->cname); goto end; } else if(ca_ret>0) { // Certificate signed and sent back. // Everything is OK, but we will close this instance // so that the client can start again with a new // connection and its new certificates. logp("Signed and returned client certificate request for %s\n", cconf->cname); ret=0; goto end; } /* Now it is time to check the certificate. */ if(ssl_check_cert(ssl, cconf)) { log_and_send(asfd, "check cert failed on server"); goto end; } set_non_blocking(*cfd); ret=child(as, conf, cconf); end: *cfd=-1; async_free(&as); asfd_free(&asfd); // This closes cfd for us. logp("exit child\n"); if(cntr) cntr_free(&cntr); if(conf) conf_free(conf); if(cconf) conf_free(cconf); return ret; }