190792Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2000-2006, 2008, 2009, 2011, 2013 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * 590792Sgshapiro * By using this file, you agree to the terms and conditions set 690792Sgshapiro * forth in the LICENSE file which can be found at the top level of 790792Sgshapiro * the sendmail distribution. 890792Sgshapiro * 990792Sgshapiro */ 1090792Sgshapiro 1190792Sgshapiro#include <sendmail.h> 1290792Sgshapiro 13266692SgshapiroSM_RCSID("@(#)$Id: tls.c,v 8.127 2013-11-27 02:51:11 gshapiro Exp $") 1490792Sgshapiro 1590792Sgshapiro#if STARTTLS 16285303Sgshapiro# include <openssl/err.h> 17285303Sgshapiro# include <openssl/bio.h> 18285303Sgshapiro# include <openssl/pem.h> 19285303Sgshapiro# ifndef HASURANDOMDEV 20285303Sgshapiro# include <openssl/rand.h> 21285303Sgshapiro# endif /* ! HASURANDOMDEV */ 2290792Sgshapiro# if !TLS_NO_RSA 2390792Sgshapirostatic RSA *rsa_tmp = NULL; /* temporary RSA key */ 2490792Sgshapirostatic RSA *tmp_rsa_key __P((SSL *, int, int)); 2590792Sgshapiro# endif /* !TLS_NO_RSA */ 26285303Sgshapiro# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L 2790792Sgshapirostatic int tls_verify_cb __P((X509_STORE_CTX *)); 28285303Sgshapiro# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ 2994334Sgshapirostatic int tls_verify_cb __P((X509_STORE_CTX *, void *)); 30285303Sgshapiro# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ 3190792Sgshapiro 32132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 33132943Sgshapirostatic int x509_verify_cb __P((int, X509_STORE_CTX *)); 34132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 35132943Sgshapiro 3694334Sgshapiro# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L 3794334Sgshapiro# define CONST097 3894334Sgshapiro# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ 3994334Sgshapiro# define CONST097 const 4094334Sgshapiro# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ 4194334Sgshapirostatic void apps_ssl_info_cb __P((CONST097 SSL *, int , int)); 42141858Sgshapirostatic bool tls_ok_f __P((char *, char *, int)); 43141858Sgshapirostatic bool tls_safe_f __P((char *, long, bool)); 44285303Sgshapirostatic int tls_verify_log __P((int, X509_STORE_CTX *, const char *)); 4590792Sgshapiro 4690792Sgshapiro# if !NO_DH 4790792Sgshapirostatic DH *get_dh512 __P((void)); 4890792Sgshapiro 4990792Sgshapirostatic unsigned char dh512_p[] = 5090792Sgshapiro{ 5190792Sgshapiro 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, 5290792Sgshapiro 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, 5390792Sgshapiro 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, 5490792Sgshapiro 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, 5590792Sgshapiro 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, 5690792Sgshapiro 0x47,0x74,0xE8,0x33 5790792Sgshapiro}; 5890792Sgshapirostatic unsigned char dh512_g[] = 5990792Sgshapiro{ 6090792Sgshapiro 0x02 6190792Sgshapiro}; 6290792Sgshapiro 6390792Sgshapirostatic DH * 6490792Sgshapiroget_dh512() 6590792Sgshapiro{ 6690792Sgshapiro DH *dh = NULL; 6790792Sgshapiro 6890792Sgshapiro if ((dh = DH_new()) == NULL) 6990792Sgshapiro return NULL; 7090792Sgshapiro dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL); 7190792Sgshapiro dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL); 7290792Sgshapiro if ((dh->p == NULL) || (dh->g == NULL)) 7390792Sgshapiro return NULL; 7490792Sgshapiro return dh; 7590792Sgshapiro} 76285303Sgshapiro 77285303Sgshapiro# if 0 78285303Sgshapiro 79285303SgshapiroThis is the data from which the C code has been generated: 80285303Sgshapiro 81285303Sgshapiro-----BEGIN DH PARAMETERS----- 82285303SgshapiroMIIBCAKCAQEArDcgcLpxEksQHPlolRKCUJ2szKRziseWV9cUSQNZGxoGw7KkROz4 83285303SgshapiroHF9QSbg5axyNIG+QbZYtx0jp3l6/GWq1dLOj27yZkgYgaYgFrvKPiZ2jJ5xETQVH 84285303SgshapiroUpZwbjRcyjyWkWYJVsx1aF4F/iY4kT0n/+iGEoimI3C9V3KXTJ2S6jIkyJ6M/CrN 85285303SgshapiroEtrDynMlUMGlc7S1ouXVOTrtKeqy3S2L9eBLxVI+sChEijGIfELupdVeXihK006p 86285303SgshapiroMgnABPDbkTx6OOtYmSZaGQX+OLW2FPmwvcrzgCz9t9cAsuUcBZv1LeHEqZZttyLU 87285303SgshapirooK0jjSXgFyeU4/NfyA+zuNeWzUL6bHmigwIBAg== 88285303Sgshapiro-----END DH PARAMETERS----- 89285303Sgshapiro# endif /* 0 */ 90285303Sgshapiro 91285303Sgshapirostatic DH * 92285303Sgshapiroget_dh2048() 93285303Sgshapiro{ 94285303Sgshapiro static unsigned char dh2048_p[]={ 95285303Sgshapiro 0xAC,0x37,0x20,0x70,0xBA,0x71,0x12,0x4B,0x10,0x1C,0xF9,0x68, 96285303Sgshapiro 0x95,0x12,0x82,0x50,0x9D,0xAC,0xCC,0xA4,0x73,0x8A,0xC7,0x96, 97285303Sgshapiro 0x57,0xD7,0x14,0x49,0x03,0x59,0x1B,0x1A,0x06,0xC3,0xB2,0xA4, 98285303Sgshapiro 0x44,0xEC,0xF8,0x1C,0x5F,0x50,0x49,0xB8,0x39,0x6B,0x1C,0x8D, 99285303Sgshapiro 0x20,0x6F,0x90,0x6D,0x96,0x2D,0xC7,0x48,0xE9,0xDE,0x5E,0xBF, 100285303Sgshapiro 0x19,0x6A,0xB5,0x74,0xB3,0xA3,0xDB,0xBC,0x99,0x92,0x06,0x20, 101285303Sgshapiro 0x69,0x88,0x05,0xAE,0xF2,0x8F,0x89,0x9D,0xA3,0x27,0x9C,0x44, 102285303Sgshapiro 0x4D,0x05,0x47,0x52,0x96,0x70,0x6E,0x34,0x5C,0xCA,0x3C,0x96, 103285303Sgshapiro 0x91,0x66,0x09,0x56,0xCC,0x75,0x68,0x5E,0x05,0xFE,0x26,0x38, 104285303Sgshapiro 0x91,0x3D,0x27,0xFF,0xE8,0x86,0x12,0x88,0xA6,0x23,0x70,0xBD, 105285303Sgshapiro 0x57,0x72,0x97,0x4C,0x9D,0x92,0xEA,0x32,0x24,0xC8,0x9E,0x8C, 106285303Sgshapiro 0xFC,0x2A,0xCD,0x12,0xDA,0xC3,0xCA,0x73,0x25,0x50,0xC1,0xA5, 107285303Sgshapiro 0x73,0xB4,0xB5,0xA2,0xE5,0xD5,0x39,0x3A,0xED,0x29,0xEA,0xB2, 108285303Sgshapiro 0xDD,0x2D,0x8B,0xF5,0xE0,0x4B,0xC5,0x52,0x3E,0xB0,0x28,0x44, 109285303Sgshapiro 0x8A,0x31,0x88,0x7C,0x42,0xEE,0xA5,0xD5,0x5E,0x5E,0x28,0x4A, 110285303Sgshapiro 0xD3,0x4E,0xA9,0x32,0x09,0xC0,0x04,0xF0,0xDB,0x91,0x3C,0x7A, 111285303Sgshapiro 0x38,0xEB,0x58,0x99,0x26,0x5A,0x19,0x05,0xFE,0x38,0xB5,0xB6, 112285303Sgshapiro 0x14,0xF9,0xB0,0xBD,0xCA,0xF3,0x80,0x2C,0xFD,0xB7,0xD7,0x00, 113285303Sgshapiro 0xB2,0xE5,0x1C,0x05,0x9B,0xF5,0x2D,0xE1,0xC4,0xA9,0x96,0x6D, 114285303Sgshapiro 0xB7,0x22,0xD4,0xA0,0xAD,0x23,0x8D,0x25,0xE0,0x17,0x27,0x94, 115285303Sgshapiro 0xE3,0xF3,0x5F,0xC8,0x0F,0xB3,0xB8,0xD7,0x96,0xCD,0x42,0xFA, 116285303Sgshapiro 0x6C,0x79,0xA2,0x83, 117285303Sgshapiro }; 118285303Sgshapiro static unsigned char dh2048_g[]={ 0x02, }; 119285303Sgshapiro DH *dh; 120285303Sgshapiro 121285303Sgshapiro if ((dh=DH_new()) == NULL) 122285303Sgshapiro return(NULL); 123285303Sgshapiro dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL); 124285303Sgshapiro dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL); 125285303Sgshapiro if ((dh->p == NULL) || (dh->g == NULL)) 126285303Sgshapiro { 127285303Sgshapiro DH_free(dh); 128285303Sgshapiro return(NULL); 129285303Sgshapiro } 130285303Sgshapiro return(dh); 131285303Sgshapiro} 13290792Sgshapiro# endif /* !NO_DH */ 13390792Sgshapiro 13490792Sgshapiro 13590792Sgshapiro/* 13690792Sgshapiro** TLS_RAND_INIT -- initialize STARTTLS random generator 13790792Sgshapiro** 13890792Sgshapiro** Parameters: 13990792Sgshapiro** randfile -- name of file with random data 14090792Sgshapiro** logl -- loglevel 14190792Sgshapiro** 14290792Sgshapiro** Returns: 14390792Sgshapiro** success/failure 14490792Sgshapiro** 14590792Sgshapiro** Side Effects: 14690792Sgshapiro** initializes PRNG for tls library. 14790792Sgshapiro*/ 14890792Sgshapiro 14990792Sgshapiro# define MIN_RAND_BYTES 128 /* 1024 bits */ 15090792Sgshapiro 15190792Sgshapiro# define RF_OK 0 /* randfile OK */ 15290792Sgshapiro# define RF_MISS 1 /* randfile == NULL || *randfile == '\0' */ 15390792Sgshapiro# define RF_UNKNOWN 2 /* unknown prefix for randfile */ 15490792Sgshapiro 15590792Sgshapiro# define RI_NONE 0 /* no init yet */ 15690792Sgshapiro# define RI_SUCCESS 1 /* init was successful */ 15790792Sgshapiro# define RI_FAIL 2 /* init failed */ 15890792Sgshapiro 15990792Sgshapirostatic bool tls_rand_init __P((char *, int)); 16090792Sgshapiro 16190792Sgshapirostatic bool 16290792Sgshapirotls_rand_init(randfile, logl) 16390792Sgshapiro char *randfile; 16490792Sgshapiro int logl; 16590792Sgshapiro{ 16690792Sgshapiro# ifndef HASURANDOMDEV 16790792Sgshapiro /* not required if /dev/urandom exists, OpenSSL does it internally */ 16890792Sgshapiro 16990792Sgshapiro bool ok; 17090792Sgshapiro int randdef; 17190792Sgshapiro static int done = RI_NONE; 17290792Sgshapiro 17390792Sgshapiro /* 17490792Sgshapiro ** initialize PRNG 17590792Sgshapiro */ 17690792Sgshapiro 17790792Sgshapiro /* did we try this before? if yes: return old value */ 17890792Sgshapiro if (done != RI_NONE) 17990792Sgshapiro return done == RI_SUCCESS; 18090792Sgshapiro 18190792Sgshapiro /* set default values */ 18290792Sgshapiro ok = false; 18390792Sgshapiro done = RI_FAIL; 18490792Sgshapiro randdef = (randfile == NULL || *randfile == '\0') ? RF_MISS : RF_OK; 18590792Sgshapiro# if EGD 18690792Sgshapiro if (randdef == RF_OK && sm_strncasecmp(randfile, "egd:", 4) == 0) 18790792Sgshapiro { 18890792Sgshapiro randfile += 4; 18990792Sgshapiro if (RAND_egd(randfile) < 0) 19090792Sgshapiro { 19190792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 19290792Sgshapiro "STARTTLS: RAND_egd(%s) failed: random number generator not seeded", 19390792Sgshapiro randfile); 19490792Sgshapiro } 19590792Sgshapiro else 19690792Sgshapiro ok = true; 19790792Sgshapiro } 19890792Sgshapiro else 19990792Sgshapiro# endif /* EGD */ 20090792Sgshapiro if (randdef == RF_OK && sm_strncasecmp(randfile, "file:", 5) == 0) 20190792Sgshapiro { 20290792Sgshapiro int fd; 20390792Sgshapiro long sff; 20490792Sgshapiro struct stat st; 20590792Sgshapiro 20690792Sgshapiro randfile += 5; 20790792Sgshapiro sff = SFF_SAFEDIRPATH | SFF_NOWLINK 20890792Sgshapiro | SFF_NOGWFILES | SFF_NOWWFILES 20990792Sgshapiro | SFF_NOGRFILES | SFF_NOWRFILES 21090792Sgshapiro | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT; 21194334Sgshapiro if (DontLockReadFiles) 21294334Sgshapiro sff |= SFF_NOLOCK; 21390792Sgshapiro if ((fd = safeopen(randfile, O_RDONLY, 0, sff)) >= 0) 21490792Sgshapiro { 21590792Sgshapiro if (fstat(fd, &st) < 0) 21690792Sgshapiro { 21790792Sgshapiro if (LogLevel > logl) 21890792Sgshapiro sm_syslog(LOG_ERR, NOQID, 21990792Sgshapiro "STARTTLS: can't fstat(%s)", 22090792Sgshapiro randfile); 22190792Sgshapiro } 22290792Sgshapiro else 22390792Sgshapiro { 22490792Sgshapiro bool use, problem; 22590792Sgshapiro 22690792Sgshapiro use = true; 22790792Sgshapiro problem = false; 22890792Sgshapiro 22990792Sgshapiro /* max. age of file: 10 minutes */ 23090792Sgshapiro if (st.st_mtime + 600 < curtime()) 23190792Sgshapiro { 23290792Sgshapiro use = bitnset(DBS_INSUFFICIENTENTROPY, 23390792Sgshapiro DontBlameSendmail); 23490792Sgshapiro problem = true; 23590792Sgshapiro if (LogLevel > logl) 23690792Sgshapiro sm_syslog(LOG_ERR, NOQID, 23790792Sgshapiro "STARTTLS: RandFile %s too old: %s", 23890792Sgshapiro randfile, 23990792Sgshapiro use ? "unsafe" : 24090792Sgshapiro "unusable"); 24190792Sgshapiro } 24290792Sgshapiro if (use && st.st_size < MIN_RAND_BYTES) 24390792Sgshapiro { 24490792Sgshapiro use = bitnset(DBS_INSUFFICIENTENTROPY, 24590792Sgshapiro DontBlameSendmail); 24690792Sgshapiro problem = true; 24790792Sgshapiro if (LogLevel > logl) 24890792Sgshapiro sm_syslog(LOG_ERR, NOQID, 24990792Sgshapiro "STARTTLS: size(%s) < %d: %s", 25090792Sgshapiro randfile, 25190792Sgshapiro MIN_RAND_BYTES, 25290792Sgshapiro use ? "unsafe" : 25390792Sgshapiro "unusable"); 25490792Sgshapiro } 25590792Sgshapiro if (use) 25690792Sgshapiro ok = RAND_load_file(randfile, -1) >= 25790792Sgshapiro MIN_RAND_BYTES; 25890792Sgshapiro if (use && !ok) 25990792Sgshapiro { 26090792Sgshapiro if (LogLevel > logl) 26190792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 26290792Sgshapiro "STARTTLS: RAND_load_file(%s) failed: random number generator not seeded", 26390792Sgshapiro randfile); 26490792Sgshapiro } 26590792Sgshapiro if (problem) 26690792Sgshapiro ok = false; 26790792Sgshapiro } 26890792Sgshapiro if (ok || bitnset(DBS_INSUFFICIENTENTROPY, 26990792Sgshapiro DontBlameSendmail)) 27090792Sgshapiro { 27190792Sgshapiro /* add this even if fstat() failed */ 272168515Sgshapiro RAND_seed((void *) &st, sizeof(st)); 27390792Sgshapiro } 27490792Sgshapiro (void) close(fd); 27590792Sgshapiro } 27690792Sgshapiro else 27790792Sgshapiro { 27890792Sgshapiro if (LogLevel > logl) 27990792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 28090792Sgshapiro "STARTTLS: Warning: safeopen(%s) failed", 28190792Sgshapiro randfile); 28290792Sgshapiro } 28390792Sgshapiro } 28490792Sgshapiro else if (randdef == RF_OK) 28590792Sgshapiro { 28690792Sgshapiro if (LogLevel > logl) 28790792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 28890792Sgshapiro "STARTTLS: Error: no proper random file definition %s", 28990792Sgshapiro randfile); 29090792Sgshapiro randdef = RF_UNKNOWN; 29190792Sgshapiro } 29290792Sgshapiro if (randdef == RF_MISS) 29390792Sgshapiro { 29490792Sgshapiro if (LogLevel > logl) 29590792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 29690792Sgshapiro "STARTTLS: Error: missing random file definition"); 29790792Sgshapiro } 29890792Sgshapiro if (!ok && bitnset(DBS_INSUFFICIENTENTROPY, DontBlameSendmail)) 29990792Sgshapiro { 30090792Sgshapiro int i; 30190792Sgshapiro long r; 30290792Sgshapiro unsigned char buf[MIN_RAND_BYTES]; 30390792Sgshapiro 30490792Sgshapiro /* assert((MIN_RAND_BYTES % sizeof(long)) == 0); */ 30590792Sgshapiro for (i = 0; i <= sizeof(buf) - sizeof(long); i += sizeof(long)) 30690792Sgshapiro { 30790792Sgshapiro r = get_random(); 30890792Sgshapiro (void) memcpy(buf + i, (void *) &r, sizeof(long)); 30990792Sgshapiro } 310168515Sgshapiro RAND_seed(buf, sizeof(buf)); 31190792Sgshapiro if (LogLevel > logl) 31290792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 31390792Sgshapiro "STARTTLS: Warning: random number generator not properly seeded"); 31490792Sgshapiro ok = true; 31590792Sgshapiro } 31690792Sgshapiro done = ok ? RI_SUCCESS : RI_FAIL; 31790792Sgshapiro return ok; 31890792Sgshapiro# else /* ! HASURANDOMDEV */ 31990792Sgshapiro return true; 32090792Sgshapiro# endif /* ! HASURANDOMDEV */ 32190792Sgshapiro} 32290792Sgshapiro/* 32390792Sgshapiro** INIT_TLS_LIBRARY -- Calls functions which setup TLS library for global use. 32490792Sgshapiro** 32590792Sgshapiro** Parameters: 326249729Sgshapiro** fipsmode -- use FIPS? 32790792Sgshapiro** 32890792Sgshapiro** Returns: 32990792Sgshapiro** succeeded? 33090792Sgshapiro*/ 33190792Sgshapiro 33290792Sgshapirobool 333249729Sgshapiroinit_tls_library(fipsmode) 334249729Sgshapiro bool fipsmode; 33590792Sgshapiro{ 336249729Sgshapiro bool bv; 337249729Sgshapiro 33890792Sgshapiro /* basic TLS initialization, ignore result for now */ 33990792Sgshapiro SSL_library_init(); 34090792Sgshapiro SSL_load_error_strings(); 341261363Sgshapiro OpenSSL_add_all_algorithms(); 34290792Sgshapiro# if 0 34390792Sgshapiro /* this is currently a macro for SSL_library_init */ 34490792Sgshapiro SSLeay_add_ssl_algorithms(); 34590792Sgshapiro# endif /* 0 */ 34690792Sgshapiro 347249729Sgshapiro bv = tls_rand_init(RandFile, 7); 348249729Sgshapiro# if _FFR_FIPSMODE 349249729Sgshapiro if (bv && fipsmode) 350249729Sgshapiro { 351249729Sgshapiro if (!FIPS_mode_set(1)) 352249729Sgshapiro { 353249729Sgshapiro unsigned long err; 354249729Sgshapiro 355249729Sgshapiro err = ERR_get_error(); 356249729Sgshapiro if (LogLevel > 0) 357249729Sgshapiro sm_syslog(LOG_ERR, NOQID, 358249729Sgshapiro "STARTTLS=init, FIPSMode=%s", 359249729Sgshapiro ERR_error_string(err, NULL)); 360249729Sgshapiro return false; 361249729Sgshapiro } 362249729Sgshapiro else 363249729Sgshapiro { 364249729Sgshapiro if (LogLevel > 9) 365249729Sgshapiro sm_syslog(LOG_INFO, NOQID, 366249729Sgshapiro "STARTTLS=init, FIPSMode=ok"); 367249729Sgshapiro } 368249729Sgshapiro } 369249729Sgshapiro#endif /* _FFR_FIPSMODE */ 370285303Sgshapiro if (bv && CertFingerprintAlgorithm != NULL) 371285303Sgshapiro { 372285303Sgshapiro const EVP_MD *md; 373285303Sgshapiro 374285303Sgshapiro md = EVP_get_digestbyname(CertFingerprintAlgorithm); 375285303Sgshapiro if (NULL == md) 376285303Sgshapiro { 377285303Sgshapiro bv = false; 378285303Sgshapiro if (LogLevel > 0) 379285303Sgshapiro sm_syslog(LOG_ERR, NOQID, 380285303Sgshapiro "STARTTLS=init, CertFingerprintAlgorithm=%s, status=invalid" 381285303Sgshapiro , CertFingerprintAlgorithm); 382285303Sgshapiro } 383285303Sgshapiro else 384285303Sgshapiro EVP_digest = md; 385285303Sgshapiro } 386249729Sgshapiro return bv; 38790792Sgshapiro} 388285303Sgshapiro 38990792Sgshapiro/* 39090792Sgshapiro** TLS_SET_VERIFY -- request client certificate? 39190792Sgshapiro** 39290792Sgshapiro** Parameters: 39390792Sgshapiro** ctx -- TLS context 39490792Sgshapiro** ssl -- TLS structure 395285303Sgshapiro** vrfy -- request certificate? 39690792Sgshapiro** 39790792Sgshapiro** Returns: 39890792Sgshapiro** none. 39990792Sgshapiro** 40090792Sgshapiro** Side Effects: 40190792Sgshapiro** Sets verification state for TLS 40290792Sgshapiro** 40390792Sgshapiro# if TLS_VRFY_PER_CTX 40490792Sgshapiro** Notice: 40590792Sgshapiro** This is per TLS context, not per TLS structure; 40690792Sgshapiro** the former is global, the latter per connection. 40790792Sgshapiro** It would be nice to do this per connection, but this 40890792Sgshapiro** doesn't work in the current TLS libraries :-( 40990792Sgshapiro# endif * TLS_VRFY_PER_CTX * 41090792Sgshapiro*/ 41190792Sgshapiro 41290792Sgshapirovoid 41390792Sgshapirotls_set_verify(ctx, ssl, vrfy) 41490792Sgshapiro SSL_CTX *ctx; 41590792Sgshapiro SSL *ssl; 41690792Sgshapiro bool vrfy; 41790792Sgshapiro{ 41890792Sgshapiro# if !TLS_VRFY_PER_CTX 41990792Sgshapiro SSL_set_verify(ssl, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); 42090792Sgshapiro# else /* !TLS_VRFY_PER_CTX */ 42190792Sgshapiro SSL_CTX_set_verify(ctx, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, 42290792Sgshapiro NULL); 42390792Sgshapiro# endif /* !TLS_VRFY_PER_CTX */ 42490792Sgshapiro} 42590792Sgshapiro 42690792Sgshapiro/* 42790792Sgshapiro** status in initialization 42890792Sgshapiro** these flags keep track of the status of the initialization 42990792Sgshapiro** i.e., whether a file exists (_EX) and whether it can be used (_OK) 43090792Sgshapiro** [due to permissions] 43190792Sgshapiro*/ 43290792Sgshapiro 433110560Sgshapiro# define TLS_S_NONE 0x00000000 /* none yet */ 434110560Sgshapiro# define TLS_S_CERT_EX 0x00000001 /* cert file exists */ 435110560Sgshapiro# define TLS_S_CERT_OK 0x00000002 /* cert file is ok */ 436110560Sgshapiro# define TLS_S_KEY_EX 0x00000004 /* key file exists */ 437110560Sgshapiro# define TLS_S_KEY_OK 0x00000008 /* key file is ok */ 438110560Sgshapiro# define TLS_S_CERTP_EX 0x00000010 /* CA cert path exists */ 439110560Sgshapiro# define TLS_S_CERTP_OK 0x00000020 /* CA cert path is ok */ 440110560Sgshapiro# define TLS_S_CERTF_EX 0x00000040 /* CA cert file exists */ 441110560Sgshapiro# define TLS_S_CERTF_OK 0x00000080 /* CA cert file is ok */ 442132943Sgshapiro# define TLS_S_CRLF_EX 0x00000100 /* CRL file exists */ 443132943Sgshapiro# define TLS_S_CRLF_OK 0x00000200 /* CRL file is ok */ 44490792Sgshapiro 445285303Sgshapiro# define TLS_S_CERT2_EX 0x00001000 /* 2nd cert file exists */ 446285303Sgshapiro# define TLS_S_CERT2_OK 0x00002000 /* 2nd cert file is ok */ 447285303Sgshapiro# define TLS_S_KEY2_EX 0x00004000 /* 2nd key file exists */ 448285303Sgshapiro# define TLS_S_KEY2_OK 0x00008000 /* 2nd key file is ok */ 44990792Sgshapiro 45090792Sgshapiro# define TLS_S_DH_OK 0x00200000 /* DH cert is ok */ 45190792Sgshapiro# define TLS_S_DHPAR_EX 0x00400000 /* DH param file exists */ 45290792Sgshapiro# define TLS_S_DHPAR_OK 0x00800000 /* DH param file is ok to use */ 45390792Sgshapiro 454125820Sgshapiro/* Type of variable */ 455125820Sgshapiro# define TLS_T_OTHER 0 456125820Sgshapiro# define TLS_T_SRV 1 457125820Sgshapiro# define TLS_T_CLT 2 458125820Sgshapiro 45990792Sgshapiro/* 46090792Sgshapiro** TLS_OK_F -- can var be an absolute filename? 46190792Sgshapiro** 46290792Sgshapiro** Parameters: 46390792Sgshapiro** var -- filename 46490792Sgshapiro** fn -- what is the filename used for? 465125820Sgshapiro** type -- type of variable 46690792Sgshapiro** 46790792Sgshapiro** Returns: 46890792Sgshapiro** ok? 46990792Sgshapiro*/ 47090792Sgshapiro 47190792Sgshapirostatic bool 472125820Sgshapirotls_ok_f(var, fn, type) 47390792Sgshapiro char *var; 47490792Sgshapiro char *fn; 475125820Sgshapiro int type; 47690792Sgshapiro{ 47790792Sgshapiro /* must be absolute pathname */ 47890792Sgshapiro if (var != NULL && *var == '/') 47990792Sgshapiro return true; 48090792Sgshapiro if (LogLevel > 12) 48190792Sgshapiro sm_syslog(LOG_WARNING, NOQID, "STARTTLS: %s%s missing", 482125820Sgshapiro type == TLS_T_SRV ? "Server" : 483132943Sgshapiro (type == TLS_T_CLT ? "Client" : ""), fn); 48490792Sgshapiro return false; 48590792Sgshapiro} 48690792Sgshapiro/* 48790792Sgshapiro** TLS_SAFE_F -- is a file safe to use? 48890792Sgshapiro** 48990792Sgshapiro** Parameters: 49090792Sgshapiro** var -- filename 49190792Sgshapiro** sff -- flags for safefile() 49290792Sgshapiro** srv -- server side? 49390792Sgshapiro** 49490792Sgshapiro** Returns: 49590792Sgshapiro** ok? 49690792Sgshapiro*/ 49790792Sgshapiro 49890792Sgshapirostatic bool 49990792Sgshapirotls_safe_f(var, sff, srv) 50090792Sgshapiro char *var; 50190792Sgshapiro long sff; 50290792Sgshapiro bool srv; 50390792Sgshapiro{ 50490792Sgshapiro int ret; 50590792Sgshapiro 50690792Sgshapiro if ((ret = safefile(var, RunAsUid, RunAsGid, RunAsUserName, sff, 50790792Sgshapiro S_IRUSR, NULL)) == 0) 50890792Sgshapiro return true; 50990792Sgshapiro if (LogLevel > 7) 51090792Sgshapiro sm_syslog(LOG_WARNING, NOQID, "STARTTLS=%s: file %s unsafe: %s", 51190792Sgshapiro srv ? "server" : "client", var, sm_errstring(ret)); 51290792Sgshapiro return false; 51390792Sgshapiro} 51490792Sgshapiro 51590792Sgshapiro/* 51690792Sgshapiro** TLS_OK_F -- macro to simplify calls to tls_ok_f 51790792Sgshapiro** 51890792Sgshapiro** Parameters: 51990792Sgshapiro** var -- filename 52090792Sgshapiro** fn -- what is the filename used for? 52190792Sgshapiro** req -- is the file required? 52290792Sgshapiro** st -- status bit to set if ok 523125820Sgshapiro** type -- type of variable 52490792Sgshapiro** 52590792Sgshapiro** Side Effects: 52690792Sgshapiro** uses r, ok; may change ok and status. 52790792Sgshapiro** 52890792Sgshapiro*/ 52990792Sgshapiro 530125820Sgshapiro# define TLS_OK_F(var, fn, req, st, type) if (ok) \ 53190792Sgshapiro { \ 532125820Sgshapiro r = tls_ok_f(var, fn, type); \ 53390792Sgshapiro if (r) \ 53490792Sgshapiro status |= st; \ 53590792Sgshapiro else if (req) \ 53690792Sgshapiro ok = false; \ 53790792Sgshapiro } 53890792Sgshapiro 53990792Sgshapiro/* 54090792Sgshapiro** TLS_UNR -- macro to return whether a file should be unreadable 54190792Sgshapiro** 54290792Sgshapiro** Parameters: 54390792Sgshapiro** bit -- flag to test 54490792Sgshapiro** req -- flags 54590792Sgshapiro** 54690792Sgshapiro** Returns: 54790792Sgshapiro** 0/SFF_NORFILES 54890792Sgshapiro*/ 54990792Sgshapiro# define TLS_UNR(bit, req) (bitset(bit, req) ? SFF_NORFILES : 0) 55090792Sgshapiro# define TLS_OUNR(bit, req) (bitset(bit, req) ? SFF_NOWRFILES : 0) 55190792Sgshapiro# define TLS_KEYSFF(req) \ 55290792Sgshapiro (bitnset(DBS_GROUPREADABLEKEYFILE, DontBlameSendmail) ? \ 55390792Sgshapiro TLS_OUNR(TLS_I_KEY_OUNR, req) : \ 55490792Sgshapiro TLS_UNR(TLS_I_KEY_UNR, req)) 55590792Sgshapiro 55690792Sgshapiro/* 55790792Sgshapiro** TLS_SAFE_F -- macro to simplify calls to tls_safe_f 55890792Sgshapiro** 55990792Sgshapiro** Parameters: 56090792Sgshapiro** var -- filename 56190792Sgshapiro** sff -- flags for safefile() 56290792Sgshapiro** req -- is the file required? 56390792Sgshapiro** ex -- does the file exist? 56490792Sgshapiro** st -- status bit to set if ok 56590792Sgshapiro** srv -- server side? 56690792Sgshapiro** 56790792Sgshapiro** Side Effects: 56890792Sgshapiro** uses r, ok, ex; may change ok and status. 56990792Sgshapiro** 57090792Sgshapiro*/ 57190792Sgshapiro 57290792Sgshapiro# define TLS_SAFE_F(var, sff, req, ex, st, srv) if (ex && ok) \ 57390792Sgshapiro { \ 57490792Sgshapiro r = tls_safe_f(var, sff, srv); \ 57590792Sgshapiro if (r) \ 57690792Sgshapiro status |= st; \ 57790792Sgshapiro else if (req) \ 57890792Sgshapiro ok = false; \ 57990792Sgshapiro } 58090792Sgshapiro 581285303Sgshapiro# if _FFR_TLS_SE_OPTS 58290792Sgshapiro/* 583285303Sgshapiro** LOAD_CERTKEY -- load cert/key for TLS session 584285303Sgshapiro** 585285303Sgshapiro** Parameters: 586285303Sgshapiro** ssl -- TLS session context 587285303Sgshapiro** certfile -- filename of certificate 588285303Sgshapiro** keyfile -- filename of private key 589285303Sgshapiro** 590285303Sgshapiro** Returns: 591285303Sgshapiro** succeeded? 592285303Sgshapiro*/ 593285303Sgshapiro 594285303Sgshapirobool 595285303Sgshapiroload_certkey(ssl, srv, certfile, keyfile) 596285303Sgshapiro SSL *ssl; 597285303Sgshapiro bool srv; 598285303Sgshapiro char *certfile; 599285303Sgshapiro char *keyfile; 600285303Sgshapiro{ 601285303Sgshapiro bool ok; 602285303Sgshapiro int r; 603285303Sgshapiro long sff, status; 604285303Sgshapiro unsigned long req; 605285303Sgshapiro char *who; 606285303Sgshapiro 607285303Sgshapiro ok = true; 608285303Sgshapiro who = srv ? "server" : "client"; 609285303Sgshapiro status = TLS_S_NONE; 610285303Sgshapiro req = TLS_I_CERT_EX|TLS_I_KEY_EX; 611285303Sgshapiro TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req), 612285303Sgshapiro TLS_S_CERT_EX, srv ? TLS_T_SRV : TLS_T_CLT); 613285303Sgshapiro TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req), 614285303Sgshapiro TLS_S_KEY_EX, srv ? TLS_T_SRV : TLS_T_CLT); 615285303Sgshapiro 616285303Sgshapiro /* certfile etc. must be "safe". */ 617285303Sgshapiro sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK 618285303Sgshapiro | SFF_NOGWFILES | SFF_NOWWFILES 619285303Sgshapiro | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT; 620285303Sgshapiro if (DontLockReadFiles) 621285303Sgshapiro sff |= SFF_NOLOCK; 622285303Sgshapiro 623285303Sgshapiro TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req), 624285303Sgshapiro bitset(TLS_I_CERT_EX, req), 625285303Sgshapiro bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv); 626285303Sgshapiro TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req), 627285303Sgshapiro bitset(TLS_I_KEY_EX, req), 628285303Sgshapiro bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv); 629285303Sgshapiro 630285303Sgshapiro# define SSL_use_cert(ssl, certfile) \ 631285303Sgshapiro SSL_use_certificate_file(ssl, certfile, SSL_FILETYPE_PEM) 632285303Sgshapiro# define SSL_USE_CERT "SSL_use_certificate_file" 633285303Sgshapiro 634285303Sgshapiro if (bitset(TLS_S_CERT_OK, status) && 635285303Sgshapiro SSL_use_cert(ssl, certfile) <= 0) 636285303Sgshapiro { 637285303Sgshapiro if (LogLevel > 7) 638285303Sgshapiro { 639285303Sgshapiro sm_syslog(LOG_WARNING, NOQID, 640285303Sgshapiro "STARTTLS=%s, error: %s(%s) failed", 641285303Sgshapiro who, SSL_USE_CERT, certfile); 642285303Sgshapiro if (LogLevel > 9) 643285303Sgshapiro tlslogerr(LOG_WARNING, who); 644285303Sgshapiro } 645285303Sgshapiro if (bitset(TLS_I_USE_CERT, req)) 646285303Sgshapiro return false; 647285303Sgshapiro } 648285303Sgshapiro if (bitset(TLS_S_KEY_OK, status) && 649285303Sgshapiro SSL_use_PrivateKey_file(ssl, keyfile, SSL_FILETYPE_PEM) <= 0) 650285303Sgshapiro { 651285303Sgshapiro if (LogLevel > 7) 652285303Sgshapiro { 653285303Sgshapiro sm_syslog(LOG_WARNING, NOQID, 654285303Sgshapiro "STARTTLS=%s, error: SSL_use_PrivateKey_file(%s) failed", 655285303Sgshapiro who, keyfile); 656285303Sgshapiro if (LogLevel > 9) 657285303Sgshapiro tlslogerr(LOG_WARNING, who); 658285303Sgshapiro } 659285303Sgshapiro if (bitset(TLS_I_USE_KEY, req)) 660285303Sgshapiro return false; 661285303Sgshapiro } 662285303Sgshapiro 663285303Sgshapiro /* check the private key */ 664285303Sgshapiro if (bitset(TLS_S_KEY_OK, status) && 665285303Sgshapiro (r = SSL_check_private_key(ssl)) <= 0) 666285303Sgshapiro { 667285303Sgshapiro /* Private key does not match the certificate public key */ 668285303Sgshapiro if (LogLevel > 5) 669285303Sgshapiro { 670285303Sgshapiro sm_syslog(LOG_WARNING, NOQID, 671285303Sgshapiro "STARTTLS=%s, error: SSL_check_private_key failed(%s): %d", 672285303Sgshapiro who, keyfile, r); 673285303Sgshapiro if (LogLevel > 9) 674285303Sgshapiro tlslogerr(LOG_WARNING, who); 675285303Sgshapiro } 676285303Sgshapiro if (bitset(TLS_I_USE_KEY, req)) 677285303Sgshapiro return false; 678285303Sgshapiro } 679285303Sgshapiro 680285303Sgshapiro return true; 681285303Sgshapiro} 682285303Sgshapiro# endif /* _FFR_TLS_SE_OPTS */ 683285303Sgshapiro 684285303Sgshapiro/* 68590792Sgshapiro** INITTLS -- initialize TLS 68690792Sgshapiro** 68790792Sgshapiro** Parameters: 68890792Sgshapiro** ctx -- pointer to context 68990792Sgshapiro** req -- requirements for initialization (see sendmail.h) 690203004Sgshapiro** options -- options 69190792Sgshapiro** srv -- server side? 69290792Sgshapiro** certfile -- filename of certificate 69390792Sgshapiro** keyfile -- filename of private key 69490792Sgshapiro** cacertpath -- path to CAs 69590792Sgshapiro** cacertfile -- file with CA(s) 69690792Sgshapiro** dhparam -- parameters for DH 69790792Sgshapiro** 69890792Sgshapiro** Returns: 69990792Sgshapiro** succeeded? 70090792Sgshapiro*/ 70190792Sgshapiro 702157001Sgshapiro/* 703157001Sgshapiro** The session_id_context identifies the service that created a session. 704157001Sgshapiro** This information is used to distinguish between multiple TLS-based 705157001Sgshapiro** servers running on the same server. We use the name of the mail system. 706157001Sgshapiro** Note: the session cache is not persistent. 707157001Sgshapiro*/ 708157001Sgshapiro 709157001Sgshapirostatic char server_session_id_context[] = "sendmail8"; 710157001Sgshapiro 711159609Sgshapiro/* 0.9.8a and b have a problem with SSL_OP_TLS_BLOCK_PADDING_BUG */ 712159609Sgshapiro#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) 713159609Sgshapiro# define SM_SSL_OP_TLS_BLOCK_PADDING_BUG 1 714159609Sgshapiro#else 715159609Sgshapiro# define SM_SSL_OP_TLS_BLOCK_PADDING_BUG 0 716159609Sgshapiro#endif 717159609Sgshapiro 71890792Sgshapirobool 719203004Sgshapiroinittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhparam) 72090792Sgshapiro SSL_CTX **ctx; 72190792Sgshapiro unsigned long req; 722285303Sgshapiro unsigned long options; 72390792Sgshapiro bool srv; 72490792Sgshapiro char *certfile, *keyfile, *cacertpath, *cacertfile, *dhparam; 72590792Sgshapiro{ 72690792Sgshapiro# if !NO_DH 72790792Sgshapiro static DH *dh = NULL; 72890792Sgshapiro# endif /* !NO_DH */ 72990792Sgshapiro int r; 73090792Sgshapiro bool ok; 731203004Sgshapiro long sff, status; 73290792Sgshapiro char *who; 73390792Sgshapiro char *cf2, *kf2; 734285303Sgshapiro# if SM_CONF_SHM 73590792Sgshapiro extern int ShmId; 736285303Sgshapiro# endif /* SM_CONF_SHM */ 737132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 738132943Sgshapiro BIO *crl_file; 739132943Sgshapiro X509_CRL *crl; 740132943Sgshapiro X509_STORE *store; 741132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 742159609Sgshapiro#if SM_SSL_OP_TLS_BLOCK_PADDING_BUG 743159609Sgshapiro long rt_version; 744159609Sgshapiro STACK_OF(SSL_COMP) *comp_methods; 745159609Sgshapiro#endif 74690792Sgshapiro 74790792Sgshapiro status = TLS_S_NONE; 74890792Sgshapiro who = srv ? "server" : "client"; 74990792Sgshapiro if (ctx == NULL) 750159609Sgshapiro { 75190792Sgshapiro syserr("STARTTLS=%s, inittls: ctx == NULL", who); 752159609Sgshapiro /* NOTREACHED */ 753159609Sgshapiro SM_ASSERT(ctx != NULL); 754159609Sgshapiro } 75590792Sgshapiro 75690792Sgshapiro /* already initialized? (we could re-init...) */ 75790792Sgshapiro if (*ctx != NULL) 75890792Sgshapiro return true; 75990792Sgshapiro ok = true; 76090792Sgshapiro 76190792Sgshapiro /* 76290792Sgshapiro ** look for a second filename: it must be separated by a ',' 76390792Sgshapiro ** no blanks allowed (they won't be skipped). 76490792Sgshapiro ** we change a global variable here! this change will be undone 76590792Sgshapiro ** before return from the function but only if it returns true. 76690792Sgshapiro ** this isn't a problem since in a failure case this function 76790792Sgshapiro ** won't be called again with the same (overwritten) values. 76890792Sgshapiro ** otherwise each return must be replaced with a goto endinittls. 76990792Sgshapiro */ 77090792Sgshapiro 77190792Sgshapiro cf2 = NULL; 77290792Sgshapiro kf2 = NULL; 77390792Sgshapiro if (certfile != NULL && (cf2 = strchr(certfile, ',')) != NULL) 77490792Sgshapiro { 77590792Sgshapiro *cf2++ = '\0'; 77690792Sgshapiro if (keyfile != NULL && (kf2 = strchr(keyfile, ',')) != NULL) 77790792Sgshapiro *kf2++ = '\0'; 77890792Sgshapiro } 77990792Sgshapiro 78090792Sgshapiro /* 78190792Sgshapiro ** Check whether files/paths are defined 78290792Sgshapiro */ 78390792Sgshapiro 78490792Sgshapiro TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req), 785125820Sgshapiro TLS_S_CERT_EX, srv ? TLS_T_SRV : TLS_T_CLT); 78690792Sgshapiro TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req), 787125820Sgshapiro TLS_S_KEY_EX, srv ? TLS_T_SRV : TLS_T_CLT); 788110560Sgshapiro TLS_OK_F(cacertpath, "CACertPath", bitset(TLS_I_CERTP_EX, req), 789125820Sgshapiro TLS_S_CERTP_EX, TLS_T_OTHER); 790110560Sgshapiro TLS_OK_F(cacertfile, "CACertFile", bitset(TLS_I_CERTF_EX, req), 791125820Sgshapiro TLS_S_CERTF_EX, TLS_T_OTHER); 79290792Sgshapiro 793132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 794132943Sgshapiro TLS_OK_F(CRLFile, "CRLFile", bitset(TLS_I_CRLF_EX, req), 795132943Sgshapiro TLS_S_CRLF_EX, TLS_T_OTHER); 796132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 797132943Sgshapiro 79890792Sgshapiro /* 79990792Sgshapiro ** if the second file is specified it must exist 80090792Sgshapiro ** XXX: it is possible here to define only one of those files 80190792Sgshapiro */ 80290792Sgshapiro 80390792Sgshapiro if (cf2 != NULL) 80490792Sgshapiro { 80590792Sgshapiro TLS_OK_F(cf2, "CertFile", bitset(TLS_I_CERT_EX, req), 806125820Sgshapiro TLS_S_CERT2_EX, srv ? TLS_T_SRV : TLS_T_CLT); 80790792Sgshapiro } 80890792Sgshapiro if (kf2 != NULL) 80990792Sgshapiro { 81090792Sgshapiro TLS_OK_F(kf2, "KeyFile", bitset(TLS_I_KEY_EX, req), 811125820Sgshapiro TLS_S_KEY2_EX, srv ? TLS_T_SRV : TLS_T_CLT); 81290792Sgshapiro } 81390792Sgshapiro 81490792Sgshapiro /* 81590792Sgshapiro ** valid values for dhparam are (only the first char is checked) 81690792Sgshapiro ** none no parameters: don't use DH 817285303Sgshapiro ** i use precomputed 2048 bit parameters 818261363Sgshapiro ** 512 use precomputed 512 bit parameters 81990792Sgshapiro ** 1024 generate 1024 bit parameters 820261363Sgshapiro ** 2048 generate 2048 bit parameters 82190792Sgshapiro ** /file/name read parameters from /file/name 82290792Sgshapiro */ 82390792Sgshapiro 824285303Sgshapiro#define SET_DH_DFL \ 825285303Sgshapiro do { \ 826285303Sgshapiro dhparam = "I"; \ 827285303Sgshapiro req |= TLS_I_DHFIXED; \ 828285303Sgshapiro } while (0) 829285303Sgshapiro 83090792Sgshapiro if (bitset(TLS_I_TRY_DH, req)) 83190792Sgshapiro { 83290792Sgshapiro if (dhparam != NULL) 83390792Sgshapiro { 83490792Sgshapiro char c = *dhparam; 83590792Sgshapiro 83690792Sgshapiro if (c == '1') 83790792Sgshapiro req |= TLS_I_DH1024; 838285303Sgshapiro else if (c == 'I' || c == 'i') 839285303Sgshapiro req |= TLS_I_DHFIXED; 840261363Sgshapiro else if (c == '2') 841261363Sgshapiro req |= TLS_I_DH2048; 84290792Sgshapiro else if (c == '5') 84390792Sgshapiro req |= TLS_I_DH512; 844285303Sgshapiro else if (c == 'n' || c == 'N') 845285303Sgshapiro req &= ~TLS_I_TRY_DH; 846285303Sgshapiro else if (c != '/') 84790792Sgshapiro { 84890792Sgshapiro if (LogLevel > 12) 84990792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 850285303Sgshapiro "STARTTLS=%s, error: illegal value '%s' for DHParameters", 85190792Sgshapiro who, dhparam); 85290792Sgshapiro dhparam = NULL; 85390792Sgshapiro } 85490792Sgshapiro } 85590792Sgshapiro if (dhparam == NULL) 856285303Sgshapiro SET_DH_DFL; 85790792Sgshapiro else if (*dhparam == '/') 85890792Sgshapiro { 85990792Sgshapiro TLS_OK_F(dhparam, "DHParameters", 86090792Sgshapiro bitset(TLS_I_DHPAR_EX, req), 861125820Sgshapiro TLS_S_DHPAR_EX, TLS_T_OTHER); 86290792Sgshapiro } 86390792Sgshapiro } 86490792Sgshapiro if (!ok) 86590792Sgshapiro return ok; 86690792Sgshapiro 86790792Sgshapiro /* certfile etc. must be "safe". */ 86890792Sgshapiro sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK 86990792Sgshapiro | SFF_NOGWFILES | SFF_NOWWFILES 87090792Sgshapiro | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT; 87190792Sgshapiro if (DontLockReadFiles) 87290792Sgshapiro sff |= SFF_NOLOCK; 87390792Sgshapiro 87490792Sgshapiro TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req), 87590792Sgshapiro bitset(TLS_I_CERT_EX, req), 87690792Sgshapiro bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv); 87790792Sgshapiro TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req), 87890792Sgshapiro bitset(TLS_I_KEY_EX, req), 87990792Sgshapiro bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv); 88090792Sgshapiro TLS_SAFE_F(cacertfile, sff | TLS_UNR(TLS_I_CERTF_UNR, req), 88190792Sgshapiro bitset(TLS_I_CERTF_EX, req), 88290792Sgshapiro bitset(TLS_S_CERTF_EX, status), TLS_S_CERTF_OK, srv); 883285303Sgshapiro if (dhparam != NULL && *dhparam == '/') 884285303Sgshapiro { 885285303Sgshapiro TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req), 886285303Sgshapiro bitset(TLS_I_DHPAR_EX, req), 887285303Sgshapiro bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv); 888285303Sgshapiro if (!bitset(TLS_S_DHPAR_OK, status)) 889285303Sgshapiro SET_DH_DFL; 890285303Sgshapiro } 891132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 892132943Sgshapiro TLS_SAFE_F(CRLFile, sff | TLS_UNR(TLS_I_CRLF_UNR, req), 893132943Sgshapiro bitset(TLS_I_CRLF_EX, req), 894132943Sgshapiro bitset(TLS_S_CRLF_EX, status), TLS_S_CRLF_OK, srv); 895132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 89690792Sgshapiro if (!ok) 89790792Sgshapiro return ok; 89890792Sgshapiro if (cf2 != NULL) 89990792Sgshapiro { 90090792Sgshapiro TLS_SAFE_F(cf2, sff | TLS_UNR(TLS_I_CERT_UNR, req), 90190792Sgshapiro bitset(TLS_I_CERT_EX, req), 90290792Sgshapiro bitset(TLS_S_CERT2_EX, status), TLS_S_CERT2_OK, srv); 90390792Sgshapiro } 90490792Sgshapiro if (kf2 != NULL) 90590792Sgshapiro { 90690792Sgshapiro TLS_SAFE_F(kf2, sff | TLS_KEYSFF(req), 90790792Sgshapiro bitset(TLS_I_KEY_EX, req), 90890792Sgshapiro bitset(TLS_S_KEY2_EX, status), TLS_S_KEY2_OK, srv); 90990792Sgshapiro } 91090792Sgshapiro 91190792Sgshapiro /* create a method and a new context */ 91290792Sgshapiro if ((*ctx = SSL_CTX_new(srv ? SSLv23_server_method() : 91390792Sgshapiro SSLv23_client_method())) == NULL) 91490792Sgshapiro { 91590792Sgshapiro if (LogLevel > 7) 91690792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 91790792Sgshapiro "STARTTLS=%s, error: SSL_CTX_new(SSLv23_%s_method()) failed", 91890792Sgshapiro who, who); 91990792Sgshapiro if (LogLevel > 9) 920249729Sgshapiro tlslogerr(LOG_WARNING, who); 92190792Sgshapiro return false; 92290792Sgshapiro } 92390792Sgshapiro 924132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 925132943Sgshapiro if (CRLFile != NULL) 926132943Sgshapiro { 927132943Sgshapiro /* get a pointer to the current certificate validation store */ 928132943Sgshapiro store = SSL_CTX_get_cert_store(*ctx); /* does not fail */ 929132943Sgshapiro crl_file = BIO_new(BIO_s_file_internal()); 930132943Sgshapiro if (crl_file != NULL) 931132943Sgshapiro { 932132943Sgshapiro if (BIO_read_filename(crl_file, CRLFile) >= 0) 933132943Sgshapiro { 934132943Sgshapiro crl = PEM_read_bio_X509_CRL(crl_file, NULL, 935132943Sgshapiro NULL, NULL); 936132943Sgshapiro BIO_free(crl_file); 937132943Sgshapiro X509_STORE_add_crl(store, crl); 938132943Sgshapiro X509_CRL_free(crl); 939132943Sgshapiro X509_STORE_set_flags(store, 940132943Sgshapiro X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); 941132943Sgshapiro X509_STORE_set_verify_cb_func(store, 942132943Sgshapiro x509_verify_cb); 943132943Sgshapiro } 944132943Sgshapiro else 945132943Sgshapiro { 946132943Sgshapiro if (LogLevel > 9) 947132943Sgshapiro { 948132943Sgshapiro sm_syslog(LOG_WARNING, NOQID, 949132943Sgshapiro "STARTTLS=%s, error: PEM_read_bio_X509_CRL(%s)=failed", 950132943Sgshapiro who, CRLFile); 951132943Sgshapiro } 952132943Sgshapiro 953132943Sgshapiro /* avoid memory leaks */ 954132943Sgshapiro BIO_free(crl_file); 955132943Sgshapiro return false; 956132943Sgshapiro } 957132943Sgshapiro 958132943Sgshapiro } 959132943Sgshapiro else if (LogLevel > 9) 960132943Sgshapiro sm_syslog(LOG_WARNING, NOQID, 961132943Sgshapiro "STARTTLS=%s, error: BIO_new=failed", who); 962132943Sgshapiro } 963168515Sgshapiro else 964168515Sgshapiro store = NULL; 965132943Sgshapiro# if _FFR_CRLPATH 966168515Sgshapiro if (CRLPath != NULL && store != NULL) 967132943Sgshapiro { 968132943Sgshapiro X509_LOOKUP *lookup; 969132943Sgshapiro 970132943Sgshapiro lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); 971132943Sgshapiro if (lookup == NULL) 972132943Sgshapiro { 973132943Sgshapiro if (LogLevel > 9) 974132943Sgshapiro { 975132943Sgshapiro sm_syslog(LOG_WARNING, NOQID, 976132943Sgshapiro "STARTTLS=%s, error: X509_STORE_add_lookup(hash)=failed", 977132943Sgshapiro who, CRLFile); 978132943Sgshapiro } 979132943Sgshapiro return false; 980132943Sgshapiro } 981132943Sgshapiro X509_LOOKUP_add_dir(lookup, CRLPath, X509_FILETYPE_PEM); 982132943Sgshapiro X509_STORE_set_flags(store, 983132943Sgshapiro X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); 984132943Sgshapiro } 985132943Sgshapiro# endif /* _FFR_CRLPATH */ 986132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 987132943Sgshapiro 98890792Sgshapiro# if TLS_NO_RSA 98990792Sgshapiro /* turn off backward compatibility, required for no-rsa */ 99090792Sgshapiro SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2); 99190792Sgshapiro# endif /* TLS_NO_RSA */ 99290792Sgshapiro 99390792Sgshapiro 99490792Sgshapiro# if !TLS_NO_RSA 99590792Sgshapiro /* 99690792Sgshapiro ** Create a temporary RSA key 99790792Sgshapiro ** XXX Maybe we shouldn't create this always (even though it 99890792Sgshapiro ** is only at startup). 99990792Sgshapiro ** It is a time-consuming operation and it is not always necessary. 100090792Sgshapiro ** maybe we should do it only on demand... 100190792Sgshapiro */ 100290792Sgshapiro 100390792Sgshapiro if (bitset(TLS_I_RSA_TMP, req) 1004285303Sgshapiro# if SM_CONF_SHM 100590792Sgshapiro && ShmId != SM_SHM_NO_ID && 100690792Sgshapiro (rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, 100790792Sgshapiro NULL)) == NULL 1008285303Sgshapiro# else /* SM_CONF_SHM */ 100990792Sgshapiro && 0 /* no shared memory: no need to generate key now */ 1010285303Sgshapiro# endif /* SM_CONF_SHM */ 101190792Sgshapiro ) 101290792Sgshapiro { 101390792Sgshapiro if (LogLevel > 7) 101490792Sgshapiro { 101590792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 101690792Sgshapiro "STARTTLS=%s, error: RSA_generate_key failed", 101790792Sgshapiro who); 101890792Sgshapiro if (LogLevel > 9) 1019249729Sgshapiro tlslogerr(LOG_WARNING, who); 102090792Sgshapiro } 102190792Sgshapiro return false; 102290792Sgshapiro } 102390792Sgshapiro# endif /* !TLS_NO_RSA */ 102490792Sgshapiro 102590792Sgshapiro /* 102690792Sgshapiro ** load private key 102790792Sgshapiro ** XXX change this for DSA-only version 102890792Sgshapiro */ 102990792Sgshapiro 103090792Sgshapiro if (bitset(TLS_S_KEY_OK, status) && 103190792Sgshapiro SSL_CTX_use_PrivateKey_file(*ctx, keyfile, 103290792Sgshapiro SSL_FILETYPE_PEM) <= 0) 103390792Sgshapiro { 103490792Sgshapiro if (LogLevel > 7) 103590792Sgshapiro { 103690792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 103790792Sgshapiro "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed", 103890792Sgshapiro who, keyfile); 103990792Sgshapiro if (LogLevel > 9) 1040249729Sgshapiro tlslogerr(LOG_WARNING, who); 104190792Sgshapiro } 104290792Sgshapiro if (bitset(TLS_I_USE_KEY, req)) 104390792Sgshapiro return false; 104490792Sgshapiro } 104590792Sgshapiro 1046285303Sgshapiro#if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE 1047285303Sgshapiro# define SSL_CTX_use_cert(ssl_ctx, certfile) \ 1048285303Sgshapiro SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile) 1049285303Sgshapiro# define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_chain_file" 1050285303Sgshapiro#else 1051285303Sgshapiro# define SSL_CTX_use_cert(ssl_ctx, certfile) \ 1052285303Sgshapiro SSL_CTX_use_certificate_file(ssl_ctx, certfile, SSL_FILETYPE_PEM) 1053285303Sgshapiro# define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_file" 1054285303Sgshapiro#endif 1055285303Sgshapiro 105690792Sgshapiro /* get the certificate file */ 105790792Sgshapiro if (bitset(TLS_S_CERT_OK, status) && 1058285303Sgshapiro SSL_CTX_use_cert(*ctx, certfile) <= 0) 105990792Sgshapiro { 106090792Sgshapiro if (LogLevel > 7) 106190792Sgshapiro { 106290792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 1063285303Sgshapiro "STARTTLS=%s, error: %s(%s) failed", 1064285303Sgshapiro who, SSL_CTX_USE_CERT, certfile); 106590792Sgshapiro if (LogLevel > 9) 1066249729Sgshapiro tlslogerr(LOG_WARNING, who); 106790792Sgshapiro } 106890792Sgshapiro if (bitset(TLS_I_USE_CERT, req)) 106990792Sgshapiro return false; 107090792Sgshapiro } 107190792Sgshapiro 107290792Sgshapiro /* check the private key */ 107390792Sgshapiro if (bitset(TLS_S_KEY_OK, status) && 107490792Sgshapiro (r = SSL_CTX_check_private_key(*ctx)) <= 0) 107590792Sgshapiro { 107690792Sgshapiro /* Private key does not match the certificate public key */ 107790792Sgshapiro if (LogLevel > 5) 107890792Sgshapiro { 107990792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 108090792Sgshapiro "STARTTLS=%s, error: SSL_CTX_check_private_key failed(%s): %d", 108190792Sgshapiro who, keyfile, r); 108290792Sgshapiro if (LogLevel > 9) 1083249729Sgshapiro tlslogerr(LOG_WARNING, who); 108490792Sgshapiro } 108590792Sgshapiro if (bitset(TLS_I_USE_KEY, req)) 108690792Sgshapiro return false; 108790792Sgshapiro } 108890792Sgshapiro 108990792Sgshapiro /* XXX this code is pretty much duplicated from above! */ 109090792Sgshapiro 109190792Sgshapiro /* load private key */ 109290792Sgshapiro if (bitset(TLS_S_KEY2_OK, status) && 109390792Sgshapiro SSL_CTX_use_PrivateKey_file(*ctx, kf2, SSL_FILETYPE_PEM) <= 0) 109490792Sgshapiro { 109590792Sgshapiro if (LogLevel > 7) 109690792Sgshapiro { 109790792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 109890792Sgshapiro "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed", 109990792Sgshapiro who, kf2); 110090792Sgshapiro if (LogLevel > 9) 1101249729Sgshapiro tlslogerr(LOG_WARNING, who); 110290792Sgshapiro } 110390792Sgshapiro } 110490792Sgshapiro 110590792Sgshapiro /* get the certificate file */ 110690792Sgshapiro if (bitset(TLS_S_CERT2_OK, status) && 1107285303Sgshapiro SSL_CTX_use_cert(*ctx, cf2) <= 0) 110890792Sgshapiro { 110990792Sgshapiro if (LogLevel > 7) 111090792Sgshapiro { 111190792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 1112285303Sgshapiro "STARTTLS=%s, error: %s(%s) failed", 1113285303Sgshapiro who, SSL_CTX_USE_CERT, cf2); 111490792Sgshapiro if (LogLevel > 9) 1115249729Sgshapiro tlslogerr(LOG_WARNING, who); 111690792Sgshapiro } 111790792Sgshapiro } 111890792Sgshapiro 111990792Sgshapiro /* also check the private key */ 112090792Sgshapiro if (bitset(TLS_S_KEY2_OK, status) && 112190792Sgshapiro (r = SSL_CTX_check_private_key(*ctx)) <= 0) 112290792Sgshapiro { 112390792Sgshapiro /* Private key does not match the certificate public key */ 112490792Sgshapiro if (LogLevel > 5) 112590792Sgshapiro { 112690792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 112790792Sgshapiro "STARTTLS=%s, error: SSL_CTX_check_private_key 2 failed: %d", 112890792Sgshapiro who, r); 112990792Sgshapiro if (LogLevel > 9) 1130249729Sgshapiro tlslogerr(LOG_WARNING, who); 113190792Sgshapiro } 113290792Sgshapiro } 113390792Sgshapiro 113490792Sgshapiro /* SSL_CTX_set_quiet_shutdown(*ctx, 1); violation of standard? */ 113590792Sgshapiro 1136159609Sgshapiro#if SM_SSL_OP_TLS_BLOCK_PADDING_BUG 1137159609Sgshapiro 1138159609Sgshapiro /* 1139159609Sgshapiro ** In OpenSSL 0.9.8[ab], enabling zlib compression breaks the 1140159609Sgshapiro ** padding bug work-around, leading to false positives and 1141159609Sgshapiro ** failed connections. We may not interoperate with systems 1142159609Sgshapiro ** with the bug, but this is better than breaking on all 0.9.8[ab] 1143159609Sgshapiro ** systems that have zlib support enabled. 1144159609Sgshapiro ** Note: this checks the runtime version of the library, not 1145159609Sgshapiro ** just the compile time version. 1146159609Sgshapiro */ 1147159609Sgshapiro 1148159609Sgshapiro rt_version = SSLeay(); 1149159609Sgshapiro if (rt_version >= 0x00908000L && rt_version <= 0x0090802fL) 1150159609Sgshapiro { 1151159609Sgshapiro comp_methods = SSL_COMP_get_compression_methods(); 1152159609Sgshapiro if (comp_methods != NULL && sk_SSL_COMP_num(comp_methods) > 0) 1153159609Sgshapiro options &= ~SSL_OP_TLS_BLOCK_PADDING_BUG; 1154159609Sgshapiro } 1155159609Sgshapiro#endif 1156285303Sgshapiro SSL_CTX_set_options(*ctx, (long) options); 1157159609Sgshapiro 115890792Sgshapiro# if !NO_DH 115990792Sgshapiro /* Diffie-Hellman initialization */ 116090792Sgshapiro if (bitset(TLS_I_TRY_DH, req)) 116190792Sgshapiro { 1162261363Sgshapiro#if _FFR_TLS_EC 1163261363Sgshapiro EC_KEY *ecdh; 1164261363Sgshapiro#endif /* _FFR_TLS_EC */ 1165285303Sgshapiro 1166285303Sgshapiro if (tTd(96, 8)) 1167285303Sgshapiro sm_dprintf("inittls: req=%#lx, status=%#lx\n", 1168285303Sgshapiro req, status); 116990792Sgshapiro if (bitset(TLS_S_DHPAR_OK, status)) 117090792Sgshapiro { 117190792Sgshapiro BIO *bio; 117290792Sgshapiro 117390792Sgshapiro if ((bio = BIO_new_file(dhparam, "r")) != NULL) 117490792Sgshapiro { 117590792Sgshapiro dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); 117690792Sgshapiro BIO_free(bio); 117790792Sgshapiro if (dh == NULL && LogLevel > 7) 117890792Sgshapiro { 117990792Sgshapiro unsigned long err; 118090792Sgshapiro 118190792Sgshapiro err = ERR_get_error(); 118290792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 118390792Sgshapiro "STARTTLS=%s, error: cannot read DH parameters(%s): %s", 118490792Sgshapiro who, dhparam, 118590792Sgshapiro ERR_error_string(err, NULL)); 118690792Sgshapiro if (LogLevel > 9) 1187249729Sgshapiro tlslogerr(LOG_WARNING, who); 1188285303Sgshapiro SET_DH_DFL; 118990792Sgshapiro } 119090792Sgshapiro } 119190792Sgshapiro else 119290792Sgshapiro { 119390792Sgshapiro if (LogLevel > 5) 119490792Sgshapiro { 119590792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 119690792Sgshapiro "STARTTLS=%s, error: BIO_new_file(%s) failed", 119790792Sgshapiro who, dhparam); 119890792Sgshapiro if (LogLevel > 9) 1199249729Sgshapiro tlslogerr(LOG_WARNING, who); 120090792Sgshapiro } 120190792Sgshapiro } 120290792Sgshapiro } 1203261363Sgshapiro if (dh == NULL && bitset(TLS_I_DH1024|TLS_I_DH2048, req)) 120490792Sgshapiro { 1205261363Sgshapiro int bits; 120690792Sgshapiro DSA *dsa; 120790792Sgshapiro 1208261363Sgshapiro bits = bitset(TLS_I_DH2048, req) ? 2048 : 1024; 1209261363Sgshapiro if (tTd(96, 2)) 1210261363Sgshapiro sm_dprintf("inittls: Generating %d bit DH parameters\n", bits); 1211261363Sgshapiro 1212261363Sgshapiro /* this takes a while! */ 1213261363Sgshapiro dsa = DSA_generate_parameters(bits, NULL, 0, NULL, 121490792Sgshapiro NULL, 0, NULL); 121590792Sgshapiro dh = DSA_dup_DH(dsa); 121690792Sgshapiro DSA_free(dsa); 121790792Sgshapiro } 1218285303Sgshapiro else if (dh == NULL && bitset(TLS_I_DHFIXED, req)) 1219261363Sgshapiro { 1220261363Sgshapiro if (tTd(96, 2)) 1221285303Sgshapiro sm_dprintf("inittls: Using precomputed 2048 bit DH parameters\n"); 1222285303Sgshapiro dh = get_dh2048(); 1223285303Sgshapiro } 1224285303Sgshapiro else if (dh == NULL && bitset(TLS_I_DH512, req)) 1225285303Sgshapiro { 1226285303Sgshapiro if (tTd(96, 2)) 1227261363Sgshapiro sm_dprintf("inittls: Using precomputed 512 bit DH parameters\n"); 122890792Sgshapiro dh = get_dh512(); 1229261363Sgshapiro } 123090792Sgshapiro 123190792Sgshapiro if (dh == NULL) 123290792Sgshapiro { 123390792Sgshapiro if (LogLevel > 9) 123490792Sgshapiro { 123590792Sgshapiro unsigned long err; 123690792Sgshapiro 123790792Sgshapiro err = ERR_get_error(); 123890792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 123990792Sgshapiro "STARTTLS=%s, error: cannot read or set DH parameters(%s): %s", 124090792Sgshapiro who, dhparam, 124190792Sgshapiro ERR_error_string(err, NULL)); 124290792Sgshapiro } 124390792Sgshapiro if (bitset(TLS_I_REQ_DH, req)) 124490792Sgshapiro return false; 124590792Sgshapiro } 124690792Sgshapiro else 124790792Sgshapiro { 124890792Sgshapiro /* important to avoid small subgroup attacks */ 124990792Sgshapiro SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_DH_USE); 1250261363Sgshapiro 1251261363Sgshapiro SSL_CTX_set_tmp_dh(*ctx, dh); 125290792Sgshapiro if (LogLevel > 13) 125390792Sgshapiro sm_syslog(LOG_INFO, NOQID, 125490792Sgshapiro "STARTTLS=%s, Diffie-Hellman init, key=%d bit (%c)", 125590792Sgshapiro who, 8 * DH_size(dh), *dhparam); 125690792Sgshapiro DH_free(dh); 125790792Sgshapiro } 1258261363Sgshapiro 1259261363Sgshapiro#if _FFR_TLS_EC 1260261363Sgshapiro ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 1261261363Sgshapiro if (ecdh != NULL) 1262261363Sgshapiro { 1263261363Sgshapiro SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_ECDH_USE); 1264261363Sgshapiro SSL_CTX_set_tmp_ecdh(*ctx, ecdh); 1265261363Sgshapiro EC_KEY_free(ecdh); 1266261363Sgshapiro } 1267261363Sgshapiro#endif /* _FFR_TLS_EC */ 1268261363Sgshapiro 126990792Sgshapiro } 127090792Sgshapiro# endif /* !NO_DH */ 127190792Sgshapiro 127290792Sgshapiro 127390792Sgshapiro /* XXX do we need this cache here? */ 127490792Sgshapiro if (bitset(TLS_I_CACHE, req)) 1275157001Sgshapiro { 1276157001Sgshapiro SSL_CTX_sess_set_cache_size(*ctx, 1); 1277157001Sgshapiro SSL_CTX_set_timeout(*ctx, 1); 1278157001Sgshapiro SSL_CTX_set_session_id_context(*ctx, 1279157001Sgshapiro (void *) &server_session_id_context, 1280157001Sgshapiro sizeof(server_session_id_context)); 1281157001Sgshapiro (void) SSL_CTX_set_session_cache_mode(*ctx, 1282157001Sgshapiro SSL_SESS_CACHE_SERVER); 1283157001Sgshapiro } 1284157001Sgshapiro else 1285157001Sgshapiro { 1286157001Sgshapiro (void) SSL_CTX_set_session_cache_mode(*ctx, 1287157001Sgshapiro SSL_SESS_CACHE_OFF); 1288157001Sgshapiro } 128990792Sgshapiro 129090792Sgshapiro /* load certificate locations and default CA paths */ 129190792Sgshapiro if (bitset(TLS_S_CERTP_EX, status) && bitset(TLS_S_CERTF_EX, status)) 129290792Sgshapiro { 129390792Sgshapiro if ((r = SSL_CTX_load_verify_locations(*ctx, cacertfile, 129490792Sgshapiro cacertpath)) == 1) 129590792Sgshapiro { 129690792Sgshapiro# if !TLS_NO_RSA 129790792Sgshapiro if (bitset(TLS_I_RSA_TMP, req)) 129890792Sgshapiro SSL_CTX_set_tmp_rsa_callback(*ctx, tmp_rsa_key); 129990792Sgshapiro# endif /* !TLS_NO_RSA */ 130090792Sgshapiro 130190792Sgshapiro /* 130290792Sgshapiro ** We have to install our own verify callback: 130390792Sgshapiro ** SSL_VERIFY_PEER requests a client cert but even 130490792Sgshapiro ** though *FAIL_IF* isn't set, the connection 130590792Sgshapiro ** will be aborted if the client presents a cert 130690792Sgshapiro ** that is not "liked" (can't be verified?) by 130790792Sgshapiro ** the TLS library :-( 130890792Sgshapiro */ 130990792Sgshapiro 131090792Sgshapiro /* 131190792Sgshapiro ** XXX currently we could call tls_set_verify() 131290792Sgshapiro ** but we hope that that function will later on 131390792Sgshapiro ** only set the mode per connection. 131490792Sgshapiro */ 131590792Sgshapiro SSL_CTX_set_verify(*ctx, 131690792Sgshapiro bitset(TLS_I_NO_VRFY, req) ? SSL_VERIFY_NONE 131790792Sgshapiro : SSL_VERIFY_PEER, 131890792Sgshapiro NULL); 131990792Sgshapiro 132090792Sgshapiro /* install verify callback */ 132190792Sgshapiro SSL_CTX_set_cert_verify_callback(*ctx, tls_verify_cb, 132290792Sgshapiro NULL); 132390792Sgshapiro SSL_CTX_set_client_CA_list(*ctx, 132490792Sgshapiro SSL_load_client_CA_file(cacertfile)); 132590792Sgshapiro } 132690792Sgshapiro else 132790792Sgshapiro { 132890792Sgshapiro /* 132990792Sgshapiro ** can't load CA data; do we care? 133090792Sgshapiro ** the data is necessary to authenticate the client, 133190792Sgshapiro ** which in turn would be necessary 133290792Sgshapiro ** if we want to allow relaying based on it. 133390792Sgshapiro */ 133490792Sgshapiro if (LogLevel > 5) 133590792Sgshapiro { 133690792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 133790792Sgshapiro "STARTTLS=%s, error: load verify locs %s, %s failed: %d", 133890792Sgshapiro who, cacertpath, cacertfile, r); 133990792Sgshapiro if (LogLevel > 9) 1340249729Sgshapiro tlslogerr(LOG_WARNING, who); 134190792Sgshapiro } 134290792Sgshapiro if (bitset(TLS_I_VRFY_LOC, req)) 134390792Sgshapiro return false; 134490792Sgshapiro } 134590792Sgshapiro } 134690792Sgshapiro 134790792Sgshapiro /* XXX: make this dependent on an option? */ 134890792Sgshapiro if (tTd(96, 9)) 134990792Sgshapiro SSL_CTX_set_info_callback(*ctx, apps_ssl_info_cb); 135090792Sgshapiro 135190792Sgshapiro /* install our own cipher list */ 135290792Sgshapiro if (CipherList != NULL && *CipherList != '\0') 135390792Sgshapiro { 135490792Sgshapiro if (SSL_CTX_set_cipher_list(*ctx, CipherList) <= 0) 135590792Sgshapiro { 135690792Sgshapiro if (LogLevel > 7) 135790792Sgshapiro { 135890792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 135990792Sgshapiro "STARTTLS=%s, error: SSL_CTX_set_cipher_list(%s) failed, list ignored", 136090792Sgshapiro who, CipherList); 136190792Sgshapiro 136290792Sgshapiro if (LogLevel > 9) 1363249729Sgshapiro tlslogerr(LOG_WARNING, who); 136490792Sgshapiro } 136590792Sgshapiro /* failure if setting to this list is required? */ 136690792Sgshapiro } 136790792Sgshapiro } 1368285303Sgshapiro 136990792Sgshapiro if (LogLevel > 12) 137090792Sgshapiro sm_syslog(LOG_INFO, NOQID, "STARTTLS=%s, init=%d", who, ok); 137190792Sgshapiro 1372285303Sgshapiro# if 0 137390792Sgshapiro /* 137490792Sgshapiro ** this label is required if we want to have a "clean" exit 137590792Sgshapiro ** see the comments above at the initialization of cf2 137690792Sgshapiro */ 137790792Sgshapiro 137890792Sgshapiro endinittls: 1379285303Sgshapiro# endif /* 0 */ 138090792Sgshapiro 138190792Sgshapiro /* undo damage to global variables */ 138290792Sgshapiro if (cf2 != NULL) 138390792Sgshapiro *--cf2 = ','; 138490792Sgshapiro if (kf2 != NULL) 138590792Sgshapiro *--kf2 = ','; 138690792Sgshapiro 138790792Sgshapiro return ok; 138890792Sgshapiro} 1389285303Sgshapiro 139090792Sgshapiro/* 1391285303Sgshapiro** CERT_FP -- get cert fingerprint 1392285303Sgshapiro** 1393285303Sgshapiro** Parameters: 1394285303Sgshapiro** cert -- TLS cert 1395285303Sgshapiro** mac -- macro storage 1396285303Sgshapiro** macro -- where to store cert fp 1397285303Sgshapiro** 1398285303Sgshapiro** Returns: 1399285303Sgshapiro** <=0: cert fp calculation failed 1400285303Sgshapiro** >0: cert fp calculation ok 1401285303Sgshapiro*/ 1402285303Sgshapiro 1403285303Sgshapirostatic int 1404285303Sgshapirocert_fp(cert, evp_digest, mac, macro) 1405285303Sgshapiro X509 *cert; 1406285303Sgshapiro const EVP_MD *evp_digest; 1407285303Sgshapiro MACROS_T *mac; 1408285303Sgshapiro char *macro; 1409285303Sgshapiro{ 1410285303Sgshapiro unsigned int n; 1411285303Sgshapiro int r; 1412285303Sgshapiro unsigned char md[EVP_MAX_MD_SIZE]; 1413285303Sgshapiro char md5h[EVP_MAX_MD_SIZE * 3]; 1414285303Sgshapiro static const char hexcodes[] = "0123456789ABCDEF"; 1415285303Sgshapiro 1416285303Sgshapiro n = 0; 1417285303Sgshapiro if (X509_digest(cert, EVP_digest, md, &n) == 0 || n <= 0) 1418285303Sgshapiro { 1419285303Sgshapiro macdefine(mac, A_TEMP, macid(macro), ""); 1420285303Sgshapiro return 0; 1421285303Sgshapiro } 1422285303Sgshapiro 1423285303Sgshapiro SM_ASSERT((n * 3) + 2 < sizeof(md5h)); 1424285303Sgshapiro for (r = 0; r < (int) n; r++) 1425285303Sgshapiro { 1426285303Sgshapiro md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4]; 1427285303Sgshapiro md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)]; 1428285303Sgshapiro md5h[(r * 3) + 2] = ':'; 1429285303Sgshapiro } 1430285303Sgshapiro md5h[(n * 3) - 1] = '\0'; 1431285303Sgshapiro macdefine(mac, A_TEMP, macid(macro), md5h); 1432285303Sgshapiro return 1; 1433285303Sgshapiro} 1434285303Sgshapiro 1435285303Sgshapiro/* 143690792Sgshapiro** TLS_GET_INFO -- get information about TLS connection 143790792Sgshapiro** 143890792Sgshapiro** Parameters: 143990792Sgshapiro** ssl -- TLS connection structure 144090792Sgshapiro** srv -- server or client 144190792Sgshapiro** host -- hostname of other side 144290792Sgshapiro** mac -- macro storage 144390792Sgshapiro** certreq -- did we ask for a cert? 144490792Sgshapiro** 144590792Sgshapiro** Returns: 144690792Sgshapiro** result of authentication. 144790792Sgshapiro** 144890792Sgshapiro** Side Effects: 1449285303Sgshapiro** sets various TLS related macros. 145090792Sgshapiro*/ 145190792Sgshapiro 145290792Sgshapiroint 145390792Sgshapirotls_get_info(ssl, srv, host, mac, certreq) 145490792Sgshapiro SSL *ssl; 145590792Sgshapiro bool srv; 145690792Sgshapiro char *host; 145790792Sgshapiro MACROS_T *mac; 145890792Sgshapiro bool certreq; 145990792Sgshapiro{ 1460223067Sgshapiro const SSL_CIPHER *c; 146190792Sgshapiro int b, r; 1462132943Sgshapiro long verifyok; 146390792Sgshapiro char *s, *who; 146490792Sgshapiro char bitstr[16]; 146590792Sgshapiro X509 *cert; 146690792Sgshapiro 146790792Sgshapiro c = SSL_get_current_cipher(ssl); 146890792Sgshapiro 146990792Sgshapiro /* cast is just workaround for compiler warning */ 147090792Sgshapiro macdefine(mac, A_TEMP, macid("{cipher}"), 147190792Sgshapiro (char *) SSL_CIPHER_get_name(c)); 147290792Sgshapiro b = SSL_CIPHER_get_bits(c, &r); 1473168515Sgshapiro (void) sm_snprintf(bitstr, sizeof(bitstr), "%d", b); 147490792Sgshapiro macdefine(mac, A_TEMP, macid("{cipher_bits}"), bitstr); 1475168515Sgshapiro (void) sm_snprintf(bitstr, sizeof(bitstr), "%d", r); 147690792Sgshapiro macdefine(mac, A_TEMP, macid("{alg_bits}"), bitstr); 1477285303Sgshapiro s = (char *) SSL_get_version(ssl); 147890792Sgshapiro if (s == NULL) 147990792Sgshapiro s = "UNKNOWN"; 148090792Sgshapiro macdefine(mac, A_TEMP, macid("{tls_version}"), s); 148190792Sgshapiro 148290792Sgshapiro who = srv ? "server" : "client"; 148390792Sgshapiro cert = SSL_get_peer_certificate(ssl); 1484132943Sgshapiro verifyok = SSL_get_verify_result(ssl); 148590792Sgshapiro if (LogLevel > 14) 148690792Sgshapiro sm_syslog(LOG_INFO, NOQID, 148790792Sgshapiro "STARTTLS=%s, get_verify: %ld get_peer: 0x%lx", 1488132943Sgshapiro who, verifyok, (unsigned long) cert); 148990792Sgshapiro if (cert != NULL) 149090792Sgshapiro { 1491203004Sgshapiro X509_NAME *subj, *issuer; 149290792Sgshapiro char buf[MAXNAME]; 149390792Sgshapiro 1494203004Sgshapiro subj = X509_get_subject_name(cert); 1495203004Sgshapiro issuer = X509_get_issuer_name(cert); 1496203004Sgshapiro X509_NAME_oneline(subj, buf, sizeof(buf)); 149790792Sgshapiro macdefine(mac, A_TEMP, macid("{cert_subject}"), 149890792Sgshapiro xtextify(buf, "<>\")")); 1499203004Sgshapiro X509_NAME_oneline(issuer, buf, sizeof(buf)); 150090792Sgshapiro macdefine(mac, A_TEMP, macid("{cert_issuer}"), 150190792Sgshapiro xtextify(buf, "<>\")")); 1502203004Sgshapiro 1503223067Sgshapiro# define LL_BADCERT 8 1504223067Sgshapiro 1505285303Sgshapiro#define CERTFPMACRO (CertFingerprintAlgorithm != NULL ? "{cert_fp}" : "{cert_md5}") 1506285303Sgshapiro 1507203004Sgshapiro#define CHECK_X509_NAME(which) \ 1508203004Sgshapiro do { \ 1509203004Sgshapiro if (r == -1) \ 1510203004Sgshapiro { \ 1511203004Sgshapiro sm_strlcpy(buf, "BadCertificateUnknown", sizeof(buf)); \ 1512223067Sgshapiro if (LogLevel > LL_BADCERT) \ 1513203004Sgshapiro sm_syslog(LOG_INFO, NOQID, \ 1514203004Sgshapiro "STARTTLS=%s, relay=%.100s, field=%s, status=failed to extract CN", \ 1515203004Sgshapiro who, \ 1516203004Sgshapiro host == NULL ? "local" : host, \ 1517203004Sgshapiro which); \ 1518203004Sgshapiro } \ 1519203004Sgshapiro else if ((size_t)r >= sizeof(buf) - 1) \ 1520203004Sgshapiro { \ 1521203004Sgshapiro sm_strlcpy(buf, "BadCertificateTooLong", sizeof(buf)); \ 1522203004Sgshapiro if (LogLevel > 7) \ 1523203004Sgshapiro sm_syslog(LOG_INFO, NOQID, \ 1524203004Sgshapiro "STARTTLS=%s, relay=%.100s, field=%s, status=CN too long", \ 1525203004Sgshapiro who, \ 1526203004Sgshapiro host == NULL ? "local" : host, \ 1527203004Sgshapiro which); \ 1528203004Sgshapiro } \ 1529203004Sgshapiro else if ((size_t)r > strlen(buf)) \ 1530203004Sgshapiro { \ 1531203004Sgshapiro sm_strlcpy(buf, "BadCertificateContainsNUL", \ 1532203004Sgshapiro sizeof(buf)); \ 1533203004Sgshapiro if (LogLevel > 7) \ 1534203004Sgshapiro sm_syslog(LOG_INFO, NOQID, \ 1535203004Sgshapiro "STARTTLS=%s, relay=%.100s, field=%s, status=CN contains NUL", \ 1536203004Sgshapiro who, \ 1537203004Sgshapiro host == NULL ? "local" : host, \ 1538203004Sgshapiro which); \ 1539203004Sgshapiro } \ 1540203004Sgshapiro } while (0) 1541203004Sgshapiro 1542203004Sgshapiro r = X509_NAME_get_text_by_NID(subj, NID_commonName, buf, 1543203004Sgshapiro sizeof buf); 1544203004Sgshapiro CHECK_X509_NAME("cn_subject"); 154590792Sgshapiro macdefine(mac, A_TEMP, macid("{cn_subject}"), 154690792Sgshapiro xtextify(buf, "<>\")")); 1547203004Sgshapiro r = X509_NAME_get_text_by_NID(issuer, NID_commonName, buf, 1548203004Sgshapiro sizeof buf); 1549203004Sgshapiro CHECK_X509_NAME("cn_issuer"); 155090792Sgshapiro macdefine(mac, A_TEMP, macid("{cn_issuer}"), 155190792Sgshapiro xtextify(buf, "<>\")")); 1552285303Sgshapiro (void) cert_fp(cert, EVP_digest, mac, CERTFPMACRO); 155390792Sgshapiro } 155490792Sgshapiro else 155590792Sgshapiro { 155690792Sgshapiro macdefine(mac, A_PERM, macid("{cert_subject}"), ""); 155790792Sgshapiro macdefine(mac, A_PERM, macid("{cert_issuer}"), ""); 155890792Sgshapiro macdefine(mac, A_PERM, macid("{cn_subject}"), ""); 155990792Sgshapiro macdefine(mac, A_PERM, macid("{cn_issuer}"), ""); 1560285303Sgshapiro macdefine(mac, A_TEMP, macid(CERTFPMACRO), ""); 156190792Sgshapiro } 1562132943Sgshapiro switch (verifyok) 156390792Sgshapiro { 156490792Sgshapiro case X509_V_OK: 156590792Sgshapiro if (cert != NULL) 156690792Sgshapiro { 156790792Sgshapiro s = "OK"; 156890792Sgshapiro r = TLS_AUTH_OK; 156990792Sgshapiro } 157090792Sgshapiro else 157190792Sgshapiro { 157290792Sgshapiro s = certreq ? "NO" : "NOT", 157390792Sgshapiro r = TLS_AUTH_NO; 157490792Sgshapiro } 157590792Sgshapiro break; 157690792Sgshapiro default: 157790792Sgshapiro s = "FAIL"; 157890792Sgshapiro r = TLS_AUTH_FAIL; 157990792Sgshapiro break; 158090792Sgshapiro } 158190792Sgshapiro macdefine(mac, A_PERM, macid("{verify}"), s); 158290792Sgshapiro if (cert != NULL) 158390792Sgshapiro X509_free(cert); 158490792Sgshapiro 158590792Sgshapiro /* do some logging */ 158690792Sgshapiro if (LogLevel > 8) 158790792Sgshapiro { 158890792Sgshapiro char *vers, *s1, *s2, *cbits, *algbits; 158990792Sgshapiro 159090792Sgshapiro vers = macget(mac, macid("{tls_version}")); 159190792Sgshapiro cbits = macget(mac, macid("{cipher_bits}")); 159290792Sgshapiro algbits = macget(mac, macid("{alg_bits}")); 159390792Sgshapiro s1 = macget(mac, macid("{verify}")); 159490792Sgshapiro s2 = macget(mac, macid("{cipher}")); 159590792Sgshapiro 159690792Sgshapiro /* XXX: maybe cut off ident info? */ 159790792Sgshapiro sm_syslog(LOG_INFO, NOQID, 159890792Sgshapiro "STARTTLS=%s, relay=%.100s, version=%.16s, verify=%.16s, cipher=%.64s, bits=%.6s/%.6s", 159990792Sgshapiro who, 160090792Sgshapiro host == NULL ? "local" : host, 160190792Sgshapiro vers, s1, s2, /* sm_snprintf() can deal with NULL */ 160290792Sgshapiro algbits == NULL ? "0" : algbits, 160390792Sgshapiro cbits == NULL ? "0" : cbits); 160490792Sgshapiro if (LogLevel > 11) 160590792Sgshapiro { 160690792Sgshapiro /* 160790792Sgshapiro ** Maybe run xuntextify on the strings? 160890792Sgshapiro ** That is easier to read but makes it maybe a bit 160990792Sgshapiro ** more complicated to figure out the right values 161090792Sgshapiro ** for the access map... 161190792Sgshapiro */ 161290792Sgshapiro 161390792Sgshapiro s1 = macget(mac, macid("{cert_subject}")); 161490792Sgshapiro s2 = macget(mac, macid("{cert_issuer}")); 161590792Sgshapiro sm_syslog(LOG_INFO, NOQID, 1616132943Sgshapiro "STARTTLS=%s, cert-subject=%.256s, cert-issuer=%.256s, verifymsg=%s", 1617132943Sgshapiro who, s1, s2, 1618132943Sgshapiro X509_verify_cert_error_string(verifyok)); 161990792Sgshapiro } 162090792Sgshapiro } 162190792Sgshapiro return r; 162290792Sgshapiro} 162390792Sgshapiro/* 162490792Sgshapiro** ENDTLS -- shutdown secure connection 162590792Sgshapiro** 162690792Sgshapiro** Parameters: 162790792Sgshapiro** ssl -- SSL connection information. 162890792Sgshapiro** side -- server/client (for logging). 162990792Sgshapiro** 163090792Sgshapiro** Returns: 163190792Sgshapiro** success? (EX_* code) 163290792Sgshapiro*/ 163390792Sgshapiro 163490792Sgshapiroint 163590792Sgshapiroendtls(ssl, side) 163690792Sgshapiro SSL *ssl; 163790792Sgshapiro char *side; 163890792Sgshapiro{ 163990792Sgshapiro int ret = EX_OK; 164090792Sgshapiro 164190792Sgshapiro if (ssl != NULL) 164290792Sgshapiro { 164390792Sgshapiro int r; 164490792Sgshapiro 164590792Sgshapiro if ((r = SSL_shutdown(ssl)) < 0) 164690792Sgshapiro { 164790792Sgshapiro if (LogLevel > 11) 164890792Sgshapiro { 164990792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 165090792Sgshapiro "STARTTLS=%s, SSL_shutdown failed: %d", 165190792Sgshapiro side, r); 1652249729Sgshapiro tlslogerr(LOG_WARNING, side); 165390792Sgshapiro } 165490792Sgshapiro ret = EX_SOFTWARE; 165590792Sgshapiro } 165690792Sgshapiro# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER > 0x0090602fL 165790792Sgshapiro 165890792Sgshapiro /* 165990792Sgshapiro ** Bug in OpenSSL (at least up to 0.9.6b): 166090792Sgshapiro ** From: Lutz.Jaenicke@aet.TU-Cottbus.DE 166190792Sgshapiro ** Message-ID: <20010723152244.A13122@serv01.aet.tu-cottbus.de> 166290792Sgshapiro ** To: openssl-users@openssl.org 166390792Sgshapiro ** Subject: Re: SSL_shutdown() woes (fwd) 166490792Sgshapiro ** 166590792Sgshapiro ** The side sending the shutdown alert first will 166690792Sgshapiro ** not care about the answer of the peer but will 166790792Sgshapiro ** immediately return with a return value of "0" 166890792Sgshapiro ** (ssl/s3_lib.c:ssl3_shutdown()). SSL_get_error will evaluate 166990792Sgshapiro ** the value of "0" and as the shutdown alert of the peer was 167090792Sgshapiro ** not received (actually, the program did not even wait for 167190792Sgshapiro ** the answer), an SSL_ERROR_SYSCALL is flagged, because this 167290792Sgshapiro ** is the default rule in case everything else does not apply. 167390792Sgshapiro ** 167490792Sgshapiro ** For your server the problem is different, because it 167590792Sgshapiro ** receives the shutdown first (setting SSL_RECEIVED_SHUTDOWN), 167690792Sgshapiro ** then sends its response (SSL_SENT_SHUTDOWN), so for the 167790792Sgshapiro ** server the shutdown was successfull. 167890792Sgshapiro ** 167990792Sgshapiro ** As is by know, you would have to call SSL_shutdown() once 168090792Sgshapiro ** and ignore an SSL_ERROR_SYSCALL returned. Then call 168190792Sgshapiro ** SSL_shutdown() again to actually get the server's response. 168290792Sgshapiro ** 168390792Sgshapiro ** In the last discussion, Bodo Moeller concluded that a 168490792Sgshapiro ** rewrite of the shutdown code would be necessary, but 168590792Sgshapiro ** probably with another API, as the change would not be 168690792Sgshapiro ** compatible to the way it is now. Things do not become 168790792Sgshapiro ** easier as other programs do not follow the shutdown 168890792Sgshapiro ** guidelines anyway, so that a lot error conditions and 168990792Sgshapiro ** compitibility issues would have to be caught. 169090792Sgshapiro ** 169190792Sgshapiro ** For now the recommondation is to ignore the error message. 169290792Sgshapiro */ 169390792Sgshapiro 169490792Sgshapiro else if (r == 0) 169590792Sgshapiro { 169690792Sgshapiro if (LogLevel > 15) 169790792Sgshapiro { 169890792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 169990792Sgshapiro "STARTTLS=%s, SSL_shutdown not done", 170090792Sgshapiro side); 1701249729Sgshapiro tlslogerr(LOG_WARNING, side); 170290792Sgshapiro } 170390792Sgshapiro ret = EX_SOFTWARE; 170490792Sgshapiro } 170590792Sgshapiro# endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER > 0x0090602fL */ 170690792Sgshapiro SSL_free(ssl); 170790792Sgshapiro ssl = NULL; 170890792Sgshapiro } 170990792Sgshapiro return ret; 171090792Sgshapiro} 171190792Sgshapiro 171290792Sgshapiro# if !TLS_NO_RSA 171390792Sgshapiro/* 171490792Sgshapiro** TMP_RSA_KEY -- return temporary RSA key 171590792Sgshapiro** 171690792Sgshapiro** Parameters: 171790792Sgshapiro** s -- TLS connection structure 171890792Sgshapiro** export -- 171990792Sgshapiro** keylength -- 172090792Sgshapiro** 172190792Sgshapiro** Returns: 172290792Sgshapiro** temporary RSA key. 172390792Sgshapiro*/ 172490792Sgshapiro 172590792Sgshapiro# ifndef MAX_RSA_TMP_CNT 172690792Sgshapiro# define MAX_RSA_TMP_CNT 1000 /* XXX better value? */ 172790792Sgshapiro# endif /* ! MAX_RSA_TMP_CNT */ 172890792Sgshapiro 172990792Sgshapiro/* ARGUSED0 */ 173090792Sgshapirostatic RSA * 173190792Sgshapirotmp_rsa_key(s, export, keylength) 173290792Sgshapiro SSL *s; 173390792Sgshapiro int export; 173490792Sgshapiro int keylength; 173590792Sgshapiro{ 173690792Sgshapiro# if SM_CONF_SHM 173790792Sgshapiro extern int ShmId; 173890792Sgshapiro extern int *PRSATmpCnt; 173990792Sgshapiro 174090792Sgshapiro if (ShmId != SM_SHM_NO_ID && rsa_tmp != NULL && 174190792Sgshapiro ++(*PRSATmpCnt) < MAX_RSA_TMP_CNT) 174290792Sgshapiro return rsa_tmp; 174390792Sgshapiro# endif /* SM_CONF_SHM */ 174490792Sgshapiro 174590792Sgshapiro if (rsa_tmp != NULL) 174690792Sgshapiro RSA_free(rsa_tmp); 174790792Sgshapiro rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, NULL); 174890792Sgshapiro if (rsa_tmp == NULL) 174990792Sgshapiro { 175090792Sgshapiro if (LogLevel > 0) 175190792Sgshapiro sm_syslog(LOG_ERR, NOQID, 175290792Sgshapiro "STARTTLS=server, tmp_rsa_key: RSA_generate_key failed!"); 175390792Sgshapiro } 175490792Sgshapiro else 175590792Sgshapiro { 175690792Sgshapiro# if SM_CONF_SHM 175790792Sgshapiro# if 0 175890792Sgshapiro /* 175990792Sgshapiro ** XXX we can't (yet) share the new key... 176090792Sgshapiro ** The RSA structure contains pointers hence it can't be 176190792Sgshapiro ** easily kept in shared memory. It must be transformed 176290792Sgshapiro ** into a continous memory region first, then stored, 176390792Sgshapiro ** and later read out again (each time re-transformed). 176490792Sgshapiro */ 176590792Sgshapiro 176690792Sgshapiro if (ShmId != SM_SHM_NO_ID) 176790792Sgshapiro *PRSATmpCnt = 0; 176890792Sgshapiro# endif /* 0 */ 176990792Sgshapiro# endif /* SM_CONF_SHM */ 177090792Sgshapiro if (LogLevel > 9) 177190792Sgshapiro sm_syslog(LOG_ERR, NOQID, 177290792Sgshapiro "STARTTLS=server, tmp_rsa_key: new temp RSA key"); 177390792Sgshapiro } 177490792Sgshapiro return rsa_tmp; 177590792Sgshapiro} 177690792Sgshapiro# endif /* !TLS_NO_RSA */ 177790792Sgshapiro/* 177890792Sgshapiro** APPS_SSL_INFO_CB -- info callback for TLS connections 177990792Sgshapiro** 178090792Sgshapiro** Parameters: 178190792Sgshapiro** s -- TLS connection structure 178290792Sgshapiro** where -- state in handshake 178390792Sgshapiro** ret -- return code of last operation 178490792Sgshapiro** 178590792Sgshapiro** Returns: 178690792Sgshapiro** none. 178790792Sgshapiro*/ 178890792Sgshapiro 178990792Sgshapirostatic void 179090792Sgshapiroapps_ssl_info_cb(s, where, ret) 179194334Sgshapiro CONST097 SSL *s; 179290792Sgshapiro int where; 179390792Sgshapiro int ret; 179490792Sgshapiro{ 179590792Sgshapiro int w; 179690792Sgshapiro char *str; 179790792Sgshapiro BIO *bio_err = NULL; 179890792Sgshapiro 179990792Sgshapiro if (LogLevel > 14) 180090792Sgshapiro sm_syslog(LOG_INFO, NOQID, 180190792Sgshapiro "STARTTLS: info_callback where=0x%x, ret=%d", 180290792Sgshapiro where, ret); 180390792Sgshapiro 180490792Sgshapiro w = where & ~SSL_ST_MASK; 180590792Sgshapiro if (bio_err == NULL) 180690792Sgshapiro bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 180790792Sgshapiro 180890792Sgshapiro if (bitset(SSL_ST_CONNECT, w)) 180990792Sgshapiro str = "SSL_connect"; 181090792Sgshapiro else if (bitset(SSL_ST_ACCEPT, w)) 181190792Sgshapiro str = "SSL_accept"; 181290792Sgshapiro else 181390792Sgshapiro str = "undefined"; 181490792Sgshapiro 181590792Sgshapiro if (bitset(SSL_CB_LOOP, where)) 181690792Sgshapiro { 181790792Sgshapiro if (LogLevel > 12) 181890792Sgshapiro sm_syslog(LOG_NOTICE, NOQID, 181990792Sgshapiro "STARTTLS: %s:%s", 182090792Sgshapiro str, SSL_state_string_long(s)); 182190792Sgshapiro } 182290792Sgshapiro else if (bitset(SSL_CB_ALERT, where)) 182390792Sgshapiro { 182490792Sgshapiro str = bitset(SSL_CB_READ, where) ? "read" : "write"; 182590792Sgshapiro if (LogLevel > 12) 182690792Sgshapiro sm_syslog(LOG_NOTICE, NOQID, 182790792Sgshapiro "STARTTLS: SSL3 alert %s:%s:%s", 182890792Sgshapiro str, SSL_alert_type_string_long(ret), 182990792Sgshapiro SSL_alert_desc_string_long(ret)); 183090792Sgshapiro } 183190792Sgshapiro else if (bitset(SSL_CB_EXIT, where)) 183290792Sgshapiro { 183390792Sgshapiro if (ret == 0) 183490792Sgshapiro { 183590792Sgshapiro if (LogLevel > 7) 183690792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 183790792Sgshapiro "STARTTLS: %s:failed in %s", 183890792Sgshapiro str, SSL_state_string_long(s)); 183990792Sgshapiro } 184090792Sgshapiro else if (ret < 0) 184190792Sgshapiro { 184290792Sgshapiro if (LogLevel > 7) 184390792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 184490792Sgshapiro "STARTTLS: %s:error in %s", 184590792Sgshapiro str, SSL_state_string_long(s)); 184690792Sgshapiro } 184790792Sgshapiro } 184890792Sgshapiro} 184990792Sgshapiro/* 185090792Sgshapiro** TLS_VERIFY_LOG -- log verify error for TLS certificates 185190792Sgshapiro** 185290792Sgshapiro** Parameters: 185390792Sgshapiro** ok -- verify ok? 185490792Sgshapiro** ctx -- x509 context 1855285303Sgshapiro** name -- from where is this called? 185690792Sgshapiro** 185790792Sgshapiro** Returns: 185890792Sgshapiro** 1 -- ok 185990792Sgshapiro*/ 186090792Sgshapiro 186190792Sgshapirostatic int 1862132943Sgshapirotls_verify_log(ok, ctx, name) 186390792Sgshapiro int ok; 186490792Sgshapiro X509_STORE_CTX *ctx; 1865285303Sgshapiro const char *name; 186690792Sgshapiro{ 186790792Sgshapiro X509 *cert; 186890792Sgshapiro int reason, depth; 186990792Sgshapiro char buf[512]; 187090792Sgshapiro 187190792Sgshapiro cert = X509_STORE_CTX_get_current_cert(ctx); 187290792Sgshapiro reason = X509_STORE_CTX_get_error(ctx); 187390792Sgshapiro depth = X509_STORE_CTX_get_error_depth(ctx); 1874168515Sgshapiro X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); 187590792Sgshapiro sm_syslog(LOG_INFO, NOQID, 1876132943Sgshapiro "STARTTLS: %s cert verify: depth=%d %s, state=%d, reason=%s", 1877132943Sgshapiro name, depth, buf, ok, X509_verify_cert_error_string(reason)); 187890792Sgshapiro return 1; 187990792Sgshapiro} 1880132943Sgshapiro 188190792Sgshapiro/* 188290792Sgshapiro** TLS_VERIFY_CB -- verify callback for TLS certificates 188390792Sgshapiro** 188490792Sgshapiro** Parameters: 188590792Sgshapiro** ctx -- x509 context 188690792Sgshapiro** 188790792Sgshapiro** Returns: 188890792Sgshapiro** accept connection? 188990792Sgshapiro** currently: always yes. 189090792Sgshapiro*/ 189190792Sgshapiro 189290792Sgshapirostatic int 189394334Sgshapiro# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L 189490792Sgshapirotls_verify_cb(ctx) 189590792Sgshapiro X509_STORE_CTX *ctx; 189694334Sgshapiro# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ 189794334Sgshapirotls_verify_cb(ctx, unused) 189894334Sgshapiro X509_STORE_CTX *ctx; 189994334Sgshapiro void *unused; 190094334Sgshapiro# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ 190190792Sgshapiro{ 190290792Sgshapiro int ok; 190390792Sgshapiro 1904203004Sgshapiro /* 1905203004Sgshapiro ** man SSL_CTX_set_cert_verify_callback(): 1906203004Sgshapiro ** callback should return 1 to indicate verification success 1907203004Sgshapiro ** and 0 to indicate verification failure. 1908203004Sgshapiro */ 1909203004Sgshapiro 191090792Sgshapiro ok = X509_verify_cert(ctx); 1911203004Sgshapiro if (ok <= 0) 191290792Sgshapiro { 191390792Sgshapiro if (LogLevel > 13) 1914132943Sgshapiro return tls_verify_log(ok, ctx, "TLS"); 191590792Sgshapiro } 1916203004Sgshapiro return 1; 191790792Sgshapiro} 191890792Sgshapiro/* 191990792Sgshapiro** TLSLOGERR -- log the errors from the TLS error stack 192090792Sgshapiro** 192190792Sgshapiro** Parameters: 1922249729Sgshapiro** level -- syslog level 192390792Sgshapiro** who -- server/client (for logging). 192490792Sgshapiro** 192590792Sgshapiro** Returns: 192690792Sgshapiro** none. 192790792Sgshapiro*/ 192890792Sgshapiro 192990792Sgshapirovoid 1930249729Sgshapirotlslogerr(level, who) 1931249729Sgshapiro int level; 1932157001Sgshapiro const char *who; 193390792Sgshapiro{ 193490792Sgshapiro unsigned long l; 193590792Sgshapiro int line, flags; 193690792Sgshapiro unsigned long es; 193790792Sgshapiro char *file, *data; 193890792Sgshapiro char buf[256]; 193990792Sgshapiro 194090792Sgshapiro es = CRYPTO_thread_id(); 1941285303Sgshapiro while ((l = ERR_get_error_line_data((const char **) &file, &line, 1942285303Sgshapiro (const char **) &data, &flags)) 194390792Sgshapiro != 0) 194490792Sgshapiro { 1945249729Sgshapiro sm_syslog(level, NOQID, 194690792Sgshapiro "STARTTLS=%s: %lu:%s:%s:%d:%s", who, es, 194790792Sgshapiro ERR_error_string(l, buf), 194890792Sgshapiro file, line, 194990792Sgshapiro bitset(ERR_TXT_STRING, flags) ? data : ""); 195090792Sgshapiro } 195190792Sgshapiro} 1952132943Sgshapiro 1953132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 1954132943Sgshapiro/* 1955132943Sgshapiro** X509_VERIFY_CB -- verify callback 1956132943Sgshapiro** 1957132943Sgshapiro** Parameters: 1958132943Sgshapiro** ctx -- x509 context 1959132943Sgshapiro** 1960132943Sgshapiro** Returns: 1961132943Sgshapiro** accept connection? 1962132943Sgshapiro** currently: always yes. 1963132943Sgshapiro*/ 1964132943Sgshapiro 1965132943Sgshapirostatic int 1966132943Sgshapirox509_verify_cb(ok, ctx) 1967132943Sgshapiro int ok; 1968132943Sgshapiro X509_STORE_CTX *ctx; 1969132943Sgshapiro{ 1970132943Sgshapiro if (ok == 0) 1971132943Sgshapiro { 1972132943Sgshapiro if (LogLevel > 13) 1973132943Sgshapiro tls_verify_log(ok, ctx, "x509"); 1974132943Sgshapiro if (ctx->error == X509_V_ERR_UNABLE_TO_GET_CRL) 1975132943Sgshapiro { 1976132943Sgshapiro ctx->error = 0; 1977132943Sgshapiro return 1; /* override it */ 1978132943Sgshapiro } 1979132943Sgshapiro } 1980132943Sgshapiro return ok; 1981132943Sgshapiro} 1982132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 198390792Sgshapiro#endif /* STARTTLS */ 1984