You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jr...@apache.org on 2019/01/30 15:57:09 UTC

[trafficserver] branch master updated: JWT Parser strips token from URI and places in buffer

This is an automated email from the ASF dual-hosted git repository.

jrushford pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 5f9d358  JWT Parser strips token from URI and places in buffer
5f9d358 is described below

commit 5f9d358b721fbe9b7660e23610d19632f7655503
Author: Dylan Souza <dy...@comcast.com>
AuthorDate: Tue Jan 15 18:50:55 2019 +0000

    JWT Parser strips token from URI and places in buffer
---
 plugins/experimental/uri_signing/parse.c           |  28 +++-
 plugins/experimental/uri_signing/parse.h           |   3 +-
 .../uri_signing/unit_tests/uri_signing_test.cc     | 174 +++++++++++++++++++++
 plugins/experimental/uri_signing/uri_signing.c     |   8 +-
 4 files changed, 208 insertions(+), 5 deletions(-)

diff --git a/plugins/experimental/uri_signing/parse.c b/plugins/experimental/uri_signing/parse.c
index 99ded7b..099acdb 100644
--- a/plugins/experimental/uri_signing/parse.c
+++ b/plugins/experimental/uri_signing/parse.c
@@ -29,10 +29,11 @@
 #include <inttypes.h>
 
 cjose_jws_t *
-get_jws_from_uri(const char *uri, size_t uri_ct, const char *paramName)
+get_jws_from_uri(const char *uri, size_t uri_ct, const char *paramName, char *strip_uri, size_t buff_ct, size_t *strip_ct)
 {
   /* Reserved characters as defined by the URI Generic Syntax RFC: https://tools.ietf.org/html/rfc3986#section-2.2 */
-  const char *reserved_string = ":/?#[]@!$&\'()*+,;=";
+  static const char *reserved_string  = ":/?#[]@!$&\'()*+,;=";
+  static const char *sub_delim_string = "!$&\'()*+,;=";
 
   /* If param name ends in reserved character this will be treated as the termination symbol when parsing for package. Default is
    * '='. */
@@ -94,6 +95,29 @@ get_jws_from_uri(const char *uri, size_t uri_ct, const char *paramName)
         PluginDebug("Unable to read JWS: %.*s, %s", (int)(key_end - key), key, err.message ? err.message : "");
       } else {
         PluginDebug("Parsed JWS: %.*s (%16p)", (int)(key_end - key), key, jws);
+
+        /* Strip token */
+        /* Check that passed buffer is large enough */
+        *strip_ct = ((key - uri) + (end - value_end));
+        if (buff_ct <= *strip_ct) {
+          PluginDebug("Strip URI buffer is not large enough");
+          return NULL;
+        }
+
+        if (value_end != end && strchr(sub_delim_string, *value_end)) {
+          /*Strip from first char of package name to sub-delimeter that terminates the signed JWT */
+          memcpy(strip_uri, uri, (key - uri));
+          memcpy(strip_uri + (key - uri), value_end + 1, (end - value_end + 1));
+        } else {
+          /*Strip from reserved char to the last char of the JWT */
+          memcpy(strip_uri, uri, (key - uri - 1));
+          memcpy(strip_uri + (key - uri - 1), value_end, (end - value_end));
+        }
+
+        if (strip_uri[*strip_ct - 1] != '\0') {
+          strip_uri[*strip_ct - 1] = '\0';
+        }
+        PluginDebug("Stripped URI: %s", strip_uri);
       }
       return jws;
     }
diff --git a/plugins/experimental/uri_signing/parse.h b/plugins/experimental/uri_signing/parse.h
index 8d82c63..d05bfd5 100644
--- a/plugins/experimental/uri_signing/parse.h
+++ b/plugins/experimental/uri_signing/parse.h
@@ -19,7 +19,8 @@
 #include <stdlib.h>
 
 struct _cjose_jws_int;
-struct _cjose_jws_int *get_jws_from_uri(const char *uri, size_t uri_ct, const char *paramName);
+struct _cjose_jws_int *get_jws_from_uri(const char *uri, size_t uri_ct, const char *paramName, char *strip_uri, size_t buff_ct,
+                                        size_t *strip_ct);
 struct _cjose_jws_int *get_jws_from_cookie(const char **cookie, size_t *cookie_ct, const char *paramName);
 
 struct config;
