예제 #1
0
static void
config_free(struct config *conf)
{
	void	*value;

	config_reset(conf);

	while (dict_poproot(&conf->conf, &value))
		free(value);

	while (dict_poproot(&conf->sources, NULL))
		;

	free(conf);
}
예제 #2
0
static int
table_static_update(struct table *table)
{
	struct table	*t;
	void		*p = NULL;

	/* no config ? ok */
	if (table->t_config[0] == '\0')
		goto ok;

	t = table_create("static", table->t_name, "update", table->t_config);
	if (!table_config(t))
		goto err;

	/* replace former table, frees t */
	while (dict_poproot(&table->t_dict, NULL, (void **)&p))
		free(p);
	dict_merge(&table->t_dict, &t->t_dict);
	table_destroy(t);

ok:
	log_info("info: Table \"%s\" successfully updated", table->t_name);
	return 1;

err:
	table_destroy(t);
	log_info("info: Failed to update table \"%s\"", table->t_name);
	return 0;
}
예제 #3
0
파일: mproc.c 프로젝트: OpenSMTPD/OpenSMTPD
void
m_clear_params(struct dict *d)
{
	char *value;

	while (dict_poproot(d, (void **)&value))
		free(value);
}
예제 #4
0
static int
table_sqlite_fetch(int service, char *dst, size_t sz)
{
	const char	*k;
	int		 s;

	if (service != K_SOURCE)
		return (-1);

	if (stmt_fetch_source == NULL)
		return (-1);

	if (source_ncall < source_refresh &&
	    time(NULL) - source_update < source_expire)
	    goto fetch;

	source_iter = NULL;
	while (dict_poproot(&sources, NULL))
		;

	while ((s = sqlite3_step(stmt_fetch_source)) == SQLITE_ROW)
		dict_set(&sources, sqlite3_column_text(stmt_fetch_source, 0), NULL);

	if (s != SQLITE_DONE)
		log_warnx("warn: table-sqlite: sqlite3_step: %s",
		    sqlite3_errmsg(db));

	sqlite3_reset(stmt_fetch_source);

	source_update = time(NULL);
	source_ncall = 0;

    fetch:

	source_ncall += 1;

        if (! dict_iter(&sources, &source_iter, &k, (void **)NULL)) {
		source_iter = NULL;
		if (! dict_iter(&sources, &source_iter, &k, (void **)NULL))
			return (0);
	}

	if (strlcpy(dst, k, sz) >= sz)
		return (-1);

	return (1);
}
예제 #5
0
static int
table_passwd_update(void)
{
	FILE	       *fp;
	char	       *buf, *lbuf = NULL;
	size_t		len;
	char	       *line;
	struct passwd	pw;
	struct dict    *npasswd;

	/* Parse configuration */
	fp = fopen(config, "r");
	if (fp == NULL)
		return (0);

	npasswd = calloc(1, sizeof *passwd);
	if (npasswd == NULL)
		goto err;

	dict_init(npasswd);

	while ((buf = fgetln(fp, &len))) {
		if (buf[len - 1] == '\n')
			buf[len - 1] = '\0';
		else {
			/* EOF without EOL, copy and add the NUL */
			if ((lbuf = malloc(len + 1)) == NULL)
				err(1, NULL);
			memcpy(lbuf, buf, len);
			lbuf[len] = '\0';
			buf = lbuf;
		}
		if (! parse_passwd_entry(&pw, buf)) {
			log_warnx("warn: table-passwd: invalid entry");
			goto err;
		}
		if ((line = strdup(buf)) == NULL)
			err(1, NULL);
		dict_set(npasswd, pw.pw_name, line);
	}
	free(lbuf);
	fclose(fp);

	/* swap passwd table and release old one*/
	if (passwd)
		while (dict_poproot(passwd, (void**)&buf))
			free(buf);
	passwd = npasswd;

	return (1);

err:
	if (fp)
		fclose(fp);
	free(lbuf);

	/* release passwd table */
	if (npasswd) {
		while (dict_poproot(npasswd, (void**)&buf))
			free(buf);
		free(npasswd);
	}
	return (0);
}
예제 #6
0
static int
table_postgres_fetch(int service, char *dst, size_t sz)
{
	char		*stmt;
	PGresult	*res;
	const char	*k, *errfld;
	int		 i;

	if (config->db == NULL && config_connect(config) == 0)
		return (-1);

    retry:

	if (service != K_SOURCE)
		return (-1);

	stmt = config->stmt_fetch_source;

	if (stmt == NULL)
		return (-1);

	if (config->source_ncall < config->source_refresh &&
	    time(NULL) - config->source_update < config->source_expire)
	    goto fetch;

	res = PQexecPrepared(config->db, stmt, 0, NULL, NULL, NULL, 0);

	if (PQresultStatus(res) != PGRES_TUPLES_OK) {
		errfld = PQresultErrorField(res, PG_DIAG_SQLSTATE);
		if (errfld[0] == '0' && errfld[1] == '8') {
			log_warnx("warn: table-postgres: trying to reconnect after error: %s",
			    PQerrorMessage(config->db));
			PQclear(res);
			if (config_connect(config))
				goto retry;
			return (-1);
		}
		log_warnx("warn: table-postgres: PQexecPrepared: %s",
		    PQerrorMessage(config->db));
		PQclear(res);
		return (-1);
	}

	config->source_iter = NULL;
	while (dict_poproot(&config->sources, NULL))
		;

	for (i = 0; i < PQntuples(res); i++)
		dict_set(&config->sources, PQgetvalue(res, i, 0), NULL);

	PQclear(res);

	config->source_update = time(NULL);
	config->source_ncall = 0;

    fetch:

	config->source_ncall += 1;

	if (! dict_iter(&config->sources, &config->source_iter, &k, (void **)NULL)) {
		config->source_iter = NULL;
		if (! dict_iter(&config->sources, &config->source_iter, &k, (void **)NULL))
			return (0);
	}

	if (strlcpy(dst, k, sz) >= sz)
		return (-1);

	return (1);
}
예제 #7
0
static int
table_mysql_fetch(int service, char *dst, size_t sz)
{
	MYSQL_STMT	*stmt;
	const char	*k;
	int		 s;

    retry:

	if (service != K_SOURCE)
		return (-1);

	stmt = config->stmt_fetch_source;

	if (stmt == NULL)
		return (-1);

	if (config->source_ncall < config->source_refresh &&
	    time(NULL) - config->source_update < config->source_expire)
	    goto fetch;

	if (mysql_stmt_execute(stmt)) {
		if (mysql_stmt_errno(stmt) == CR_SERVER_LOST ||
		    mysql_stmt_errno(stmt) == CR_SERVER_GONE_ERROR ||
		    mysql_stmt_errno(stmt) == CR_COMMANDS_OUT_OF_SYNC) {
			log_warnx("warn: table-mysql: trying to reconnect after error: %s",
			    mysql_stmt_error(stmt));
			if (config_connect(config))
				goto retry;
			return (-1);
		}
		log_warnx("warn: table-mysql: mysql_stmt_execute: %s",
		    mysql_stmt_error(stmt));
		return (-1);
	}

	config->source_iter = NULL;
	while(dict_poproot(&config->sources, NULL, NULL))
		;

	while ((s = mysql_stmt_fetch(stmt)) == 0)
		dict_set(&config->sources, results_buffer[0], NULL);

	if (s && s != MYSQL_NO_DATA)
		log_warnx("warn: table-mysql: mysql_stmt_fetch: %s",
		    mysql_stmt_error(stmt));

	if (mysql_stmt_free_result(stmt))
		log_warnx("warn: table-mysql: mysql_stmt_free_result: %s",
		    mysql_stmt_error(stmt));

	config->source_update = time(NULL);
	config->source_ncall = 0;

    fetch:

	config->source_ncall += 1;

	if (! dict_iter(&config->sources, &config->source_iter, &k, (void **)NULL)) {
		config->source_iter = NULL;
		if (! dict_iter(&config->sources, &config->source_iter, &k, (void **)NULL))
			return (0);
	}

	if (strlcpy(dst, k, sz) >= sz)
		return (-1);

	return (1);
}
예제 #8
0
파일: config.c 프로젝트: gunhu/OpenSMTPD
void
purge_config(uint8_t what)
{
    struct listener	*l;
    struct table	*t;
    struct rule	*r;
    struct pki	*p;
    const char	*k;
    void		*iter_dict;

    if (what & PURGE_LISTENERS) {
        while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) {
            TAILQ_REMOVE(env->sc_listeners, l, entry);
            free(l);
        }
        free(env->sc_listeners);
        env->sc_listeners = NULL;
    }
    if (what & PURGE_TABLES) {
        while (dict_root(env->sc_tables_dict, NULL, (void **)&t))
            table_destroy(t);
        free(env->sc_tables_dict);
        env->sc_tables_dict = NULL;
    }
    if (what & PURGE_RULES) {
        while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) {
            TAILQ_REMOVE(env->sc_rules, r, r_entry);
            free(r);
        }
        free(env->sc_rules);
        env->sc_rules = NULL;
    }
    if (what & PURGE_PKI) {
        while (dict_poproot(env->sc_pki_dict, (void **)&p)) {
            explicit_bzero(p->pki_cert, p->pki_cert_len);
            free(p->pki_cert);
            if (p->pki_key) {
                explicit_bzero(p->pki_key, p->pki_key_len);
                free(p->pki_key);
            }
            if (p->pki_pkey)
                EVP_PKEY_free(p->pki_pkey);
            free(p);
        }
        free(env->sc_pki_dict);
        env->sc_pki_dict = NULL;
    } else if (what & PURGE_PKI_KEYS) {
        iter_dict = NULL;
        while (dict_iter(env->sc_pki_dict, &iter_dict, &k,
                         (void **)&p)) {
            explicit_bzero(p->pki_cert, p->pki_cert_len);
            free(p->pki_cert);
            p->pki_cert = NULL;
            if (p->pki_key) {
                explicit_bzero(p->pki_key, p->pki_key_len);
                free(p->pki_key);
                p->pki_key = NULL;
            }
            if (p->pki_pkey)
                EVP_PKEY_free(p->pki_pkey);
            p->pki_pkey = NULL;
        }
    }
}
예제 #9
0
파일: table_api.c 프로젝트: Sp1l/OpenSMTPD
static void
table_clear_params(struct dict *params)
{
	while (dict_poproot(params, NULL))
		;
}
예제 #10
0
static int
table_passwd_update(void)
{
	FILE	       *fp;
	char	       *buf, *lbuf = NULL;
	char		tmp[LINE_MAX];
	size_t		len;
	char	       *line;
	struct passwd	pw;
	struct dict    *npasswd;
	char	       *skip;

	/* Parse configuration */
	fp = fopen(config, "r");
	if (fp == NULL)
		return (0);

	npasswd = calloc(1, sizeof *passwd);
	if (npasswd == NULL)
		goto err;

	dict_init(npasswd);

	while ((buf = fgetln(fp, &len))) {
		if (buf[len - 1] == '\n')
			buf[len - 1] = '\0';
		else {
			/* EOF without EOL, copy and add the NUL */
			if ((lbuf = malloc(len + 1)) == NULL)
				err(1, NULL);
			memcpy(lbuf, buf, len);
			lbuf[len] = '\0';
			buf = lbuf;
		}

		/* skip commented entries */
		for (skip = buf; *skip; ++skip)
			if (*skip == '#') {
				*skip = '\0';
				break;
			}

		/* skip empty lines */
		if (strlen(buf) == 0)
			continue;

		if (strlcpy(tmp, buf, sizeof tmp) >= sizeof tmp) {
			log_warnx("warn: table-passwd: line too long");
			goto err;
		}
		if (! parse_passwd_entry(&pw, tmp)) {
			log_warnx("warn: table-passwd: invalid entry");
			goto err;
		}
		if ((line = strdup(buf)) == NULL)
			err(1, NULL);
		dict_set(npasswd, pw.pw_name, line);
	}
	free(lbuf);
	fclose(fp);

	/* swap passwd table and release old one*/
	if (passwd)
		while (dict_poproot(passwd, (void**)&buf))
			free(buf);
	passwd = npasswd;

	return (1);

err:
	if (fp)
		fclose(fp);
	free(lbuf);

	/* release passwd table */
	if (npasswd) {
		while (dict_poproot(npasswd, (void**)&buf))
			free(buf);
		free(npasswd);
	}
	return (0);
}