You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by sh...@apache.org on 2015/01/22 15:29:27 UTC

trafficserver git commit: TS-3100: Extend tr-pass to allow malformed HTTP GET requests to be blind tunneled.

Repository: trafficserver
Updated Branches:
  refs/heads/master 9e2689b78 -> 497e4755d


TS-3100: Extend tr-pass to allow malformed HTTP GET requests to be blind
tunneled.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/497e4755
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/497e4755
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/497e4755

Branch: refs/heads/master
Commit: 497e4755d7773590204b89b6c262f6605a9c8e21
Parents: 9e2689b
Author: shinrich <sh...@yahoo-inc.com>
Authored: Thu Jan 22 08:28:52 2015 -0600
Committer: shinrich <sh...@yahoo-inc.com>
Committed: Thu Jan 22 08:28:52 2015 -0600

----------------------------------------------------------------------
 CHANGES                    |  3 ++
 proxy/hdrs/HTTP.h          | 66 +++++++++++++++++++++++++++++++++++++--
 proxy/hdrs/MIME.h          |  9 ++++++
 proxy/http/HttpSM.cc       | 23 +++++++++++---
 proxy/http/HttpTransact.cc | 68 ++---------------------------------------
 5 files changed, 97 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/497e4755/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index ddbd7e0..2d81063 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 5.3.0
+  *) [TS-3100] Extend tr-pass to allow malformed HTTP GET requested to be blind
+   tunneled.
+
   *) [TS-3140] Traffic Server asserts during response redirect.
 
   *) [TS-3309] Document TLS session ticket rotation.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/497e4755/proxy/hdrs/HTTP.h
----------------------------------------------------------------------
diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h
index 00a9c78..fa0281d 100644
--- a/proxy/hdrs/HTTP.h
+++ b/proxy/hdrs/HTTP.h
@@ -549,7 +549,7 @@ public:
 
   HTTPType type_get() const;
 
-  HTTPVersion version_get();
+  HTTPVersion version_get() const;
   void version_set(HTTPVersion version);
 
   const char *method_get(int *length);
@@ -662,6 +662,9 @@ public:
   // Utility routines
   bool is_cache_control_set(const char *cc_directive_wks);
   bool is_pragma_no_cache_set();
+  bool is_keep_alive_set() const;
+  HTTPKeepAlive keep_alive_get() const;
+
 
 protected:
   /** Load the target cache.
@@ -1006,7 +1009,7 @@ http_hdr_version_get(HTTPHdrImpl *hh)
   -------------------------------------------------------------------------*/
 
 inline HTTPVersion
