Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions plugins/experimental/uri_signing/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
* '='. */
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion plugins/experimental/uri_signing/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
174 changes: 174 additions & 0 deletions plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extern "C" {
#include <cjose/cjose.h>
#include "../jwt.h"
#include "../normalize.h"
#include "../parse.h"
}

bool
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down
8 changes: 6 additions & 2 deletions plugins/experimental/uri_signing/uri_signing.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down