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

« back to all changes in this revision

Viewing changes to src/global/scache.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
/*      scache 3
 
4
/* SUMMARY
 
5
/*      generic session cache API
 
6
/* SYNOPSIS
 
7
/*      #include <scache.h>
 
8
/* DESCRIPTION
 
9
/*      typedef struct {
 
10
/* .in +4
 
11
/*              int     dest_count;
 
12
/*              int     endp_count;
 
13
/*              int     sess_count;
 
14
/* .in -4
 
15
/*      } SCACHE_SIZE;
 
16
/*
 
17
/*      unsigned scache_size(scache, size)
 
18
/*      SCACHE  *scache;
 
19
/*      SCACHE_SIZE *size;
 
20
/*
 
21
/*      void    scache_free(scache)
 
22
/*      SCACHE  *scache;
 
23
/*
 
24
/*      void    scache_save_endp(scache, endp_ttl, endp_label, endp_prop, fd)
 
25
/*      SCACHE  *scache;
 
26
/*      int     endp_ttl;
 
27
/*      const char *endp_label;
 
28
/*      const char *endp_prop;
 
29
/*      int     fd;
 
30
/*
 
31
/*      int     scache_find_endp(scache, endp_label, endp_prop)
 
32
/*      SCACHE  *scache;
 
33
/*      const char *endp_label;
 
34
/*      VSTRING *endp_prop;
 
35
/*
 
36
/*      void    scache_save_dest(scache, dest_ttl, dest_label,
 
37
/*                              dest_prop, endp_label)
 
38
/*      SCACHE  *scache;
 
39
/*      int     dest_ttl;
 
40
/*      const char *dest_label;
 
41
/*      const char *dest_prop;
 
42
/*      const char *endp_label;
 
43
/*
 
44
/*      int     scache_find_dest(dest_label, dest_prop, endp_prop)
 
45
/*      SCACHE  *scache;
 
46
/*      const char *dest_label;
 
47
/*      VSTRING *dest_prop;
 
48
/*      VSTRING *endp_prop;
 
49
/* DESCRIPTION
 
50
/*      This module implements a generic session cache interface.
 
51
/*      Specific cache types are described in scache_single(3),
 
52
/*      scache_clnt(3) and scache_multi(3). These documents also
 
53
/*      describe now to instantiate a specific session cache type.
 
54
/*
 
55
/*      The code maintains two types of association: a) physical
 
56
/*      endpoint to file descriptor, and b) logical endpoint
 
57
/*      to physical endpoint. Physical endpoints are stored and
 
58
/*      looked up under their low-level session details such as
 
59
/*      numerical addresses, while logical endpoints are stored
 
60
/*      and looked up by the domain name that humans use. One logical
 
61
/*      endpoint can refer to multiple physical endpoints, one
 
62
/*      physical endpoint may be referenced by multiple logical
 
63
/*      endpoints, and one physical endpoint may have multiple
 
64
/*      sessions.
 
65
/*
 
66
/*      scache_size() returns the number of logical destination
 
67
/*      names, physical endpoint addresses, and cached sessions.
 
68
/*
 
69
/*      scache_free() destroys the specified session cache.
 
70
/*
 
71
/*      scache_save_endp() stores an open session under the specified
 
72
/*      physical endpoint name.
 
73
/*
 
74
/*      scache_find_endp() looks up a saved session under the
 
75
/*      specified physical endpoint name.
 
76
/*
 
77
/*      scache_save_dest() associates the specified physical endpoint
 
78
/*      with the specified logical endpoint name.
 
79
/*
 
80
/*      scache_find_dest() looks up a saved session under the
 
81
/*      specified physical endpoint name.
 
82
/*
 
83
/*      Arguments:
 
84
/* .IP endp_ttl
 
85
/*      How long the session should be cached.  When information
 
86
/*      expires it is purged automatically.
 
87
/* .IP endp_label
 
88
/*      The transport name and the physical endpoint name under
 
89
/*      which the session is stored and looked up.
 
90
/*
 
91
/*      In the case of SMTP, the physical endpoint includes the numerical
 
92
/*      IP address, address family information, and the numerical TCP port.
 
93
/* .IP endp_prop
 
94
/*      Application-specific data with endpoint attributes.  It is up to
 
95
/*      the application to passivate (flatten) and re-activate this content
 
96
/*      upon storage and retrieval, respectively.
 
97
/* .sp
 
98
/*      In the case of SMTP, the endpoint attributes specify the
 
99
/*      server hostname, IP address, numerical TCP port, as well
 
100
/*      as ESMTP features advertised by the server, and when information
 
101
/*      expires. All this in some application-specific format that is easy
 
102
/*      to unravel when re-activating a cached session.
 
103
/* .IP dest_ttl
 
104
/*      How long the destination-to-endpoint binding should be
 
105
/*      cached. When information expires it is purged automatically.
 
106
/* .IP dest_label
 
107
/*      The transport name and the logical destination under which the
 
108
/*      destination-to-endpoint binding is stored and looked up.
 
109
/*
 
110
/*      In the case of SMTP, the logical destination is the DNS
 
111
/*      host or domain name with or without [], plus the numerical TCP port.
 
112
/* .IP dest_prop
 
113
/*      Application-specific attributes that describe features of
 
114
/*      this logical to physical binding. It is up to the application
 
115
/*      to passivate (flatten) and re-activate this content.
 
116
/*      upon storage and retrieval, respectively
 
117
/* .sp
 
118
/*      In case the of an SMTP logical destination to physical
 
119
/*      endpoint binding, the attributes specify the logical
 
120
/*      destination name, numerical port, whether the physical
 
121
/*      endpoint is best mx host with respect to a logical or
 
122
/*      fall-back destination, and when information expires.
 
123
/* .IP fd
 
124
/*      File descriptor with session to be cached.
 
125
/* DIAGNOSTICS
 
126
/*      scache_find_endp() and scache_find_dest() return -1 when
 
127
/*      the lookup fails, and a file descriptor upon success.
 
128
/*
 
129
/*      Other diagnostics: fatal error: memory allocation problem;
 
130
/*      panic: internal consistency failure.
 
131
/* SEE ALSO
 
132
/*      scache_single(3), single-session, in-memory cache
 
133
/*      scache_clnt(3), session cache client
 
134
/*      scache_multi(3), multi-session, in-memory cache
 
135
/* LICENSE
 
136
/* .ad
 
137
/* .fi
 
138
/*      The Secure Mailer license must be distributed with this software.
 
139
/* AUTHOR(S)
 
140
/*      Wietse Venema
 
141
/*      IBM T.J. Watson Research
 
142
/*      P.O. Box 704
 
143
/*      Yorktown Heights, NY 10598, USA
 
144
/*--*/
 
