Exemple #1
0
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");
}
Exemple #2
0
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;
}
Exemple #3
0
/**
 * 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;
}
Exemple #4
0
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;
}
Exemple #5
0
/**
 * 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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}