summaryrefslogtreecommitdiffstats
path: root/src/tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls.c')
-rw-r--r--src/tls.c200
1 files changed, 113 insertions, 87 deletions
diff --git a/src/tls.c b/src/tls.c
index 75207ee..b76ba9f 100644
--- a/src/tls.c
+++ b/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));
@@ -311,8 +311,25 @@ 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?
**
@@ -369,12 +386,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 */
@@ -545,7 +560,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 +571,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 +599,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 +617,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 +636,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,7 +651,6 @@ 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)
@@ -715,7 +724,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 +736,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 +830,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 +872,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 +915,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 +933,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 +959,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 +982,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 */
@@ -1153,7 +1167,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 +1184,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 +1265,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 +1293,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 +1307,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 +1321,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 +1368,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 +1376,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 +1671,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 +1681,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 +1690,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 +1755,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,
OpenPOWER on IntegriCloud