~ubuntu-branches/ubuntu/hoary/postfix/hoary-security

« back to all changes in this revision

Viewing changes to src/tlsmgr/tlsmgr.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-10-06 11:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20041006115033-9oky44ylqmhjy7eq
Tags: 2.1.3-1ubuntu17
* Deliver man pages for master.cf services in section 8postfix.
  Remove smtpd.8.gz diversion. Closes: #274777
* Clean up postfix-mysql documentation (created README.Debian files).
  Closes: Warty#2022
* Fix typo in postmap man page.  Closes: #271369

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifdef USE_TLS
 
2
/*++
 
3
/* NAME
 
4
/*      tlsmgr 8
 
5
/* SUMMARY
 
6
/*      Postfix TLS session cache and PRNG handling manager
 
7
/* SYNOPSIS
 
8
/*      \fBtlsmgr\fR [generic Postfix daemon options]
 
9
/* DESCRIPTION
 
10
/*      The tlsmgr process does housekeeping on the session cache database
 
11
/*      files. It runs through the databases and removes expired entries
 
12
/*      and entries written by older (incompatible) versions.
 
13
/*
 
14
/*      The tlsmgr is responsible for the PRNG handling. The used internal
 
15
/*      OpenSSL PRNG has a pool size of 8192 bits (= 1024 bytes). The pool
 
16
/*      is initially seeded at startup from an external source (EGD or
 
17
/*      /dev/urandom) and additional seed is obtained later during program
 
18
/*      run at a configurable period. The exact time of seed query is
 
19
/*      using random information and is equally distributed in the range of
 
20
/*      [0-\fBtls_random_reseed_period\fR] with a \fBtls_random_reseed_period\fR
 
21
/*      having a default of 1 hour.
 
22
/*
 
23
/*      Tlsmgr can be run chrooted and with dropped privileges, as it will
 
24
/*      connect to the entropy source at startup.
 
25
/*
 
26
/*      The PRNG is additionally seeded internally by the data found in the
 
27
/*      session cache and timevalues.
 
28
/*
 
29
/*      Tlsmgr reads the old value of the exchange file at startup to keep
 
30
/*      entropy already collected during previous runs.
 
31
/*
 
32
/*      From the PRNG random pool a cryptographically strong 1024 byte random
 
33
/*      sequence is written into the PRNG exchange file. The file is updated
 
34
/*      periodically with the time changing randomly from
 
35
/*      [0-\fBtls_random_prng_update_period\fR].
 
36
/* STANDARDS
 
37
/* SECURITY
 
38
/* .ad
 
39
/* .fi
 
40
/*      Tlsmgr is not security-sensitive. It only deals with external data
 
41
/*      to be fed into the PRNG, the contents is never trusted. The session
 
42
/*      cache housekeeping will only remove entries if expired and will never
 
43
/*      touch the contents of the cached data.
 
44
/* DIAGNOSTICS
 
45
/*      Problems and transactions are logged to the syslog daemon.
 
46
/* BUGS
 
47
/*      There is no automatic means to limit the number of entries in the
 
48
/*      session caches and/or the size of the session cache files.
 
49
/* CONFIGURATION PARAMETERS
 
50
/* .ad
 
51
/* .fi
 
52
/*      The following \fBmain.cf\fR parameters are especially relevant to
 
53
/*      this program. See the Postfix \fBmain.cf\fR file for syntax details
 
54
/*      and for default values. Use the \fBpostfix reload\fR command after
 
55
/*      a configuration change.
 
56
/* .SH Session Cache
 
57
/* .ad
 
58
/* .fi
 
59
/* .IP \fBsmtpd_tls_session_cache_database\fR
 
60
/*      Name of the SDBM file (type sdbm:) containing the SMTP server session
 
61
/*      cache. If the file does not exist, it is created.
 
62
/* .IP \fBsmtpd_tls_session_cache_timeout\fR
 
63
/*      Expiry time of SMTP server session cache entries in seconds. Entries
 
64
/*      older than this are removed from the session cache. A cleanup-run is
 
65
/*      performed periodically every \fBsmtpd_tls_session_cache_timeout\fR
 
66
/*      seconds. Default is 3600 (= 1 hour).
 
67
/* .IP \fBsmtp_tls_session_cache_database\fR
 
68
/*      Name of the SDBM file (type sdbm:) containing the SMTP client session
 
69
/*      cache. If the file does not exist, it is created.
 
70
/* .IP \fBsmtp_tls_session_cache_timeout\fR
 
71
/*      Expiry time of SMTP client session cache entries in seconds. Entries
 
72
/*      older than this are removed from the session cache. A cleanup-run is
 
73
/*      performed periodically every \fBsmtp_tls_session_cache_timeout\fR
 
74
/*      seconds. Default is 3600 (= 1 hour).
 
75
/* .SH Pseudo Random Number Generator
 
76
/* .ad
 
77
/* .fi
 
78
/* .IP \fBtls_random_source\fR
 
79
/*      Name of the EGD socket or device or regular file to obtain entropy
 
80
/*      from. The type of entropy source must be specified by preceding the
 
81
/*      name with the appropriate type: egd:/path/to/egd_socket,
 
82
/*      dev:/path/to/devicefile, or /path/to/regular/file.
 
83
/*      tlsmgr opens \fBtls_random_source\fR and tries to read
 
84
/*      \fBtls_random_bytes\fR from it.
 
85
/* .IP \fBtls_random_bytes\fR
 
86
/*      Number of bytes to be read from \fBtls_random_source\fR.
 
87
/*      Default value is 32 bytes. If using EGD, a maximum of 255 bytes is read.
 
88
/* .IP \fBtls_random_exchange_name\fR
 
89
/*      Name of the file written by tlsmgr and read by smtp and smtpd at
 
90
/*      startup. The length is 1024 bytes. Default value is
 
91
/*      /etc/postfix/prng_exch.
 
92
/* .IP \fBtls_random_reseed_period\fR
 
93
/*      Time in seconds until the next reseed from external sources is due.
 
94
/*      This is the maximum value. The actual point in time is calculated
 
95
/*      with a random factor equally distributed between 0 and this maximum
 
96
/*      value. Default is 3600 (= 60 minutes).
 
97
/* .IP \fBtls_random_prng_update_period\fR
 
98
/*      Time in seconds until the PRNG exchange file is updated with new
 
99
/*      pseude random values. This is the maximum value. The actual point
 
100
/*      in time is calculated with a random factor equally distributed
 
101
/*      between 0 and this maximum value. Default is 60 (= 1 minute).
 
102
/* SEE ALSO
 
103
/*      smtp(8) SMTP client
 
104
/*      smtpd(8) SMTP server
 
105
/* LICENSE
 
106
/* .ad
 
107
/* .fi
 
108
/*      The Secure Mailer license must be distributed with this software.
 
109
/* AUTHOR(S)
 
110
/*--*/
 
