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 */