summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-05-26 14:47:36 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-05-26 14:47:36 +0200
commitbc5eb93e40534f55b240d33dd605ed3e52bae555 (patch)
treebad1c9e41b3e1586f353bae49eae5e746ed23826
parentb674dd69bd35ee4da511ae73e70946ce4040b439 (diff)
downloadrsyslog-bc5eb93e40534f55b240d33dd605ed3e52bae555.tar.gz
rsyslog-bc5eb93e40534f55b240d33dd605ed3e52bae555.tar.xz
rsyslog-bc5eb93e40534f55b240d33dd605ed3e52bae555.zip
added certificate validity date check (gtls)
-rw-r--r--runtime/nsd_gtls.c65
-rw-r--r--runtime/rsyslog.h3
2 files changed, 58 insertions, 10 deletions
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index f3c0d983..5c82d082 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -113,7 +113,7 @@ gtlsGetCertInfo(nsd_gtls_t *pThis, cstr_t **ppStr)
if(cert_list_size > 0) {
/* we only print information about the first certificate */
- gnutls_x509_crt_init( &cert);
+ CHKgnutls(gnutls_x509_crt_init(&cert));
CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
@@ -762,25 +762,35 @@ gtlsChkPeerCertValidity(nsd_gtls_t *pThis)
char *pszErrCause;
int gnuRet;
cstr_t *pStr;
+ unsigned stateCert;
+ const gnutls_datum *cert_list;
+ unsigned cert_list_size = 0;
+ gnutls_x509_crt cert;
+ unsigned i;
+ time_t ttCert;
+ time_t ttNow;
ISOBJ_TYPE_assert(pThis, nsd_gtls);
- gnuRet = gnutls_certificate_verify_peers(pThis->sess);
- if(gnuRet == GNUTLS_E_NO_CERTIFICATE_FOUND) {
+
+ /* check if we have at least one cert */
+ cert_list = gnutls_certificate_get_peers(pThis->sess, &cert_list_size);
+ if(cert_list_size < 1) {
errno = 0;
errmsg.LogError(NO_ERRCODE, "peer did not provide a certificate, not permitted to talk to it");
ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
- } else if(gnuRet < 1)
- CHKgnutls(gnuRet);
+ }
+
+ CHKgnutls(gnutls_certificate_verify_peers2(pThis->sess, &stateCert));
- if(gnuRet & GNUTLS_CERT_INVALID) {
+ if(stateCert & GNUTLS_CERT_INVALID) {
/* provide error details if we have them */
- if(gnuRet & GNUTLS_CERT_SIGNER_NOT_FOUND) {
+ if(stateCert & GNUTLS_CERT_SIGNER_NOT_FOUND) {
pszErrCause = "signer not found";
- } else if(gnuRet & GNUTLS_CERT_SIGNER_NOT_FOUND) {
+ } else if(stateCert & GNUTLS_CERT_SIGNER_NOT_FOUND) {
pszErrCause = "signer is not a CA";
- } else if(gnuRet & GNUTLS_CERT_SIGNER_NOT_CA) {
+ } else if(stateCert & GNUTLS_CERT_SIGNER_NOT_CA) {
pszErrCause = "insecure algorithm";
- } else if(gnuRet & GNUTLS_CERT_REVOKED) {
+ } else if(stateCert & GNUTLS_CERT_REVOKED) {
pszErrCause = "certificate revoked";
} else {
pszErrCause = "no specific reason";
@@ -793,6 +803,41 @@ gtlsChkPeerCertValidity(nsd_gtls_t *pThis)
ABORT_FINALIZE(RS_RET_CERT_INVALID);
}
+ /* get current time for certificate validation */
+ if(time(&ttNow) == -1)
+ ABORT_FINALIZE(RS_RET_SYS_ERR);
+
+ /* as it looks, we need to validate the expiration dates ourselves...
+ * We need to loop through all certificates as we need to make sure the
+ * interim certificates are also not expired.
+ */
+ for(i = 0 ; i < cert_list_size ; ++i) {
+ CHKgnutls(gnutls_x509_crt_init(&cert));
+ CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER));
+ ttCert = gnutls_x509_crt_get_activation_time(cert);
+ if(ttCert == -1)
+ ABORT_FINALIZE(RS_RET_TLS_CERT_ERR);
+ else if(ttCert > ttNow) {
+ errmsg.LogError(NO_ERRCODE, "not permitted to talk to peer: certificate %d not yet active", i);
+ gtlsGetCertInfo(pThis, &pStr);
+ errmsg.LogError(NO_ERRCODE, "info on invalid cert: %s", rsCStrGetSzStr(pStr));
+ rsCStrDestruct(&pStr);
+ ABORT_FINALIZE(RS_RET_CERT_NOT_YET_ACTIVE);
+ }
+
+ ttCert = gnutls_x509_crt_get_expiration_time(cert);
+ if(ttCert == -1)
+ ABORT_FINALIZE(RS_RET_TLS_CERT_ERR);
+ else if(ttCert > ttNow) {
+ errmsg.LogError(NO_ERRCODE, "not permitted to talk to peer: certificate %d expired", i);
+ gtlsGetCertInfo(pThis, &pStr);
+ errmsg.LogError(NO_ERRCODE, "info on invalid cert: %s", rsCStrGetSzStr(pStr));
+ rsCStrDestruct(&pStr);
+ ABORT_FINALIZE(RS_RET_CERT_EXPIRED);
+ }
+ gnutls_x509_crt_deinit(cert);
+ }
+
finalize_it:
RETiRet;
}
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 4f858928..5f39c3d8 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -231,6 +231,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_CONNECTION_ABORTREQ = -2089, /**< connection was abort requested due to previous error */
RS_RET_CERT_INVALID = -2090, /**< a x509 certificate failed validation */
RS_RET_CERT_INVALID_DN = -2091, /**< distinguised name in x509 certificate is invalid (e.g. wrong escaping) */
+ RS_RET_CERT_EXPIRED = -2092, /**< we are past a x.509 cert's expiration time */
+ RS_RET_CERT_NOT_YET_ACTIVE = -2094, /**< x.509 cert's activation time not yet reached */
+ RS_RET_SYS_ERR = -2095, /**< system error occured (e.g. time() returned -1, quite unexpected) */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */