[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Fri Jan 18 11:16:47 UTC 2019


The branch master has been updated
       via  69738dadcda1b242a0b5e41d5d2fe4be3f55a448 (commit)
      from  3afd537a3c2319f68280804004e9bf2e798a43f7 (commit)


- Log -----------------------------------------------------------------
commit 69738dadcda1b242a0b5e41d5d2fe4be3f55a448
Author: Marc <34656315+MarcT512 at users.noreply.github.com>
Date:   Thu Jan 3 00:32:00 2019 +0000

    s_client: Add basic proxy authentication support
    
    1) Add two new flags (-proxy_user & -proxy_pass) to s_client to add support for basic (base64) proxy authentication.
    2) Add a "Proxy-Connection: Keep-Alive" HTTP header which is a workaround for some broken proxies which otherwise close the connection when entering tunnel mode (eg Squid 2.6).
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/7975)

-----------------------------------------------------------------------

Summary of changes:
 apps/s_client.c       | 81 +++++++++++++++++++++++++++++++++++++++++++++++----
 doc/man1/s_client.pod | 17 +++++++++++
 2 files changed, 93 insertions(+), 5 deletions(-)

diff --git a/apps/s_client.c b/apps/s_client.c
index 51001d5..d788b89 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -74,6 +74,7 @@ static void print_stuff(BIO *berr, SSL *con, int full);
 static int ocsp_resp_cb(SSL *s, void *arg);
 #endif
 static int ldap_ExtendedResponse_parse(const char *buf, long rem);
+static char *base64encode (const void *buf, size_t len);
 
 static int saved_errno;
 
