123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- --[[
- Copyright (c) 2019, Vsevolod Stakhov <vsevolod@highsecure.ru>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ]]--
-
- --[[[
- -- @module lua_ffi/spf
- -- This module contains ffi interfaces to SPF
- --]]
-
- local ffi = require 'ffi'
-
- ffi.cdef[[
- enum spf_mech_e {
- SPF_FAIL,
- SPF_SOFT_FAIL,
- SPF_PASS,
- SPF_NEUTRAL
- };
- static const unsigned RSPAMD_SPF_FLAG_IPV6 = (1 << 0);
- static const unsigned RSPAMD_SPF_FLAG_IPV4 = (1 << 1);
- static const unsigned RSPAMD_SPF_FLAG_ANY = (1 << 3);
- struct spf_addr {
- unsigned char addr6[16];
- unsigned char addr4[4];
- union {
- struct {
- uint16_t mask_v4;
- uint16_t mask_v6;
- } dual;
- uint32_t idx;
- } m;
- unsigned flags;
- enum spf_mech_e mech;
- char *spf_string;
- struct spf_addr *prev, *next;
- };
-
- struct spf_resolved {
- char *domain;
- unsigned ttl;
- int temp_failed;
- int na;
- int perm_failed;
- uint64_t digest;
- struct GArray *elts;
- struct ref_entry_s ref;
- };
-
- typedef void (*spf_cb_t)(struct spf_resolved *record,
- struct rspamd_task *task, void *data);
- struct rspamd_task;
- int rspamd_spf_resolve(struct rspamd_task *task, spf_cb_t callback,
- void *cbdata);
- const char * rspamd_spf_get_domain (struct rspamd_task *task);
- struct spf_resolved * spf_record_ref (struct spf_resolved *rec);
- void spf_record_unref (struct spf_resolved *rec);
- char * spf_addr_mask_to_string (struct spf_addr *addr);
- struct spf_addr * spf_addr_match_task (struct rspamd_task *task, struct spf_resolved *rec);
- ]]
-
- local function convert_mech(mech)
- if mech == ffi.C.SPF_FAIL then
- return 'fail'
- elseif mech == ffi.C.SPF_SOFT_FAIL then
- return 'softfail'
- elseif mech == ffi.C.SPF_PASS then
- return 'pass'
- elseif mech == ffi.C.SPF_NEUTRAL then
- return 'neutral'
- end
- end
-
- local NULL = ffi.new 'void*'
-
- local function spf_addr_tolua(ffi_spf_addr)
- local ipstr = ffi.C.spf_addr_mask_to_string(ffi_spf_addr)
- local ret = {
- res = convert_mech(ffi_spf_addr.mech),
- ipnet = ffi.string(ipstr),
- }
-
- if ffi_spf_addr.spf_string ~= NULL then
- ret.spf_str = ffi.string(ffi_spf_addr.spf_string)
- end
-
- ffi.C.g_free(ipstr)
- return ret
- end
-
- local function spf_resolve(task, cb)
- local function spf_cb(rec, _, _)
- if not rec then
- cb(false, 'record is empty')
- else
- local nelts = rec.elts.len
- local elts = ffi.cast("struct spf_addr *", rec.elts.data)
- local res = {
- addrs = {}
- }
- local digstr = ffi.new("char[64]")
- ffi.C.rspamd_snprintf(digstr, 64, "0x%xuL", rec.digest)
- res.digest = ffi.string(digstr)
- for i = 1,nelts do
- res.addrs[i] = spf_addr_tolua(elts[i - 1])
- end
-
- local matched = ffi.C.spf_addr_match_task(task:topointer(), rec)
-
- if matched ~= NULL then
- cb(true, res, spf_addr_tolua(matched))
- else
- cb(true, res, nil)
- end
- end
- end
-
- local ret = ffi.C.rspamd_spf_resolve(task:topointer(), spf_cb, nil)
-
- if not ret then
- cb(false, 'cannot perform resolving')
- end
- end
-
- local function spf_unref(rec)
- ffi.C.spf_record_unref(rec)
- end
-
- return {
- spf_resolve = spf_resolve,
- spf_unref = spf_unref
- }
|