111
 
 
112
/* System library. */
 
113
 
 
114
#include <sys_defs.h>
 
115
#include <stdlib.h>
 
116
#include <unistd.h>
 
117
#include <ctype.h>
 
118
#include <errno.h>
 
119
#include <string.h>
 
120
#include <sys/time.h>                   /* gettimeofday, not POSIX */
 
121
 
 
122
/* OpenSSL library. */
 
123
#ifdef USE_SSL
 
124
#include <openssl/rand.h>               /* For the PRNG */
 
125
#endif
 
126
 
 
127
/* Utility library. */
 
128
 
 
129
#include <msg.h>
 
130
#include <events.h>
 
131
#include <dict.h>
 
132
#include <stringops.h>
 
133
#include <mymalloc.h>
 
134
#include <connect.h>
 
135
#include <myflock.h>
 
136
 
 
137
/* Global library. */
 
138
 
 
139
#include <mail_conf.h>
 
140
#include <mail_params.h>
 
141
#include <pfixtls.h>
 
142
 
 
143
/* Master process interface */
 
144
 
 
145
#include <master_proto.h>
 
146
#include <mail_server.h>
 
147
 
 
148
/* Application-specific. */
 
149
 
 
150
#ifdef USE_SSL
 
151
 /*
 
152
  * Tunables.
 
153
  */
 
