-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgreylist.c
122 lines (103 loc) · 2.57 KB
/
greylist.c
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
#include "config.h"
#include "letter.h"
#include "dbif.h"
#include <syslog.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#if HAVE_ALLOCA_H
# include <alloca.h>
#endif
#include <limits.h>
#define GREYLIST "/var/db/smtpauth"
#define WINDOW 600 /* 10 minutes windows for mail from <> */
/* returns the # of seconds left until the address is no longer
* greylisted
*/
int
greylist(struct letter *let, int delete)
{
#ifdef WITH_GREYLIST
DBhandle db;
char *value;
char *key; /* let->from->user + @ + let->deliveredIP */
time_t now, delay;
int mode,status;
int mailerdaemon = 0;
int multiplier = 1;
char dates[80];
time(&now);
if ( (db = dbif_open(GREYLIST, DBIF_WRITER|DBIF_CREAT, 0600)) == 0) {
syslog(LOG_ERR, "Cannot open greylist database %s: %m", GREYLIST);
return 0; /* fail open */
}
if (let->from && let->from->user) {
char *p;
if ( let->env->greylist_from ) {
key = alloca(strlen(let->from->full)+1);
if ( key )
strcpy(key, let->from->full);
}
else {
key = alloca(strlen(let->from->user) + strlen(let->deliveredIP) + 10);
if (key)
sprintf(key, "%s@[%s]", let->from->user, let->deliveredIP);
}
for (p = let->from->user; *p; ++p)
if (*p <= ' ' || !isprint(*p))
multiplier++;
}
else {
/* mailerdaemon greylit is always by IP */
mailerdaemon = 1;
multiplier += 4;
if (key = alloca(strlen(let->deliveredIP) + 10))
sprintf(key, "<>@[%s]", let->deliveredIP);
}
if (strcmp(let->deliveredIP, let->deliveredby) == 0)
multiplier ++;
if (key == 0) {
syslog(LOG_ERR, "Cannot build key: %m");
return 0;
}
if (delete) {
dbif_delete(db, key);
status = let->env->delay;
}
else {
if ( (value = dbif_get(db, key)) == 0 && let->from && let->from->full )
value = dbif_get(db, let->from->full);
if ( value ) {
if (value[0] == '*')
delay = status = INT_MAX;
else {
delay = atol(value);
status = (now > delay) ? 0 : delay-now;
}
if (mailerdaemon && (status == 0) && (now-delay < WINDOW) ) {
dbif_delete(db, key);
dbif_close(db);
return 0;
}
mode = DBIF_REPLACE;
}
else {
mode = DBIF_INSERT;
status = multiplier * let->env->delay;
delay = now + status;
}
if ( status == INT_MAX )
sprintf(dates, "* %ld", now);
else
sprintf(dates, "%ld %ld", delay-10, now);
if (dbif_put(db, key, dates, mode) != 0)
syslog(LOG_ERR, "Cannot %s %s in greylist",
(mode==DBIF_INSERT) ? "insert" : "update", key);
}
dbif_close(db);
return status;
#else
return 0;
#endif
}