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
|
Index: sendmail/milter.c
diff -pur sendmail-8.13.7-orig/sendmail/milter.c sendmail-8.13.7/sendmail/milter.c
--- sendmail-8.13.7-orig/sendmail/milter.c 2005-08-06 00:49:04.000000000 +0300
+++ sendmail-8.13.7/sendmail/milter.c 2007-04-19 20:33:12.000000000 +0300
@@ -3417,29 +3437,30 @@ milter_connect(hostname, addr, e, state)
milter_per_connection_check(e);
/*
+ * There used to be the following comment here:
+ *
** SMFIR_REPLYCODE can't work with connect due to
** the requirements of SMTP. Therefore, ignore the
** reply code text but keep the state it would reflect.
+ *
+ * However, this is wrong. RFC2821, section 3.9 states, that:
+ *
+ * "An SMTP server MUST NOT intentionally close the connection except:
+ * [...]
+ * - After detecting the need to shut down the SMTP service and
+ * returning a 421 response code. This response code can be issued
+ * after the server receives any command or, if necessary,
+ * asynchronously from command receipt (on the assumption that the
+ * client will receive it after the next command is issued)."
+ *
+ * I see no reason why a milter cannot supply its own textual
+ * explanation in xxfi_connect. So, instead of blindly filtering
+ * out the user-supllied response, I return it to smtp(). The latter
+ * is crafted so that it will graciously abort the connection, if
+ * the response begins with 421, giving the user-supplied textual
+ * message, and will proceed with nullserver otherwise.
+ * --gray
*/
-
- if (*state == SMFIR_REPLYCODE)
- {
- if (response != NULL &&
- *response == '4')
- {
- if (strncmp(response, "421 ", 4) == 0)
- *state = SMFIR_SHUTDOWN;
- else
- *state = SMFIR_TEMPFAIL;
- }
- else
- *state = SMFIR_REJECT;
- if (response != NULL)
- {
- sm_free(response); /* XXX */
- response = NULL;
- }
- }
return response;
}
/*
Index: sendmail/srvrsmtp.c
diff -pur sendmail-8.13.7-orig/sendmail/srvrsmtp.c sendmail-8.13.7/sendmail/srvrsmtp.c
--- sendmail-8.13.7-orig/sendmail/srvrsmtp.c 2006-05-31 23:56:37.000000000 +0300
+++ sendmail-8.13.7/sendmail/srvrsmtp.c 2007-04-19 20:34:01.000000000 +0300
@@ -850,12 +850,38 @@ smtp(nullserver, d_flags, e)
{
char state;
char *response;
-
+ static char greetcodebuf[4];
+ size_t len;
+
response = milter_connect(peerhostname, RealHostAddr,
e, &state);
switch (state)
{
case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */
+ if (MilterLogLevel > 3)
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter: connect: host=%s, addr=%s, reject=%s",
+ peerhostname,
+ anynet_ntoa(&RealHostAddr),
+ response);
+ len = strlen(response);
+ if (len >= 3) {
+ /* RFC 2821, Section 3.9 */
+ if (memcmp(response, "421", 3) == 0) {
+ message(response);
+ /* arrange to ignore send list */
+ e->e_sendqueue = NULL;
+ goto doquit;
+ } else {
+ nullserver = newstr(response);
+ memcpy(greetcodebuf, response, 3);
+ greetcodebuf[3] = 0;
+ greetcode = greetcodebuf;
+ break;
+ }
+ }
+ /* FALL THROUGH */
+
case SMFIR_REJECT:
if (MilterLogLevel > 3)
sm_syslog(LOG_INFO, e->e_id,
|