154
char   *var_tls_rand_source;
 
155
int     var_tls_rand_bytes;
 
156
int     var_tls_reseed_period;
 
157
int     var_tls_prng_upd_period;
 
158
 
 
159
static int rand_exch_fd;
 
160
static int rand_source_dev_fd = -1;
 
161
static int rand_source_socket_fd = -1;
 
162
static int srvr_scache_db_active;
 
163
static int clnt_scache_db_active;
 
164
static DICT *srvr_scache_db = NULL;
 
165
static DICT *clnt_scache_db = NULL;
 
166
 
 
167
static void tlsmgr_prng_upd_event(int unused_event, char *dummy)
 
168
{
 
169
    struct timeval tv;
 
170
    unsigned char buffer[1024];
 
171
    int next_period;
 
172
 
 
173
    /*
 
174
     * It is time to update the PRNG exchange file. Since other processes might
 
175
     * have added entropy, we do this in a read_stir-back_write cycle.
 
176
     */
 
177
    GETTIMEOFDAY(&tv);
 
178
    RAND_seed(&tv, sizeof(struct timeval));
 
179
 
 
180
    if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0)
 
181
        msg_fatal("Could not lock random exchange file: %s",
 
182
                  strerror(errno));
 
183
 
 
184
    lseek(rand_exch_fd, 0, SEEK_SET);
 
185
    if (read(rand_exch_fd, buffer, 1024) < 0)
 
186
        msg_fatal("reading exchange file failed");
 
187
    RAND_seed(buffer, 1024);
 
188
 
 
189
    RAND_bytes(buffer, 1024);
 
190
    lseek(rand_exch_fd, 0, SEEK_SET);
 
191
    if (write(rand_exch_fd, buffer, 1024) != 1024)
 
192
        msg_fatal("Writing exchange file failed");
 
193
 
 
194
    if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0)
 
195
        msg_fatal("Could not unlock random exchange file: %s",
 
196
                  strerror(errno));
 
197
 
 
198
    /*
 
199
     * Make prediction difficult for outsiders and calculate the time for the
 
200
     * next execution randomly.
 
201
     */
 
202
    next_period = (var_tls_prng_upd_period * buffer[0]) / 255;
 
203
    event_request_timer(tlsmgr_prng_upd_event, dummy, next_period);
 
204
}
 
205
 
 
206
 
 
207
static void tlsmgr_reseed_event(int unused_event, char *dummy)
 
208
{
 
209
    int egd_success;
 
210
    int next_period;
 
211
    int rand_bytes;
 
212
    char buffer[255];
 
213
    struct timeval tv;
 
214
    unsigned char randbyte;
 
215
 
 
216
    /*
 
217
     * It is time to reseed the PRNG.
 
218
     */
 
219
 
 
220
    GETTIMEOFDAY(&tv);
 
221
    RAND_seed(&tv, sizeof(struct timeval));
 
222
    if (rand_source_dev_fd != -1) {
 
223
        rand_bytes = read(rand_source_dev_fd, buffer, var_tls_rand_bytes);
 
224
        if (rand_bytes > 0)
 
225
            RAND_seed(buffer, rand_bytes);
 
226
        else if (rand_bytes < 0) {
 
227
            msg_fatal("Read from entropy device %s failed",
 
228
                      var_tls_rand_source);
 
229
        }
 
230
    } else if (rand_source_socket_fd != -1) {
 
231
        egd_success = 0;
 
232
        buffer[0] = 1;
 
233
        buffer[1] = var_tls_rand_bytes;
 
234
        if (write(rand_source_socket_fd, buffer, 2) != 2)
 
235
            msg_info("Could not talk to %s", var_tls_rand_source);
 
236
        else if (read(rand_source_socket_fd, buffer, 1) != 1)
 
237
            msg_info("Could not read info from %s", var_tls_rand_source);
 
238
        else {
 
239
            rand_bytes = buffer[0];
 
240
            if (read(rand_source_socket_fd, buffer, rand_bytes) != rand_bytes)
 
241
                msg_info("Could not read data from %s", var_tls_rand_source);
 
242
            else {
 
243
                egd_success = 1;
 
244
                RAND_seed(buffer, rand_bytes);
 
245
            }
 
246
        }
 
247
        if (!egd_success) {
 
248
            msg_info("Lost connection to EGD-device, exiting to reconnect.");
 
249
            exit(0);
 
250
        }
 
251
    } else if (*var_tls_rand_source) {
 
252
        rand_bytes = RAND_load_file(var_tls_rand_source, var_tls_rand_bytes);
 
253
    }
 
254
 
 
255
    /*
 
256
     * Make prediction difficult for outsiders and calculate the time for the
 
257
     * next execution randomly.
 
258
     */
 
259
    RAND_bytes(&randbyte, 1);
 
260
    next_period = (var_tls_reseed_period * randbyte) / 255;
 
261
    event_request_timer(tlsmgr_reseed_event, dummy, next_period);
 
262
}
 
