#define config_param_register(Param)
-config_param_register("first_filter");
+/* Filter to execute on "CONNECT"
+ */
+config_param_register("client_filter");
+
+/* Filter to execute on "MAIL FROM"
+ */
+config_param_register("sender_filter");
+
+/* Filter to execute on "RCPT TO"
+ */
+config_param_register("recipient_filter");
+
+/* Filter to execute on "DATA"
+ */
+config_param_register("data_filter");
+
+/* Filter to execute on "END-OF-DATA"
+ */
+config_param_register("end_of_data_filter");
+
+/* Filter to execute on "ETRN"
+ */
+config_param_register("etrn_filter");
+
+/* Filter to execute on "HELO"
+ */
+config_param_register("helo_filter");
+config_param_register("ehlo_filter");
+
+/* Filter to execute on "VRFY"
+ */
+config_param_register("verify_filter");
static inline config_t *config_new(void)
{
config_t *config = p_new(config_t, 1);
- config->entry_point = -1;
+ for (int i = 0 ; i < SMTP_count ; ++i) {
+ config->entry_points[i] = -1;
+ }
return config;
}
break;
}
}}
+ if (!ok) {
+ return false;
+ }
- config->entry_point = -1;
+ ok = false;
foreach (filter_param_t *param, config->params) {
switch (param->type) {
- case ATK_FIRST_FILTER:
- config->entry_point = filter_find_with_name(&config->filters,
- param->value);
- break;
+#define CASE(Param, State) \
+ case ATK_ ## Param ## _FILTER: \
+ ok = true; \
+ config->entry_points[SMTP_ ## State] \
+ = filter_find_with_name(&config->filters, param->value); \
+ break;
+ CASE(CLIENT, CONNECT)
+ CASE(EHLO, EHLO)
+ CASE(HELO, HELO)
+ CASE(SENDER, MAIL)
+ CASE(RECIPIENT, RCPT)
+ CASE(DATA, DATA)
+ CASE(END_OF_DATA, END_OF_MESSAGE)
+ CASE(VERIFY, VRFY)
+ CASE(ETRN, ETRN)
+#undef CASE
default: break;
}
}}
array_deep_wipe(config->params, filter_params_wipe);
- if (config->entry_point == -1) {
- ok = false;
+ if (!ok) {
syslog(LOG_ERR, "no entry point defined");
}
syslog(LOG_ERR, "Unexpected end of file");
error:
- filter_wipe(&filter);
+ if (filter.name) {
+ filter_wipe(&filter);
+ }
config_delete(&config);
file_map_close(&map);
return NULL;
struct config_t {
A(filter_t) filters;
A(filter_param_t) params;
- int entry_point;
+ int entry_points[SMTP_count];
};
__attribute__((nonnull(1)))
{
int start = 0;
int end = filter->hooks.len;
- syslog(LOG_DEBUG, "running filter %s (%s)",
- filter->name, ftokens[filter->type]);
+ //syslog(LOG_DEBUG, "running filter %s (%s)",
+ // filter->name, ftokens[filter->type]);
filter_result_t res = runners[filter->type](filter, query);
- syslog(LOG_DEBUG, "filter run, result is %s", htokens[res]);
+ //syslog(LOG_DEBUG, "filter run, result is %s", htokens[res]);
while (start < end) {
int mid = (start + end) / 2;
filter_hook_t *hook = array_ptr(filter->hooks, mid);
if (hook->type == res) {
- syslog(LOG_DEBUG, "return hook of type %s, value %s",
- htokens[hook->type], hook->value);
+ //syslog(LOG_DEBUG, "return hook of type %s, value %s",
+ // htokens[hook->type], hook->value);
return hook;
} else if (res < hook->type) {
end = mid;
#define GREYLIST_INIT { .lookup_by_host = false, \
.delay = 300, \
- .retry_window = 2 * 24 * 2600, \
+ .retry_window = 2 * 24 * 3600, \
.client_awl = 5, \
.awl_db = NULL, \
.obj_db = NULL }
/* OK.
*/
- syslog(LOG_INFO, "client whitelisted");
+ //syslog(LOG_INFO, "client whitelisted");
return true;
}
}
/* OK
*/
- syslog(LOG_INFO, "client whitelisted");
+ //syslog(LOG_INFO, "client whitelisted");
return true;
}
/* DUNNO
*/
- syslog(LOG_INFO, "client greylisted");
+ //syslog(LOG_INFO, "client greylisted");
return false;
}
const greylist_config_t *config = filter->data;
return try_greylist(config, query->sender, query->client_address,
query->client_name, query->recipient) ?
- HTK_MATCH : HTK_FAIL;
+ HTK_WHITELIST : HTK_GREYLIST;
}
static int greylist_init(void)
/* Hooks.
*/
(void)filter_hook_register(type, "error");
- (void)filter_hook_register(type, "fail");
- (void)filter_hook_register(type, "match");
+ (void)filter_hook_register(type, "greylist");
+ (void)filter_hook_register(type, "whitelist");
/* Parameters.
*/
} while (0)
p_clear(query, 1);
+ query->state = SMTP_UNKNOWN;
while (*p != '\n') {
char *k, *v;
int klen, vlen, vtk;
vtk = policy_tokenize(v, vlen);
switch (policy_tokenize(k, klen)) {
-#define CASE(up, low) case PTK_##up: query->low = v; v[vlen] = '\0'; break;
+#define CASE(up, low) case PTK_##up: query->low = v; v[vlen] = '\0'; syslog(LOG_DEBUG, "%s = %s", ptokens[PTK_##up], query->low); break;
CASE(HELO_NAME, helo_name);
CASE(QUEUE_ID, queue_id);
CASE(SENDER, sender);
static void policy_process(server_t *pcy, config_t *config)
{
const query_t* query = pcy->data;
- filter_t *filter = array_ptr(config->filters, config->entry_point);
+ filter_t *filter;
+ if (config->entry_points[query->state] == -1) {
+ syslog(LOG_WARNING, "no filter defined for current protocol_state (%d)", query->state);
+ policy_answer(pcy, "DUNNO");
+ return;
+ }
+ filter = array_ptr(config->filters, config->entry_points[query->state]);
while (true) {
filter_hook_t *hook = filter_run(filter, query);
if (hook == NULL) {
#include "mem.h"
enum smtp_state {
- SMTP_UNKNOWN,
SMTP_CONNECT,
SMTP_EHLO,
SMTP_HELO = SMTP_EHLO,
SMTP_END_OF_MESSAGE,
SMTP_VRFY,
SMTP_ETRN,
+ SMTP_count,
+ SMTP_UNKNOWN,
};
/* \see http://www.postfix.org/SMTPD_POLICY_README.html */