145
 
 
146
/* System library. */
 
147
 
 
148
#include <sys_defs.h>
 
149
#include <stdlib.h>
 
150
#include <unistd.h>
 
151
 
 
152
/* Utility library. */
 
153
 
 
154
#include <msg.h>
 
155
#include <vstream.h>
 
156
#include <vstring.h>
 
157
#include <vstring_vstream.h>
 
158
#include <argv.h>
 
159
#include <events.h>
 
160
 
 
161
/* Global library. */
 
162
 
 
163
#include <scache.h>
 
164
 
 
165
#ifdef TEST
 
166
 
 
167
 /*
 
168
  * Driver program for cache regression tests. Although all variants are
 
169
  * relatively simple to verify by hand for single session storage, more
 
170
  * sophisticated instrumentation is needed to demonstrate that the
 
171
  * multi-session cache manager properly handles collisions in the time
 
172
  * domain and in all the name space domains.
 
173
  */
 
174
static SCACHE *scache;
 
175
static VSTRING *endp_prop;
 
176
static VSTRING *dest_prop;
 
177
static int verbose_level = 3;
 
178
 
 
179
 /*
 
180
  * Cache mode lookup table. We don't do the client-server variant because
 
181
  * that drags in a ton of configuration junk; the client-server protocol is
 
182
  * relatively easy to verify manually.
 
183
  */
 
184
struct cache_type {
 
185
    char   *mode;
 
186
    SCACHE *(*create) (void);
 
187
};
 
