1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
/*
* Copyright 2024 Vsevolod Stakhov
*
* 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.
*/
#ifndef RSPAMD_SPF_H
#define RSPAMD_SPF_H
#include "config.h"
#include "ref.h"
#include "addr.h"
#ifdef __cplusplus
extern "C" {
#endif
struct rspamd_task;
struct spf_resolved;
typedef void (*spf_cb_t)(struct spf_resolved *record,
struct rspamd_task *task, gpointer cbdata);
typedef enum spf_mech_e {
SPF_FAIL,
SPF_SOFT_FAIL,
SPF_PASS,
SPF_NEUTRAL
} spf_mech_t;
static inline char spf_mech_char(spf_mech_t mech)
{
switch (mech) {
case SPF_FAIL:
return '-';
case SPF_SOFT_FAIL:
return '~';
case SPF_PASS:
return '+';
case SPF_NEUTRAL:
default:
return '?';
}
}
typedef enum spf_action_e {
SPF_RESOLVE_MX,
SPF_RESOLVE_A,
SPF_RESOLVE_PTR,
SPF_RESOLVE_AAA,
SPF_RESOLVE_REDIRECT,
SPF_RESOLVE_INCLUDE,
SPF_RESOLVE_EXISTS,
SPF_RESOLVE_EXP
} spf_action_t;
#define RSPAMD_SPF_FLAG_IPV6 (1u << 0u)
#define RSPAMD_SPF_FLAG_IPV4 (1u << 1u)
#define RSPAMD_SPF_FLAG_PROCESSED (1u << 2u)
#define RSPAMD_SPF_FLAG_ANY (1u << 3u)
#define RSPAMD_SPF_FLAG_PARSED (1u << 4u)
#define RSPAMD_SPF_FLAG_INVALID (1u << 5u)
#define RSPAMD_SPF_FLAG_REFERENCE (1u << 6u)
#define RSPAMD_SPF_FLAG_REDIRECT (1u << 7u)
#define RSPAMD_SPF_FLAG_TEMPFAIL (1u << 8u)
#define RSPAMD_SPF_FLAG_NA (1u << 9u)
#define RSPAMD_SPF_FLAG_PERMFAIL (1u << 10u)
#define RSPAMD_SPF_FLAG_RESOLVED (1u << 11u)
#define RSPAMD_SPF_FLAG_CACHED (1u << 12u)
#define RSPAMD_SPF_FLAG_PLUSALL (1u << 13u)
/** Default SPF limits for avoiding abuse **/
#define SPF_MAX_NESTING 10
#define SPF_MAX_DNS_REQUESTS 30
#define SPF_MIN_CACHE_TTL (60 * 5) /* 5 minutes */
struct spf_addr {
unsigned char addr6[sizeof(struct in6_addr)];
unsigned char addr4[sizeof(struct in_addr)];
union {
struct {
uint16_t mask_v4;
uint16_t mask_v6;
} dual;
uint32_t idx;
} m;
unsigned int flags;
spf_mech_t mech;
char *spf_string;
struct spf_addr *prev, *next;
};
enum rspamd_spf_resolved_flags {
RSPAMD_SPF_RESOLVED_NORMAL = 0,
RSPAMD_SPF_RESOLVED_TEMP_FAILED = (1u << 0u),
RSPAMD_SPF_RESOLVED_PERM_FAILED = (1u << 1u),
RSPAMD_SPF_RESOLVED_NA = (1u << 2u),
RSPAMD_SPF_RESOLVED_PLUSALL = (1u << 3u),
};
struct spf_resolved {
char *domain;
char *top_record;
unsigned int ttl;
int flags;
double timestamp;
uint64_t digest;
GArray *elts; /* Flat list of struct spf_addr */
ref_entry_t ref; /* Refcounting */
};
struct rspamd_spf_cred {
char *local_part;
char *domain;
char *sender;
};
/*
* Resolve spf record for specified task and call a callback after resolution fails/succeed
*/
gboolean rspamd_spf_resolve(struct rspamd_task *task,
spf_cb_t callback,
gpointer cbdata,
struct rspamd_spf_cred *cred);
/*
* Get a domain for spf for specified task
*/
const char *rspamd_spf_get_domain(struct rspamd_task *task);
struct rspamd_spf_cred *rspamd_spf_get_cred(struct rspamd_task *task);
/*
* Increase refcount
*/
struct spf_resolved *_spf_record_ref(struct spf_resolved *rec, const char *loc);
#define spf_record_ref(rec) \
_spf_record_ref((rec), G_STRLOC)
/*
* Decrease refcount
*/
void _spf_record_unref(struct spf_resolved *rec, const char *loc);
#define spf_record_unref(rec) \
_spf_record_unref((rec), G_STRLOC)
/**
* Prints address + mask in a freshly allocated string (must be freed)
* @param addr
* @return
*/
char *spf_addr_mask_to_string(struct spf_addr *addr);
/**
* Returns spf address that matches the specific task (or nil if not matched)
* @param task
* @param rec
* @return
*/
struct spf_addr *spf_addr_match_task(struct rspamd_task *task,
struct spf_resolved *rec);
void spf_library_config(const ucl_object_t *obj);
#ifdef __cplusplus
}
#endif
#endif
|