~ubuntu-branches/ubuntu/dapper/postfix/dapper-security

« back to all changes in this revision

Viewing changes to src/smtp/smtp_reuse.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2005-12-07 15:39:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051207153911-hutf07z6i8ty25z5
Tags: 2.2.6-1
* New upstream.
  - the *SQL clients did not uniformly choose the database host from
    the available pool
  - raise the "policy violation" flag when a client request exceeds
    a concurrency or rate limit.
  - don't do smtpd_end_of_data_restrictions after the transaction
    failed due to, e.g., a write error.
  - two messages could get the same message ID due to a race
    condition. This time window was increased when queue file creation
    was postponed from MAIL FROM until the first accepted RCPT TO.  The
    window is closed again.
  - the queue manager did not write a per-recipient defer logfile record
    when the delivery agent crashed after the initial handshake with the
    queue manager, and before reporting the delivery status to the queue
    manager.
  - moved code around from one place to another to make REDIRECT, FILTER,
    HOLD and DISCARD access(5) table actions work in
    smtpd_end_of_data_restrictions.  PREPEND will not be fixed; it must
    be specified before the message content is received.
* Updated Italian translations.  Closes: #336925
* Swedish translations.  Closes: #339746
* Switch to libdb4.3.  Closes: #336488
* Add Replaces: mail-transport-agent.  Closes: #325624
* Merge changes from ubuntu.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      smtp_reuse 3
 
4
/* SUMMARY
 
5
/*      SMTP session cache glue
 
6
/* SYNOPSIS
 
7
/*      #include <smtp.h>
 
8
/*      #include <smtp_reuse.h>
 
9
/*
 
10
/*      void    smtp_save_session(state)
 
11
/*      SMTP_STATE *state;
 
12
/*
 
13
/*      SMTP_SESSION *smtp_reuse_domain(state, lookup_mx, domain, port)
 
14
/*      SMTP_STATE *state;
 
15
/*      int     lookup_mx;
 
16
/*      char    *domain;
 
17
/*      unsigned port;
 
18
/*
 
19
/*      SMTP_SESSION *smtp_reuse_addr(state, addr, port)
 
20
/*      SMTP_STATE *state;
 
21
/*      DNS_RR  *addr;
 
22
/*      unsigned port;
 
23
/* DESCRIPTION
 
24
/*      This module implements the SMTP client specific interface to
 
25
/*      the generic session cache infrastructure.
 
26
/*
 
27
/*      smtp_save_session() stores the current session under the
 
28
/*      next-hop logical destination (if available) and under the
 
29
/*      remote server address.  The SMTP_SESSION object is destroyed.
 
30
/*
 
31
/*      smtp_reuse_domain() looks up a cached session by its logical
 
32
/*      destination, and verifies that the session is still alive.
 
33
/*      The restored session information includes the "best MX" bit.
 
34
/*      The result is null in case of failure.
 
35
/*
 
36
/*      smtp_reuse_addr() looks up a cached session by its server
 
37
/*      address, and verifies that the session is still alive.
 
38
/*      The result is null in case of failure.
 
39
/*
 
40
/*      Arguments:
 
41
/* .IP state
 
42
/*      SMTP client state, including the current session, the original
 
43
/*      next-hop domain, etc.
 
44
/* .IP lookup_mx
 
45
/*      Whether or not the domain is subject to MX lookup.
 
46
/* .IP domain
 
47
/*      Domain name or bare numerical address.
 
48
/* .IP addr
 
49
/*      The remote server name and address.
 
50
/* .IP port
 
51
/*      The remote server port, network byte order.
 
52
/* LICENSE
 
53
/* .ad
 
54
/* .fi
 
55
/*      The Secure Mailer license must be distributed with this software.
 
56
/* AUTHOR(S)
 
57
/*      Wietse Venema
 
58
/*      IBM T.J. Watson Research
 
59
/*      P.O. Box 704
 
60
/*      Yorktown Heights, NY 10598, USA
 
61
/*--*/
 
62
 
 
63
/* System library. */
 
64
 
 
65
#include <sys_defs.h>
 
66
#include <sys/socket.h>
 
67
#include <netinet/in.h>
 