188
 
 
189
static struct cache_type cache_types[] = {
 
190
    "single", scache_single_create,
 
191
    "multi", scache_multi_create,
 
192
    0,
 
193
};
 
194
 
 
195
#define STR(x) vstring_str(x)
 
196
 
 
197
/* cache_type - select session cache type */
 
198
 
 
199
static void cache_type(ARGV *argv)
 
200
{
 
201
    struct cache_type *cp;
 
202
 
 
203
    if (argv->argc != 2) {
 
204
        msg_error("usage: %s mode", argv->argv[0]);
 
205
        return;
 
206
    }
 
207
    if (scache != 0)
 
208
        scache_free(scache);
 
209
    for (cp = cache_types; cp->mode != 0; cp++) {
 
210
        if (strcmp(cp->mode, argv->argv[1]) == 0) {
 
211
            scache = cp->create();
 
212
            return;
 
213
        }
 
214
    }
 
215
    msg_error("unknown cache type: %s", argv->argv[1]);
 
216
}
 
217
 
 
218
/* handle_events - handle events while time advances */
 
219
 
 
220
static void handle_events(ARGV *argv)
 
221
{
 
222
    int     delay;
 
223
    time_t  before;
 
224
    time_t  after;
 
225
 
 
226
    if (argv->argc != 2 || (delay = atoi(argv->argv[1])) <= 0) {
 
227
        msg_error("usage: %s time", argv->argv[0]);
 
228
        return;
 
229
    }
 
230
    before = event_time();
 
231
    event_drain(delay);
 
232
    after = event_time();
 
233
    if (after < before + delay)
 
234
        sleep(before + delay - after);
 
235
}
 
236
 
 
237
/* save_endp - save endpoint->session binding */
 
238
 
 
239
static void save_endp(ARGV *argv)
 
240
{
 
241
    int     ttl;
 
242
    int     fd;
 
243
 
 
244
    if (argv->argc != 5
 
245
        || (ttl = atoi(argv->argv[1])) <= 0
 
246
        || (fd = atoi(argv->argv[4])) <= 0) {
 
247
        msg_error("usage: save_endp ttl endpoint endp_props fd");
 
248
        return;
 
249
    }
 
250
    if (DUP2(0, fd) < 0)
 
251
        msg_fatal("dup2(0, %d): %m", fd);
 
252
    scache_save_endp(scache, ttl, argv->argv[2], argv->argv[3], fd);
 
253
}
 
254
 
 
255
/* find_endp - find endpoint->session binding */
 
256
 
 
257
static void find_endp(ARGV *argv)
 
258
{
 
259
    int     fd;
 
260
 
 
261
    if (argv->argc != 2) {
 
262
        msg_error("usage: find_endp endpoint");
 
263
        return;
 
264
    }
 
265
    if ((fd = scache_find_endp(scache, argv->argv[1], endp_prop)) >= 0)
 
266
        close(fd);
 
267
}
 
268
 
 
269
/* save_dest - save destination->endpoint binding */
 
270
 
 
271
static void save_dest(ARGV *argv)
 
272
{
 
273
    int     ttl;
 
274
 
 
275
    if (argv->argc != 5 || (ttl = atoi(argv->argv[1])) <= 0) {
 
276
        msg_error("usage: save_dest ttl destination dest_props endpoint");
 
277
        return;
 
278
    }
 
279
    scache_save_dest(scache, ttl, argv->argv[2], argv->argv[3], argv->argv[4]);
 
280
}
 
281
 
 
282
/* find_dest - find destination->endpoint->session binding */
 
283
 
 
284
static void find_dest(ARGV *argv)
 
285
{
 
286
    int     fd;
 
287
 
 
288
    if (argv->argc != 2) {
 
289
        msg_error("usage: find_dest destination");
 
290
        return;
 
291
    }
 
292
    if ((fd = scache_find_dest(scache, argv->argv[1], dest_prop, endp_prop)) >= 0)
 
293
        close(fd);
 
294
}
 
295
 
 
296
/* verbose - adjust noise level during cache manipulation */
 
297
 
 
298
static void verbose(ARGV *argv)
 
