static void rspamd_stat_cache_redis_generate_id (struct rspamd_task *task) { rspamd_cryptobox_hash_state_t st; rspamd_token_t *tok; guint i; guchar out[rspamd_cryptobox_HASHBYTES]; gchar *b32out; gchar *user = NULL; rspamd_cryptobox_hash_init (&st, NULL, 0); user = rspamd_mempool_get_variable (task->task_pool, "stat_user"); /* Use dedicated hash space for per users cache */ if (user != NULL) { rspamd_cryptobox_hash_update (&st, user, strlen (user)); } for (i = 0; i < task->tokens->len; i ++) { tok = g_ptr_array_index (task->tokens, i); rspamd_cryptobox_hash_update (&st, tok->data, tok->datalen); } rspamd_cryptobox_hash_final (&st, out); b32out = rspamd_encode_base32 (out, sizeof (out)); g_assert (b32out != NULL); rspamd_mempool_set_variable (task->task_pool, "words_hash", b32out, g_free); }
static void dkim_sign_callback (struct rspamd_task *task, void *unused) { lua_State *L; struct rspamd_task **ptask; gboolean sign = FALSE; gint err_idx; GString *tb, *hdr; GError *err = NULL; const gchar *selector = NULL, *domain = NULL, *key = NULL; rspamd_dkim_sign_context_t *ctx; rspamd_dkim_sign_key_t *dkim_key; if (dkim_module_ctx->sign_condition_ref != -1) { sign = FALSE; L = task->cfg->lua_state; lua_pushcfunction (L, &rspamd_lua_traceback); err_idx = lua_gettop (L); lua_rawgeti (L, LUA_REGISTRYINDEX, dkim_module_ctx->sign_condition_ref); ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); *ptask = task; rspamd_lua_setclass (L, "rspamd{task}", -1); if (lua_pcall (L, 1, 1, err_idx) != 0) { tb = lua_touserdata (L, -1); msg_err_task ("call to user extraction script failed: %v", tb); g_string_free (tb, TRUE); } else { if (lua_istable (L, -1)) { /* * Get the following elements: * - selector * - domain * - key */ if (!rspamd_lua_parse_table_arguments (L, -1, &err, "*key=S;*domain=S;*selector=S", &key, &domain, &selector)) { msg_err_task ("invalid return value from sign condition: %e", err); g_error_free (err); return; } dkim_key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash, key, time (NULL)); if (dkim_key == NULL) { dkim_key = rspamd_dkim_sign_key_load (key, &err); if (dkim_key == NULL) { msg_err_task ("cannot load dkim key %s: %e", key, err); g_error_free (err); return; } rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash, g_strdup (key), dkim_key, time (NULL), 0); } ctx = rspamd_create_dkim_sign_context (task, dkim_key, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, dkim_module_ctx->sign_headers, &err); if (ctx == NULL) { msg_err_task ("cannot create sign context: %e", key, err); g_error_free (err); return; } hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, ctx); if (hdr) { rspamd_mempool_set_variable (task->task_pool, "dkim-signature", hdr, rspamd_gstring_free_hard); } sign = TRUE; } else { sign = FALSE; } } /* Result + error function */ lua_settop (L, 0); if (!sign) { msg_debug_task ("skip signing as dkim condition callback returned" " false"); return; } } }
gint lua_dkim_sign_handler (lua_State *L) { struct rspamd_task *task = lua_check_task (L, 1); luaL_argcheck (L, lua_type (L, 2) == LUA_TTABLE, 2, "'table' expected"); GError *err = NULL; GString *hdr; const gchar *selector = NULL, *domain = NULL, *key = NULL; rspamd_dkim_sign_context_t *ctx; rspamd_dkim_sign_key_t *dkim_key; /* * Get the following elements: * - selector * - domain * - key */ if (!rspamd_lua_parse_table_arguments (L, 2, &err, "*key=S;*domain=S;*selector=S", &key, &domain, &selector)) { msg_err_task ("invalid return value from sign condition: %e", err); g_error_free (err); lua_pushboolean (L, FALSE); return 1; } if (dkim_module_ctx->dkim_sign_hash == NULL) { dkim_module_ctx->dkim_sign_hash = rspamd_lru_hash_new ( 128, g_free, /* Keys are just C-strings */ (GDestroyNotify)rspamd_dkim_sign_key_unref); } dkim_key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash, key, time (NULL)); if (dkim_key == NULL) { dkim_key = rspamd_dkim_sign_key_load (key, &err); if (dkim_key == NULL) { msg_err_task ("cannot load dkim key %s: %e", key, err); g_error_free (err); lua_pushboolean (L, FALSE); return 1; } rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash, g_strdup (key), dkim_key, time (NULL), 0); } ctx = rspamd_create_dkim_sign_context (task, dkim_key, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, dkim_module_ctx->sign_headers, &err); if (ctx == NULL) { msg_err_task ("cannot create sign context: %e", err); g_error_free (err); lua_pushboolean (L, FALSE); return 1; } hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, ctx); if (hdr) { rspamd_mempool_set_variable (task->task_pool, "dkim-signature", hdr, rspamd_gstring_free_hard); lua_pushboolean (L, TRUE); return 1; } lua_pushboolean (L, FALSE); return 1; }
/* * Non-static for lua unit testing */ gsize rspamd_redis_expand_object (const gchar *pattern, struct redis_stat_ctx *ctx, struct rspamd_task *task, gchar **target) { gsize tlen = 0; const gchar *p = pattern, *elt; gchar *d, *end; enum { just_char, percent_char, mod_char } state = just_char; struct rspamd_statfile_config *stcf; lua_State *L = NULL; struct rspamd_task **ptask; GString *tb; const gchar *rcpt = NULL; gint err_idx; g_assert (ctx != NULL); stcf = ctx->stcf; if (task) { L = task->cfg->lua_state; } if (ctx->enable_users) { if (ctx->cbref_user == -1) { rcpt = rspamd_task_get_principal_recipient (task); } else if (L) { /* Execute lua function to get userdata */ lua_pushcfunction (L, &rspamd_lua_traceback); err_idx = lua_gettop (L); lua_rawgeti (L, LUA_REGISTRYINDEX, ctx->cbref_user); ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); *ptask = task; rspamd_lua_setclass (L, "rspamd{task}", -1); if (lua_pcall (L, 1, 1, err_idx) != 0) { tb = lua_touserdata (L, -1); msg_err_task ("call to user extraction script failed: %v", tb); g_string_free (tb, TRUE); } else { rcpt = rspamd_mempool_strdup (task->task_pool, lua_tostring (L, -1)); } /* Result + error function */ lua_pop (L, 2); } if (rcpt) { rspamd_mempool_set_variable (task->task_pool, "stat_user", (gpointer)rcpt, NULL); } } /* Length calculation */ while (*p) { switch (state) { case just_char: if (*p == '%') { state = percent_char; } else { tlen ++; } p ++; break; case percent_char: switch (*p) { case '%': tlen ++; state = just_char; break; case 'u': elt = GET_TASK_ELT (task, user); if (elt) { tlen += strlen (elt); } break; case 'r': if (rcpt == NULL) { elt = rspamd_task_get_principal_recipient (task); } else { elt = rcpt; } if (elt) { tlen += strlen (elt); } break; case 'l': if (stcf->label) { tlen += strlen (stcf->label); } break; case 's': if (stcf->symbol) { tlen += strlen (stcf->symbol); } break; default: state = just_char; tlen ++; break; } if (state == percent_char) { state = mod_char; } p ++; break; case mod_char: switch (*p) { case 'd': p ++; state = just_char; break; default: state = just_char; break; } break; } } if (target == NULL || task == NULL) { return tlen; } *target = rspamd_mempool_alloc (task->task_pool, tlen + 1); d = *target; end = d + tlen + 1; d[tlen] = '\0'; p = pattern; state = just_char; /* Expand string */ while (*p && d < end) { switch (state) { case just_char: if (*p == '%') { state = percent_char; } else { *d++ = *p; } p ++; break; case percent_char: switch (*p) { case '%': *d++ = *p; state = just_char; break; case 'u': elt = GET_TASK_ELT (task, user); if (elt) { d += rspamd_strlcpy (d, elt, end - d); } break; case 'r': if (rcpt == NULL) { elt = rspamd_task_get_principal_recipient (task); } else { elt = rcpt; } if (elt) { d += rspamd_strlcpy (d, elt, end - d); } break; case 'l': if (stcf->label) { d += rspamd_strlcpy (d, stcf->label, end - d); } break; case 's': if (stcf->symbol) { d += rspamd_strlcpy (d, stcf->symbol, end - d); } break; default: state = just_char; *d++ = *p; break; } if (state == percent_char) { state = mod_char; } p ++; break; case mod_char: switch (*p) { case 'd': /* TODO: not supported yet */ p ++; state = just_char; break; default: state = just_char; break; } break; } } return tlen; }