@@ -590,7 +591,8 @@ typedef enum OPTION_choice {
     OPT_V_ENUM,
     OPT_X_ENUM,
     OPT_S_ENUM,
-    OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN,
+    OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS,
+    OPT_DANE_TLSA_DOMAIN,
 #ifndef OPENSSL_NO_CT
     OPT_CT, OPT_NOCT, OPT_CTLOG_FILE,
 #endif
@@ -608,6 +610,8 @@ const OPTIONS s_client_options[] = {
     {"bind", OPT_BIND, 's', "bind local address for connection"},
     {"proxy", OPT_PROXY, 's',
      "Connect to via specified proxy to the real server"},
+    {"proxy_user", OPT_PROXY_USER, 's', "UserID for proxy authentication"},
+    {"proxy_pass", OPT_PROXY_PASS, 's', "Proxy authentication password source"},
 #ifdef AF_UNIX
     {"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"},
 #endif
@@ -894,8 +898,10 @@ int s_client_main(int argc, char **argv)
     STACK_OF(X509_CRL) *crls = NULL;
     const SSL_METHOD *meth = TLS_client_method();
     const char *CApath = NULL, *CAfile = NULL;
-    char *cbuf = NULL, *sbuf = NULL;
-    char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL;
+    char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL;
+    char *proxystr = NULL, *proxyuser = NULL;
+    char *proxypassarg = NULL, *proxypass = NULL;
+    char *connectstr = NULL, *bindstr = NULL;
     char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
     char *chCApath = NULL, *chCAfile = NULL, *host = NULL;
     char *port = OPENSSL_strdup(PORT);
@@ -1075,6 +1081,12 @@ int s_client_main(int argc, char **argv)
             proxystr = opt_arg();
             starttls_proto = PROTO_CONNECT;
             break;
+        case OPT_PROXY_USER:
+            proxyuser = opt_arg();
+            break;
+        case OPT_PROXY_PASS:
+            proxypassarg = opt_arg();
+            break;
 #ifdef AF_UNIX
         case OPT_UNIX:
             connect_type = use_unix;
@@ -1619,7 +1631,17 @@ int s_client_main(int argc, char **argv)
 #endif
 
     if (!app_passwd(passarg, NULL, &pass, NULL)) {
-        BIO_printf(bio_err, "Error getting password\n");
+        BIO_printf(bio_err, "Error getting private key password\n");
+        goto end;
+    }
+
+    if (!app_passwd(proxypassarg, NULL, &proxypass, NULL)) {
+        BIO_printf(bio_err, "Error getting proxy password\n");
+        goto end;
+    }
+
+    if (proxypass != NULL && proxyuser == NULL) {
+        BIO_printf(bio_err, "Error: Must specify proxy_user with proxy_pass\n");
         goto end;
     }
 
@@ -2322,7 +2344,31 @@ int s_client_main(int argc, char **argv)
             BIO *fbio = BIO_new(BIO_f_buffer());
 
             BIO_push(fbio, sbio);
-            BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr);
+            BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n", connectstr);
+            /* 
+             * Workaround for broken proxies which would otherwise close
+             * the connection when entering tunnel mode (eg Squid 2.6)
+             */
+            BIO_printf(fbio, "Proxy-Connection: Keep-Alive\r\n");
+
+            /* Support for basic (base64) proxy authentication */
+            if (proxyuser != NULL) {
+                size_t l;
+                char *proxyauth, *proxyauthenc;
+
+                l = strlen(proxyuser);
+                if (proxypass != NULL)
+                    l += strlen(proxypass);
+                proxyauth = app_malloc(l + 2, "Proxy auth string");
+                snprintf(proxyauth, l + 2, "%s:%s", proxyuser, (proxypass != NULL) ? proxypass : "");
+                proxyauthenc = base64encode(proxyauth, strlen(proxyauth));
+                BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n", proxyauthenc); 
+                OPENSSL_clear_free(proxyauth, strlen(proxyauth));
+                OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc));
+            }
+
+            /* Terminate the HTTP CONNECT request */
+            BIO_printf(fbio, "\r\n");
             (void)BIO_flush(fbio);
             /*
              * The first line is the HTTP response.  According to RFC 7230,
@@ -3128,6 +3174,8 @@ int s_client_main(int argc, char **argv)
     OPENSSL_clear_free(cbuf, BUFSIZZ);
     OPENSSL_clear_free(sbuf, BUFSIZZ);
     OPENSSL_clear_free(mbuf, BUFSIZZ);
+    if (proxypass != NULL)
+        OPENSSL_clear_free(proxypass, strlen(proxypass));
     release_engine(e);
     BIO_free(bio_c_out);
     bio_c_out = NULL;
@@ -3467,4 +3515,27 @@ static int ldap_ExtendedResponse_parse(const char *buf, long rem)
     return ret;
 }
 
+/*
+ * BASE64 encoder: used only for encoding basic proxy authentication credentials
+ */
+static char *base64encode (const void *buf, size_t len)
+{
+    int i;
+    size_t outl;
+    char  *out;
+
+    /* Calculate size of encoded data */
+    outl = (len / 3);
+    if (len % 3 > 0)
+        outl++;
+    outl <<= 2;
+    out = app_malloc(outl + 1, "base64 encode buffer");
+
+    i = EVP_EncodeBlock((unsigned char *)out, buf, len);
+    assert(i <= (int)outl);
+    if (i < 0)
+        *out = '\0'; 
+    return out;
+}
+
 #endif                          /* OPENSSL_NO_SOCK */
diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod
index 1a241e6..70b97bf 100644
--- a/doc/man1/s_client.pod
+++ b/doc/man1/s_client.pod
@@ -12,6 +12,8 @@ B<openssl> B<s_client>
 [B<-connect host:port>]
 [B<-bind host:port>]
 [B<-proxy host:port>]
+[B<-proxy_user userid>]
+[B<-proxy_pass arg>]
 [B<-unix path>]
 [B<-4>]
 [B<-6>]
@@ -175,6 +177,21 @@ When used with the B<-connect> flag, the program uses the host and port
 specified with this flag and issues an HTTP CONNECT command to connect
 to the desired server.
 
+=item B<-proxy_user userid>
+
+When used with the B<-proxy> flag, the program will attempt to authenticate
+with the specified proxy using basic (base64) authentication.
+NB: Basic authentication is insecure; the credentials are sent to the proxy
+in easily reversible base64 encoding before any TLS/SSL session is established.
+Therefore these credentials are easily recovered by anyone able to sniff/trace
+the network. Use with caution.
+
+=item B<-proxy_pass arg>
+
+The proxy password source, used with the B<-proxy_user> flag.
+For more information about the format of B<arg> see the B<PASS PHRASE ARGUMENTS>
+section in L<openssl(1)>.
+
 =item B<-unix path>
 
 Connect over the specified Unix-domain socket.


More information about the openssl-commits mailing list