[PATCH] catch expired certificates in the chain
Ludwig Nussel
ludwig.nussel at suse.de
Mon Feb 2 11:35:49 EST 2009
Next try. This time with separate failure bits. I don't know how to
implement that for gnutls though.
Signed-off-by: Ludwig Nussel <ludwig.nussel at suse.de>
cu
Ludwig
---
src/ne_openssl.c | 9 ++++++++-
src/ne_session.c | 2 ++
src/ne_session.h | 6 +++++-
test/makekeys.sh | 38 ++++++++++++++++++++++++++------------
test/openssl.conf | 10 ++++++----
test/ssl.c | 14 ++++++++++++++
6 files changed, 61 insertions(+), 18 deletions(-)
diff --git a/src/ne_openssl.c b/src/ne_openssl.c
index 91ef671..54ba35b 100644
--- a/src/ne_openssl.c
+++ b/src/ne_openssl.c
@@ -411,9 +411,16 @@ static int check_certificate(ne_session *sess, SSL *ssl, ne_ssl_certificate *cha
/* TODO: and probably more result codes here... */
failures |= NE_SSL_UNTRUSTED;
break;
- /* ignore these, since we've already noticed them: */
+ /* if we see those and haven't recorded them yet a chained
+ * cert is to blame */
case X509_V_ERR_CERT_NOT_YET_VALID:
+ if ((failures&NE_SSL_NOTYETVALID) != NE_SSL_NOTYETVALID)
+ failures |= NE_SSL_CHAIN_NOTYETVALID;
+ break;
case X509_V_ERR_CERT_HAS_EXPIRED:
+ if ((failures&NE_SSL_EXPIRED) != NE_SSL_EXPIRED)
+ failures |= NE_SSL_CHAIN_EXPIRED;
+ break;
/* cert was trusted: */
case X509_V_OK:
break;
diff --git a/src/ne_session.c b/src/ne_session.c
index 7b0d672..3f77a43 100644
--- a/src/ne_session.c
+++ b/src/ne_session.c
@@ -540,6 +540,8 @@ void ne__ssl_set_verify_err(ne_session *sess, int failures)
{ NE_SSL_EXPIRED, N_("certificate has expired") },
{ NE_SSL_IDMISMATCH, N_("certificate issued for a different hostname") },
{ NE_SSL_UNTRUSTED, N_("issuer is not trusted") },
+ { NE_SSL_CHAIN_NOTYETVALID, N_("a chained certificate is not yet valid") },
+ { NE_SSL_CHAIN_EXPIRED, N_("a chained certificate has expired") },
{ 0, NULL }
};
int n, flag = 0;
diff --git a/src/ne_session.h b/src/ne_session.h
index 1d52385..19c81ed 100644
--- a/src/ne_session.h
+++ b/src/ne_session.h
@@ -218,11 +218,15 @@ void ne_set_notifier(ne_session *sess, ne_notify_status status, void *userdata);
* not trusted: there is no indicatation the server is who they claim
* to be: */
#define NE_SSL_UNTRUSTED (0x08)
+ /* A certificate in the chain is not yet valid: */
+#define NE_SSL_CHAIN_NOTYETVALID (0x10)
+/* The certificate in the chain has expired: */
+#define NE_SSL_CHAIN_EXPIRED (0x20)
/* The bitmask of known failure bits: if (failures & ~NE_SSL_FAILMASK)
* is non-zero, an unrecognized failure is given, and the verification
* should be failed. */
-#define NE_SSL_FAILMASK (0x0f)
+#define NE_SSL_FAILMASK (0x3f)
/* A callback which is used when server certificate verification is
* needed. The reasons for verification failure are given in the
diff --git a/test/makekeys.sh b/test/makekeys.sh
index b020874..64ba053 100755
--- a/test/makekeys.sh
+++ b/test/makekeys.sh
@@ -12,7 +12,8 @@ MKCERT="${REQ} -x509 -new -days 900"
REQDN=reqDN
STRMASK=default
-export REQDN STRMASK
+CADIR=./ca
+export REQDN STRMASK CADIR
asn1date() {
date -d "$1" "+%y%m%d%H%M%SZ"
@@ -22,17 +23,14 @@ openssl version 1>&2
set -ex
-rm -rf ca ca2
-mkdir ca
-touch ca/index.txt
-echo 01 > ca/serial
-
-mkdir ca2
-touch ca2/index.txt
-echo 01 > ca2/serial
+for i in ca ca1 ca2 ca3; do
+ rm -rf $i
+ mkdir $i
+ touch $i/index.txt
+ echo 01 > $i/serial
+ ${OPENSSL} genrsa -rand ${srcdir}/../configure > $i/key.pem
+done
-${OPENSSL} genrsa -rand ${srcdir}/../configure > ca/key.pem
-${OPENSSL} genrsa -rand ${srcdir}/../configure > ca2/key.pem
${OPENSSL} genrsa -rand ${srcdir}/../configure > client.key
${OPENSSL} dsaparam -genkey -rand ${srcdir}/../configure 1024 > client.dsap
@@ -72,6 +70,16 @@ EOF
csr_fields IntermediaryCA | ${REQ} -new -key ca2/key.pem -out ca2.csr
${CA} -extensions caExt -days 3560 -in ca2.csr -out ca2/cert.pem
+csr_fields ExpiredCA | ${REQ} -new -key ca1/key.pem -out ca1/cert.csr
+
+csr_fields NotYetValidCA | ${REQ} -new -key ca3/key.pem -out ca3/cert.csr
+
+CADIR=./ca1 ${CA} -name neoncainit -startdate `asn1date "2 days ago"` -enddate `asn1date "yesterday"` \
+ -in ca1/cert.csr -keyfile ca1/key.pem -out ca1/cert.pem -selfsign
+
+CADIR=./ca3 ${CA} -name neoncainit -startdate `asn1date "tomorrow"` -enddate `asn1date "2 days"` \
+ -in ca3/cert.csr -keyfile ca3/key.pem -out ca3/cert.pem -selfsign
+
csr_fields | ${REQ} -new -key ${srcdir}/server.key -out server.csr
csr_fields | ${REQ} -new -key ${srcdir}/server.key -out expired.csr
@@ -190,10 +198,16 @@ for n in 1 2 3 4 5 6 7 8 9; do
done
# Sign this CSR using the intermediary CA
-${CA} -name neonca2 -days 900 -in server.csr -out ca2server.cert
+CADIR=./ca2 ${CA} -days 900 -in server.csr -out ca2server.cert
# And create a file with the concatenation of both EE and intermediary
# cert.
cat ca2server.cert ca2/cert.pem > ca2server.pem
+
+# sign with expired CA
+CADIR=./ca1 ${CA} -days 3 -in server.csr -out ca1server.cert
+
+# sign with not yet valid CA
+CADIR=./ca3 ${CA} -days 3 -in server.csr -out ca3server.cert
MKPKCS12="${OPENSSL} pkcs12 -export -passout stdin -in client.cert -inkey client.key"
diff --git a/test/openssl.conf b/test/openssl.conf
index 3c5e699..bdaffec 100644
--- a/test/openssl.conf
+++ b/test/openssl.conf
@@ -2,7 +2,7 @@
default_ca = neonca
[neonca]
-dir = ./ca
+dir = ${ENV::CADIR}
database = $dir/index.txt
new_certs_dir = $dir
certificate = $dir/cert.pem
@@ -13,17 +13,19 @@ default_md = md5
x509_extensions = issuedExt
unique_subject = no
-[neonca2]
-dir = ./ca2
+# same as neonca1 just +basicConstraints and without certificate to
+# allow creation of the initial self signed certificate
+[neoncainit]
+dir = ${ENV::CADIR}
database = $dir/index.txt
new_certs_dir = $dir
-certificate = $dir/cert.pem
serial = $dir/serial
private_key = $dir/key.pem
policy = policy_any
default_md = md5
x509_extensions = issuedExt
unique_subject = no
+basicConstraints = CA:TRUE
[policy_any]
countryName = optional
diff --git a/test/ssl.c b/test/ssl.c
index bfc3692..e3a290a 100644
--- a/test/ssl.c
+++ b/test/ssl.c
@@ -864,6 +864,18 @@ static int fail_wildcard(void)
"subjaltname not honored", NE_SSL_IDMISMATCH);
}
+static int fail_ca_expired(void)
+{
+ return fail_ssl_request("ca1server.cert", "ca1/cert.pem", "localhost",
+ "isser ca expired", NE_SSL_CHAIN_EXPIRED);
+}
+
+static int fail_ca_notyetvalid(void)
+{
+ return fail_ssl_request("ca3server.cert", "ca3/cert.pem", "localhost",
+ "isser ca not yet valid", NE_SSL_CHAIN_NOTYETVALID);
+}
+
/* Test that the SSL session is cached across connections. */
static int session_cache(void)
{
@@ -1763,6 +1775,8 @@ ne_test tests[] = {
T(fail_bad_ipaltname),
T(fail_bad_urialtname),
T(fail_wildcard),
+ T(fail_ca_expired),
+ T(fail_ca_notyetvalid),
T(session_cache),
--
1.6.0.2
More information about the neon
mailing list