From a521b71ad0f256bf499afa915bc258f6793fed1c Mon Sep 17 00:00:00 2001 From: "John J. Rushford" Date: Thu, 14 Jan 2016 19:22:35 +0000 Subject: [PATCH] TS-4133: Update the url_sig plugin so that application query parameters are left intact on the request. --- plugins/experimental/url_sig/README | 9 ++++ plugins/experimental/url_sig/sign.pl | 28 +++++++++-- plugins/experimental/url_sig/url_sig.c | 67 ++++++++++++++++++++++++-- plugins/experimental/url_sig/url_sig.h | 1 + 4 files changed, 98 insertions(+), 7 deletions(-) diff --git a/plugins/experimental/url_sig/README b/plugins/experimental/url_sig/README index aa9a650e130..b5d87924a96 100644 --- a/plugins/experimental/url_sig/README +++ b/plugins/experimental/url_sig/README @@ -41,6 +41,15 @@ Edge cache debugging to traffic.out. Failed transactions (signature check fails that is) will be logged in to error.log. +Application Query Parameters. + If a request to be signed has application query parameters, the signing + parameters must be concatenated to the end of the requests application + query parameters. The application query parameters will be included in + the signing calculation as determined by the 'Parts' signing explained + below. At the edge after verification of the signing by this plugin, + the signing parameters are removed and the application query parameters + are preserved in the request. + Signing a URL At the signing portal take the full URL, without any query string, and add on a query string with the following parameters: diff --git a/plugins/experimental/url_sig/sign.pl b/plugins/experimental/url_sig/sign.pl index d3fbdeb13d1..7f2cc7bb9c7 100755 --- a/plugins/experimental/url_sig/sign.pl +++ b/plugins/experimental/url_sig/sign.pl @@ -65,12 +65,24 @@ } $j++; } +my $urlHasParams = index($string,"?"); + chop($string); if ( defined($client) ) { - $string .= "?C=" . $client . "&E=" . ( time() + $duration ) . "&A=" . $algorithm . "&K=" . $keyindex . "&P=" . $useparts . "&S="; + if ($urlHasParams > 0) { + $string .= "&C=" . $client . "&E=" . ( time() + $duration ) . "&A=" . $algorithm . "&K=" . $keyindex . "&P=" . $useparts . "&S="; + } + else { + $string .= "?C=" . $client . "&E=" . ( time() + $duration ) . "&A=" . $algorithm . "&K=" . $keyindex . "&P=" . $useparts . "&S="; + } } else { - $string .= "?E=" . ( time() + $duration ) . "&A=" . $algorithm . "&K=" . $keyindex . "&P=" . $useparts . "&S="; + if ($urlHasParams > 0) { + $string .= "&E=" . ( time() + $duration ) . "&A=" . $algorithm . "&K=" . $keyindex . "&P=" . $useparts . "&S="; + } + else { + $string .= "?E=" . ( time() + $duration ) . "&A=" . $algorithm . "&K=" . $keyindex . "&P=" . $useparts . "&S="; + } } $verbose && print "signed string = " . $string . "\n"; @@ -82,9 +94,17 @@ else { $digest = hmac_md5_hex( $string, $key ); } -my $qstring = ( split( /\?/, $string ) )[1]; +if ($urlHasParams == -1) { + my $qstring = ( split( /\?/, $string ) )[1]; -print "curl -s -o /dev/null -v --max-redirs 0 'http://" . $url . "?" . $qstring . $digest . "'\n"; + print "curl -s -o /dev/null -v --max-redirs 0 'http://" . $url . "?" . $qstring . $digest . "'\n"; +} +else { + my $url_noparams = ( split( /\?/, $url ) )[0]; + my $qstring = ( split( /\?/, $string ) )[1]; + + print "curl -s -o /dev/null -v --max-redirs 0 'http://" . $url_noparams . "?" . $qstring . $digest . "'\n"; +} sub help { print "sign.pl - Example signing utility in perl for signed URLs\n"; diff --git a/plugins/experimental/url_sig/url_sig.c b/plugins/experimental/url_sig/url_sig.c index 96a55216c0e..70a3f0009ef 100644 --- a/plugins/experimental/url_sig/url_sig.c +++ b/plugins/experimental/url_sig/url_sig.c @@ -245,6 +245,60 @@ err_log(char *url, char *msg) } } +// See the README. All Signing parameters must be concatenated to the end +// of the url and any application query parameters. +static char * +getAppQueryString(char *query_string, int query_length) +{ + int done = 0; + char *p; + char buf[MAX_QUERY_LEN]; + + if (query_length > MAX_QUERY_LEN) { + TSDebug(PLUGIN_NAME, "Cannot process the query string as the length exceeds %d bytes.", MAX_QUERY_LEN); + return NULL; + } + memset(buf, 0, MAX_QUERY_LEN); + strncpy(buf, query_string, query_length); + p = buf; + + TSDebug(PLUGIN_NAME, "query_string: %s, query_length: %d", query_string, query_length); + if (p == NULL) { + return NULL; + } + + do { + switch (*p) { + case 'A': + case 'C': + case 'E': + case 'K': + case 'P': + case 'S': + done = 1; + if (*(p - 1) == '&') { + *(p - 1) = '\0'; + } else + (*p = '\0'); + break; + default: + p = strchr(p, '&'); + if (p == NULL) + done = 1; + else + p++; + break; + } + } while (!done); + + if (strlen(buf) > 0) { + p = TSstrdup(buf); + return p; + } else { + return NULL; + } +} + TSRemapStatus TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri) { @@ -275,7 +329,7 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri) char *parts = NULL; char *part = NULL; char *p = NULL, *pp = NULL; - char *query = NULL; + char *query = NULL, *app_qry = NULL; int retval, sockfd; socklen_t peer_len; @@ -510,11 +564,18 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri) /* ********* Allow ********* */ allow: + app_qry = getAppQueryString(query, strlen(query)); + TSfree(url); /* drop the query string so we can cache-hit */ - rval = TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, NULL, 0); + if (app_qry != NULL) { + rval = TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, app_qry, strlen(app_qry)); + TSfree(app_qry); + } else { + rval = TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, NULL, 0); + } if (rval != TS_SUCCESS) { - TSError("[url_sig] Error stripping query string: %d.", rval); + TSError("[url_sig] Error setting the query string: %d.", rval); } return TSREMAP_NO_REMAP; } diff --git a/plugins/experimental/url_sig/url_sig.h b/plugins/experimental/url_sig/url_sig.h index 6e22600bf5a..46e8e72a78a 100644 --- a/plugins/experimental/url_sig/url_sig.h +++ b/plugins/experimental/url_sig/url_sig.h @@ -45,6 +45,7 @@ #define MAX_REQ_LEN 8192 #define MAX_KEY_LEN 256 #define MAX_KEY_NUM 16 +#define MAX_QUERY_LEN 4096 #define USIG_HMAC_SHA1 1 #define USIG_HMAC_MD5 2