mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- Add routine from getdns to add windows cert store to the SSL_CTX.
git-svn-id: file:///svn/unbound/trunk@4697 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
6792d2d036
commit
5a726fb61f
11 changed files with 127 additions and 15 deletions
2
configure
vendored
2
configure
vendored
|
|
@ -19468,7 +19468,7 @@ else
|
|||
WINDRES="$ac_cv_prog_WINDRES"
|
||||
fi
|
||||
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
|
|
|
|||
|
|
@ -1246,7 +1246,7 @@ if test "$USE_WINSOCK" = 1; then
|
|||
#include <windows.h>
|
||||
])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
AC_SUBST(WINAPPS)
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
|
|
|
|||
|
|
@ -431,7 +431,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
|||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle)))
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
28 May 2018: Wouter
|
||||
- Fix windows tcp and tls spin on events.
|
||||
- Add routine from getdns to add windows cert store to the SSL_CTX.
|
||||
|
||||
25 May 2018: Wouter
|
||||
- For TCP and TLS connections that don't establish, perform address
|
||||
|
|
|
|||
|
|
@ -158,9 +158,9 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
|||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0])) {
|
||||
if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0]) || cfg->tls_win_cert) {
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle);
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
|
|||
SSL* ssl = NULL;
|
||||
if(!buf) fatal_exit("out of memory");
|
||||
if(usessl) {
|
||||
ctx = connect_sslctx_create(NULL, NULL, NULL);
|
||||
ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
|
||||
if(!ctx) fatal_exit("cannot create ssl ctx");
|
||||
ssl = outgoing_ssl_fd(ctx, fd);
|
||||
if(!ssl) fatal_exit("cannot create ssl");
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ config_create(void)
|
|||
cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT;
|
||||
cfg->ssl_upstream = 0;
|
||||
cfg->tls_cert_bundle = NULL;
|
||||
cfg->tls_win_cert = 0;
|
||||
cfg->use_syslog = 1;
|
||||
cfg->log_identity = NULL; /* changed later with argv[0] */
|
||||
cfg->log_time_ascii = 0;
|
||||
|
|
|
|||
|
|
@ -102,6 +102,8 @@ struct config_file {
|
|||
int ssl_upstream;
|
||||
/** cert bundle for outgoing connections */
|
||||
char* tls_cert_bundle;
|
||||
/** should the system certificate store get added to the cert bundle */
|
||||
int tls_win_cert;
|
||||
/** additional tls ports */
|
||||
struct config_strlist* additional_tls_port;
|
||||
|
||||
|
|
|
|||
120
util/net_help.c
120
util/net_help.c
|
|
@ -52,6 +52,9 @@
|
|||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
#ifdef USE_WINSOCK
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
/** max length of an IP address (the address portion) that we allow */
|
||||
#define MAX_ADDR_STRLEN 128 /* characters */
|
||||
|
|
@ -796,7 +799,97 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
|
|||
#endif
|
||||
}
|
||||
|
||||
void* connect_sslctx_create(char* key, char* pem, char* verifypem)
|
||||
#ifdef USE_WINSOCK
|
||||
/* For windows, the CA trust store is not read by openssl.
|
||||
Add code to open the trust store using wincrypt API and add
|
||||
the root certs into openssl trust store */
|
||||
static int
|
||||
add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
|
||||
{
|
||||
HCERTSTORE hSystemStore;
|
||||
PCCERT_CONTEXT pTargetCert = NULL;
|
||||
X509_STORE* store;
|
||||
|
||||
verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store");
|
||||
|
||||
/* load just once per context lifetime for this version
|
||||
TODO: dynamically update CA trust changes as they are available */
|
||||
if (!tls_ctx)
|
||||
return 0;
|
||||
|
||||
/* Call wincrypt's CertOpenStore to open the CA root store. */
|
||||
|
||||
if ((hSystemStore = CertOpenStore(
|
||||
CERT_STORE_PROV_SYSTEM,
|
||||
0,
|
||||
0,
|
||||
/* NOTE: mingw does not have this const: replace with 1 << 16 from code
|
||||
CERT_SYSTEM_STORE_CURRENT_USER, */
|
||||
1 << 16,
|
||||
L"root")) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
store = SSL_CTX_get_cert_store(tls_ctx);
|
||||
if (!store)
|
||||
return 0;
|
||||
|
||||
/* failure if the CA store is empty or the call fails */
|
||||
if ((pTargetCert = CertEnumCertificatesInStore(
|
||||
hSystemStore, pTargetCert)) == 0) {
|
||||
verbose(VERB_ALGO, "CA certificate store for Windows is empty.");
|
||||
return 0;
|
||||
}
|
||||
/* iterate over the windows cert store and add to openssl store */
|
||||
do
|
||||
{
|
||||
X509 *cert1 = d2i_X509(NULL,
|
||||
(const unsigned char **)&pTargetCert->pbCertEncoded,
|
||||
pTargetCert->cbCertEncoded);
|
||||
if (!cert1) {
|
||||
/* return error if a cert fails */
|
||||
verbose(VERB_ALGO, "%s %d:%s",
|
||||
"Unable to parse certificate in memory",
|
||||
(int)ERR_get_error(), ERR_error_string(ERR_get_error(), NULL));
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* return error if a cert add to store fails */
|
||||
if (X509_STORE_add_cert(store, cert1) == 0) {
|
||||
unsigned long error = ERR_peek_last_error();
|
||||
|
||||
/* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
|
||||
* certificate is already in the store. */
|
||||
if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
|
||||
ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
|
||||
verbose(VERB_ALGO, "%s %d:%s\n",
|
||||
"Error adding certificate", (int)ERR_get_error(),
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
X509_free(cert1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
X509_free(cert1);
|
||||
}
|
||||
} while ((pTargetCert = CertEnumCertificatesInStore(
|
||||
hSystemStore, pTargetCert)) != 0);
|
||||
|
||||
/* Clean up memory and quit. */
|
||||
if (pTargetCert)
|
||||
CertFreeCertificateContext(pTargetCert);
|
||||
if (hSystemStore)
|
||||
{
|
||||
if (!CertCloseStore(
|
||||
hSystemStore, 0))
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully");
|
||||
return 1;
|
||||
}
|
||||
#endif /* USE_WINSOCK */
|
||||
|
||||
void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
|
|
@ -836,17 +929,30 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if(verifypem && verifypem[0]) {
|
||||
if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
|
||||
log_crypto_err("error in SSL_CTX verify");
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
if((verifypem && verifypem[0]) || wincert) {
|
||||
if(verifypem && verifypem[0]) {
|
||||
if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
|
||||
log_crypto_err("error in SSL_CTX verify");
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
if(wincert) {
|
||||
if(!add_WIN_cacerts_to_openssl_store(ctx)) {
|
||||
log_crypto_err("error in add_WIN_cacerts_to_openssl_store");
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)wincert;
|
||||
#endif
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||
}
|
||||
return ctx;
|
||||
#else
|
||||
(void)key; (void)pem; (void)verifypem;
|
||||
(void)key; (void)pem; (void)verifypem; (void)wincert;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,9 +395,11 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem);
|
|||
* @param key: if nonNULL (also pem nonNULL), the client private key.
|
||||
* @param pem: client public key (or NULL if key is NULL).
|
||||
* @param verifypem: if nonNULL used for verifylocation file.
|
||||
* @param wincert: add system certificate store to ctx (add to verifypem ca
|
||||
* certs).
|
||||
* @return SSL_CTX* or NULL on failure (logged).
|
||||
*/
|
||||
void* connect_sslctx_create(char* key, char* pem, char* verifypem);
|
||||
void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert);
|
||||
|
||||
/**
|
||||
* accept a new fd and wrap it in a BIO in SSL
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ service_init(int r, struct daemon** d, struct config_file** c)
|
|||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle)))
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
|
||||
/* open ports */
|
||||
|
|
|
|||
Loading…
Reference in a new issue