source: trunk/third/sendmail/sendmail/tls.c @ 19204

Revision 19204, 35.4 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
3 *      All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sendmail.h>
12
13SM_RCSID("@(#)$Id: tls.c,v 1.1.1.1 2003-04-08 15:09:14 zacheiss Exp $")
14
15#if STARTTLS
16#  include <openssl/err.h>
17#  include <openssl/bio.h>
18#  include <openssl/pem.h>
19#  ifndef HASURANDOMDEV
20#   include <openssl/rand.h>
21#  endif /* ! HASURANDOMDEV */
22# if !TLS_NO_RSA
23static RSA *rsa_tmp = NULL;     /* temporary RSA key */
24static RSA *tmp_rsa_key __P((SSL *, int, int));
25# endif /* !TLS_NO_RSA */
26#  if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L
27static int      tls_verify_cb __P((X509_STORE_CTX *));
28#  else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
29static int      tls_verify_cb __P((X509_STORE_CTX *, void *));
30#  endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
31
32# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L
33#  define CONST097
34# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
35#  define CONST097 const
36# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
37static void     apps_ssl_info_cb __P((CONST097 SSL *, int , int));
38
39# if !NO_DH
40static DH *get_dh512 __P((void));
41
42static unsigned char dh512_p[] =
43{
44        0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
45        0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
46        0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
47        0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
48        0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
49        0x47,0x74,0xE8,0x33
50};
51static unsigned char dh512_g[] =
52{
53        0x02
54};
55
56static DH *
57get_dh512()
58{
59        DH *dh = NULL;
60
61        if ((dh = DH_new()) == NULL)
62                return NULL;
63        dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
64        dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
65        if ((dh->p == NULL) || (dh->g == NULL))
66                return NULL;
67        return dh;
68}
69# endif /* !NO_DH */
70
71
72/*
73**  TLS_RAND_INIT -- initialize STARTTLS random generator
74**
75**      Parameters:
76**              randfile -- name of file with random data
77**              logl -- loglevel
78**
79**      Returns:
80**              success/failure
81**
82**      Side Effects:
83**              initializes PRNG for tls library.
84*/
85
86# define MIN_RAND_BYTES 128     /* 1024 bits */
87
88# define RF_OK          0       /* randfile OK */
89# define RF_MISS        1       /* randfile == NULL || *randfile == '\0' */
90# define RF_UNKNOWN     2       /* unknown prefix for randfile */
91
92# define RI_NONE        0       /* no init yet */
93# define RI_SUCCESS     1       /* init was successful */
94# define RI_FAIL        2       /* init failed */
95
96static bool     tls_rand_init __P((char *, int));
97
98static bool
99tls_rand_init(randfile, logl)
100        char *randfile;
101        int logl;
102{
103# ifndef HASURANDOMDEV
104        /* not required if /dev/urandom exists, OpenSSL does it internally */
105
106        bool ok;
107        int randdef;
108        static int done = RI_NONE;
109
110        /*
111        **  initialize PRNG
112        */
113
114        /* did we try this before? if yes: return old value */
115        if (done != RI_NONE)
116                return done == RI_SUCCESS;
117
118        /* set default values */
119        ok = false;
120        done = RI_FAIL;
121        randdef = (randfile == NULL || *randfile == '\0') ? RF_MISS : RF_OK;
122#   if EGD
123        if (randdef == RF_OK && sm_strncasecmp(randfile, "egd:", 4) == 0)
124        {
125                randfile += 4;
126                if (RAND_egd(randfile) < 0)
127                {
128                        sm_syslog(LOG_WARNING, NOQID,
129                                  "STARTTLS: RAND_egd(%s) failed: random number generator not seeded",
130                                   randfile);
131                }
132                else
133                        ok = true;
134        }
135        else
136#   endif /* EGD */
137        if (randdef == RF_OK && sm_strncasecmp(randfile, "file:", 5) == 0)
138        {
139                int fd;
140                long sff;
141                struct stat st;
142
143                randfile += 5;
144                sff = SFF_SAFEDIRPATH | SFF_NOWLINK
145                      | SFF_NOGWFILES | SFF_NOWWFILES
146                      | SFF_NOGRFILES | SFF_NOWRFILES
147                      | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT;
148                if (DontLockReadFiles)
149                        sff |= SFF_NOLOCK;
150                if ((fd = safeopen(randfile, O_RDONLY, 0, sff)) >= 0)
151                {
152                        if (fstat(fd, &st) < 0)
153                        {
154                                if (LogLevel > logl)
155                                        sm_syslog(LOG_ERR, NOQID,
156                                                  "STARTTLS: can't fstat(%s)",
157                                                  randfile);
158                        }
159                        else
160                        {
161                                bool use, problem;
162
163                                use = true;
164                                problem = false;
165
166                                /* max. age of file: 10 minutes */
167                                if (st.st_mtime + 600 < curtime())
168                                {
169                                        use = bitnset(DBS_INSUFFICIENTENTROPY,
170                                                      DontBlameSendmail);
171                                        problem = true;
172                                        if (LogLevel > logl)
173                                                sm_syslog(LOG_ERR, NOQID,
174                                                          "STARTTLS: RandFile %s too old: %s",
175                                                          randfile,
176                                                          use ? "unsafe" :
177                                                                "unusable");
178                                }
179                                if (use && st.st_size < MIN_RAND_BYTES)
180                                {
181                                        use = bitnset(DBS_INSUFFICIENTENTROPY,
182                                                      DontBlameSendmail);
183                                        problem = true;
184                                        if (LogLevel > logl)
185                                                sm_syslog(LOG_ERR, NOQID,
186                                                          "STARTTLS: size(%s) < %d: %s",
187                                                          randfile,
188                                                          MIN_RAND_BYTES,
189                                                          use ? "unsafe" :
190                                                                "unusable");
191                                }
192                                if (use)
193                                        ok = RAND_load_file(randfile, -1) >=
194                                             MIN_RAND_BYTES;
195                                if (use && !ok)
196                                {
197                                        if (LogLevel > logl)
198                                                sm_syslog(LOG_WARNING, NOQID,
199                                                          "STARTTLS: RAND_load_file(%s) failed: random number generator not seeded",
200                                                          randfile);
201                                }
202                                if (problem)
203                                        ok = false;
204                        }
205                        if (ok || bitnset(DBS_INSUFFICIENTENTROPY,
206                                          DontBlameSendmail))
207                        {
208                                /* add this even if fstat() failed */
209                                RAND_seed((void *) &st, sizeof st);
210                        }
211                        (void) close(fd);
212                }
213                else
214                {
215                        if (LogLevel > logl)
216                                sm_syslog(LOG_WARNING, NOQID,
217                                          "STARTTLS: Warning: safeopen(%s) failed",
218                                          randfile);
219                }
220        }
221        else if (randdef == RF_OK)
222        {
223                if (LogLevel > logl)
224                        sm_syslog(LOG_WARNING, NOQID,
225                                  "STARTTLS: Error: no proper random file definition %s",
226                                  randfile);
227                randdef = RF_UNKNOWN;
228        }
229        if (randdef == RF_MISS)
230        {
231                if (LogLevel > logl)
232                        sm_syslog(LOG_WARNING, NOQID,
233                                  "STARTTLS: Error: missing random file definition");
234        }
235        if (!ok && bitnset(DBS_INSUFFICIENTENTROPY, DontBlameSendmail))
236        {
237                int i;
238                long r;
239                unsigned char buf[MIN_RAND_BYTES];
240
241                /* assert((MIN_RAND_BYTES % sizeof(long)) == 0); */
242                for (i = 0; i <= sizeof(buf) - sizeof(long); i += sizeof(long))
243                {
244                        r = get_random();
245                        (void) memcpy(buf + i, (void *) &r, sizeof(long));
246                }
247                RAND_seed(buf, sizeof buf);
248                if (LogLevel > logl)
249                        sm_syslog(LOG_WARNING, NOQID,
250                                  "STARTTLS: Warning: random number generator not properly seeded");
251                ok = true;
252        }
253        done = ok ? RI_SUCCESS : RI_FAIL;
254        return ok;
255# else /* ! HASURANDOMDEV */
256        return true;
257# endif /* ! HASURANDOMDEV */
258}
259/*
260**  INIT_TLS_LIBRARY -- Calls functions which setup TLS library for global use.
261**
262**      Parameters:
263**              none.
264**
265**      Returns:
266**              succeeded?
267*/
268
269bool
270init_tls_library()
271{
272        /* basic TLS initialization, ignore result for now */
273        SSL_library_init();
274        SSL_load_error_strings();
275# if 0
276        /* this is currently a macro for SSL_library_init */
277        SSLeay_add_ssl_algorithms();
278# endif /* 0 */
279
280        return tls_rand_init(RandFile, 7);
281}
282/*
283**  TLS_SET_VERIFY -- request client certificate?
284**
285**      Parameters:
286**              ctx -- TLS context
287**              ssl -- TLS structure
288**              vrfy -- require certificate?
289**
290**      Returns:
291**              none.
292**
293**      Side Effects:
294**              Sets verification state for TLS
295**
296# if TLS_VRFY_PER_CTX
297**      Notice:
298**              This is per TLS context, not per TLS structure;
299**              the former is global, the latter per connection.
300**              It would be nice to do this per connection, but this
301**              doesn't work in the current TLS libraries :-(
302# endif * TLS_VRFY_PER_CTX *
303*/
304
305void
306tls_set_verify(ctx, ssl, vrfy)
307        SSL_CTX *ctx;
308        SSL *ssl;
309        bool vrfy;
310{
311# if !TLS_VRFY_PER_CTX
312        SSL_set_verify(ssl, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
313# else /* !TLS_VRFY_PER_CTX */
314        SSL_CTX_set_verify(ctx, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE,
315                        NULL);
316# endif /* !TLS_VRFY_PER_CTX */
317}
318
319/*
320**  status in initialization
321**  these flags keep track of the status of the initialization
322**  i.e., whether a file exists (_EX) and whether it can be used (_OK)
323**  [due to permissions]
324*/
325
326# define TLS_S_NONE     0x00000000      /* none yet */
327# define TLS_S_CERT_EX  0x00000001      /* cert file exists */
328# define TLS_S_CERT_OK  0x00000002      /* cert file is ok */
329# define TLS_S_KEY_EX   0x00000004      /* key file exists */
330# define TLS_S_KEY_OK   0x00000008      /* key file is ok */
331# define TLS_S_CERTP_EX 0x00000010      /* CA cert path exists */
332# define TLS_S_CERTP_OK 0x00000020      /* CA cert path is ok */
333# define TLS_S_CERTF_EX 0x00000040      /* CA cert file exists */
334# define TLS_S_CERTF_OK 0x00000080      /* CA cert file is ok */
335
336# if _FFR_TLS_1
337#  define TLS_S_CERT2_EX        0x00001000      /* 2nd cert file exists */
338#  define TLS_S_CERT2_OK        0x00002000      /* 2nd cert file is ok */
339#  define TLS_S_KEY2_EX 0x00004000      /* 2nd key file exists */
340#  define TLS_S_KEY2_OK 0x00008000      /* 2nd key file is ok */
341# endif /* _FFR_TLS_1 */
342
343# define TLS_S_DH_OK    0x00200000      /* DH cert is ok */
344# define TLS_S_DHPAR_EX 0x00400000      /* DH param file exists */
345# define TLS_S_DHPAR_OK 0x00800000      /* DH param file is ok to use */
346
347/*
348**  TLS_OK_F -- can var be an absolute filename?
349**
350**      Parameters:
351**              var -- filename
352**              fn -- what is the filename used for?
353**              srv -- server side?
354**
355**      Returns:
356**              ok?
357*/
358
359static bool
360tls_ok_f(var, fn, srv)
361        char *var;
362        char *fn;
363        bool srv;
364{
365        /* must be absolute pathname */
366        if (var != NULL && *var == '/')
367                return true;
368        if (LogLevel > 12)
369                sm_syslog(LOG_WARNING, NOQID, "STARTTLS: %s%s missing",
370                          srv ? "Server" : "Client", fn);
371        return false;
372}
373/*
374**  TLS_SAFE_F -- is a file safe to use?
375**
376**      Parameters:
377**              var -- filename
378**              sff -- flags for safefile()
379**              srv -- server side?
380**
381**      Returns:
382**              ok?
383*/
384
385static bool
386tls_safe_f(var, sff, srv)
387        char *var;
388        long sff;
389        bool srv;
390{
391        int ret;
392
393        if ((ret = safefile(var, RunAsUid, RunAsGid, RunAsUserName, sff,
394                            S_IRUSR, NULL)) == 0)
395                return true;
396        if (LogLevel > 7)
397                sm_syslog(LOG_WARNING, NOQID, "STARTTLS=%s: file %s unsafe: %s",
398                          srv ? "server" : "client", var, sm_errstring(ret));
399        return false;
400}
401
402/*
403**  TLS_OK_F -- macro to simplify calls to tls_ok_f
404**
405**      Parameters:
406**              var -- filename
407**              fn -- what is the filename used for?
408**              req -- is the file required?
409**              st -- status bit to set if ok
410**              srv -- server side?
411**
412**      Side Effects:
413**              uses r, ok; may change ok and status.
414**
415*/
416
417# define TLS_OK_F(var, fn, req, st, srv) if (ok) \
418        { \
419                r = tls_ok_f(var, fn, srv); \
420                if (r) \
421                        status |= st; \
422                else if (req) \
423                        ok = false; \
424        }
425
426/*
427**  TLS_UNR -- macro to return whether a file should be unreadable
428**
429**      Parameters:
430**              bit -- flag to test
431**              req -- flags
432**
433**      Returns:
434**              0/SFF_NORFILES
435*/
436# define TLS_UNR(bit, req)      (bitset(bit, req) ? SFF_NORFILES : 0)
437# define TLS_OUNR(bit, req)     (bitset(bit, req) ? SFF_NOWRFILES : 0)
438# define TLS_KEYSFF(req)        \
439        (bitnset(DBS_GROUPREADABLEKEYFILE, DontBlameSendmail) ? \
440                TLS_OUNR(TLS_I_KEY_OUNR, req) :                 \
441                TLS_UNR(TLS_I_KEY_UNR, req))
442
443/*
444**  TLS_SAFE_F -- macro to simplify calls to tls_safe_f
445**
446**      Parameters:
447**              var -- filename
448**              sff -- flags for safefile()
449**              req -- is the file required?
450**              ex -- does the file exist?
451**              st -- status bit to set if ok
452**              srv -- server side?
453**
454**      Side Effects:
455**              uses r, ok, ex; may change ok and status.
456**
457*/
458
459# define TLS_SAFE_F(var, sff, req, ex, st, srv) if (ex && ok) \
460        { \
461                r = tls_safe_f(var, sff, srv); \
462                if (r) \
463                        status |= st;   \
464                else if (req) \
465                        ok = false;     \
466        }
467
468/*
469**  INITTLS -- initialize TLS
470**
471**      Parameters:
472**              ctx -- pointer to context
473**              req -- requirements for initialization (see sendmail.h)
474**              srv -- server side?
475**              certfile -- filename of certificate
476**              keyfile -- filename of private key
477**              cacertpath -- path to CAs
478**              cacertfile -- file with CA(s)
479**              dhparam -- parameters for DH
480**
481**      Returns:
482**              succeeded?
483*/
484
485bool
486inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
487        SSL_CTX **ctx;
488        unsigned long req;
489        bool srv;
490        char *certfile, *keyfile, *cacertpath, *cacertfile, *dhparam;
491{
492# if !NO_DH
493        static DH *dh = NULL;
494# endif /* !NO_DH */
495        int r;
496        bool ok;
497        long sff, status;
498        char *who;
499# if _FFR_TLS_1
500        char *cf2, *kf2;
501# endif /* _FFR_TLS_1 */
502#  if SM_CONF_SHM
503        extern int ShmId;
504#  endif /* SM_CONF_SHM */
505
506        status = TLS_S_NONE;
507        who = srv ? "server" : "client";
508        if (ctx == NULL)
509                syserr("STARTTLS=%s, inittls: ctx == NULL", who);
510
511        /* already initialized? (we could re-init...) */
512        if (*ctx != NULL)
513                return true;
514        ok = true;
515
516# if _FFR_TLS_1
517        /*
518        **  look for a second filename: it must be separated by a ','
519        **  no blanks allowed (they won't be skipped).
520        **  we change a global variable here! this change will be undone
521        **  before return from the function but only if it returns true.
522        **  this isn't a problem since in a failure case this function
523        **  won't be called again with the same (overwritten) values.
524        **  otherwise each return must be replaced with a goto endinittls.
525        */
526
527        cf2 = NULL;
528        kf2 = NULL;
529        if (certfile != NULL && (cf2 = strchr(certfile, ',')) != NULL)
530        {
531                *cf2++ = '\0';
532                if (keyfile != NULL && (kf2 = strchr(keyfile, ',')) != NULL)
533                        *kf2++ = '\0';
534        }
535# endif /* _FFR_TLS_1 */
536
537        /*
538        **  Check whether files/paths are defined
539        */
540
541        TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req),
542                 TLS_S_CERT_EX, srv);
543        TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req),
544                 TLS_S_KEY_EX, srv);
545        TLS_OK_F(cacertpath, "CACertPath", bitset(TLS_I_CERTP_EX, req),
546                 TLS_S_CERTP_EX, srv);
547        TLS_OK_F(cacertfile, "CACertFile", bitset(TLS_I_CERTF_EX, req),
548                 TLS_S_CERTF_EX, srv);
549
550# if _FFR_TLS_1
551        /*
552        **  if the second file is specified it must exist
553        **  XXX: it is possible here to define only one of those files
554        */
555
556        if (cf2 != NULL)
557        {
558                TLS_OK_F(cf2, "CertFile", bitset(TLS_I_CERT_EX, req),
559                         TLS_S_CERT2_EX, srv);
560        }
561        if (kf2 != NULL)
562        {
563                TLS_OK_F(kf2, "KeyFile", bitset(TLS_I_KEY_EX, req),
564                         TLS_S_KEY2_EX, srv);
565        }
566# endif /* _FFR_TLS_1 */
567
568        /*
569        **  valid values for dhparam are (only the first char is checked)
570        **  none        no parameters: don't use DH
571        **  512         generate 512 bit parameters (fixed)
572        **  1024        generate 1024 bit parameters
573        **  /file/name  read parameters from /file/name
574        **  default is: 1024 for server, 512 for client (OK? XXX)
575        */
576
577        if (bitset(TLS_I_TRY_DH, req))
578        {
579                if (dhparam != NULL)
580                {
581                        char c = *dhparam;
582
583                        if (c == '1')
584                                req |= TLS_I_DH1024;
585                        else if (c == '5')
586                                req |= TLS_I_DH512;
587                        else if (c != 'n' && c != 'N' && c != '/')
588                        {
589                                if (LogLevel > 12)
590                                        sm_syslog(LOG_WARNING, NOQID,
591                                                  "STARTTLS=%s, error: illegal value '%s' for DHParam",
592                                                  who, dhparam);
593                                dhparam = NULL;
594                        }
595                }
596                if (dhparam == NULL)
597                        dhparam = srv ? "1" : "5";
598                else if (*dhparam == '/')
599                {
600                        TLS_OK_F(dhparam, "DHParameters",
601                                 bitset(TLS_I_DHPAR_EX, req),
602                                 TLS_S_DHPAR_EX, srv);
603                }
604        }
605        if (!ok)
606                return ok;
607
608        /* certfile etc. must be "safe". */
609        sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK
610             | SFF_NOGWFILES | SFF_NOWWFILES
611             | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT;
612        if (DontLockReadFiles)
613                sff |= SFF_NOLOCK;
614
615        TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req),
616                   bitset(TLS_I_CERT_EX, req),
617                   bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv);
618        TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req),
619                   bitset(TLS_I_KEY_EX, req),
620                   bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv);
621        TLS_SAFE_F(cacertfile, sff | TLS_UNR(TLS_I_CERTF_UNR, req),
622                   bitset(TLS_I_CERTF_EX, req),
623                   bitset(TLS_S_CERTF_EX, status), TLS_S_CERTF_OK, srv);
624        TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req),
625                   bitset(TLS_I_DHPAR_EX, req),
626                   bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv);
627        if (!ok)
628                return ok;
629# if _FFR_TLS_1
630        if (cf2 != NULL)
631        {
632                TLS_SAFE_F(cf2, sff | TLS_UNR(TLS_I_CERT_UNR, req),
633                           bitset(TLS_I_CERT_EX, req),
634                           bitset(TLS_S_CERT2_EX, status), TLS_S_CERT2_OK, srv);
635        }
636        if (kf2 != NULL)
637        {
638                TLS_SAFE_F(kf2, sff | TLS_KEYSFF(req),
639                           bitset(TLS_I_KEY_EX, req),
640                           bitset(TLS_S_KEY2_EX, status), TLS_S_KEY2_OK, srv);
641        }
642# endif /* _FFR_TLS_1 */
643
644        /* create a method and a new context */
645        if ((*ctx = SSL_CTX_new(srv ? SSLv23_server_method() :
646                                      SSLv23_client_method())) == NULL)
647        {
648                if (LogLevel > 7)
649                        sm_syslog(LOG_WARNING, NOQID,
650                                  "STARTTLS=%s, error: SSL_CTX_new(SSLv23_%s_method()) failed",
651                                  who, who);
652                if (LogLevel > 9)
653                        tlslogerr(who);
654                return false;
655        }
656
657# if TLS_NO_RSA
658        /* turn off backward compatibility, required for no-rsa */
659        SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2);
660# endif /* TLS_NO_RSA */
661
662
663# if !TLS_NO_RSA
664        /*
665        **  Create a temporary RSA key
666        **  XXX  Maybe we shouldn't create this always (even though it
667        **  is only at startup).
668        **  It is a time-consuming operation and it is not always necessary.
669        **  maybe we should do it only on demand...
670        */
671
672        if (bitset(TLS_I_RSA_TMP, req)
673#   if SM_CONF_SHM
674            && ShmId != SM_SHM_NO_ID &&
675            (rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL,
676                                        NULL)) == NULL
677#   else /* SM_CONF_SHM */
678            && 0        /* no shared memory: no need to generate key now */
679#   endif /* SM_CONF_SHM */
680           )
681        {
682                if (LogLevel > 7)
683                {
684                        sm_syslog(LOG_WARNING, NOQID,
685                                  "STARTTLS=%s, error: RSA_generate_key failed",
686                                  who);
687                        if (LogLevel > 9)
688                                tlslogerr(who);
689                }
690                return false;
691        }
692# endif /* !TLS_NO_RSA */
693
694        /*
695        **  load private key
696        **  XXX change this for DSA-only version
697        */
698
699        if (bitset(TLS_S_KEY_OK, status) &&
700            SSL_CTX_use_PrivateKey_file(*ctx, keyfile,
701                                         SSL_FILETYPE_PEM) <= 0)
702        {
703                if (LogLevel > 7)
704                {
705                        sm_syslog(LOG_WARNING, NOQID,
706                                  "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed",
707                                  who, keyfile);
708                        if (LogLevel > 9)
709                                tlslogerr(who);
710                }
711                if (bitset(TLS_I_USE_KEY, req))
712                        return false;
713        }
714
715        /* get the certificate file */
716        if (bitset(TLS_S_CERT_OK, status) &&
717            SSL_CTX_use_certificate_file(*ctx, certfile,
718                                         SSL_FILETYPE_PEM) <= 0)
719        {
720                if (LogLevel > 7)
721                {
722                        sm_syslog(LOG_WARNING, NOQID,
723                                  "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed",
724                                  who, certfile);
725                        if (LogLevel > 9)
726                                tlslogerr(who);
727                }
728                if (bitset(TLS_I_USE_CERT, req))
729                        return false;
730        }
731
732        /* check the private key */
733        if (bitset(TLS_S_KEY_OK, status) &&
734            (r = SSL_CTX_check_private_key(*ctx)) <= 0)
735        {
736                /* Private key does not match the certificate public key */
737                if (LogLevel > 5)
738                {
739                        sm_syslog(LOG_WARNING, NOQID,
740                                  "STARTTLS=%s, error: SSL_CTX_check_private_key failed(%s): %d",
741                                  who, keyfile, r);
742                        if (LogLevel > 9)
743                                tlslogerr(who);
744                }
745                if (bitset(TLS_I_USE_KEY, req))
746                        return false;
747        }
748
749# if _FFR_TLS_1
750        /* XXX this code is pretty much duplicated from above! */
751
752        /* load private key */
753        if (bitset(TLS_S_KEY2_OK, status) &&
754            SSL_CTX_use_PrivateKey_file(*ctx, kf2, SSL_FILETYPE_PEM) <= 0)
755        {
756                if (LogLevel > 7)
757                {
758                        sm_syslog(LOG_WARNING, NOQID,
759                                  "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed",
760                                  who, kf2);
761                        if (LogLevel > 9)
762                                tlslogerr(who);
763                }
764        }
765
766        /* get the certificate file */
767        if (bitset(TLS_S_CERT2_OK, status) &&
768            SSL_CTX_use_certificate_file(*ctx, cf2, SSL_FILETYPE_PEM) <= 0)
769        {
770                if (LogLevel > 7)
771                {
772                        sm_syslog(LOG_WARNING, NOQID,
773                                  "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed",
774                                  who, cf2);
775                        if (LogLevel > 9)
776                                tlslogerr(who);
777                }
778        }
779
780        /* also check the private key */
781        if (bitset(TLS_S_KEY2_OK, status) &&
782            (r = SSL_CTX_check_private_key(*ctx)) <= 0)
783        {
784                /* Private key does not match the certificate public key */
785                if (LogLevel > 5)
786                {
787                        sm_syslog(LOG_WARNING, NOQID,
788                                  "STARTTLS=%s, error: SSL_CTX_check_private_key 2 failed: %d",
789                                  who, r);
790                        if (LogLevel > 9)
791                                tlslogerr(who);
792                }
793        }
794# endif /* _FFR_TLS_1 */
795
796        /* SSL_CTX_set_quiet_shutdown(*ctx, 1); violation of standard? */
797        SSL_CTX_set_options(*ctx, SSL_OP_ALL);  /* XXX bug compatibility? */
798
799# if !NO_DH
800        /* Diffie-Hellman initialization */
801        if (bitset(TLS_I_TRY_DH, req))
802        {
803                if (bitset(TLS_S_DHPAR_OK, status))
804                {
805                        BIO *bio;
806
807                        if ((bio = BIO_new_file(dhparam, "r")) != NULL)
808                        {
809                                dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
810                                BIO_free(bio);
811                                if (dh == NULL && LogLevel > 7)
812                                {
813                                        unsigned long err;
814
815                                        err = ERR_get_error();
816                                        sm_syslog(LOG_WARNING, NOQID,
817                                                  "STARTTLS=%s, error: cannot read DH parameters(%s): %s",
818                                                  who, dhparam,
819                                                  ERR_error_string(err, NULL));
820                                        if (LogLevel > 9)
821                                                tlslogerr(who);
822                                }
823                        }
824                        else
825                        {
826                                if (LogLevel > 5)
827                                {
828                                        sm_syslog(LOG_WARNING, NOQID,
829                                                  "STARTTLS=%s, error: BIO_new_file(%s) failed",
830                                                  who, dhparam);
831                                        if (LogLevel > 9)
832                                                tlslogerr(who);
833                                }
834                        }
835                }
836                if (dh == NULL && bitset(TLS_I_DH1024, req))
837                {
838                        DSA *dsa;
839
840                        /* this takes a while! (7-130s on a 450MHz AMD K6-2) */
841                        dsa = DSA_generate_parameters(1024, NULL, 0, NULL,
842                                                      NULL, 0, NULL);
843                        dh = DSA_dup_DH(dsa);
844                        DSA_free(dsa);
845                }
846                else
847                if (dh == NULL && bitset(TLS_I_DH512, req))
848                        dh = get_dh512();
849
850                if (dh == NULL)
851                {
852                        if (LogLevel > 9)
853                        {
854                                unsigned long err;
855
856                                err = ERR_get_error();
857                                sm_syslog(LOG_WARNING, NOQID,
858                                          "STARTTLS=%s, error: cannot read or set DH parameters(%s): %s",
859                                          who, dhparam,
860                                          ERR_error_string(err, NULL));
861                        }
862                        if (bitset(TLS_I_REQ_DH, req))
863                                return false;
864                }
865                else
866                {
867                        SSL_CTX_set_tmp_dh(*ctx, dh);
868
869                        /* important to avoid small subgroup attacks */
870                        SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_DH_USE);
871                        if (LogLevel > 13)
872                                sm_syslog(LOG_INFO, NOQID,
873                                          "STARTTLS=%s, Diffie-Hellman init, key=%d bit (%c)",
874                                          who, 8 * DH_size(dh), *dhparam);
875                        DH_free(dh);
876                }
877        }
878# endif /* !NO_DH */
879
880
881        /* XXX do we need this cache here? */
882        if (bitset(TLS_I_CACHE, req))
883                SSL_CTX_sess_set_cache_size(*ctx, 128);
884        /* timeout? SSL_CTX_set_timeout(*ctx, TimeOut...); */
885
886        /* load certificate locations and default CA paths */
887        if (bitset(TLS_S_CERTP_EX, status) && bitset(TLS_S_CERTF_EX, status))
888        {
889                if ((r = SSL_CTX_load_verify_locations(*ctx, cacertfile,
890                                                       cacertpath)) == 1)
891                {
892# if !TLS_NO_RSA
893                        if (bitset(TLS_I_RSA_TMP, req))
894                                SSL_CTX_set_tmp_rsa_callback(*ctx, tmp_rsa_key);
895# endif /* !TLS_NO_RSA */
896
897                        /*
898                        **  We have to install our own verify callback:
899                        **  SSL_VERIFY_PEER requests a client cert but even
900                        **  though *FAIL_IF* isn't set, the connection
901                        **  will be aborted if the client presents a cert
902                        **  that is not "liked" (can't be verified?) by
903                        **  the TLS library :-(
904                        */
905
906                        /*
907                        **  XXX currently we could call tls_set_verify()
908                        **  but we hope that that function will later on
909                        **  only set the mode per connection.
910                        */
911                        SSL_CTX_set_verify(*ctx,
912                                bitset(TLS_I_NO_VRFY, req) ? SSL_VERIFY_NONE
913                                                           : SSL_VERIFY_PEER,
914                                NULL);
915
916                        /* install verify callback */
917                        SSL_CTX_set_cert_verify_callback(*ctx, tls_verify_cb,
918                                                         NULL);
919                        SSL_CTX_set_client_CA_list(*ctx,
920                                SSL_load_client_CA_file(cacertfile));
921                }
922                else
923                {
924                        /*
925                        **  can't load CA data; do we care?
926                        **  the data is necessary to authenticate the client,
927                        **  which in turn would be necessary
928                        **  if we want to allow relaying based on it.
929                        */
930                        if (LogLevel > 5)
931                        {
932                                sm_syslog(LOG_WARNING, NOQID,
933                                          "STARTTLS=%s, error: load verify locs %s, %s failed: %d",
934                                          who, cacertpath, cacertfile, r);
935                                if (LogLevel > 9)
936                                        tlslogerr(who);
937                        }
938                        if (bitset(TLS_I_VRFY_LOC, req))
939                                return false;
940                }
941        }
942
943        /* XXX: make this dependent on an option? */
944        if (tTd(96, 9))
945                SSL_CTX_set_info_callback(*ctx, apps_ssl_info_cb);
946
947# if _FFR_TLS_1
948        /* install our own cipher list */
949        if (CipherList != NULL && *CipherList != '\0')
950        {
951                if (SSL_CTX_set_cipher_list(*ctx, CipherList) <= 0)
952                {
953                        if (LogLevel > 7)
954                        {
955                                sm_syslog(LOG_WARNING, NOQID,
956                                          "STARTTLS=%s, error: SSL_CTX_set_cipher_list(%s) failed, list ignored",
957                                          who, CipherList);
958
959                                if (LogLevel > 9)
960                                        tlslogerr(who);
961                        }
962                        /* failure if setting to this list is required? */
963                }
964        }
965# endif /* _FFR_TLS_1 */
966        if (LogLevel > 12)
967                sm_syslog(LOG_INFO, NOQID, "STARTTLS=%s, init=%d", who, ok);
968
969# if _FFR_TLS_1
970#  if 0
971        /*
972        **  this label is required if we want to have a "clean" exit
973        **  see the comments above at the initialization of cf2
974        */
975
976    endinittls:
977#  endif /* 0 */
978
979        /* undo damage to global variables */
980        if (cf2 != NULL)
981                *--cf2 = ',';
982        if (kf2 != NULL)
983                *--kf2 = ',';
984# endif /* _FFR_TLS_1 */
985
986        return ok;
987}
988/*
989**  TLS_GET_INFO -- get information about TLS connection
990**
991**      Parameters:
992**              ssl -- TLS connection structure
993**              srv -- server or client
994**              host -- hostname of other side
995**              mac -- macro storage
996**              certreq -- did we ask for a cert?
997**
998**      Returns:
999**              result of authentication.
1000**
1001**      Side Effects:
1002**              sets macros: {cipher}, {tls_version}, {verify},
1003**              {cipher_bits}, {alg_bits}, {cert}, {cert_subject},
1004**              {cert_issuer}, {cn_subject}, {cn_issuer}
1005*/
1006
1007int
1008tls_get_info(ssl, srv, host, mac, certreq)
1009        SSL *ssl;
1010        bool srv;
1011        char *host;
1012        MACROS_T *mac;
1013        bool certreq;
1014{
1015        SSL_CIPHER *c;
1016        int b, r;
1017        char *s, *who;
1018        char bitstr[16];
1019        X509 *cert;
1020
1021        c = SSL_get_current_cipher(ssl);
1022
1023        /* cast is just workaround for compiler warning */
1024        macdefine(mac, A_TEMP, macid("{cipher}"),
1025                  (char *) SSL_CIPHER_get_name(c));
1026        b = SSL_CIPHER_get_bits(c, &r);
1027        (void) sm_snprintf(bitstr, sizeof bitstr, "%d", b);
1028        macdefine(mac, A_TEMP, macid("{cipher_bits}"), bitstr);
1029        (void) sm_snprintf(bitstr, sizeof bitstr, "%d", r);
1030        macdefine(mac, A_TEMP, macid("{alg_bits}"), bitstr);
1031        s = SSL_CIPHER_get_version(c);
1032        if (s == NULL)
1033                s = "UNKNOWN";
1034        macdefine(mac, A_TEMP, macid("{tls_version}"), s);
1035
1036        who = srv ? "server" : "client";
1037        cert = SSL_get_peer_certificate(ssl);
1038        if (LogLevel > 14)
1039                sm_syslog(LOG_INFO, NOQID,
1040                          "STARTTLS=%s, get_verify: %ld get_peer: 0x%lx",
1041                          who, SSL_get_verify_result(ssl),
1042                          (unsigned long) cert);
1043        if (cert != NULL)
1044        {
1045                unsigned int n;
1046                unsigned char md[EVP_MAX_MD_SIZE];
1047                char buf[MAXNAME];
1048
1049                X509_NAME_oneline(X509_get_subject_name(cert),
1050                                  buf, sizeof buf);
1051                macdefine(mac, A_TEMP, macid("{cert_subject}"),
1052                         xtextify(buf, "<>\")"));
1053                X509_NAME_oneline(X509_get_issuer_name(cert),
1054                                  buf, sizeof buf);
1055                macdefine(mac, A_TEMP, macid("{cert_issuer}"),
1056                         xtextify(buf, "<>\")"));
1057                X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
1058                                          NID_commonName, buf, sizeof buf);
1059                macdefine(mac, A_TEMP, macid("{cn_subject}"),
1060                         xtextify(buf, "<>\")"));
1061                X509_NAME_get_text_by_NID(X509_get_issuer_name(cert),
1062                                          NID_commonName, buf, sizeof buf);
1063                macdefine(mac, A_TEMP, macid("{cn_issuer}"),
1064                         xtextify(buf, "<>\")"));
1065                if (X509_digest(cert, EVP_md5(), md, &n))
1066                {
1067                        char md5h[EVP_MAX_MD_SIZE * 3];
1068                        static const char hexcodes[] = "0123456789ABCDEF";
1069
1070                        SM_ASSERT((n * 3) + 2 < sizeof(md5h));
1071                        for (r = 0; r < (int) n; r++)
1072                        {
1073                                md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4];
1074                                md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)];
1075                                md5h[(r * 3) + 2] = ':';
1076                        }
1077                        md5h[(n * 3) - 1] = '\0';
1078                        macdefine(mac, A_TEMP, macid("{cert_md5}"), md5h);
1079                }
1080                else
1081                        macdefine(mac, A_TEMP, macid("{cert_md5}"), "");
1082        }
1083        else
1084        {
1085                macdefine(mac, A_PERM, macid("{cert_subject}"), "");
1086                macdefine(mac, A_PERM, macid("{cert_issuer}"), "");
1087                macdefine(mac, A_PERM, macid("{cn_subject}"), "");
1088                macdefine(mac, A_PERM, macid("{cn_issuer}"), "");
1089                macdefine(mac, A_TEMP, macid("{cert_md5}"), "");
1090        }
1091        switch (SSL_get_verify_result(ssl))
1092        {
1093          case X509_V_OK:
1094                if (cert != NULL)
1095                {
1096                        s = "OK";
1097                        r = TLS_AUTH_OK;
1098                }
1099                else
1100                {
1101                        s = certreq ? "NO" : "NOT",
1102                        r = TLS_AUTH_NO;
1103                }
1104                break;
1105          default:
1106                s = "FAIL";
1107                r = TLS_AUTH_FAIL;
1108                break;
1109        }
1110        macdefine(mac, A_PERM, macid("{verify}"), s);
1111        if (cert != NULL)
1112                X509_free(cert);
1113
1114        /* do some logging */
1115        if (LogLevel > 8)
1116        {
1117                char *vers, *s1, *s2, *cbits, *algbits;
1118
1119                vers = macget(mac, macid("{tls_version}"));
1120                cbits = macget(mac, macid("{cipher_bits}"));
1121                algbits = macget(mac, macid("{alg_bits}"));
1122                s1 = macget(mac, macid("{verify}"));
1123                s2 = macget(mac, macid("{cipher}"));
1124
1125                /* XXX: maybe cut off ident info? */
1126                sm_syslog(LOG_INFO, NOQID,
1127                          "STARTTLS=%s, relay=%.100s, version=%.16s, verify=%.16s, cipher=%.64s, bits=%.6s/%.6s",
1128                          who,
1129                          host == NULL ? "local" : host,
1130                          vers, s1, s2, /* sm_snprintf() can deal with NULL */
1131                          algbits == NULL ? "0" : algbits,
1132                          cbits == NULL ? "0" : cbits);
1133                if (LogLevel > 11)
1134                {
1135                        /*
1136                        **  Maybe run xuntextify on the strings?
1137                        **  That is easier to read but makes it maybe a bit
1138                        **  more complicated to figure out the right values
1139                        **  for the access map...
1140                        */
1141
1142                        s1 = macget(mac, macid("{cert_subject}"));
1143                        s2 = macget(mac, macid("{cert_issuer}"));
1144                        sm_syslog(LOG_INFO, NOQID,
1145                                  "STARTTLS=%s, cert-subject=%.128s, cert-issuer=%.128s",
1146                                  who, s1, s2);
1147                }
1148        }
1149        return r;
1150}
1151/*
1152**  ENDTLS -- shutdown secure connection
1153**
1154**      Parameters:
1155**              ssl -- SSL connection information.
1156**              side -- server/client (for logging).
1157**
1158**      Returns:
1159**              success? (EX_* code)
1160*/
1161
1162int
1163endtls(ssl, side)
1164        SSL *ssl;
1165        char *side;
1166{
1167        int ret = EX_OK;
1168
1169        if (ssl != NULL)
1170        {
1171                int r;
1172
1173                if ((r = SSL_shutdown(ssl)) < 0)
1174                {
1175                        if (LogLevel > 11)
1176                        {
1177                                sm_syslog(LOG_WARNING, NOQID,
1178                                          "STARTTLS=%s, SSL_shutdown failed: %d",
1179                                          side, r);
1180                                tlslogerr(side);
1181                        }
1182                        ret = EX_SOFTWARE;
1183                }
1184# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER > 0x0090602fL
1185
1186                /*
1187                **  Bug in OpenSSL (at least up to 0.9.6b):
1188                **  From: Lutz.Jaenicke@aet.TU-Cottbus.DE
1189                **  Message-ID: <20010723152244.A13122@serv01.aet.tu-cottbus.de>
1190                **  To: openssl-users@openssl.org
1191                **  Subject: Re: SSL_shutdown() woes (fwd)
1192                **
1193                **  The side sending the shutdown alert first will
1194                **  not care about the answer of the peer but will
1195                **  immediately return with a return value of "0"
1196                **  (ssl/s3_lib.c:ssl3_shutdown()). SSL_get_error will evaluate
1197                **  the value of "0" and as the shutdown alert of the peer was
1198                **  not received (actually, the program did not even wait for
1199                **  the answer), an SSL_ERROR_SYSCALL is flagged, because this
1200                **  is the default rule in case everything else does not apply.
1201                **
1202                **  For your server the problem is different, because it
1203                **  receives the shutdown first (setting SSL_RECEIVED_SHUTDOWN),
1204                **  then sends its response (SSL_SENT_SHUTDOWN), so for the
1205                **  server the shutdown was successfull.
1206                **
1207                **  As is by know, you would have to call SSL_shutdown() once
1208                **  and ignore an SSL_ERROR_SYSCALL returned. Then call
1209                **  SSL_shutdown() again to actually get the server's response.
1210                **
1211                **  In the last discussion, Bodo Moeller concluded that a
1212                **  rewrite of the shutdown code would be necessary, but
1213                **  probably with another API, as the change would not be
1214                **  compatible to the way it is now.  Things do not become
1215                **  easier as other programs do not follow the shutdown
1216                **  guidelines anyway, so that a lot error conditions and
1217                **  compitibility issues would have to be caught.
1218                **
1219                **  For now the recommondation is to ignore the error message.
1220                */
1221
1222                else if (r == 0)
1223                {
1224                        if (LogLevel > 15)
1225                        {
1226                                sm_syslog(LOG_WARNING, NOQID,
1227                                          "STARTTLS=%s, SSL_shutdown not done",
1228                                          side);
1229                                tlslogerr(side);
1230                        }
1231                        ret = EX_SOFTWARE;
1232                }
1233# endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER > 0x0090602fL */
1234                SSL_free(ssl);
1235                ssl = NULL;
1236        }
1237        return ret;
1238}
1239
1240# if !TLS_NO_RSA
1241/*
1242**  TMP_RSA_KEY -- return temporary RSA key
1243**
1244**      Parameters:
1245**              s -- TLS connection structure
1246**              export --
1247**              keylength --
1248**
1249**      Returns:
1250**              temporary RSA key.
1251*/
1252
1253#   ifndef MAX_RSA_TMP_CNT
1254#    define MAX_RSA_TMP_CNT     1000    /* XXX better value? */
1255#   endif /* ! MAX_RSA_TMP_CNT */
1256
1257/* ARGUSED0 */
1258static RSA *
1259tmp_rsa_key(s, export, keylength)
1260        SSL *s;
1261        int export;
1262        int keylength;
1263{
1264#   if SM_CONF_SHM
1265        extern int ShmId;
1266        extern int *PRSATmpCnt;
1267
1268        if (ShmId != SM_SHM_NO_ID && rsa_tmp != NULL &&
1269            ++(*PRSATmpCnt) < MAX_RSA_TMP_CNT)
1270                return rsa_tmp;
1271#   endif /* SM_CONF_SHM */
1272
1273        if (rsa_tmp != NULL)
1274                RSA_free(rsa_tmp);
1275        rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, NULL);
1276        if (rsa_tmp == NULL)
1277        {
1278                if (LogLevel > 0)
1279                        sm_syslog(LOG_ERR, NOQID,
1280                                  "STARTTLS=server, tmp_rsa_key: RSA_generate_key failed!");
1281        }
1282        else
1283        {
1284#   if SM_CONF_SHM
1285#    if 0
1286                /*
1287                **  XXX we can't (yet) share the new key...
1288                **      The RSA structure contains pointers hence it can't be
1289                **      easily kept in shared memory.  It must be transformed
1290                **      into a continous memory region first, then stored,
1291                **      and later read out again (each time re-transformed).
1292                */
1293
1294                if (ShmId != SM_SHM_NO_ID)
1295                        *PRSATmpCnt = 0;
1296#    endif /* 0 */
1297#   endif /* SM_CONF_SHM */
1298                if (LogLevel > 9)
1299                        sm_syslog(LOG_ERR, NOQID,
1300                                  "STARTTLS=server, tmp_rsa_key: new temp RSA key");
1301        }
1302        return rsa_tmp;
1303}
1304# endif /* !TLS_NO_RSA */
1305/*
1306**  APPS_SSL_INFO_CB -- info callback for TLS connections
1307**
1308**      Parameters:
1309**              s -- TLS connection structure
1310**              where -- state in handshake
1311**              ret -- return code of last operation
1312**
1313**      Returns:
1314**              none.
1315*/
1316
1317static void
1318apps_ssl_info_cb(s, where, ret)
1319        CONST097 SSL *s;
1320        int where;
1321        int ret;
1322{
1323        int w;
1324        char *str;
1325        BIO *bio_err = NULL;
1326
1327        if (LogLevel > 14)
1328                sm_syslog(LOG_INFO, NOQID,
1329                          "STARTTLS: info_callback where=0x%x, ret=%d",
1330                          where, ret);
1331
1332        w = where & ~SSL_ST_MASK;
1333        if (bio_err == NULL)
1334                bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1335
1336        if (bitset(SSL_ST_CONNECT, w))
1337                str = "SSL_connect";
1338        else if (bitset(SSL_ST_ACCEPT, w))
1339                str = "SSL_accept";
1340        else
1341                str = "undefined";
1342
1343        if (bitset(SSL_CB_LOOP, where))
1344        {
1345                if (LogLevel > 12)
1346                        sm_syslog(LOG_NOTICE, NOQID,
1347                                "STARTTLS: %s:%s",
1348                                str, SSL_state_string_long(s));
1349        }
1350        else if (bitset(SSL_CB_ALERT, where))
1351        {
1352                str = bitset(SSL_CB_READ, where) ? "read" : "write";
1353                if (LogLevel > 12)
1354                        sm_syslog(LOG_NOTICE, NOQID,
1355                                "STARTTLS: SSL3 alert %s:%s:%s",
1356                                str, SSL_alert_type_string_long(ret),
1357                                SSL_alert_desc_string_long(ret));
1358        }
1359        else if (bitset(SSL_CB_EXIT, where))
1360        {
1361                if (ret == 0)
1362                {
1363                        if (LogLevel > 7)
1364                                sm_syslog(LOG_WARNING, NOQID,
1365                                        "STARTTLS: %s:failed in %s",
1366                                        str, SSL_state_string_long(s));
1367                }
1368                else if (ret < 0)
1369                {
1370                        if (LogLevel > 7)
1371                                sm_syslog(LOG_WARNING, NOQID,
1372                                        "STARTTLS: %s:error in %s",
1373                                        str, SSL_state_string_long(s));
1374                }
1375        }
1376}
1377/*
1378**  TLS_VERIFY_LOG -- log verify error for TLS certificates
1379**
1380**      Parameters:
1381**              ok -- verify ok?
1382**              ctx -- x509 context
1383**
1384**      Returns:
1385**              0 -- fatal error
1386**              1 -- ok
1387*/
1388
1389static int
1390tls_verify_log(ok, ctx)
1391        int ok;
1392        X509_STORE_CTX *ctx;
1393{
1394        SSL *ssl;
1395        X509 *cert;
1396        int reason, depth;
1397        char buf[512];
1398
1399        cert = X509_STORE_CTX_get_current_cert(ctx);
1400        reason = X509_STORE_CTX_get_error(ctx);
1401        depth = X509_STORE_CTX_get_error_depth(ctx);
1402        ssl = (SSL *) X509_STORE_CTX_get_ex_data(ctx,
1403                        SSL_get_ex_data_X509_STORE_CTX_idx());
1404
1405        if (ssl == NULL)
1406        {
1407                /* internal error */
1408                sm_syslog(LOG_ERR, NOQID,
1409                          "STARTTLS: internal error: tls_verify_cb: ssl == NULL");
1410                return 0;
1411        }
1412
1413        X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof buf);
1414        sm_syslog(LOG_INFO, NOQID,
1415                  "STARTTLS: cert verify: depth=%d %s, state=%d, reason=%s",
1416                  depth, buf, ok, X509_verify_cert_error_string(reason));
1417        return 1;
1418}
1419/*
1420**  TLS_VERIFY_CB -- verify callback for TLS certificates
1421**
1422**      Parameters:
1423**              ctx -- x509 context
1424**
1425**      Returns:
1426**              accept connection?
1427**              currently: always yes.
1428*/
1429
1430static int
1431#  if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L
1432tls_verify_cb(ctx)
1433        X509_STORE_CTX *ctx;
1434#  else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
1435tls_verify_cb(ctx, unused)
1436        X509_STORE_CTX *ctx;
1437        void *unused;
1438#  endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
1439{
1440        int ok;
1441
1442        ok = X509_verify_cert(ctx);
1443        if (ok == 0)
1444        {
1445                if (LogLevel > 13)
1446                        return tls_verify_log(ok, ctx);
1447                return 1;       /* override it */
1448        }
1449        return ok;
1450}
1451/*
1452**  TLSLOGERR -- log the errors from the TLS error stack
1453**
1454**      Parameters:
1455**              who -- server/client (for logging).
1456**
1457**      Returns:
1458**              none.
1459*/
1460
1461void
1462tlslogerr(who)
1463        char *who;
1464{
1465        unsigned long l;
1466        int line, flags;
1467        unsigned long es;
1468        char *file, *data;
1469        char buf[256];
1470#  define CP (const char **)
1471
1472        es = CRYPTO_thread_id();
1473        while ((l = ERR_get_error_line_data(CP &file, &line, CP &data, &flags))
1474                != 0)
1475        {
1476                sm_syslog(LOG_WARNING, NOQID,
1477                          "STARTTLS=%s: %lu:%s:%s:%d:%s", who, es,
1478                          ERR_error_string(l, buf),
1479                          file, line,
1480                          bitset(ERR_TXT_STRING, flags) ? data : "");
1481        }
1482}
1483#endif /* STARTTLS */
Note: See TracBrowser for help on using the repository browser.