5128fb83640188e13bbd88c4ae876b32b03dff52
galt
  Fri Feb 4 01:55:05 2022 -0800
Further moving getenv together and cloning values for better safer getenv use.

diff --git src/lib/https.c src/lib/https.c
index 37e17dc..53c6cbc 100644
--- src/lib/https.c
+++ src/lib/https.c
@@ -10,30 +10,35 @@
 #include <unistd.h>
 #include <pthread.h>
 #include <signal.h>
 
 #include "common.h"
 #include "internet.h"
 #include "errAbort.h"
 #include "hash.h"
 #include "net.h"
 
 char *https_cert_check = NULL;
 char *https_cert_check_depth = NULL;
 char *https_cert_check_verbose = NULL;
 char *https_cert_check_domain_exceptions = NULL;
 
+char *https_proxy = NULL;
+char *log_proxy = NULL;
+
+char *SCRIPT_NAME = NULL;
+
 // For use with callback. Set a variable into the connection itself,
 // and then use that during the callback.
 struct myData
     {
     char *hostName;
     };
 
 int myDataIndex = -1;
 
 static pthread_mutex_t *mutexes = NULL;
  
 static unsigned long openssl_id_callback(void)
 {
 return ((unsigned long)pthread_self());
 }
@@ -84,35 +89,39 @@
 char *thisSetting = getenv(setting);
 if (thisSetting)
     return cloneString(thisSetting);
 else
     return cloneString(defaultValue);
 }
 
 void openSslInit()
 /* do only once */
 {
 static boolean done = FALSE;
 static pthread_mutex_t osiMutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_mutex_lock( &osiMutex );
 if (!done)
     {
-    // setenv here for thread-safety
+    // setenv avoided since not thread-safe
     https_cert_check                   = mySetenv("https_cert_check", "log");                  // DEFAULT certificate check is log.
     https_cert_check_depth             = mySetenv("https_cert_check_depth", "9");              // DEFAULT depth check level is 9.
     https_cert_check_verbose           = mySetenv("https_cert_check_verbose", "off");          // DEFAULT verbose is off.
     https_cert_check_domain_exceptions = mySetenv("https_cert_check_domain_exceptions", "");   // DEFAULT space separated list is empty string.
+    // getenv here for thread-safety
+    https_proxy = cloneString(getenv("https_proxy"));
+    log_proxy   = cloneString(getenv("log_proxy"));
+    SCRIPT_NAME = cloneString(getenv("SCRIPT_NAME"));
 
     SSL_library_init();
     ERR_load_crypto_strings();
     ERR_load_SSL_strings();
     OpenSSL_add_all_algorithms();
     openssl_pthread_setup();
     myDataIndex = SSL_get_ex_new_index(0, "myDataIndex", NULL, NULL, NULL);
     initDomainWhiteListHash();
     done = TRUE;
     }
 pthread_mutex_unlock( &osiMutex );
 }
 
 
 void *netConnectHttpsThread(void *threadParam)