263
 
 
264
 
 
265
static int tlsmgr_do_scache_check(DICT *scache_db, int scache_timeout,
 
266
                                  int start)
 
267
{
 
268
    int func;
 
269
    int len;
 
270
    int n;
 
271
    int delete = 0;
 
272
    int result;
 
273
    struct timeval tv;
 
274
    const char *member;
 
275
    const char *value;
 
276
    char *member_copy;
 
277
    unsigned char nibble, *data;
 
278
    pfixtls_scache_info_t scache_info;
 
279
 
 
280
    GETTIMEOFDAY(&tv);
 
281
    RAND_seed(&tv, sizeof(struct timeval));
 
282
 
 
283
    /*
 
284
     * Run through the given dictionary and check the stored sessions.
 
285
     * If "start" is set to 1, a new run is initiated, otherwise the next
 
286
     * item is accessed. The state is internally kept in the DICT.
 
287
     */
 
288
    if (start)
 
289
        func = DICT_SEQ_FUN_FIRST;
 
290
    else
 
291
        func = DICT_SEQ_FUN_NEXT;
 
292
    result = dict_seq(scache_db, func, &member, &value);
 
293
 
 
294
    if (result > 0)
 
295
        return 0;       /* End of list reached */
 
296
    else if (result < 0)
 
297
        msg_fatal("Database fault, should already be caught.");
 
298
    else {
 
299
        member_copy = mystrdup(member);
 
300
        len = strlen(value);
 
301
        RAND_seed(value, len);          /* Use it to increase entropy */
 
302
        if (len < 2 * sizeof(pfixtls_scache_info_t))
 
303
            delete = 1;         /* Messed up, delete */
 
304
        else if (len > 2 * sizeof(pfixtls_scache_info_t))
 
305
            len = 2 * sizeof(pfixtls_scache_info_t);
 
306
        if (!delete) {
 
307
            data = (unsigned char *)(&scache_info);
 
308
            memset(data, 0, len / 2);
 
309
            for (n = 0; n < len; n++) {
 
310
            if ((value[n] >= '0') && (value[n] <= '9'))
 
311
                nibble = value[n] - '0';
 
312
            else
 
313
                nibble = value[n] - 'A' + 10;
 
314
            if (n % 2)
 
315
                data[n / 2] |= nibble;
 
316
            else
 
317
                data[n / 2] |= (nibble << 4);
 
318
        }
 
319
 
 
320
        if ((scache_info.scache_db_version != scache_db_version) ||
 
321
            (scache_info.openssl_version != openssl_version) ||
 
322
            (scache_info.timestamp + scache_timeout < time(NULL)))
 
323
            delete = 1;
 
324
        }
 
325
        if (delete)
 
326
            result = dict_del(scache_db, member_copy);
 
327
        myfree(member_copy);
 
328
    }
 
329
 
 
330
    if (delete && result)
 
331
        msg_info("Could not delete %s", member);
 
332
    return 1;
 
333
 
 
334
}
 
335
 
 
336
static void tlsmgr_clnt_cache_run_event(int unused_event, char *dummy)
 