diff --git a/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc b/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
index 30b8681..b879f7c 100644
--- a/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
+++ b/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
@@ -28,6 +28,7 @@ extern "C" {
 #include <cjose/cjose.h>
 #include "../jwt.h"
 #include "../normalize.h"
+#include "../parse.h"
 }
 
 bool
@@ -92,6 +93,28 @@ remove_dot_helper(const char *path, const char *expected_path)
   }
 }
 
+bool
+jws_parsing_helper(const char *uri, const char *paramName, const char *expected_strip)
+{
+  bool resp;
+  size_t uri_ct   = strlen(uri);
+  size_t strip_ct = 0;
+  char uri_strip[uri_ct + 1];
+  memset(uri_strip, 0, sizeof uri_strip);
+  cjose_jws_t *jws = get_jws_from_uri(uri, uri_ct, paramName, uri_strip, uri_ct, &strip_ct);
+  if (jws) {
+    resp = true;
+    if (strcmp(uri_strip, expected_strip) != 0) {
+      cjose_jws_release(jws);
+      resp = false;
+    }
+  } else {
+    resp = false;
+  }
+  cjose_jws_release(jws);
+  return resp;
+}
+
 TEST_CASE("1", "[JWSParsingTest]")
 {
   INFO("TEST 1, Test JWT Parsing From Token Strings");
@@ -136,6 +159,157 @@ TEST_CASE("1", "[JWSParsingTest]")
   fprintf(stderr, "\n");
 }
 
