[mod_openssl,mbedtls,gnutls,nss] fdevent_load_file
employ fdevent_load_file() to load CRL, X509 cert, and private key files into memory
This commit is contained in:
parent
cc04468762
commit
0ad57da55b
|
@ -214,10 +214,6 @@ static void elogf(log_error_st * const errh,
|
|||
* https://gitlab.com/gnutls/gnutls/-/issues/1002
|
||||
* https://gitlab.com/gnutls/gnutls/-/merge_requests/1270
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include "fdevent.h"
|
||||
static int
|
||||
mod_gnutls_load_file (const char * const fn, gnutls_datum_t * const d, log_error_st *errh)
|
||||
{
|
||||
|
@ -227,49 +223,12 @@ mod_gnutls_load_file (const char * const fn, gnutls_datum_t * const d, log_error
|
|||
elogf(errh, __FILE__, __LINE__, rc, "%s() %s", __func__, fn);
|
||||
return rc;
|
||||
#else
|
||||
int fd = -1;
|
||||
unsigned int sz = 0;
|
||||
char *buf = NULL;
|
||||
do {
|
||||
fd = fdevent_open_cloexec(fn, 1, O_RDONLY, 0); /*(1: follows symlinks)*/
|
||||
if (fd < 0) break;
|
||||
|
||||
struct stat st;
|
||||
if (0 != fstat(fd, &st)) break;
|
||||
if (st.st_size >= UINT_MAX) { /*(file too large for gnutls_datum_t)*/
|
||||
errno = EOVERFLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
sz = (unsigned int)st.st_size;
|
||||
buf = gnutls_malloc(sz+1); /*(+1 trailing '\0' for gnutls_load_file())*/
|
||||
if (NULL == buf) break;
|
||||
|
||||
ssize_t rd = 0;
|
||||
unsigned int off = 0;
|
||||
do {
|
||||
rd = read(fd, buf+off, sz-off);
|
||||
} while (rd > 0 ? (off += (unsigned int)rd) != sz : errno == EINTR);
|
||||
if (off != sz) { /*(file truncated?)*/
|
||||
if (rd >= 0) errno = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
buf[sz] = '\0';
|
||||
d->data = (unsigned char *)buf;
|
||||
d->size = sz;
|
||||
close(fd);
|
||||
return 0;
|
||||
} while (0);
|
||||
int errnum = errno;
|
||||
log_perror(errh, __FILE__, __LINE__, "%s() %s", __func__, fn);
|
||||
if (fd >= 0) close(fd);
|
||||
if (buf) {
|
||||
gnutls_memset(buf, 0, sz);
|
||||
gnutls_free(buf);
|
||||
}
|
||||
errno = errnum;
|
||||
return GNUTLS_E_FILE_ERROR;
|
||||
off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
|
||||
char *data = fdevent_load_file(fn, &dlen, errh, gnutls_malloc, gnutls_free);
|
||||
if (NULL == data) return GNUTLS_E_FILE_ERROR;
|
||||
d->data = (unsigned char *)data;
|
||||
d->size = (unsigned int)dlen;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
#include "http_header.h"
|
||||
#include "log.h"
|
||||
#include "plugin.h"
|
||||
#include "safe_memclear.h"
|
||||
|
||||
typedef struct {
|
||||
/* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */
|
||||
|
@ -753,6 +754,70 @@ mod_mbedtls_conf_verify (handler_ctx *hctx, mbedtls_ssl_config *ssl_ctx)
|
|||
}
|
||||
|
||||
|
||||
/* mbedTLS interfaces are generally excellent. mbedTLS convenience interfaces
|
||||
* to read CRLs, X509 certs, and private keys are uniformly paranoid about
|
||||
* clearing memory. At the moment, stdio routines fopen(), fread(), fclose()
|
||||
* are used for portability, but without setvbuf(stream, NULL, _IOLBF, 0),
|
||||
* again for portability, since setvbuf() is not necessarily available. Since
|
||||
* stdio buffers by default, use our own funcs to read files without buffering.
|
||||
* mbedtls_pk_load_file() includes trailing '\0' in size when contents in PEM
|
||||
* format, so do the same with the value returned from fdevent_load_file().
|
||||
*/
|
||||
|
||||
|
||||
static int
|
||||
mod_mbedtls_x509_crl_parse_file (mbedtls_x509_crl *chain, const char *fn)
|
||||
{
|
||||
int rc = MBEDTLS_ERR_X509_FILE_IO_ERROR;
|
||||
off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
|
||||
char *data = fdevent_load_file(fn, &dlen, NULL, malloc, free);
|
||||
if (NULL == data) return rc;
|
||||
|
||||
rc = mbedtls_x509_crl_parse(chain, (unsigned char *)data, (size_t)dlen+1);
|
||||
|
||||
if (dlen) safe_memclear(data, (size_t)dlen);
|
||||
free(data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mod_mbedtls_x509_crt_parse_file (mbedtls_x509_crt *chain, const char *fn)
|
||||
{
|
||||
int rc = MBEDTLS_ERR_X509_FILE_IO_ERROR;
|
||||
off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
|
||||
char *data = fdevent_load_file(fn, &dlen, NULL, malloc, free);
|
||||
if (NULL == data) return rc;
|
||||
|
||||
rc = mbedtls_x509_crt_parse(chain, (unsigned char *)data, (size_t)dlen+1);
|
||||
|
||||
if (dlen) safe_memclear(data, (size_t)dlen);
|
||||
free(data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mod_mbedtls_pk_parse_keyfile (mbedtls_pk_context *ctx, const char *fn, const char *pwd)
|
||||
{
|
||||
int rc = MBEDTLS_ERR_PK_FILE_IO_ERROR;
|
||||
off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
|
||||
char *data = fdevent_load_file(fn, &dlen, NULL, malloc, free);
|
||||
if (NULL == data) return rc;
|
||||
|
||||
rc = mbedtls_pk_parse_key(ctx, (unsigned char *)data, (size_t)dlen+1,
|
||||
(const unsigned char *)pwd,
|
||||
pwd ? strlen(pwd) : 0);
|
||||
|
||||
if (dlen) safe_memclear(data, (size_t)dlen);
|
||||
free(data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
network_mbedtls_load_pemfile (server *srv, const buffer *pemfile, const buffer *privkey)
|
||||
{
|
||||
|
@ -761,7 +826,7 @@ network_mbedtls_load_pemfile (server *srv, const buffer *pemfile, const buffer *
|
|||
int rc;
|
||||
|
||||
mbedtls_x509_crt_init(&ssl_pemfile_x509); /* init cert structure */
|
||||
rc = mbedtls_x509_crt_parse_file(&ssl_pemfile_x509, pemfile->ptr);
|
||||
rc = mod_mbedtls_x509_crt_parse_file(&ssl_pemfile_x509, pemfile->ptr);
|
||||
if (0 != rc) {
|
||||
elogf(srv->errh, __FILE__, __LINE__, rc,
|
||||
"PEM file cert read failed (%s)", pemfile->ptr);
|
||||
|
@ -769,7 +834,7 @@ network_mbedtls_load_pemfile (server *srv, const buffer *pemfile, const buffer *
|
|||
}
|
||||
|
||||
mbedtls_pk_init(&ssl_pemfile_pkey); /* init private key context */
|
||||
rc = mbedtls_pk_parse_keyfile(&ssl_pemfile_pkey, privkey->ptr, NULL);
|
||||
rc = mod_mbedtls_pk_parse_keyfile(&ssl_pemfile_pkey, privkey->ptr, NULL);
|
||||
if (0 != rc) {
|
||||
elogf(srv->errh, __FILE__, __LINE__, rc,
|
||||
"PEM file private key read failed %s", privkey->ptr);
|
||||
|
@ -837,7 +902,7 @@ mod_mbedtls_acme_tls_1 (handler_ctx *hctx)
|
|||
ssl_pemfile_x509 = malloc(sizeof(*ssl_pemfile_x509));
|
||||
force_assert(ssl_pemfile_x509);
|
||||
mbedtls_x509_crt_init(ssl_pemfile_x509); /* init cert structure */
|
||||
rc = mbedtls_x509_crt_parse_file(ssl_pemfile_x509, b->ptr);
|
||||
rc = mod_mbedtls_x509_crt_parse_file(ssl_pemfile_x509, b->ptr);
|
||||
if (0 != rc) {
|
||||
elogf(errh, __FILE__, __LINE__, rc,
|
||||
"Failed to load acme-tls/1 pemfile: %s", b->ptr);
|
||||
|
@ -849,7 +914,7 @@ mod_mbedtls_acme_tls_1 (handler_ctx *hctx)
|
|||
ssl_pemfile_pkey = malloc(sizeof(*ssl_pemfile_pkey));
|
||||
force_assert(ssl_pemfile_pkey);
|
||||
mbedtls_pk_init(ssl_pemfile_pkey); /* init private key context */
|
||||
rc = mbedtls_pk_parse_keyfile(ssl_pemfile_pkey, b->ptr, NULL);
|
||||
rc = mod_mbedtls_pk_parse_keyfile(ssl_pemfile_pkey, b->ptr, NULL);
|
||||
if (0 != rc) {
|
||||
elogf(errh, __FILE__, __LINE__, rc,
|
||||
"Failed to load acme-tls/1 pemfile: %s", b->ptr);
|
||||
|
@ -1533,7 +1598,8 @@ SETDEFAULTS_FUNC(mod_mbedtls_set_defaults)
|
|||
mbedtls_x509_crt *cacert = calloc(1, sizeof(*cacert));
|
||||
force_assert(cacert);
|
||||
mbedtls_x509_crt_init(cacert);
|
||||
int rc = mbedtls_x509_crt_parse_file(cacert, cpv->v.b->ptr);
|
||||
int rc =
|
||||
mod_mbedtls_x509_crt_parse_file(cacert, cpv->v.b->ptr);
|
||||
if (0 == rc) {
|
||||
cpv->vtype = T_CONFIG_LOCAL;
|
||||
cpv->v.v = cacert;
|
||||
|
@ -1552,7 +1618,8 @@ SETDEFAULTS_FUNC(mod_mbedtls_set_defaults)
|
|||
mbedtls_x509_crl *crl = malloc(sizeof(*crl));
|
||||
force_assert(crl);
|
||||
mbedtls_x509_crl_init(crl);
|
||||
int rc = mbedtls_x509_crl_parse_file(crl, cpv->v.b->ptr);
|
||||
int rc =
|
||||
mod_mbedtls_x509_crl_parse_file(crl, cpv->v.b->ptr);
|
||||
if (0 == rc) {
|
||||
cpv->vtype = T_CONFIG_LOCAL;
|
||||
cpv->v.v = crl;
|
||||
|
|
|
@ -330,57 +330,16 @@ mod_nss_io_dtor (PRFileDesc *ssl)
|
|||
}
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include "fdevent.h"
|
||||
static int
|
||||
mod_nss_load_file (const char * const fn, SECItem * const d, log_error_st *errh)
|
||||
{
|
||||
int fd = -1;
|
||||
unsigned int sz = 0;
|
||||
char *buf = NULL;
|
||||
do {
|
||||
fd = fdevent_open_cloexec(fn, 1, O_RDONLY, 0); /*(1: follows symlinks)*/
|
||||
if (fd < 0) break;
|
||||
|
||||
struct stat st;
|
||||
if (0 != fstat(fd, &st)) break;
|
||||
if (st.st_size >= UINT_MAX) { /*(file too large for SECItem)*/
|
||||
errno = EOVERFLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
sz = (unsigned int)st.st_size;
|
||||
buf = PORT_Alloc(sz+1); /*(+1 trailing '\0' for str funcs on PEM)*/
|
||||
if (NULL == buf) break;
|
||||
|
||||
ssize_t rd = 0;
|
||||
unsigned int off = 0;
|
||||
do {
|
||||
rd = read(fd, buf+off, sz-off);
|
||||
} while (rd > 0 ? (off += (unsigned int)rd) != sz : errno == EINTR);
|
||||
if (off != sz) { /*(file truncated?)*/
|
||||
if (rd >= 0) errno = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
buf[sz] = '\0';
|
||||
d->type = siBuffer;
|
||||
d->data = (unsigned char *)buf;
|
||||
d->len = sz;
|
||||
close(fd);
|
||||
return 0;
|
||||
} while (0);
|
||||
int errnum = errno;
|
||||
log_perror(errh, __FILE__, __LINE__, "%s() %s", __func__, fn);
|
||||
if (fd >= 0) close(fd);
|
||||
if (buf) {
|
||||
safe_memclear(buf, sz);
|
||||
PORT_Free(buf); /* safe_memclear() is safer than PORT_ZFree() */
|
||||
}
|
||||
errno = errnum;
|
||||
return -1;
|
||||
off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
|
||||
char *data = fdevent_load_file(fn, &dlen, errh, PORT_Alloc, PORT_Free);
|
||||
if (NULL == data) return -1;
|
||||
d->type = siBuffer;
|
||||
d->data = (unsigned char *)data;
|
||||
d->len = (unsigned int)dlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1403,55 +1403,21 @@ mod_openssl_load_stapling_file (const char *file, log_error_st *errh, buffer *b)
|
|||
* typically the same size with the signature and dates refreshed.
|
||||
*/
|
||||
|
||||
#ifdef BORINGSSL_API_VERSION
|
||||
#if defined(BORINGSSL_API_VERSION) \
|
||||
|| defined(WOLFSSL_VERSION)
|
||||
|
||||
/* load raw .der file */
|
||||
/* (similar to mod_gnutls.c:mod_gnutls_load_file(), but some differences) */
|
||||
int fd = -1;
|
||||
uint32_t sz = 0;
|
||||
char *buf = NULL;
|
||||
do {
|
||||
fd = fdevent_open_cloexec(file,1,O_RDONLY,0); /*(1: follows symlinks)*/
|
||||
if (fd < 0) break;
|
||||
|
||||
struct stat st;
|
||||
if (0 != fstat(fd, &st)) break;
|
||||
if (st.st_size == 0) break;
|
||||
if (st.st_size >= UINT32_MAX) { /*(file too large for buffer uint32_t)*/
|
||||
errno = EOVERFLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
sz = (uint32_t)st.st_size;
|
||||
buf = malloc(sz+1); /*(+1 trailing '\0')*/
|
||||
if (NULL == buf) break;
|
||||
|
||||
ssize_t rd = 0;
|
||||
unsigned int off = 0;
|
||||
do {
|
||||
rd = read(fd, buf+off, sz-off);
|
||||
} while (rd > 0 ? (off += (unsigned int)rd) != sz : errno == EINTR);
|
||||
if (off != sz) { /*(file truncated?)*/
|
||||
if (rd >= 0) errno = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL == b) b = buffer_init();
|
||||
buffer_copy_string_len(b, buf, sz);
|
||||
memset(buf, 0, sz);
|
||||
free(buf);
|
||||
close(fd);
|
||||
return b;
|
||||
} while (0);
|
||||
int errnum = errno;
|
||||
log_perror(errh, __FILE__, __LINE__, "%s() %s", __func__, file);
|
||||
if (fd >= 0) close(fd);
|
||||
if (buf) {
|
||||
memset(buf, 0, sz);
|
||||
free(buf);
|
||||
}
|
||||
errno = errnum;
|
||||
return NULL;;
|
||||
off_t dlen = 1*1024*1024;/*(arbitrary limit: 1 MB file; expect < 1 KB)*/
|
||||
char *data = fdevent_load_file(file, &dlen, errh, malloc, free);
|
||||
if (NULL == data) return NULL;
|
||||
if (NULL == b)
|
||||
b = buffer_init();
|
||||
else if (b->ptr)
|
||||
free(b->ptr);
|
||||
b->ptr = data;
|
||||
b->used = (uint32_t)dlen;
|
||||
b->size = (uint32_t)dlen+1;
|
||||
return b;
|
||||
|
||||
#else
|
||||
|
||||
|
|
Loading…
Reference in New Issue