68
#include <arpa/inet.h>
 
69
#include <unistd.h>
 
70
#include <string.h>
 
71
 
 
72
/* Utility library. */
 
73
 
 
74
#include <msg.h>
 
75
#include <mymalloc.h>
 
76
#include <vstream.h>
 
77
#include <vstring.h>
 
78
#include <htable.h>
 
79
#include <stringops.h>
 
80
 
 
81
/* Global library. */
 
82
 
 
83
#include <scache.h>
 
84
#include <mail_params.h>
 
85
 
 
86
/* Application-specific. */
 
87
 
 
88
#include <smtp.h>
 
89
#include <smtp_reuse.h>
 
90
 
 
91
 /*
 
92
  * We encode the MX lookup/A lookup method into the name under which SMTP
 
93
  * session information is cached. The following macros serve to make the
 
94
  * remainder of the code less obscure.
 
95
  */
 
96
#define NO_MX_LOOKUP    0
 
97
 
 
98
#define SMTP_SCACHE_LABEL(mx_lookup_flag) \
 
99
        ((mx_lookup_flag) ? "%s:%s:%u" : "%s:[%s]:%u")
 
100
 
 
101
#define STR(x)  vstring_str(x)
 
102
 
 
103
/* smtp_save_session - save session under next-hop name and server address */
 
104
 
 
105
void    smtp_save_session(SMTP_STATE *state)
 
106
{
 
107
    SMTP_SESSION *session = state->session;
 
108
    int     fd;
 
109
 
 
110
    /*
 
111
     * Encode the next-hop logical destination, if available. Reuse storage
 
112
     * that is also used for cache lookup queries.
 
113
     * 
 
114
     * Note: if the label needs to be made more specific (with e.g., SASL login
 
115
     * information), just append the text with vstring_sprintf_append().
 
116
     */
 
117
    if (HAVE_NEXTHOP_STATE(state))
 
118
        vstring_sprintf(state->dest_label,
 
119
                        SMTP_SCACHE_LABEL(state->nexthop_lookup_mx),
 
120
                        state->service, state->nexthop_domain,
 
121
                        ntohs(state->nexthop_port));
 
122
 
 
123
    /*
 
124
     * Encode the physical endpoint name. Reuse storage that is also used for
 
125
     * cache lookup queries.
 
126
     * 
 
127
     * Note: if the label needs to be made more specific (with e.g., SASL login
 
128
     * information), just append the text with vstring_sprintf_append().
 
129
     */
 
130
    vstring_sprintf(state->endp_label,
 
131
                    SMTP_SCACHE_LABEL(NO_MX_LOOKUP),
 
132
                    state->service, session->addr, ntohs(session->port));
 
133
 
 
134
    /*
 
135
     * Passivate the SMTP_SESSION object, destroying the object in the
 
136
     * process. Reuse storage that is also used for cache lookup results.
 
137
     */
 
138
    fd = smtp_session_passivate(session, state->dest_prop, state->endp_prop);
 
139
    state->session = 0;
 
140
 
 
141
    /*
 
142
     * Save the session under the next-hop name, if available.
 
143
     * 
 
144
     * XXX The logical to physical binding can be kept for as long as the DNS
 
145
     * allows us to (but that could result in the caching of lots of unused
 
146
     * bindings). The session should be idle for no more than 30 seconds or
 
147
     * so.
 
148
     */
 
149
    if (HAVE_NEXTHOP_STATE(state))
 
150
        scache_save_dest(smtp_scache, var_smtp_cache_conn, STR(state->dest_label),
 
151
                         STR(state->dest_prop), STR(state->endp_label));
 
152
 
 
153
    /*
 
154
     * Save every good session under its physical endpoint address.
 
155
     */
 
156
    scache_save_endp(smtp_scache, var_smtp_cache_conn, STR(state->endp_label),
 
157
                     STR(state->endp_prop), fd);
 
158
}
 
159
 
 
160
/* smtp_reuse_common - common session reuse code */
 
161
 
 
162
static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd,
 
163
                                               const char *label)
 
