RT266: Add HTTP proxy/CONNECT to s_client
authorMichael Trapp <m.trapp@gmx.de>
Fri, 8 May 2015 19:34:07 +0000 (15:34 -0400)
committerRich Salz <rsalz@openssl.org>
Fri, 22 May 2015 20:56:59 +0000 (16:56 -0400)
Signed-off-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
apps/s_client.c
doc/apps/s_client.pod

index 9717ad131c6239c0ab51b661e6fcc20b54db0fdc..c3c5bce78794fc184051a52f431c310e69af858b 100644 (file)
@@ -481,7 +481,7 @@ typedef enum OPTION_choice {
     OPT_V_ENUM,
     OPT_X_ENUM,
     OPT_S_ENUM,
     OPT_V_ENUM,
     OPT_X_ENUM,
     OPT_S_ENUM,
-    OPT_FALLBACKSCSV, OPT_NOCMDS
+    OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY
 } OPTION_CHOICE;
 
 OPTIONS s_client_options[] = {
 } OPTION_CHOICE;
 
 OPTIONS s_client_options[] = {
@@ -490,6 +490,8 @@ OPTIONS s_client_options[] = {
     {"port", OPT_PORT, 'p', "Use -connect instead"},
     {"connect", OPT_CONNECT, 's',
      "TCP/IP where to connect (default is " SSL_HOST_NAME ":" PORT_STR ")"},
     {"port", OPT_PORT, 'p', "Use -connect instead"},
     {"connect", OPT_CONNECT, 's',
      "TCP/IP where to connect (default is " SSL_HOST_NAME ":" PORT_STR ")"},
+    {"proxy", OPT_PROXY, 's',
+     "Connect to via specified proxy to the real server"},
     {"unix", OPT_UNIX, 's', "Connect over unix domain sockets"},
     {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
     {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"},
     {"unix", OPT_UNIX, 's', "Connect over unix domain sockets"},
     {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
     {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"},
@@ -610,7 +612,8 @@ typedef enum PROTOCOL_choice {
     PROTO_IMAP,
     PROTO_FTP,
     PROTO_TELNET,
     PROTO_IMAP,
     PROTO_FTP,
     PROTO_TELNET,
-    PROTO_XMPP
+    PROTO_XMPP,
+    PROTO_CONNECT
 } PROTOCOL_CHOICE;
 
 static OPT_PAIR services[] = {
 } PROTOCOL_CHOICE;
 
 static OPT_PAIR services[] = {
@@ -637,8 +640,8 @@ int s_client_main(int argc, char **argv)
     STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
     STACK_OF(X509_CRL) *crls = NULL;
     const SSL_METHOD *meth = TLS_client_method();
     STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
     STACK_OF(X509_CRL) *crls = NULL;
     const SSL_METHOD *meth = TLS_client_method();
-    char *CApath = NULL, *CAfile = NULL, *cbuf = NULL, *sbuf = NULL, *mbuf =
-        NULL;
+    char *CApath = NULL, *CAfile = NULL, *cbuf = NULL, *sbuf = NULL;
+    char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL;
     char *cert_file = NULL, *key_file = NULL, *chain_file = NULL, *prog;
     char *chCApath = NULL, *chCAfile = NULL, *host = SSL_HOST_NAME, *inrand =
         NULL;
     char *cert_file = NULL, *key_file = NULL, *chain_file = NULL, *prog;
     char *chCApath = NULL, *chCAfile = NULL, *host = SSL_HOST_NAME, *inrand =
         NULL;
@@ -752,8 +755,11 @@ int s_client_main(int argc, char **argv)
             port = atoi(opt_arg());
             break;
         case OPT_CONNECT:
             port = atoi(opt_arg());
             break;
         case OPT_CONNECT:
-            if (!extract_host_port(opt_arg(), &host, NULL, &port))
-                goto end;
+            connectstr = opt_arg();
+            break;
+        case OPT_PROXY:
+            proxystr = opt_arg();
+            starttls_proto = PROTO_CONNECT;
             break;
         case OPT_UNIX:
             unix_path = opt_arg();
             break;
         case OPT_UNIX:
             unix_path = opt_arg();
@@ -1069,6 +1075,17 @@ int s_client_main(int argc, char **argv)
     argc = opt_num_rest();
     argv = opt_rest();
 
     argc = opt_num_rest();
     argv = opt_rest();
 
+    if (proxystr) {
+        if (connectstr == NULL) {
+            BIO_printf(bio_err, "%s: -proxy requires use of -connect\n", prog);
+            goto opthelp;
+        }
+        if (!extract_host_port(proxystr, &host, NULL, &port))
+            goto end;
+    }
+    else if (!extract_host_port(connectstr, &host, NULL, &port))
+        goto end;
+
     if (unix_path && (socket_type != SOCK_STREAM)) {
         BIO_printf(bio_err,
                    "Can't use unix sockets and datagrams together\n");
     if (unix_path && (socket_type != SOCK_STREAM)) {
         BIO_printf(bio_err,
                    "Can't use unix sockets and datagrams together\n");
@@ -1619,6 +1636,31 @@ int s_client_main(int argc, char **argv)
             if (bytes != 6 || memcmp(mbuf, tls_follows, 6) != 0)
                 goto shut;
         }
             if (bytes != 6 || memcmp(mbuf, tls_follows, 6) != 0)
                 goto shut;
         }
+        break;
+    case PROTO_CONNECT:
+        {
+            int foundit = 0;
+            BIO *fbio = BIO_new(BIO_f_buffer());
+
+            BIO_push(fbio, sbio);
+            BIO_printf(fbio, "CONNECT %s\r\n\r\n", connectstr);
+            (void)BIO_flush(fbio);
+            /* wait for multi-line response to end CONNECT response */
+            do {
+                mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+                if (strstr(mbuf, "200") != NULL
+                    && strstr(mbuf, "established") != NULL)
+                    foundit++;
+            } while (mbuf_len > 3 && foundit == 0);
+            (void)BIO_flush(fbio);
+            BIO_pop(fbio);
+            BIO_free(fbio);
+            if (!foundit) {
+                BIO_printf(bio_err, "%s: HTTP CONNECT failed\n", prog);
+                goto shut;
+            }
+        }
+        break;
     }
 
     for (;;) {
     }
 
     for (;;) {
index 6aaef19788d21626a734818dfccd6441e96f6b62..12a6ef7cf8485e1f11d269a4a04f68aa2c3e0b81 100644 (file)
@@ -9,6 +9,7 @@ s_client - SSL/TLS client program
 
 B<openssl> B<s_client>
 [B<-connect host:port>]
 
 B<openssl> B<s_client>
 [B<-connect host:port>]
+[B<-proxy host:port>]
 [B<-servername name>]
 [B<-verify depth>]
 [B<-verify_return_error>]
 [B<-servername name>]
 [B<-verify depth>]
 [B<-verify_return_error>]
@@ -100,6 +101,12 @@ manual page.
 This specifies the host and optional port to connect to. If not specified
 then an attempt is made to connect to the local host on port 4433.
 
 This specifies the host and optional port to connect to. If not specified
 then an attempt is made to connect to the local host on port 4433.
 
+=item B<-proxy host:port>
+
+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<-servername name>
 
 Set the TLS SNI (Server Name Indication) extension in the ClientHello message.
 =item B<-servername name>
 
 Set the TLS SNI (Server Name Indication) extension in the ClientHello message.