Exemple #1
0
static void
cf_load_functions(void)
{
	cf_function_t *function;
	var_t *v;
	void *data;

	for(function = cf_functions; function->cf_type; ++function) {

		if(vtable_get(cf_config, function->cf_name)) {
			continue;
		}

		function->cf_callback(&data);
		if (data == NULL) {
			log_die(EX_CONFIG, "cf_load_functions: callback for "
				"\"%s\" failed", function->cf_name);
		}

		v = var_create(function->cf_type, function->cf_name, data,
			VF_KEEPNAME);
		if (v == NULL) {
			log_die(EX_CONFIG, "cf_load_functions: var_create "
				"failed");
		}

		if(vtable_set(cf_config, v) == -1) {
			log_die(EX_CONFIG, "cf_load_functions: var_table_set "
				"failed");
		}
	}

	return;
}
Exemple #2
0
void
watchdog_close(var_t *table)
{
	char *id;

	if (pthread_mutex_lock(&watchdog_mutex))
	{
		log_sys_error("watchdog_remove: pthread_mutex_lock");
		goto exit;
	}

	id = vtable_get(table, "id");
	if (id == NULL)
	{
		log_error("watchdog_remove: vtable_get returned no id");
		goto exit;
	}

	sht_remove(&watchdog_table, id);

exit:
	if (pthread_mutex_unlock(&watchdog_mutex))
	{
		log_sys_error("watchdog_remove: pthread_mutex_unlock");
	}

	return;
}
Exemple #3
0
void
watchdog(var_t *table, char *stage)
{
	watchdog_t *wd;
	char *id;

	if (pthread_mutex_lock(&watchdog_mutex))
	{
		log_sys_error("watchdog: pthread_mutex_lock");
		return;
	}

	watchdog_init();

	// In init id is not set. No problem.
	id = vtable_get(table, "id");
	if (id == NULL)
	{
		goto exit;
	}


	// Record does not exist
	wd = sht_lookup(&watchdog_table, id);
	if (wd == NULL)
	{
		wd = watchdog_create(id, stage);
		if (wd == NULL)
		{
			log_error("watchdog: watchdog_create failed");
			goto exit;
		}

		if (sht_insert(&watchdog_table, id, wd))
		{
			log_error("watchdog: sht_insert failed");
			goto exit;
		}
	}
	else
	{
		wd->wd_stage = stage;
		wd->wd_instage = time(NULL);
	}


exit:
	if (pthread_mutex_unlock(&watchdog_mutex))
	{
		log_sys_error("watchdog: pthread_mutex_unlock");
	}

	return;
}
Exemple #4
0
static var_t *
exp_eval_macro(exp_t *exp, var_t *mailspec)
{
	VAR_INT_T *stage;
	var_t *v;
	char *value;

	if (exp->ex_type != EX_MACRO)
	{
		log_error("exp_eval_macro: bad type");
		return NULL;
	}

	stage = vtable_get(mailspec, "stage");
	if (stage == NULL)
	{
		log_error("exp_eval_macro: milter stage not set");
		return NULL;
	}

	value = milter_macro_lookup(*stage, exp->ex_data, mailspec);
	if (value == NULL)
	{
		return EXP_EMPTY;
	}

	v = var_create(VT_STRING, exp->ex_data, value, VF_KEEPNAME |
		VF_COPYDATA | VF_EXP_FREE);
	if (v == NULL)
	{
		log_error("exp_eval_macro: var_create failed");
		return NULL;
	}

	return v;
}
Exemple #5
0
int
spamd_query(milter_stage_t stage, char *name, var_t *attrs)
{
	int sock = 0;
	var_t *symbols = NULL;
	int n;
	char recv_header[BUFLEN];
	char buffer[BUFLEN];
	char *p, *q;
	char *message = NULL;
	VAR_INT_T spam;
	VAR_FLOAT_T score;
	VAR_INT_T *message_size;
	long header_size, size;

	/*
         * Build received header
         */
	header_size = spamd_header(attrs, recv_header, sizeof recv_header);
	if (header_size == -1)
	{
		log_error("spamd_query: spamd_header failed");
		goto error;
	}

	log_debug("spamd_query: received header:\n%s", recv_header);

	/*
         * Get message size
         */
	message_size = vtable_get(attrs, "message_size");
	if (message_size == NULL)
	{
		log_error("spamd_query: vtable_get failed");
		goto error;
	}

	size = header_size + *message_size;

	/*
	 * Allocate message buffer
	 */
	message = (char *) malloc(size + 1);
	if (message == NULL)
	{
		log_sys_error("spamd_query: malloc");
		goto error;
	}

	/*
	 * Dump message
	 */
	memcpy(message, recv_header, header_size);
	if (milter_dump_message(message + header_size, size - header_size + 1,
	    attrs) == -1)
	{
		log_error("spamd_query: milter_dump_message failed");
		goto error;
	}

	snprintf(buffer, sizeof(buffer), "SYMBOLS SPAMC/1.2\r\n"
	    "Content-length: %ld\r\n\r\n", size);

	sock = sock_connect_rr(&spamd_srr);
	if (sock == -1)
	{
		log_error("spamd_query: sock_connect failed");
		goto error;
	}
	 
	 /*
	  * Write spamassassin request
	  */
	if (write(sock, buffer, strlen(buffer)) == -1) {
		log_sys_error("spamd_query: write");
		goto error;
	}

	/*
	 * Write message
	 */
	if (write(sock, message, size) == -1) {
		log_sys_error("spamd_query: write");
		goto error;
	}

	/*
	 * Read response
	 */
	n = read(sock, buffer, sizeof buffer - 1);
	if (n == -1) {
		log_sys_error("spamd_query: read");
		goto error;
	}
	buffer[n] = 0;

	/*
	 * No answer. Seen when spamd ran out of mem.
         */
	if (n == 0)
	{
		log_error("spamd_query: no data received");
		goto error;
	}

	/*
	 * Parse response
	 */
	p = buffer;
	if (strncmp(p, SPAMD_SPAMD, SPAMD_SPAMDLEN)) {
		spamd_printable_buffer(p, SPAMD_SPAMDLEN + 1);
		log_error("spamd_query: protocol error: expected='%s' "
			"received='%s'", SPAMD_SPAMD, p);
		goto error;
	}

	p += SPAMD_SPAMDLEN;
	if (strncmp(p, SPAMD_VERSION, SPAMD_VERSIONLEN)) {
		spamd_printable_buffer(p, SPAMD_VERSIONLEN + 1);
		log_notice("spamd_query: protocol version mismtach: "
			"expected='%s' received='%s'", SPAMD_VERSION, p);
	}

	p += SPAMD_VERSIONLEN;
	p = strstr(p, SPAMD_EX_OK);
	if(p == NULL) {
		log_error("spamd_query: spamd returned non EX_OK");
		goto error;
	}

	/*
	 * Spamd returns 2 lines. Read 2nd line if neccessary.
	 */
	p += SPAMD_EX_OKLEN;
	if(strlen(p) <= 2) {  /* '\r\n' */

		n = read(sock, buffer, sizeof(buffer));
		if (n == -1) {
			log_sys_error("spamd_query: read");
			goto error;
		}

		buffer[n] = 0;
		p = buffer;
	}
	else {
		p += 2;  /* '\r\n' */
	}

	/*
	 * Parse results
	 */
	if(strncmp(p, SPAMD_SPAM, SPAMD_SPAMLEN)) {
		spamd_printable_buffer(p, SPAMD_SPAMLEN + 1);
		log_error("spamd_query: protocol error: expected='%s' "
			"received='%s'", SPAMD_SPAM, p);
		goto error;
	}

	p += SPAMD_SPAMLEN;
	if(!strncmp(p, SPAMD_TRUE, SPAMD_TRUELEN)) {
		spam = 1;
		p += SPAMD_TRUELEN;
	}
	else if(!strncmp(p, SPAMD_FALSE, SPAMD_FALSELEN)) {
		spam = 0;
		p += SPAMD_FALSELEN;
	}
	else
	{
		spamd_printable_buffer(p, (SPAMD_TRUELEN > SPAMD_FALSELEN ?
			SPAMD_TRUELEN: SPAMD_FALSELEN) + 1);
		log_error("spamd_query: protocol error: expected: '%s|%s' "
			"received='%s'", SPAMD_TRUE, SPAMD_FALSE, p);
		goto error;
	}

	/*
	 * Cut score.
	 */
	q = strchr(p, ' ');
	if (q == NULL) {
		log_error("spamd_query: protocol error: couldn't find the "
			"next space character");
		goto error;
	}
	*q++ = 0;

	score = (VAR_FLOAT_T) strtod(p, NULL);

	/*
	 * Set SYMBOLS
	 */
	p = strchr(q, '\r');
	if (p == NULL) {
		log_error("spamd_query: protocol error: couldn't find the "
			"start of the spamd symbols");
		goto error;
	}
	p += 4; /* \r\n\r\n */

	q = strchr(p, '\r');
	if (q == NULL) {
		log_error("spamd_query: protocol error: couldn't find the "
			"end of the spamd symbols");
		goto error;
	}
	*q = 0;

	log_message(LOG_ERR, attrs, "spamd: spam=%d score=%.1f symbols=%s",
	    spam, score, p);

	symbols = var_create(VT_LIST, "spamd_symbols", NULL,
		VF_KEEPNAME | VF_CREATE);
	if (symbols == NULL) {
		log_error("spamd_query: var_create failed");
		goto error;
	}

	do {
		q = strchr(p, ',');
		if (q) {
			*q = 0;
		}

		if (vlist_append_new(symbols, VT_STRING, NULL, p,
			VF_COPYDATA) == -1) {
			log_error("spamd_query: vlist_append failed");
			goto error;
		}

		p = q + 1;
	} while (q);

	if (vtable_setv(attrs, VT_INT, "spamd_spam", &spam,
		VF_KEEPNAME | VF_COPYDATA, VT_FLOAT, "spamd_score", &score,
		VF_KEEPNAME | VF_COPYDATA, VT_NULL)) {
		log_error("spamd_query: vtable_setv failed");
		goto error;
	}

	if (vtable_set(attrs, symbols)) {
		log_error("spamd_query: vtable_set failed");
		goto error;
	}

	close(sock);

	free(message);

	return 0;

error:
	if (message)
	{
		free(message);
	}

	if (sock > 0) {
		close(sock);
	}

	if (symbols) {
		var_delete(symbols);
	}

	return -1;
}
Exemple #6
0
acl_action_type_t
msgmod(milter_stage_t stage, char *stagename, var_t *mailspec, void *data,
	int depth)
{
	msgmod_t *mm = data;
	void *ctx;
	acl_action_type_t action = ACL_ERROR;
	var_t **args = NULL;
	int argc;
	int size;
	var_t *v, *copy;
	int i;
	exp_t *exp;
	ll_t *ll;
	ll_entry_t *pos;

	/*
	 * Get milter ctx pointer
	 */
	ctx = vtable_get(mailspec, "milter_ctx");
	if (ctx == NULL)
	{
		log_error("msgmod: ctx not set");
		goto error;
	}

	/*
	 * Evaluate arguments
	 */
	argc = mm->mm_args->ll_size;
	size = (argc + 1) * sizeof (var_t *);

	args = (var_t **) malloc(size);
	if (args == NULL)
	{
		log_sys_error("msgmod: malloc");
		goto error;
	}

	memset(args, 0, size);

	ll = mm->mm_args;
	pos = LL_START(ll);

	for (i = 0; i < argc; ++i)
	{
		exp = ll_next(ll, &pos);
		if (exp == NULL)
		{
			log_die(EX_SOFTWARE, "msgmod: empty argument");
		}

		v = exp_eval(exp, mailspec);
		if (v == NULL)
		{
			log_error("msgmod: exp_eval failed");
			goto error;
		}

		// Cast all aruments to VT_STRING
		if (v->v_type != VT_STRING)
		{
			copy = var_cast_copy(VT_STRING, v);
			if (copy == NULL)
			{
				log_error("msgmod: var_cast_copy failed");
				goto error;
			}

			exp_free(v);

			/*
			 * args are freed using exp_free. Set VF_EXP_FREE to
			 * free copy.
			 */
			copy->v_flags |= VF_EXP_FREE;
			
			v = copy;
		}
		
		args[i] = v;
	}

	if (mm->mm_callback(ctx, argc, args))
	{
		log_error("msgmod: mm_callback failed");
		goto error;
	}

	action = ACL_NONE;

error:

	/*
	 * Free args
	 */
	for (i = 0; args[i]; ++i)
	{
		exp_free(args[i]);
	}

	if (args)
	{
		free(args);
	}

	return action;
}