Пример #1
0
static var_t *
exp_eval_function_simple(char *name, acl_function_t *af, ll_t *args)
{
	ll_t garbage;
	ll_entry_t *pos;
	void **argv = NULL;
	var_t *v = NULL;
	int argc;
	int size;
	int i;
	var_t *arg;

	/*
	 * Initialize garbage
	 */
	ll_init(&garbage);

	/*
	 * Check argc
	 */
	argc = args->ll_size;
	if (argc != af->af_argc)
	{
		log_error("exp_eval_function_simple: function \"%s\" requires "
		    "%d arguments", name, af->af_argc);
		return NULL;
	}

	size = (argc + 1) * sizeof (void *);

	argv = (void **) malloc(size);
	if (argv == NULL)
	{
		log_sys_error("exp_eval_function_simple: malloc");
		return NULL;
	}

	memset(argv, 0, size);

	/*
	 * Prepare argv
	 */
	pos = LL_START(args);
	for (i = 0; (arg = ll_next(args, &pos)); ++i)
	{
		if (af->af_types[i] == arg->v_type)
		{
			argv[i] = arg->v_data;
			continue;
		}

		/*
		 * Type casting required. Don't care about the remains of arg
		 * (freed with args!).
		 */
		arg = var_cast_copy(af->af_types[i], arg);
		if (arg == NULL)
		{
			log_error("exp_eval_function_simple: var_cast_copy "
			    "failed");

			goto error;
		}

		/*
		 * Need to free copy later
		 */
		if (LL_INSERT(&garbage, arg) == -1)
		{
			log_error("exp_eval_function_simlpe: LL_INSERT "
			    "failed");

			var_delete(arg);
			goto error;
		}

		argv[i] = arg->v_data;
	}

	v = af->af_callback.fc_simple(argc, argv);


error:
	ll_clear(&garbage, (ll_delete_t) var_delete);

	if (argv)
	{
		free(argv);
	}

	return v;
}
Пример #2
0
static var_t *
exp_eval_regex(int op, var_t *left, var_t *right)
{
	char *p;
	int e;
	char error[1024];
	int flags = REG_EXTENDED | REG_NOSUB;
	int match;
	regex_t r;

	var_t *pattern_copy = NULL;
	var_t *str_copy = NULL;

	char *pattern;
	char *str;

	if (left == NULL || right == NULL)
	{
		return EXP_EMPTY;
	}

	if (left->v_data == NULL || right->v_data == NULL)
	{
		log_debug("exp_eval_regex: empty value");
		return EXP_EMPTY;
	}

	// Make sure left is a string
	if (left->v_type != VT_STRING)
	{
		str_copy = var_cast_copy(VT_STRING, left);
		if (str_copy == NULL)
		{
			log_error("exp_eval_regex: var_cast_copy failed");
			goto error;
		}
		str = str_copy->v_data;
	}
	else
	{
		str = left->v_data;
	}

	// Make sure right is a string
	if (right->v_type != VT_STRING)
	{
		pattern_copy = var_cast_copy(VT_STRING, right);
		if (pattern_copy == NULL)
		{
			log_error("exp_eval_regex: var_cast_copy failed");
			goto error;
		}
		pattern = pattern_copy->v_data;
	}
	else
	{
		pattern = right->v_data;
	}

	// Test if pattern contains upper case chars
	flags = REG_EXTENDED | REG_NOSUB;
	for (p = pattern; *p; ++p)
	{
		if (isupper((int) *p))
		{
			break;
		}
	}
	// If pattern is all lower perform case insensitiv matching
	if(*p == 0)
	{
		flags |= REG_ICASE;
	}

	e = regcomp(&r, pattern, flags);
	if (e)
	{
		regerror(e, &r, error, sizeof error);
		log_error("exp_eval_regex: regcomp: %s", error);
		goto error;
	}

	// Regexec returns 0 if pattern matched.
	match = regexec(&r, str, 0, NULL, 0);

	// free memory
	regfree(&r);
	if (str_copy)
	{
		var_delete(str_copy);
	}
	if (pattern_copy)
	{
		var_delete(pattern_copy);
	}

	if (op == NR)
	{
		match = !match;
	}

	if (match)
	{
		return EXP_FALSE;
	}

	return EXP_TRUE;

error:
	if (str_copy)
	{
		var_delete(str_copy);
	}
	if (pattern_copy)
	{
		var_delete(pattern_copy);
	}

	return NULL;
}
Пример #3
0
var_t *
exp_eval_operation(exp_t *exp, var_t *mailspec)
{
	var_t *left = NULL, *right = NULL, *copy;
	exp_operation_t *eo = exp->ex_data;
	var_t *result = NULL;
	var_type_t type;

	/*
	 * Variable assigment
	 */
	if (eo->eo_operator == '=')
	{
		return exp_assign(eo->eo_operand[0], eo->eo_operand[1],
		    mailspec);
	}

	/*
	 * isset operator
	 */
	if (eo->eo_operator == IS_SET)
	{
		return exp_isset(mailspec, eo->eo_operand[0]);
	}

	/*
	 * Do not load unneccessary symbols in boolean operations
	 */
	if (eo->eo_operator == AND || eo->eo_operator == OR)
	{
		result = exp_bool(mailspec, eo->eo_operator, eo->eo_operand[0],
			eo->eo_operand[1]);
		goto exit;
	}

	/*
 	 * Load left operand
 	 */
	left = exp_eval(eo->eo_operand[0], mailspec);

	/*
	 * ! operator
	 */
	if (eo->eo_operator == '!')
	{
		return exp_not(left);
	}

	/*
	 * Hack: IS_NULL operator
	 */
	if (eo->eo_operator == IS_NULL)
	{
		result = exp_is_null(left);
		goto exit;
	}

	/*
 	 * Evaluate right operand
 	 */
	if (eo->eo_operand[1])
	{
		right = exp_eval(eo->eo_operand[1], mailspec);
	}

	switch(eo->eo_operator)
	{
	// Comparator
	case '<':
	case '>':
	case LE:
	case GE:
	case EQ:
	case NE:
		result = exp_compare(eo->eo_operator, left, right);
		goto exit;

	// Regex
	case '~':
	case NR:
		result = exp_eval_regex(eo->eo_operator, left, right);
		goto exit;

	// In
	case IN:
		result = exp_eval_in(left, right);
		goto exit;



	// Address prefix operator
	case '/':
		if (left == NULL || right == NULL)
		{
			break;
		}
		if (!(left->v_type == VT_ADDR && right->v_type == VT_INT))
		{
			break;
		}

		result = exp_addr_prefix(left, right);
		goto exit;

	default:
		break;
	}

	// Math operators need left and right to be set
	if (left == NULL || right ==  NULL)
	{
		result = EXP_EMPTY;
		goto exit;
	}

	// Make sure we work with the same types
	if (left->v_type != right->v_type)
	{
		/*
		 * The biggest type has precedence (see exp.h)
		 * STRING > FLOAT > INT
		 */
		type = VAR_MAX_TYPE(left, right);

		if (type == left->v_type)
		{
			copy = var_cast_copy(type, right);
		}
		else
		{
			copy = var_cast_copy(type, left);
		}

		if (copy == NULL)
		{
			log_error("exp_eval_operation: var_cast_copy "
			    "failed");
			goto exit;
		}

		if (type == left->v_type)
		{
			exp_free(right);
			right = copy;
			right->v_flags |= VF_EXP_FREE;
		}
		else
		{
			exp_free(left);
			left = copy;
			left->v_flags |= VF_EXP_FREE;
		}
	}

	switch (left->v_type)
	{
	case VT_INT:
		result = exp_math_int(eo->eo_operator, left, right);
		break;

	case VT_FLOAT:
		result = exp_math_float(eo->eo_operator, left, right);
		break;

	case VT_STRING:
		result = exp_math_string(eo->eo_operator, left, right);
		break;

	default:
		log_error("exp_eval_operation: bad type");
		goto exit;
	}

exit:
	if (left)
	{
		exp_free(left);
	}

	if (right)
	{
		exp_free(right);
	}

	return result;
}
Пример #4
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;
}