On Thu, 18 Jan 2018 16:27:35 +0100 Arne Nordmark <nordm...@mech.kth.se> wrote:
>
> gtlsLoadOurCertKey() uses gnutls_x509_crt_import() on the file data, and this function only handles one cert.
>

If one uses gnutls_x509_crt_list_import() instead, intermediate certs could be supported. With the attached patch,
the server sends all certificates in the file.

Arne



--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -173,6 +173,7 @@
 	gnutls_datum_t data = { NULL, 0 };
 	uchar *keyFile;
 	uchar *certFile;
+	int lenRcvd;
 
 	ISOBJ_TYPE_assert(pThis, nsd_gtls);
 
@@ -192,9 +193,12 @@
 
 	/* try load certificate */
 	CHKiRet(readFile(certFile, &data));
-	CHKgnutls(gnutls_x509_crt_init(&pThis->ourCert));
+	pThis->nOurCerts=sizeof(pThis->pOurCerts);
+	lenRcvd=gnutls_x509_crt_list_import(pThis->pOurCerts, &pThis->nOurCerts, &data, GNUTLS_X509_FMT_PEM,0);
+	if (lenRcvd<0) {
+		CHKgnutls(lenRcvd);
+	}
 	pThis->bOurCertIsInit = 1;
-	CHKgnutls(gnutls_x509_crt_import(pThis->ourCert, &data, GNUTLS_X509_FMT_PEM));
 	free(data.data);
 	data.data = NULL;
 
@@ -210,7 +214,9 @@
 		if(data.data != NULL)
 			free(data.data);
 		if(pThis->bOurCertIsInit) {
-			gnutls_x509_crt_deinit(pThis->ourCert);
+			for (int i=0; i<pThis->nOurCerts; ++i) {
+				gnutls_x509_crt_deinit(pThis->pOurCerts[i]);
+			}
 			pThis->bOurCertIsInit = 0;
 		}
 		if(pThis->bOurKeyIsInit) {
@@ -255,8 +261,8 @@
 #else
 	st->type = GNUTLS_CRT_X509;
 #endif
-	st->ncerts = 1;
-	st->cert.x509 = &pThis->ourCert;
+	st->ncerts = pThis->nOurCerts;
+	st->cert.x509 = pThis->pOurCerts;
 	st->key.x509 = pThis->ourKey;
 	st->deinit_all = 0;
 
@@ -1204,7 +1210,9 @@
 	}
 
 	if(pThis->bOurCertIsInit)
-		gnutls_x509_crt_deinit(pThis->ourCert);
+                  for (int i=0; i<pThis->nOurCerts; ++i) {
+			gnutls_x509_crt_deinit(pThis->pOurCerts[i]);
+                  }
 	if(pThis->bOurKeyIsInit)
 		gnutls_x509_privkey_deinit(pThis->ourKey);
 	if(pThis->bHaveSess)
--- a/runtime/nsd_gtls.h
+++ b/runtime/nsd_gtls.h
@@ -25,6 +25,7 @@
 #include "nsd.h"
 
 #define NSD_GTLS_MAX_RCVBUF 8 * 1024 /* max size of buffer for message reception */
+#define NSD_GTLS_MAX_CERT 10 /* max number of certs in our chain */
 
 typedef enum {
 	gtlsRtry_None = 0,	/**< no call needs to be retried */
@@ -56,7 +57,8 @@
 				 * set to 1 and changed to 0 after the first report. It is changed back to 1 after
 				 * one successful authentication. */
 	permittedPeers_t *pPermPeers; /* permitted peers */
-	gnutls_x509_crt_t ourCert;	/**< our certificate, if in client mode (unused in server mode) */
+	gnutls_x509_crt_t pOurCerts[NSD_GTLS_MAX_CERT];	/**< our certificate, if in client mode (unused in server mode) */
+	unsigned int nOurCerts;  /* number of certificates in our chain */
 	gnutls_x509_privkey_t ourKey;	/**< our private key, if in client mode (unused in server mode) */
 	short	bOurCertIsInit;	/**< 1 if our certificate is initialized and must be deinit on destruction */
 	short	bOurKeyIsInit;	/**< 1 if our private key is initialized and must be deinit on destruction */

Reply via email to