@@ -333,34 +342,34 @@
 myData = SSL_get_ex_data(ssl, myDataIndex);
 
 
 if (depth > atoi(https_cert_check_depth))
     {
     preverify_ok = 0;
     err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
     X509_STORE_CTX_set_error(ctx, err);
     }
 if (sameString(https_cert_check_verbose, "on"))
     {
     fprintf(stderr,"depth=%d:%s\n", depth, buf);
     }
 if (!preverify_ok) 
     {
-    if (getenv("SCRIPT_NAME"))  // CGI mode
+    if (SCRIPT_NAME)  // CGI mode
 	{
 	fprintf(stderr, "verify error:num=%d:%s:depth=%d:%s hostName=%s CGI=%s\n", err,
-	    X509_verify_cert_error_string(err), depth, buf, myData->hostName, getenv("SCRIPT_NAME"));
+	    X509_verify_cert_error_string(err), depth, buf, myData->hostName, SCRIPT_NAME);
 	}
     if (!sameString(https_cert_check, "log"))
 	{
 	char *cn = strstr(buf, "/CN=");
 	if (cn) cn+=4;  // strlen /CN=
 	if (sameString(cn, myData->hostName))
 	    warn("%s on %s", X509_verify_cert_error_string(err), cn);
 	else
 	    warn("%s on %s (%s)", X509_verify_cert_error_string(err), cn, myData->hostName);
 	}
     }
 /* err contains the last verification error.  */
 if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
     {
     X509_NAME_oneline(X509_get_issuer_name(cert), buf, 256);
@@ -518,60 +527,60 @@
 	safef(wildHost, sizeof wildHost, "*%s", dot);
 	result = hashLookup(domainWhiteList, wildHost);
 	}
     }
 return result;
 }
 
 int netConnectHttps(char *hostName, int port, boolean noProxy)
 /* Return socket for https connection with server or -1 if error. */
 {
 
 int fd=0;
 
 // https_cert_check env var can be abort warn or none.
 
-char *proxyUrl = getenv("https_proxy");
+char *proxyUrl = https_proxy;
 
 if (noProxy)
     proxyUrl = NULL;
 char *connectHost;
 int connectPort;
 
 BIO *fbio=NULL;  // file descriptor bio
 BIO *sbio=NULL;  // ssl bio
 SSL_CTX *ctx;
 SSL *ssl;
 
 openSslInit();
 
 ctx = SSL_CTX_new(SSLv23_client_method());
 
 fd_set readfds;
 fd_set writefds;
 int err;
 struct timeval tv;
 
 struct myData myData;
 boolean doSetMyData = FALSE;
 
 if (!sameString(https_cert_check, "none"))
     {
     if (checkIfInHashWithWildCard(hostName))
 	{
 	// old existing domains which are not (yet) compatible with openssl.
-	if (getenv("SCRIPT_NAME"))  // CGI mode
+	if (SCRIPT_NAME)  // CGI mode
 	    {
 	    fprintf(stderr, "domain %s cert check skipped because it is white-listed as an exception.\n", hostName);
 	    }
 	}
     else
 	{
 
 	// verify peer cert of the server.
 	// Set TRUSTED_FIRST for openssl 1.0
 	// Fixes common issue openssl 1.0 had with with LetsEncrypt certs in the Fall of 2021.
 	X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), X509_V_FLAG_TRUSTED_FIRST);
 
         // This flag causes intermediate certificates in the trust store to be treated as trust-anchors, in the same way as the self-signed root CA certificates. 
         // This makes it possible to trust certificates issued by an intermediate CA without having to trust its ancestor root CA.
         // GNU-TLS uses it, and openssl probably will do it in the future. 
@@ -620,32 +629,31 @@
     }
 else
     {
     connectHost = hostName;
     connectPort = port;
     }
 fd = netConnect(connectHost,connectPort);
 if (fd == -1)
     {
     warn("netConnect() failed");
     goto cleanup2;
     }
 
 if (proxyUrl)
     {
-    char *logProxy = getenv("log_proxy");
-    if (sameOk(logProxy,"on"))
+    if (sameOk(log_proxy,"on"))
 	verbose(1, "CONNECT %s:%d HTTP/1.0 via %s:%d\n", hostName, port, connectHost,connectPort);
     struct dyString *dy = newDyString(512);
     dyStringPrintf(dy, "CONNECT %s:%d HTTP/1.0\r\n", hostName, port);
     setAuthorization(pxy, "Proxy-Authorization", dy);
     dyStringAppend(dy, "\r\n");
     mustWriteFd(fd, dy->string, dy->stringSize);
     dyStringFree(&dy);
     // verify response
     char *newUrl = NULL;
     boolean success = netSkipHttpHeaderLinesWithRedirect(fd, proxyUrl, &newUrl);
     if (!success) 
 	{
 	warn("proxy server response failed");
 	goto cleanup2;
 	}