299
{
 
300
    int     level;
 
301
 
 
302
    if (argv->argc != 2 || (level = atoi(argv->argv[1])) < 0) {
 
303
        msg_error("usage: verbose level");
 
304
        return;
 
305
    }
 
306
    verbose_level = level;
 
307
}
 
308
 
 
309
 /*
 
310
  * The command lookup table.
 
311
  */
 
312
struct action {
 
313
    char   *command;
 
314
    void    (*action) (ARGV *);
 
315
    int     flags;
 
316
};
 
317
 
 
318
#define FLAG_NEED_CACHE (1<<0)
 
319
 
 
320
static void help(ARGV *);
 
321
 
 
322
static struct action actions[] = {
 
323
    "cache_type", cache_type, 0,
 
324
    "save_endp", save_endp, FLAG_NEED_CACHE,
 
325
    "find_endp", find_endp, FLAG_NEED_CACHE,
 
326
    "save_dest", save_dest, FLAG_NEED_CACHE,
 
327
    "find_dest", find_dest, FLAG_NEED_CACHE,
 
328
    "sleep", handle_events, 0,
 
329
    "verbose", verbose, 0,
 
330
    "?", help, 0,
 
331
    0,
 
332
};
 
333
 
 
334
/* help - list commands */
 
335
 
 
336
static void help(ARGV *argv)
 
337
{
 
338
    struct action *ap;
 
339
 
 
340
    vstream_printf("commands:");
 
341
    for (ap = actions; ap->command != 0; ap++)
 
342
        vstream_printf(" %s", ap->command);
 
343
    vstream_printf("\n");
 
344
    vstream_fflush(VSTREAM_OUT);
 
345
}
 
346
 
 
347
/* get_buffer - prompt for input or log input */
 
348
 
 
349
static int get_buffer(VSTRING *buf, VSTREAM *fp, int interactive)
 
350
{
 
351
    int     status;
 
352
 
 
353
    if (interactive) {
 
354
        vstream_printf("> ");
 
355
        vstream_fflush(VSTREAM_OUT);
 
356
    }
 
357
    if ((status = vstring_get_nonl(buf, fp)) != VSTREAM_EOF) {
 
358
        if (!interactive) {
 
359
            vstream_printf(">>> %s\n", STR(buf));
 
360
            vstream_fflush(VSTREAM_OUT);
 
361
        }
 
362
    }
 
363
    return (status);
 
364
}
 
365
 
 
366
/* at last, the main program */
 
367
 
 
368
int     main(int unused_argc, char **unused_argv)
 
369
{
 
370
    VSTRING *buf = vstring_alloc(1);
 
371
    ARGV   *argv;
 
372
    struct action *ap;
 
373
    int     interactive = isatty(0);
 
374
 
 
375
    endp_prop = vstring_alloc(1);
 
376
    dest_prop = vstring_alloc(1);
 
377
 
 
378
    vstream_fileno(VSTREAM_ERR) = 1;
 
379
 
 
380
    while (get_buffer(buf, VSTREAM_IN, interactive) != VSTREAM_EOF) {
 
381
        argv = argv_split(STR(buf), " \t\r\n");
 
382
        if (argv->argc > 0 && argv->argv[0][0] != '#') {
 
383
            msg_verbose = verbose_level;
 
384
            for (ap = actions; ap->command != 0; ap++) {
 
385
                if (strcmp(ap->command, argv->argv[0]) == 0) {
 
386
                    if ((ap->flags & FLAG_NEED_CACHE) != 0 && scache == 0)
 
387
                        msg_error("no session cache");
 
388
                    else
 
389
                        ap->action(argv);
 
390
                    break;
 
391
                }
 
392
            }
 
393
            msg_verbose = 0;
 
394
            if (ap->command == 0)
 
395
                msg_error("bad command: %s", argv->argv[0]);
 
396
        }
 
397
        argv_free(argv);
 
398
    }
 
399
    scache_free(scache);
 
400
    vstring_free(endp_prop);
 
401
    vstring_free(dest_prop);
 
402
    vstring_free(buf);
 
403
    exit(0);
 
404
}
 
405
 
 
406
#endif