+TEST_CASE("2", "[JWSFromURLTest]")
+{
+  INFO("TEST 2, Test JWT Parsing and Stripping From URLs");
+
+  SECTION("Token at end of URI")
+  {
+    REQUIRE(jws_parsing_helper(
+      "www.foo.com/hellothere/"
+      "URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+      "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
+      "URISigningPackage", "www.foo.com/hellothere"));
+  }
+
+  SECTION("No Token in URL")
+  {
+    REQUIRE(!jws_parsing_helper(
+      "www.foo.com/hellothere/"
+      "URISigningPackag=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+      "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
+      "URISigningPackage", NULL));
+  }
+
+  SECTION("Token in middle of the URL")
+  {
+    REQUIRE(jws_parsing_helper("www.foo.com/hellothere/"
+                               "URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/Something/Else",
+                               "URISigningPackage", "www.foo.com/hellothere/Something/Else"));
+  }
+
+  SECTION("Token at the start of the URL")
+  {
+    REQUIRE(jws_parsing_helper(":URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/www.foo.com/hellothere/Something/Else",
+                               "URISigningPackage", "/www.foo.com/hellothere/Something/Else"));
+  }
+
+  SECTION("Pass empty path parameter at end")
+  {
+    REQUIRE(!jws_parsing_helper("www.foobar.com/hellothere/URISigningPackage=", "URISigningPackage", NULL));
+  }
+
+  SECTION("Pass empty path parameter in the middle of URL")
+  {
+    REQUIRE(!jws_parsing_helper("www.foobar.com/hellothere/URISigningPackage=/Something/Else", "URISigningPackage", NULL));
+  }
+
+  SECTION("Partial package name in previous path parameter")
+  {
+    REQUIRE(jws_parsing_helper("www.foobar.com/URISig/"
+                               "URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/Something/Else",
+                               "URISigningPackage", "www.foobar.com/URISig/Something/Else"));
+  }
+
+  SECTION("Package comes directly after two reserved characters")
+  {
+    REQUIRE(jws_parsing_helper("www.foobar.com/"
+                               ":URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/Something/Else",
+                               "URISigningPackage", "www.foobar.com//Something/Else"));
+  }
+
+  SECTION("Package comes directly after string of reserved characters")
+  {
+    REQUIRE(jws_parsing_helper("www.foobar.com/?!/"
+                               ":URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/Something/Else",
+                               "URISigningPackage", "www.foobar.com/?!//Something/Else"));
+  }
+
+  SECTION("Invalid token passed before a valid token")
+  {
+    REQUIRE(!jws_parsing_helper("www.foobar.com/URISigningPackage=/"
+                                "URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                                "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                                "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/Something/Else",
+                                "URISigningPackage", NULL));
+  }
+
+  SECTION("Empty string as URL") { REQUIRE(!jws_parsing_helper("", "URISigningPackage", NULL)); }
+
+  SECTION("Empty package name to parser")
+  {
+    REQUIRE(!jws_parsing_helper(
+      "www.foobar.com/"
+      "URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+      "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
+      "", NULL));
+  }
+
+  SECTION("Custom package name with a reserved character - at the end of the URI")
+  {
+    REQUIRE(jws_parsing_helper(
+      "www.foobar.com/CustomPackage/"
+      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+      "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
+      "CustomPackage/", "www.foobar.com"));
+  }
+
+  SECTION("Custom package name with a reserved character - in the middle of the URI")
+  {
+    REQUIRE(jws_parsing_helper(
+      "www.foobar.com/CustomPackage/"
+      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+      "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/Something/Else",
+      "CustomPackage/", "www.foobar.com/Something/Else"));
+  }
+
+  SECTION("URI signing package passed as the only a query parameter")
+  {
+    REQUIRE(jws_parsing_helper(
+      "www.foobar.com/Something/"
+      "Here?URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+      "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
+      "URISigningPackage", "www.foobar.com/Something/Here"));
+  }
+
+  SECTION("URI signing package passed as first of many query parameters")
+  {
+    REQUIRE(jws_parsing_helper("www.foobar.com/Something/"
+                               "Here?URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&query3=foobar&query1=foo&query2=bar",
+                               "URISigningPackage", "www.foobar.com/Something/Here?query3=foobar&query1=foo&query2=bar"));
+  }
+
+  SECTION("URI signing package passed as one of many query parameters - passed in middle")
+  {
+    REQUIRE(jws_parsing_helper("www.foobar.com/Something/"
+                               "Here?query1=foo&query2=bar&URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&query3=foobar",
+                               "URISigningPackage", "www.foobar.com/Something/Here?query1=foo&query2=bar&query3=foobar"));
+  }
+
+  SECTION("URI signing package passed as last of many query parameters")
+  {
+    REQUIRE(jws_parsing_helper("www.foobar.com/Something/"
+                               "Here?query1=foo&query2=bar&URISigningPackage=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+                               "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+                               "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
+                               "URISigningPackage", "www.foobar.com/Something/Here?query1=foo&query2=bar"));
+  }
+}
+
 TEST_CASE("3", "[RemoveDotSegmentsTest]")
 {
   INFO("TEST 3, Test Removal of Dot Segments From Paths");
diff --git a/plugins/experimental/uri_signing/uri_signing.c b/plugins/experimental/uri_signing/uri_signing.c
index 044731b..fadd269 100644
--- a/plugins/experimental/uri_signing/uri_signing.c
+++ b/plugins/experimental/uri_signing/uri_signing.c
@@ -175,7 +175,11 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
   if (cpi < max_cpi) {
     checkpoints[cpi++] = mark_timer(&t);
   }
-  cjose_jws_t *jws = get_jws_from_uri(url, url_ct, package);
+
+  char strip_uri[2000] = {0};
+  size_t strip_ct;
+  cjose_jws_t *jws = get_jws_from_uri(url, url_ct, package, strip_uri, 2000, &strip_ct);
+
   if (cpi < max_cpi) {
     checkpoints[cpi++] = mark_timer(&t);
   }
@@ -222,7 +226,7 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
   if (cpi < max_cpi) {
     checkpoints[cpi++] = mark_timer(&t);
   }
-  struct jwt *jwt = validate_jws(jws, (struct config *)ih, url, url_ct);
+  struct jwt *jwt = validate_jws(jws, (struct config *)ih, strip_uri, strip_ct);
   cjose_jws_release(jws);
   if (cpi < max_cpi) {
     checkpoints[cpi++] = mark_timer(&t);