summaryrefslogtreecommitdiffstats
path: root/runtime/nsd_gtls.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/nsd_gtls.c')
-rw-r--r--runtime/nsd_gtls.c65
1 files changed, 55 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;
}