337
{
 
338
 
 
339
    /*
 
340
     * This routine runs when it is time for another tls session cache scan.
 
341
     * Make sure this routine gets called again in the future.
 
342
     */
 
343
    clnt_scache_db_active = tlsmgr_do_scache_check(clnt_scache_db, 
 
344
                                var_smtp_tls_scache_timeout, 1);
 
345
    event_request_timer(tlsmgr_clnt_cache_run_event, dummy,
 
346
                 var_smtp_tls_scache_timeout);
 
347
}
 
348
 
 
349
 
 
350
static void tlsmgr_srvr_cache_run_event(int unused_event, char *dummy)
 
351
{
 
352
 
 
353
    /*
 
354
     * This routine runs when it is time for another tls session cache scan.
 
355
     * Make sure this routine gets called again in the future.
 
356
     */
 
357
    srvr_scache_db_active = tlsmgr_do_scache_check(srvr_scache_db,
 
358
                                var_smtpd_tls_scache_timeout, 1);
 
359
    event_request_timer(tlsmgr_srvr_cache_run_event, dummy,
 
360
                 var_smtpd_tls_scache_timeout);
 
361
}
 
362
 
 
363
 
 
364
static DICT *tlsmgr_cache_open(const char *dbname)
 
365
{
 
366
    DICT *retval;
 
367
    char *dbpagname;
 
368
    char *dbdirname;
 
369
 
 
370
    /*
 
371
     * First, try to find out the real name of the database file, so that
 
372
     * it can be removed.
 
373
     */
 
374
    if (!strncmp(dbname, "sdbm:", 5)) {
 
375
        dbpagname = concatenate(dbname + 5, ".pag", NULL);
 
376
        REMOVE(dbpagname);
 
377
        myfree(dbpagname);
 
378
        dbdirname = concatenate(dbname + 5, ".dir", NULL);
 
379
        REMOVE(dbdirname);
 
380
        myfree(dbdirname);
 
381
    }
 
382
    else {
 
383
        msg_warn("Only type sdbm: supported: %s", dbname);
 
384
        return NULL;
 
385
    }
 
386
 
 
387
    /*
 
388
     * Now open the dictionary. Do it with O_EXCL, so that we only open a
 
389
     * fresh file. If we cannot open it with a fresh file, then we won't
 
390
     * touch it.
 
391
     */
 
392
    retval = dict_open(dbname, O_RDWR | O_CREAT | O_EXCL,
 
393
              DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE);
 
394
    if (!retval)
 
395
        msg_warn("Could not create dictionary %s", dbname);
 
396
    return retval;
 
397
}
 
398
 
 
399
/* tlsmgr_trigger_event - respond to external trigger(s) */
 
400
 
 
401
static void tlsmgr_trigger_event(char *buf, int len,
 
402
                                       char *unused_service, char **argv)
 
403
{
 
404
    /*
 
405
     * Sanity check. This service takes no command-line arguments.
 
406
     */
 
407
    if (argv[0])
 
408
        msg_fatal("unexpected command-line argument: %s", argv[0]);
 
409
 
 
410
}
 
411
 
 
412
/* tlsmgr_loop - queue manager main loop */
 
413
 
 
414
static int tlsmgr_loop(char *unused_name, char **unused_argv)
 
415
{
 
416
    /*
 
417
     * This routine runs as part of the event handling loop, after the event
 
418
     * manager has delivered a timer or I/O event (including the completion
 
419
     * of a connection to a delivery process), or after it has waited for a
 
420
     * specified amount of time. The result value of qmgr_loop() specifies
 
421
     * how long the event manager should wait for the next event.
 
422
     */
 
423
#define DONT_WAIT       0
 
424
#define WAIT_FOR_EVENT  (-1)
 
425
 
 
426
    if (clnt_scache_db_active)
 
427
        clnt_scache_db_active = tlsmgr_do_scache_check(clnt_scache_db,
 
428
                                        var_smtp_tls_scache_timeout, 0);
 
429
    if (srvr_scache_db_active)
 
430
        srvr_scache_db_active = tlsmgr_do_scache_check(srvr_scache_db,
 
431
                                        var_smtpd_tls_scache_timeout, 0);
 
432
    if (clnt_scache_db_active || srvr_scache_db_active)
 
433
        return (DONT_WAIT);
 
434
    return (WAIT_FOR_EVENT);
 
435
}
 
436
 
 
437
/* pre_accept - see if tables have changed */
 
438
 
 
439
static void pre_accept(char *unused_name, char **unused_argv)
 
440
{
 
441
    if (dict_changed()) {
 
442
        msg_info("table has changed -- exiting");
 
443
        exit(0);
 
444
    }
 
445
}
 
446
 
 
447
/* tlsmgr_pre_init - pre-jail initialization */
 
448
 
 
449
static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
 
450
{
 
451
    int rand_bytes;
 
452
    unsigned char buffer[255];
 
453
 
 
454
    /*
 
455
     * Access the external sources for random seed. We may not be able to
 
456
     * access them again if we are sent to chroot jail, so we must leave
 
457
     * dev: and egd: type sources open.
 
458
     */
 
459
    if (*var_tls_rand_source) {
 
460
        if (!strncmp(var_tls_rand_source, "dev:", 4)) {
 
461
            /*
 
462
             * Source is a random device
 
463
             */
 
464
            rand_source_dev_fd = open(var_tls_rand_source + 4, 0, 0);
 
465
            if (rand_source_dev_fd == -1) 
 
466
                msg_fatal("Could not open entropy device %s",
 
467
                          var_tls_rand_source);
 
468
            if (var_tls_rand_bytes > 255)
 
469
                var_tls_rand_bytes = 255;
 
470
            rand_bytes = read(rand_source_dev_fd, buffer, var_tls_rand_bytes);
 
471
            RAND_seed(buffer, rand_bytes);
 
472
        } else if (!strncmp(var_tls_rand_source, "egd:", 4)) {
 
473
            /*
 
474
             * Source is a EGD compatible socket
 
475
             */
 
476
            rand_source_socket_fd = unix_connect(var_tls_rand_source +4,
 
477
                                                 BLOCKING, 10);
 
478
            if (rand_source_socket_fd == -1)
 
479
                msg_fatal("Could not connect to %s", var_tls_rand_source);
 
480
            if (var_tls_rand_bytes > 255)
 
481
                var_tls_rand_bytes = 255;
 
482
            buffer[0] = 1;
 
483
            buffer[1] = var_tls_rand_bytes;
 
484
            if (write(rand_source_socket_fd, buffer, 2) != 2)
 
485
                msg_fatal("Could not talk to %s", var_tls_rand_source);
 
486
            if (read(rand_source_socket_fd, buffer, 1) != 1)
 
487
                msg_fatal("Could not read info from %s", var_tls_rand_source);
 
488
            rand_bytes = buffer[0];
 
489
            if (read(rand_source_socket_fd, buffer, rand_bytes) != rand_bytes)
 
490
                msg_fatal("Could not read data from %s", var_tls_rand_source);
 
491
            RAND_seed(buffer, rand_bytes);
 
492
        } else {
 
493
            rand_bytes = RAND_load_file(var_tls_rand_source,
 
494
                                        var_tls_rand_bytes);
 
495
        }
 
496
    }
 
497
 
 
498
    /*
 
499
     * Now open the PRNG exchange file
 
500
     */
 
501
    if (*var_tls_rand_exch_name) {
 
502
        rand_exch_fd = open(var_tls_rand_exch_name, O_RDWR | O_CREAT, 0600);
 
503
    }
 
504
 
 
505
    /*
 
506
     * Finally, open the session cache files. Remove old files, if still there.
 
507
     * If we could not remove the old files, something is pretty wrong and we
 
508
     * won't touch it!!
 
509
     */
 
510
    if (*var_smtp_tls_scache_db)
 
511
        clnt_scache_db = tlsmgr_cache_open(var_smtp_tls_scache_db);
 
512
    if (*var_smtpd_tls_scache_db)
 
513
        srvr_scache_db = tlsmgr_cache_open(var_smtpd_tls_scache_db);
 
514
}
 
515
 
 
516
/* qmgr_post_init - post-jail initialization */
 
517
 
 
518
static void tlsmgr_post_init(char *unused_name, char **unused_argv)
 
