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