164
{
 
165
    const char *myname = "smtp_reuse_common";
 
166
    SMTP_SESSION *session;
 
167
 
 
168
    /*
 
169
     * Re-activate the SMTP_SESSION object.
 
170
     */
 
171
    session = smtp_session_activate(fd, state->dest_prop, state->endp_prop);
 
172
    if (session == 0) {
 
173
        msg_warn("%s: bad cached session attribute for %s", myname, label);
 
174
        (void) close(fd);
 
175
        return (0);
 
176
    }
 
177
    state->session = session;
 
178
 
 
179
    /*
 
180
     * Send an RSET probe to verify that the session is still good.
 
181
     */
 
182
    if (smtp_rset(state) < 0
 
183
        || (session->features & SMTP_FEATURE_RSET_REJECTED) != 0) {
 
184
        smtp_session_free(session);
 
185
        return (state->session = 0);
 
186
    }
 
187
 
 
188
    /*
 
189
     * Update the list of used cached addresses.
 
190
     */
 
191
    htable_enter(state->cache_used, session->addr, (char *) 0);
 
192
 
 
193
    return (session);
 
194
}
 
195
 
 
196
/* smtp_reuse_domain - reuse session cached under domain name */
 
197
 
 
198
SMTP_SESSION *smtp_reuse_domain(SMTP_STATE *state, int lookup_mx,
 
199
                                        const char *domain, unsigned port)
 
200
{
 
201
    SMTP_SESSION *session;
 
202
    int     fd;
 
203
 
 
204
    /*
 
205
     * Look up the session by its logical name.
 
206
     * 
 
207
     * Note: if the label needs to be made more specific (with e.g., SASL login
 
208
     * information), just append the text with vstring_sprintf_append().
 
209
     */
 
210
    vstring_sprintf(state->dest_label, SMTP_SCACHE_LABEL(lookup_mx),
 
211
                    state->service, domain, ntohs(port));
 
212
    if ((fd = scache_find_dest(smtp_scache, STR(state->dest_label),
 
213
                               state->dest_prop, state->endp_prop)) < 0)
 
214
        return (0);
 
215
 
 
216
    /*
 
217
     * Re-activate the SMTP_SESSION object, and verify that the session is
 
218
     * still good.
 
219
     */
 
220
    session = smtp_reuse_common(state, fd, STR(state->dest_label));
 
221
    return (session);
 
222
}
 
223
 
 
224
/* smtp_reuse_addr - reuse session cached under numerical address */
 
225
 
 
226
SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, DNS_RR *addr, unsigned port)
 
227
{
 
228
    MAI_HOSTADDR_STR hostaddr;
 
229
    SMTP_SESSION *session;
 
230
    int     fd;
 
231
 
 
232
    /*
 
233
     * Look up the session by its IP address. This means that we have no
 
234
     * destination-to-address binding properties.
 
235
     * 
 
236
     * Note: if the label needs to be made more specific (with e.g., SASL login
 
237
     * information), just append the text with vstring_sprintf_append().
 
238
     */
 
239
    if (dns_rr_to_pa(addr, &hostaddr) == 0)
 
240
        return (0);
 
241
    vstring_sprintf(state->endp_label, SMTP_SCACHE_LABEL(NO_MX_LOOKUP),
 
242
                    state->service, hostaddr.buf, ntohs(port));
 
243
    if ((fd = scache_find_endp(smtp_scache, STR(state->endp_label),
 
244
                               state->endp_prop)) < 0)
 
245
        return (0);
 
246
    VSTRING_RESET(state->dest_prop);
 
247
    VSTRING_TERMINATE(state->dest_prop);
 
248
 
 
249
    /*
 
250
     * Re-activate the SMTP_SESSION object, and verify that the session is
 
251
     * still good.
 
252
     */
 
253
    session = smtp_reuse_common(state, fd, STR(state->endp_label));
 
254
 
 
255
    /*
 
256
     * XXX What if hostnames don't match (addr->name versus session->name),
 
257
     * or if the SASL login name for this host does not match the SASL login
 
258
     * name that was used when opening this session? If something depends
 
259
     * critically on such information being identical, then that information
 
260
     * should be included in the logical and physical labels under which a
 
261
     * session is cached.
 
262
     */
 
263
    return (session);
 
264
}