519
{
 
520
    unsigned char buffer[1024];
 
521
 
 
522
    /*
 
523
     * This routine runs after the skeleton code has entered the chroot jail.
 
524
     * Prevent automatic process suicide after a limited number of client
 
525
     * requests or after a limited amount of idle time.
 
526
     */
 
527
    var_use_limit = 0;
 
528
    var_idle_limit = 0;
 
529
 
 
530
    /*
 
531
     * Complete thie initialization by reading the additional seed from the
 
532
     * PRNG exchange file. Don't care how many bytes were actually read, just
 
533
     * seed buffer into the PRNG, regardless of its contents.
 
534
     */
 
535
    if (rand_exch_fd >= 0) {
 
536
        if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) == -1)
 
537
            msg_fatal("Could not lock random exchange file: %s",
 
538
                      strerror(errno));
 
539
        read(rand_exch_fd, buffer, 1024);
 
540
        if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) == -1)
 
541
            msg_fatal("Could not unlock random exchange file: %s",
 
542
                      strerror(errno));
 
543
        RAND_seed(buffer, 1024);
 
544
        tlsmgr_prng_upd_event(0, (char *) 0);
 
545
        tlsmgr_reseed_event(0, (char *) 0);
 
546
    }
 
547
 
 
548
    clnt_scache_db_active = 0;
 
549
    srvr_scache_db_active = 0;
 
550
    if (clnt_scache_db)
 
551
        tlsmgr_clnt_cache_run_event(0, (char *) 0);
 
552
    if (srvr_scache_db)
 
553
        tlsmgr_srvr_cache_run_event(0, (char *) 0);
 
554
}
 
555
 
 
556
 
 
557
/* main - the main program */
 
558
 
 
559
int     main(int argc, char **argv)
 
560
{
 
561
    static CONFIG_STR_TABLE str_table[] = {
 
562
        VAR_TLS_RAND_SOURCE, DEF_TLS_RAND_SOURCE, &var_tls_rand_source, 0, 0,
 
563
        0,
 
564
    };
 
565
    static CONFIG_TIME_TABLE time_table[] = {
 
566
        VAR_TLS_RESEED_PERIOD, DEF_TLS_RESEED_PERIOD, &var_tls_reseed_period, 0, 0,
 
567
        VAR_TLS_PRNG_UPD_PERIOD, DEF_TLS_PRNG_UPD_PERIOD, &var_tls_prng_upd_period, 0, 0,
 
568
        0,
 
569
    };
 
570
    static CONFIG_INT_TABLE int_table[] = {
 
571
        VAR_TLS_RAND_BYTES, DEF_TLS_RAND_BYTES, &var_tls_rand_bytes, 0, 0,
 
572
        0,
 
573
    };
 
574
 
 
575
    /*
 
576
     * Use the trigger service skeleton, because no-one else should be
 
577
     * monitoring our service port while this process runs, and because we do
 
578
     * not talk back to the client.
 
579
     */
 
580
    trigger_server_main(argc, argv, tlsmgr_trigger_event,
 
581
                        MAIL_SERVER_TIME_TABLE, time_table,
 
582
                        MAIL_SERVER_INT_TABLE, int_table,
 
583
                        MAIL_SERVER_STR_TABLE, str_table,
 
584
                        MAIL_SERVER_PRE_INIT, tlsmgr_pre_init,
 
585
                        MAIL_SERVER_POST_INIT, tlsmgr_post_init,
 
586
                        MAIL_SERVER_LOOP, tlsmgr_loop,
 
587
                        MAIL_SERVER_PRE_ACCEPT, pre_accept,
 
588
                        0);
 
589
    trigger_server_main(argc, argv, tlsmgr_trigger_event,
 
590
                        MAIL_SERVER_PRE_INIT, tlsmgr_pre_init,
 
591
                        0);
 
592
}
 
593
 
 
594
#else
 
595
int     main(int argc, char **argv)
 
596
{
 
597
    msg_fatal("Do not run tlsmgr with TLS support compiled in\n");
 
598
}
 
599
#endif
 
600
#endif