diff options
author | Stuart Henderson <sthen@cvs.openbsd.org> | 2018-09-17 09:46:13 +0000 |
---|---|---|
committer | Stuart Henderson <sthen@cvs.openbsd.org> | 2018-09-17 09:46:13 +0000 |
commit | c93a0df3072712747929b99ef944a83cbc3ee43f (patch) | |
tree | dc7873115241ed4718c2ccb2eb3601fb754ae60c /usr.sbin/unbound/util/net_help.c | |
parent | a85ed5e1b2a44f86f07a2b0539cba80d8b1a4da5 (diff) |
merge conflicts
Diffstat (limited to 'usr.sbin/unbound/util/net_help.c')
-rw-r--r-- | usr.sbin/unbound/util/net_help.c | 178 |
1 files changed, 163 insertions, 15 deletions
diff --git a/usr.sbin/unbound/util/net_help.c b/usr.sbin/unbound/util/net_help.c index fdc8b0558af..a5059b0addc 100644 --- a/usr.sbin/unbound/util/net_help.c +++ b/usr.sbin/unbound/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 */ @@ -241,7 +244,8 @@ ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, socklen_t* addrlen, int* net) { - char* s = NULL; + char buf[64]; + char* s; *net = (str_is_ip6(str)?128:32); if((s=strchr(str, '/'))) { if(atoi(s+1) > *net) { @@ -253,24 +257,65 @@ int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, log_err("cannot parse netblock: '%s'", str); return 0; } - if(!(s = strdup(str))) { - log_err("out of memory"); - return 0; - } - *strchr(s, '/') = '\0'; + strlcpy(buf, str, sizeof(buf)); + s = strchr(buf, '/'); + if(s) *s = 0; + s = buf; } if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { - free(s); log_err("cannot parse ip address: '%s'", str); return 0; } if(s) { - free(s); addr_mask(addr, *addrlen, *net); } return 1; } +int authextstrtoaddr(char* str, struct sockaddr_storage* addr, + socklen_t* addrlen, char** auth_name) +{ + char* s; + int port = UNBOUND_DNS_PORT; + if((s=strchr(str, '@'))) { + char buf[MAX_ADDR_STRLEN]; + size_t len = (size_t)(s-str); + char* hash = strchr(s+1, '#'); + if(hash) { + *auth_name = hash+1; + } else { + *auth_name = NULL; + } + if(len >= MAX_ADDR_STRLEN) { + return 0; + } + (void)strlcpy(buf, str, sizeof(buf)); + buf[len] = 0; + port = atoi(s+1); + if(port == 0) { + if(!hash && strcmp(s+1,"0")!=0) + return 0; + if(hash && strncmp(s+1,"0#",2)!=0) + return 0; + } + return ipstrtoaddr(buf, port, addr, addrlen); + } + if((s=strchr(str, '#'))) { + char buf[MAX_ADDR_STRLEN]; + size_t len = (size_t)(s-str); + if(len >= MAX_ADDR_STRLEN) { + return 0; + } + (void)strlcpy(buf, str, sizeof(buf)); + buf[len] = 0; + port = UNBOUND_DNS_OVER_TLS_PORT; + *auth_name = s+1; + return ipstrtoaddr(buf, port, addr, addrlen); + } + *auth_name = NULL; + return ipstrtoaddr(str, port, addr, addrlen); +} + /** store port number into sockaddr structure */ void sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) @@ -754,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()); @@ -794,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 } |