-HTTPHdr::version_get()
+HTTPHdr::version_get() const
 {
   ink_assert(valid());
   return HTTPVersion(http_hdr_version_get(m_http));
@@ -1015,6 +1018,65 @@ HTTPHdr::version_get()
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
+inline static HTTPKeepAlive
+is_header_keep_alive(const HTTPVersion & http_version, const MIMEField* con_hdr)
+{
+  enum {
+    CON_TOKEN_NONE = 0,
+    CON_TOKEN_KEEP_ALIVE,
+    CON_TOKEN_CLOSE
+  };
+
+  int con_token = CON_TOKEN_NONE;
+  HTTPKeepAlive keep_alive = HTTP_NO_KEEPALIVE;
+  //    *unknown_tokens = false;
+
+  if (con_hdr) {
+    if (con_hdr->value_get_index("keep-alive", 10) >= 0)
+      con_token = CON_TOKEN_KEEP_ALIVE;
+    else if (con_hdr->value_get_index("close", 5) >= 0) 
+      con_token = CON_TOKEN_CLOSE;
+  }
+
+  if (HTTPVersion(1, 0) == http_version) {
+    keep_alive = (con_token == CON_TOKEN_KEEP_ALIVE) ? (HTTP_KEEPALIVE) : (HTTP_NO_KEEPALIVE);
+  } else if (HTTPVersion(1, 1) == http_version) {
+    // We deviate from the spec here.  If the we got a response where
+    //   where there is no Connection header and the request 1.0 was
+    //   1.0 don't treat this as keep-alive since Netscape-Enterprise/3.6 SP1
+    //   server doesn't
+    keep_alive = ((con_token == CON_TOKEN_KEEP_ALIVE) ||
+                  (con_token == CON_TOKEN_NONE && HTTPVersion(1, 1) == http_version)) ? (HTTP_KEEPALIVE)
+      : (HTTP_NO_KEEPALIVE);
+  } else {
+    keep_alive = HTTP_NO_KEEPALIVE;
+  }
+  return (keep_alive);
+}
+
+inline HTTPKeepAlive
+HTTPHdr::keep_alive_get() const
+{
+  HTTPKeepAlive retval = HTTP_NO_KEEPALIVE;
+  const MIMEField *pc = this->field_find(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION);
+  if (pc != NULL) {
+    retval = is_header_keep_alive(this->version_get(), pc);
+  } else {
+    const MIMEField *c = this->field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
+    retval = is_header_keep_alive(this->version_get(), c);
+  }
+  return retval; 
+}
+
+inline bool
+HTTPHdr::is_keep_alive_set() const
+{
+  return this->keep_alive_get() == HTTP_KEEPALIVE;
+}
+
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
 inline void
 HTTPHdr::version_set(HTTPVersion version)
 {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/497e4755/proxy/hdrs/MIME.h
----------------------------------------------------------------------
diff --git a/proxy/hdrs/MIME.h b/proxy/hdrs/MIME.h
index 127da61..860af82 100644
--- a/proxy/hdrs/MIME.h
+++ b/proxy/hdrs/MIME.h
@@ -905,6 +905,7 @@ public:
 
   MIMEField *field_create(const char *name = NULL, int length = -1);
   MIMEField *field_find(const char *name, int length);
+  const MIMEField *field_find(const char *name, int length) const;
   void field_attach(MIMEField * field);
   void field_detach(MIMEField * field, bool detach_all_dups = true);
   void field_delete(MIMEField * field, bool delete_all_dups = true);
@@ -1101,6 +1102,14 @@ MIMEHdr::field_find(const char *name, int length)
   return mime_hdr_field_find(m_mime, name, length);
 }
 
+inline const MIMEField *
+MIMEHdr::field_find(const char *name, int length) const
+{
+//    ink_assert(valid());
+  MIMEField *retval =  mime_hdr_field_find(const_cast<MIMEHdr *>(this)->m_mime, name, length);
+  return retval;
+}
+
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/497e4755/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 3998771..8323929 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -680,11 +680,25 @@ HttpSM::state_read_client_request_header(int event, void *data)
   // We need to handle EOS as well as READ_READY because the client
   // may have sent all of the data already followed by a fIN and that
   // should be OK.
-  if ((event == VC_EVENT_READ_READY || event == VC_EVENT_EOS) &&
-      state == PARSE_ERROR &&
-      is_transparent_passthrough_allowed() &&
+  if (is_transparent_passthrough_allowed() &&
       ua_raw_buffer_reader != NULL) {
-
+    bool do_blind_tunnel = false;
+    // If we had a parse error and we're done reading data
+    // blind tunnel
+    if ((event == VC_EVENT_READ_READY || event == VC_EVENT_EOS) &&
+        state == PARSE_ERROR) {
+      do_blind_tunnel = true;
+
+    // If we had a GET request that has data after the
+    // get request, do blind tunnel
+    } else if (state == PARSE_DONE &&
+               t_state.hdr_info.client_request.method_get_wksidx() == 
+               HTTP_WKSIDX_GET &&
+               ua_raw_buffer_reader->read_avail() > 0 &&
+               !t_state.hdr_info.client_request.is_keep_alive_set()) {
+      do_blind_tunnel = true;
+    }
+    if (do_blind_tunnel) {
       DebugSM("http", "[%" PRId64 "] first request on connection failed parsing, switching to passthrough.", sm_id);
 
       t_state.transparent_passthrough = true;
@@ -703,6 +717,7 @@ HttpSM::state_read_client_request_header(int event, void *data)
         t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
       }
       return 0;
+    }
   }
 
   // Check to see if we are done parsing the header

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/497e4755/proxy/http/HttpTransact.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 987a084..e3f06f0 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -69,47 +69,6 @@ extern HttpBodyFactory *body_factory;
 
 static const char local_host_ip_str[] = "127.0.0.1";
 
-
-// someday, reduce the amount of duplicate code between this
-// function and _process_xxx_connection_field_in_outgoing_header
-inline static HTTPKeepAlive
-is_header_keep_alive(const HTTPVersion & http_version, const HTTPVersion & request_http_version, MIMEField* con_hdr    /*, bool* unknown_tokens */)
-{
-  enum
-  {
-    CON_TOKEN_NONE = 0,
-    CON_TOKEN_KEEP_ALIVE,
-    CON_TOKEN_CLOSE
-  };
-
-  int con_token = CON_TOKEN_NONE;
-  HTTPKeepAlive keep_alive = HTTP_NO_KEEPALIVE;
-  //    *unknown_tokens = false;
-
-  if (con_hdr) {
-    if (con_hdr->value_get_index("keep-alive", 10) >= 0)
-      con_token = CON_TOKEN_KEEP_ALIVE;
-    else if (con_hdr->value_get_index("close", 5) >= 0)
-      con_token = CON_TOKEN_CLOSE;
-  }
-
-  if (HTTPVersion(1, 0) == http_version) {
-    keep_alive = (con_token == CON_TOKEN_KEEP_ALIVE) ? (HTTP_KEEPALIVE) : (HTTP_NO_KEEPALIVE);
-  } else if (HTTPVersion(1, 1) == http_version) {
-    // We deviate from the spec here.  If the we got a response where
-    //   where there is no Connection header and the request 1.0 was
-    //   1.0 don't treat this as keep-alive since Netscape-Enterprise/3.6 SP1
-    //   server doesn't
-    keep_alive = ((con_token == CON_TOKEN_KEEP_ALIVE) ||
-                  (con_token == CON_TOKEN_NONE && HTTPVersion(1, 1) == request_http_version)) ? (HTTP_KEEPALIVE)
-      : (HTTP_NO_KEEPALIVE);
-  } else {
-    keep_alive = HTTP_NO_KEEPALIVE;
-  }
-
-  return (keep_alive);
-}
-
 inline static bool
 is_request_conditional(HTTPHdr* header)
 {
@@ -5468,14 +5427,7 @@ HttpTransact::initialize_state_variables_from_request(State* s, HTTPHdr* obsolet
   if (!s->txn_conf->keep_alive_enabled_in) {
     s->client_info.keep_alive = HTTP_NO_KEEPALIVE;
   } else {
-    // If there is a Proxy-Connection header use that, otherwise use the Connection header
-    if (pc != NULL) {
-      s->client_info.keep_alive = is_header_keep_alive(s->client_info.http_version, s->client_info.http_version, pc);
-    } else {
-      MIMEField *c = incoming_request->field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
-
-      s->client_info.keep_alive = is_header_keep_alive(s->client_info.http_version, s->client_info.http_version, c);
-    }
+    s->client_info.keep_alive = incoming_request->keep_alive_get();
   }
 
   if (s->client_info.keep_alive == HTTP_KEEPALIVE && s->client_info.http_version == HTTPVersion(1, 1)) {
@@ -5582,23 +5534,7 @@ HttpTransact::initialize_state_variables_from_response(State* s, HTTPHdr* incomi
    *   if we sent "Connection: close"  We need check the response
    *   header regardless of what we sent to the server
    */
-  MIMEField *c_hdr;
-  if ((s->current.request_to != ORIGIN_SERVER) &&
-      (s->current.request_to == PARENT_PROXY ||
-       s->current.request_to == ICP_SUGGESTED_HOST)) {
-    c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION);
-
-    // If there is a Proxy-Connection header use that,
-    //   otherwise use the Connection header
-    if (c_hdr == NULL) {
-      c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
-    }
-  } else {
-    c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
-  }
-
-  s->current.server->keep_alive = is_header_keep_alive(s->hdr_info.server_response.version_get(),
-                                                       s->hdr_info.server_request.version_get(), c_hdr);
+  s->current.server->keep_alive = s->hdr_info.server_response.keep_alive_get();
 
   // Don't allow an upgrade request to Keep Alive
   if (s->is_upgrade_request) {