diff options
Diffstat (limited to 'contrib/sendmail/src/tls.c')
-rw-r--r-- | contrib/sendmail/src/tls.c | 407 |
1 files changed, 307 insertions, 100 deletions
diff --git a/contrib/sendmail/src/tls.c b/contrib/sendmail/src/tls.c index ca93ee8..6b0ea25 100644 --- a/contrib/sendmail/src/tls.c +++ b/contrib/sendmail/src/tls.c @@ -13,21 +13,21 @@ SM_RCSID("@(#)$Id: tls.c,v 8.127 2013-11-27 02:51:11 gshapiro Exp $") #if STARTTLS -# include <openssl/err.h> -# include <openssl/bio.h> -# include <openssl/pem.h> -# ifndef HASURANDOMDEV -# include <openssl/rand.h> -# endif /* ! HASURANDOMDEV */ +# include <openssl/err.h> +# include <openssl/bio.h> +# include <openssl/pem.h> +# ifndef HASURANDOMDEV +# include <openssl/rand.h> +# endif /* ! HASURANDOMDEV */ # if !TLS_NO_RSA static RSA *rsa_tmp = NULL; /* temporary RSA key */ static RSA *tmp_rsa_key __P((SSL *, int, int)); # endif /* !TLS_NO_RSA */ -# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L +# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L static int tls_verify_cb __P((X509_STORE_CTX *)); -# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ static int tls_verify_cb __P((X509_STORE_CTX *, void *)); -# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ # if OPENSSL_VERSION_NUMBER > 0x00907000L static int x509_verify_cb __P((int, X509_STORE_CTX *)); @@ -41,7 +41,7 @@ static int x509_verify_cb __P((int, X509_STORE_CTX *)); static void apps_ssl_info_cb __P((CONST097 SSL *, int , int)); static bool tls_ok_f __P((char *, char *, int)); static bool tls_safe_f __P((char *, long, bool)); -static int tls_verify_log __P((int, X509_STORE_CTX *, char *)); +static int tls_verify_log __P((int, X509_STORE_CTX *, const char *)); # if !NO_DH static DH *get_dh512 __P((void)); @@ -73,6 +73,62 @@ get_dh512() return NULL; return dh; } + +# if 0 + +This is the data from which the C code has been generated: + +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEArDcgcLpxEksQHPlolRKCUJ2szKRziseWV9cUSQNZGxoGw7KkROz4 +HF9QSbg5axyNIG+QbZYtx0jp3l6/GWq1dLOj27yZkgYgaYgFrvKPiZ2jJ5xETQVH +UpZwbjRcyjyWkWYJVsx1aF4F/iY4kT0n/+iGEoimI3C9V3KXTJ2S6jIkyJ6M/CrN +EtrDynMlUMGlc7S1ouXVOTrtKeqy3S2L9eBLxVI+sChEijGIfELupdVeXihK006p +MgnABPDbkTx6OOtYmSZaGQX+OLW2FPmwvcrzgCz9t9cAsuUcBZv1LeHEqZZttyLU +oK0jjSXgFyeU4/NfyA+zuNeWzUL6bHmigwIBAg== +-----END DH PARAMETERS----- +# endif /* 0 */ + +static DH * +get_dh2048() +{ + static unsigned char dh2048_p[]={ + 0xAC,0x37,0x20,0x70,0xBA,0x71,0x12,0x4B,0x10,0x1C,0xF9,0x68, + 0x95,0x12,0x82,0x50,0x9D,0xAC,0xCC,0xA4,0x73,0x8A,0xC7,0x96, + 0x57,0xD7,0x14,0x49,0x03,0x59,0x1B,0x1A,0x06,0xC3,0xB2,0xA4, + 0x44,0xEC,0xF8,0x1C,0x5F,0x50,0x49,0xB8,0x39,0x6B,0x1C,0x8D, + 0x20,0x6F,0x90,0x6D,0x96,0x2D,0xC7,0x48,0xE9,0xDE,0x5E,0xBF, + 0x19,0x6A,0xB5,0x74,0xB3,0xA3,0xDB,0xBC,0x99,0x92,0x06,0x20, + 0x69,0x88,0x05,0xAE,0xF2,0x8F,0x89,0x9D,0xA3,0x27,0x9C,0x44, + 0x4D,0x05,0x47,0x52,0x96,0x70,0x6E,0x34,0x5C,0xCA,0x3C,0x96, + 0x91,0x66,0x09,0x56,0xCC,0x75,0x68,0x5E,0x05,0xFE,0x26,0x38, + 0x91,0x3D,0x27,0xFF,0xE8,0x86,0x12,0x88,0xA6,0x23,0x70,0xBD, + 0x57,0x72,0x97,0x4C,0x9D,0x92,0xEA,0x32,0x24,0xC8,0x9E,0x8C, + 0xFC,0x2A,0xCD,0x12,0xDA,0xC3,0xCA,0x73,0x25,0x50,0xC1,0xA5, + 0x73,0xB4,0xB5,0xA2,0xE5,0xD5,0x39,0x3A,0xED,0x29,0xEA,0xB2, + 0xDD,0x2D,0x8B,0xF5,0xE0,0x4B,0xC5,0x52,0x3E,0xB0,0x28,0x44, + 0x8A,0x31,0x88,0x7C,0x42,0xEE,0xA5,0xD5,0x5E,0x5E,0x28,0x4A, + 0xD3,0x4E,0xA9,0x32,0x09,0xC0,0x04,0xF0,0xDB,0x91,0x3C,0x7A, + 0x38,0xEB,0x58,0x99,0x26,0x5A,0x19,0x05,0xFE,0x38,0xB5,0xB6, + 0x14,0xF9,0xB0,0xBD,0xCA,0xF3,0x80,0x2C,0xFD,0xB7,0xD7,0x00, + 0xB2,0xE5,0x1C,0x05,0x9B,0xF5,0x2D,0xE1,0xC4,0xA9,0x96,0x6D, + 0xB7,0x22,0xD4,0xA0,0xAD,0x23,0x8D,0x25,0xE0,0x17,0x27,0x94, + 0xE3,0xF3,0x5F,0xC8,0x0F,0xB3,0xB8,0xD7,0x96,0xCD,0x42,0xFA, + 0x6C,0x79,0xA2,0x83, + }; + static unsigned char dh2048_g[]={ 0x02, }; + DH *dh; + + if ((dh=DH_new()) == NULL) + return(NULL); + dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL); + dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL); + if ((dh->p == NULL) || (dh->g == NULL)) + { + DH_free(dh); + return(NULL); + } + return(dh); +} # endif /* !NO_DH */ @@ -311,15 +367,32 @@ init_tls_library(fipsmode) } } #endif /* _FFR_FIPSMODE */ + if (bv && CertFingerprintAlgorithm != NULL) + { + const EVP_MD *md; + + md = EVP_get_digestbyname(CertFingerprintAlgorithm); + if (NULL == md) + { + bv = false; + if (LogLevel > 0) + sm_syslog(LOG_ERR, NOQID, + "STARTTLS=init, CertFingerprintAlgorithm=%s, status=invalid" + , CertFingerprintAlgorithm); + } + else + EVP_digest = md; + } return bv; } + /* ** TLS_SET_VERIFY -- request client certificate? ** ** Parameters: ** ctx -- TLS context ** ssl -- TLS structure -** vrfy -- require certificate? +** vrfy -- request certificate? ** ** Returns: ** none. @@ -369,12 +442,10 @@ tls_set_verify(ctx, ssl, vrfy) # define TLS_S_CRLF_EX 0x00000100 /* CRL file exists */ # define TLS_S_CRLF_OK 0x00000200 /* CRL file is ok */ -# if _FFR_TLS_1 -# define TLS_S_CERT2_EX 0x00001000 /* 2nd cert file exists */ -# define TLS_S_CERT2_OK 0x00002000 /* 2nd cert file is ok */ -# define TLS_S_KEY2_EX 0x00004000 /* 2nd key file exists */ -# define TLS_S_KEY2_OK 0x00008000 /* 2nd key file is ok */ -# endif /* _FFR_TLS_1 */ +# define TLS_S_CERT2_EX 0x00001000 /* 2nd cert file exists */ +# define TLS_S_CERT2_OK 0x00002000 /* 2nd cert file is ok */ +# define TLS_S_KEY2_EX 0x00004000 /* 2nd key file exists */ +# define TLS_S_KEY2_OK 0x00008000 /* 2nd key file is ok */ # define TLS_S_DH_OK 0x00200000 /* DH cert is ok */ # define TLS_S_DHPAR_EX 0x00400000 /* DH param file exists */ @@ -507,6 +578,109 @@ tls_safe_f(var, sff, srv) ok = false; \ } +# if _FFR_TLS_SE_OPTS +/* +** LOAD_CERTKEY -- load cert/key for TLS session +** +** Parameters: +** ssl -- TLS session context +** certfile -- filename of certificate +** keyfile -- filename of private key +** +** Returns: +** succeeded? +*/ + +bool +load_certkey(ssl, srv, certfile, keyfile) + SSL *ssl; + bool srv; + char *certfile; + char *keyfile; +{ + bool ok; + int r; + long sff, status; + unsigned long req; + char *who; + + ok = true; + who = srv ? "server" : "client"; + status = TLS_S_NONE; + req = TLS_I_CERT_EX|TLS_I_KEY_EX; + TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req), + TLS_S_CERT_EX, srv ? TLS_T_SRV : TLS_T_CLT); + TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req), + TLS_S_KEY_EX, srv ? TLS_T_SRV : TLS_T_CLT); + + /* certfile etc. must be "safe". */ + sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK + | SFF_NOGWFILES | SFF_NOWWFILES + | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT; + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + + TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req), + bitset(TLS_I_CERT_EX, req), + bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv); + TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req), + bitset(TLS_I_KEY_EX, req), + bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv); + +# define SSL_use_cert(ssl, certfile) \ + SSL_use_certificate_file(ssl, certfile, SSL_FILETYPE_PEM) +# define SSL_USE_CERT "SSL_use_certificate_file" + + if (bitset(TLS_S_CERT_OK, status) && + SSL_use_cert(ssl, certfile) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: %s(%s) failed", + who, SSL_USE_CERT, certfile); + if (LogLevel > 9) + tlslogerr(LOG_WARNING, who); + } + if (bitset(TLS_I_USE_CERT, req)) + return false; + } + if (bitset(TLS_S_KEY_OK, status) && + SSL_use_PrivateKey_file(ssl, keyfile, SSL_FILETYPE_PEM) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_use_PrivateKey_file(%s) failed", + who, keyfile); + if (LogLevel > 9) + tlslogerr(LOG_WARNING, who); + } + if (bitset(TLS_I_USE_KEY, req)) + return false; + } + + /* check the private key */ + if (bitset(TLS_S_KEY_OK, status) && + (r = SSL_check_private_key(ssl)) <= 0) + { + /* Private key does not match the certificate public key */ + if (LogLevel > 5) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_check_private_key failed(%s): %d", + who, keyfile, r); + if (LogLevel > 9) + tlslogerr(LOG_WARNING, who); + } + if (bitset(TLS_I_USE_KEY, req)) + return false; + } + + return true; +} +# endif /* _FFR_TLS_SE_OPTS */ + /* ** INITTLS -- initialize TLS ** @@ -545,7 +719,7 @@ bool inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhparam) SSL_CTX **ctx; unsigned long req; - long options; + unsigned long options; bool srv; char *certfile, *keyfile, *cacertpath, *cacertfile, *dhparam; { @@ -556,12 +730,10 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar bool ok; long sff, status; char *who; -# if _FFR_TLS_1 char *cf2, *kf2; -# endif /* _FFR_TLS_1 */ -# if SM_CONF_SHM +# if SM_CONF_SHM extern int ShmId; -# endif /* SM_CONF_SHM */ +# endif /* SM_CONF_SHM */ # if OPENSSL_VERSION_NUMBER > 0x00907000L BIO *crl_file; X509_CRL *crl; @@ -586,7 +758,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar return true; ok = true; -# if _FFR_TLS_1 /* ** look for a second filename: it must be separated by a ',' ** no blanks allowed (they won't be skipped). @@ -605,7 +776,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar if (keyfile != NULL && (kf2 = strchr(keyfile, ',')) != NULL) *kf2++ = '\0'; } -# endif /* _FFR_TLS_1 */ /* ** Check whether files/paths are defined @@ -625,7 +795,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar TLS_S_CRLF_EX, TLS_T_OTHER); # endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ -# if _FFR_TLS_1 /* ** if the second file is specified it must exist ** XXX: it is possible here to define only one of those files @@ -641,18 +810,23 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar TLS_OK_F(kf2, "KeyFile", bitset(TLS_I_KEY_EX, req), TLS_S_KEY2_EX, srv ? TLS_T_SRV : TLS_T_CLT); } -# endif /* _FFR_TLS_1 */ /* ** valid values for dhparam are (only the first char is checked) ** none no parameters: don't use DH + ** i use precomputed 2048 bit parameters ** 512 use precomputed 512 bit parameters ** 1024 generate 1024 bit parameters ** 2048 generate 2048 bit parameters ** /file/name read parameters from /file/name - ** default is: 1024 */ +#define SET_DH_DFL \ + do { \ + dhparam = "I"; \ + req |= TLS_I_DHFIXED; \ + } while (0) + if (bitset(TLS_I_TRY_DH, req)) { if (dhparam != NULL) @@ -661,24 +835,25 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar if (c == '1') req |= TLS_I_DH1024; + else if (c == 'I' || c == 'i') + req |= TLS_I_DHFIXED; else if (c == '2') req |= TLS_I_DH2048; else if (c == '5') req |= TLS_I_DH512; - else if (c != 'n' && c != 'N' && c != '/') + else if (c == 'n' || c == 'N') + req &= ~TLS_I_TRY_DH; + else if (c != '/') { if (LogLevel > 12) sm_syslog(LOG_WARNING, NOQID, - "STARTTLS=%s, error: illegal value '%s' for DHParam", + "STARTTLS=%s, error: illegal value '%s' for DHParameters", who, dhparam); dhparam = NULL; } } if (dhparam == NULL) - { - dhparam = "1"; - req |= TLS_I_DH1024; - } + SET_DH_DFL; else if (*dhparam == '/') { TLS_OK_F(dhparam, "DHParameters", @@ -705,9 +880,14 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar TLS_SAFE_F(cacertfile, sff | TLS_UNR(TLS_I_CERTF_UNR, req), bitset(TLS_I_CERTF_EX, req), bitset(TLS_S_CERTF_EX, status), TLS_S_CERTF_OK, srv); - TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req), - bitset(TLS_I_DHPAR_EX, req), - bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv); + if (dhparam != NULL && *dhparam == '/') + { + TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req), + bitset(TLS_I_DHPAR_EX, req), + bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv); + if (!bitset(TLS_S_DHPAR_OK, status)) + SET_DH_DFL; + } # if OPENSSL_VERSION_NUMBER > 0x00907000L TLS_SAFE_F(CRLFile, sff | TLS_UNR(TLS_I_CRLF_UNR, req), bitset(TLS_I_CRLF_EX, req), @@ -715,7 +895,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar # endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ if (!ok) return ok; -# if _FFR_TLS_1 if (cf2 != NULL) { TLS_SAFE_F(cf2, sff | TLS_UNR(TLS_I_CERT_UNR, req), @@ -728,7 +907,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar bitset(TLS_I_KEY_EX, req), bitset(TLS_S_KEY2_EX, status), TLS_S_KEY2_OK, srv); } -# endif /* _FFR_TLS_1 */ /* create a method and a new context */ if ((*ctx = SSL_CTX_new(srv ? SSLv23_server_method() : @@ -823,13 +1001,13 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar */ if (bitset(TLS_I_RSA_TMP, req) -# if SM_CONF_SHM +# if SM_CONF_SHM && ShmId != SM_SHM_NO_ID && (rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, NULL)) == NULL -# else /* SM_CONF_SHM */ +# else /* SM_CONF_SHM */ && 0 /* no shared memory: no need to generate key now */ -# endif /* SM_CONF_SHM */ +# endif /* SM_CONF_SHM */ ) { if (LogLevel > 7) @@ -865,16 +1043,25 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar return false; } +#if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE +# define SSL_CTX_use_cert(ssl_ctx, certfile) \ + SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile) +# define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_chain_file" +#else +# define SSL_CTX_use_cert(ssl_ctx, certfile) \ + SSL_CTX_use_certificate_file(ssl_ctx, certfile, SSL_FILETYPE_PEM) +# define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_file" +#endif + /* get the certificate file */ if (bitset(TLS_S_CERT_OK, status) && - SSL_CTX_use_certificate_file(*ctx, certfile, - SSL_FILETYPE_PEM) <= 0) + SSL_CTX_use_cert(*ctx, certfile) <= 0) { if (LogLevel > 7) { sm_syslog(LOG_WARNING, NOQID, - "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed", - who, certfile); + "STARTTLS=%s, error: %s(%s) failed", + who, SSL_CTX_USE_CERT, certfile); if (LogLevel > 9) tlslogerr(LOG_WARNING, who); } @@ -899,7 +1086,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar return false; } -# if _FFR_TLS_1 /* XXX this code is pretty much duplicated from above! */ /* load private key */ @@ -918,13 +1104,13 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar /* get the certificate file */ if (bitset(TLS_S_CERT2_OK, status) && - SSL_CTX_use_certificate_file(*ctx, cf2, SSL_FILETYPE_PEM) <= 0) + SSL_CTX_use_cert(*ctx, cf2) <= 0) { if (LogLevel > 7) { sm_syslog(LOG_WARNING, NOQID, - "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed", - who, cf2); + "STARTTLS=%s, error: %s(%s) failed", + who, SSL_CTX_USE_CERT, cf2); if (LogLevel > 9) tlslogerr(LOG_WARNING, who); } @@ -944,7 +1130,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar tlslogerr(LOG_WARNING, who); } } -# endif /* _FFR_TLS_1 */ /* SSL_CTX_set_quiet_shutdown(*ctx, 1); violation of standard? */ @@ -968,7 +1153,7 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar options &= ~SSL_OP_TLS_BLOCK_PADDING_BUG; } #endif - SSL_CTX_set_options(*ctx, options); + SSL_CTX_set_options(*ctx, (long) options); # if !NO_DH /* Diffie-Hellman initialization */ @@ -977,6 +1162,10 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar #if _FFR_TLS_EC EC_KEY *ecdh; #endif /* _FFR_TLS_EC */ + + if (tTd(96, 8)) + sm_dprintf("inittls: req=%#lx, status=%#lx\n", + req, status); if (bitset(TLS_S_DHPAR_OK, status)) { BIO *bio; @@ -996,6 +1185,7 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar ERR_error_string(err, NULL)); if (LogLevel > 9) tlslogerr(LOG_WARNING, who); + SET_DH_DFL; } } else @@ -1025,8 +1215,13 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar dh = DSA_dup_DH(dsa); DSA_free(dsa); } - else - if (dh == NULL && bitset(TLS_I_DH512, req)) + else if (dh == NULL && bitset(TLS_I_DHFIXED, req)) + { + if (tTd(96, 2)) + sm_dprintf("inittls: Using precomputed 2048 bit DH parameters\n"); + dh = get_dh2048(); + } + else if (dh == NULL && bitset(TLS_I_DH512, req)) { if (tTd(96, 2)) sm_dprintf("inittls: Using precomputed 512 bit DH parameters\n"); @@ -1153,7 +1348,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar if (tTd(96, 9)) SSL_CTX_set_info_callback(*ctx, apps_ssl_info_cb); -# if _FFR_TLS_1 /* install our own cipher list */ if (CipherList != NULL && *CipherList != '\0') { @@ -1171,29 +1365,73 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar /* failure if setting to this list is required? */ } } -# endif /* _FFR_TLS_1 */ + if (LogLevel > 12) sm_syslog(LOG_INFO, NOQID, "STARTTLS=%s, init=%d", who, ok); -# if _FFR_TLS_1 -# if 0 +# if 0 /* ** this label is required if we want to have a "clean" exit ** see the comments above at the initialization of cf2 */ endinittls: -# endif /* 0 */ +# endif /* 0 */ /* undo damage to global variables */ if (cf2 != NULL) *--cf2 = ','; if (kf2 != NULL) *--kf2 = ','; -# endif /* _FFR_TLS_1 */ return ok; } + +/* +** CERT_FP -- get cert fingerprint +** +** Parameters: +** cert -- TLS cert +** mac -- macro storage +** macro -- where to store cert fp +** +** Returns: +** <=0: cert fp calculation failed +** >0: cert fp calculation ok +*/ + +static int +cert_fp(cert, evp_digest, mac, macro) + X509 *cert; + const EVP_MD *evp_digest; + MACROS_T *mac; + char *macro; +{ + unsigned int n; + int r; + unsigned char md[EVP_MAX_MD_SIZE]; + char md5h[EVP_MAX_MD_SIZE * 3]; + static const char hexcodes[] = "0123456789ABCDEF"; + + n = 0; + if (X509_digest(cert, EVP_digest, md, &n) == 0 || n <= 0) + { + macdefine(mac, A_TEMP, macid(macro), ""); + return 0; + } + + SM_ASSERT((n * 3) + 2 < sizeof(md5h)); + for (r = 0; r < (int) n; r++) + { + md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4]; + md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)]; + md5h[(r * 3) + 2] = ':'; + } + md5h[(n * 3) - 1] = '\0'; + macdefine(mac, A_TEMP, macid(macro), md5h); + return 1; +} + /* ** TLS_GET_INFO -- get information about TLS connection ** @@ -1208,9 +1446,7 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar ** result of authentication. ** ** Side Effects: -** sets macros: {cipher}, {tls_version}, {verify}, -** {cipher_bits}, {alg_bits}, {cert}, {cert_subject}, -** {cert_issuer}, {cn_subject}, {cn_issuer} +** sets various TLS related macros. */ int @@ -1238,7 +1474,7 @@ tls_get_info(ssl, srv, host, mac, certreq) macdefine(mac, A_TEMP, macid("{cipher_bits}"), bitstr); (void) sm_snprintf(bitstr, sizeof(bitstr), "%d", r); macdefine(mac, A_TEMP, macid("{alg_bits}"), bitstr); - s = SSL_CIPHER_get_version(c); + s = (char *) SSL_get_version(ssl); if (s == NULL) s = "UNKNOWN"; macdefine(mac, A_TEMP, macid("{tls_version}"), s); @@ -1252,9 +1488,7 @@ tls_get_info(ssl, srv, host, mac, certreq) who, verifyok, (unsigned long) cert); if (cert != NULL) { - unsigned int n; X509_NAME *subj, *issuer; - unsigned char md[EVP_MAX_MD_SIZE]; char buf[MAXNAME]; subj = X509_get_subject_name(cert); @@ -1268,6 +1502,8 @@ tls_get_info(ssl, srv, host, mac, certreq) # define LL_BADCERT 8 +#define CERTFPMACRO (CertFingerprintAlgorithm != NULL ? "{cert_fp}" : "{cert_md5}") + #define CHECK_X509_NAME(which) \ do { \ if (r == -1) \ @@ -1313,24 +1549,7 @@ tls_get_info(ssl, srv, host, mac, certreq) CHECK_X509_NAME("cn_issuer"); macdefine(mac, A_TEMP, macid("{cn_issuer}"), xtextify(buf, "<>\")")); - n = 0; - if (X509_digest(cert, EVP_md5(), md, &n) != 0 && n > 0) - { - char md5h[EVP_MAX_MD_SIZE * 3]; - static const char hexcodes[] = "0123456789ABCDEF"; - - SM_ASSERT((n * 3) + 2 < sizeof(md5h)); - for (r = 0; r < (int) n; r++) - { - md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4]; - md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)]; - md5h[(r * 3) + 2] = ':'; - } - md5h[(n * 3) - 1] = '\0'; - macdefine(mac, A_TEMP, macid("{cert_md5}"), md5h); - } - else - macdefine(mac, A_TEMP, macid("{cert_md5}"), ""); + (void) cert_fp(cert, EVP_digest, mac, CERTFPMACRO); } else { @@ -1338,7 +1557,7 @@ tls_get_info(ssl, srv, host, mac, certreq) macdefine(mac, A_PERM, macid("{cert_issuer}"), ""); macdefine(mac, A_PERM, macid("{cn_subject}"), ""); macdefine(mac, A_PERM, macid("{cn_issuer}"), ""); - macdefine(mac, A_TEMP, macid("{cert_md5}"), ""); + macdefine(mac, A_TEMP, macid(CERTFPMACRO), ""); } switch (verifyok) { @@ -1633,9 +1852,9 @@ apps_ssl_info_cb(s, where, ret) ** Parameters: ** ok -- verify ok? ** ctx -- x509 context +** name -- from where is this called? ** ** Returns: -** 0 -- fatal error ** 1 -- ok */ @@ -1643,9 +1862,8 @@ static int tls_verify_log(ok, ctx, name) int ok; X509_STORE_CTX *ctx; - char *name; + const char *name; { - SSL *ssl; X509 *cert; int reason, depth; char buf[512]; @@ -1653,17 +1871,6 @@ tls_verify_log(ok, ctx, name) cert = X509_STORE_CTX_get_current_cert(ctx); reason = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); - ssl = (SSL *) X509_STORE_CTX_get_ex_data(ctx, - SSL_get_ex_data_X509_STORE_CTX_idx()); - - if (ssl == NULL) - { - /* internal error */ - sm_syslog(LOG_ERR, NOQID, - "STARTTLS: internal error: tls_verify_cb: ssl == NULL"); - return 0; - } - X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); sm_syslog(LOG_INFO, NOQID, "STARTTLS: %s cert verify: depth=%d %s, state=%d, reason=%s", @@ -1729,10 +1936,10 @@ tlslogerr(level, who) unsigned long es; char *file, *data; char buf[256]; -# define CP (const char **) es = CRYPTO_thread_id(); - while ((l = ERR_get_error_line_data(CP &file, &line, CP &data, &flags)) + while ((l = ERR_get_error_line_data((const char **) &file, &line, + (const char **) &data, &flags)) != 0) { sm_syslog(level, NOQID, |