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
27 changes: 16 additions & 11 deletions plugins/experimental/uri_signing/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
URI Signing Plugin
==================

This remap plugin implements the draft URI Signing protocol documented here:
https://tools.ietf.org/html/draft-ietf-cdni-uri-signing-16 .
This remap plugin implements the draft URI Signing protocol documented [here](https://tools.ietf.org/html/draft-ietf-cdni-uri-signing-16):

It takes a single argument: the name of a config file that contains key information.

Expand Down Expand Up @@ -77,16 +76,25 @@ It's worth noting that multiple issuers can provide `auth_directives`.
Each issuer will be processed in order and any issuer can provide access to
a path.

### Token Stripping
### More Configuration Options

When The boolean strip_token parameter is set to true, the plugin removes the
**Strip Token**
When the strip_token parameter is set to true, the plugin removes the
token from both the url that is sent upstream to the origin and the url that
is used as the cache key. It can be set like this:
is used as the cache key. The strip_token parameter defaults to false and should
be set by only one issuer.
**ID**
The id field takes a string indicating the identification of the entity processing the request.
This is used in aud claim checks to ensure that the receiver is the intended audience of a
tokenized request. The id parameter can only be set by one issuer.

Example:

{
"Kabletown URI Authority": {
"renewal_kid": "Second Key",
"strip_token" : true,
"id" : "mycdn",
"auth_directives": [
]
Expand All @@ -95,8 +103,6 @@ is used as the cache key. It can be set like this:
]
}

The strip_token parameter defaults to false and should be set by only one issuer.

Usage
-----

Expand All @@ -107,17 +113,18 @@ will receive a 403 Forbidden response, instead of receiving content.
Tokens will be found in either of these places:

- A query parameter named `URISigningPackage`. The value must be the JWT.
- A path parameter named `URISigningPackage`. The value must be the JWT.
- A cookie named `URISigningPackage`. The value of the cookie must be the JWT.

Path parameters will not be searched for JWTs.

### Supported Claims

The following claims are understood:

- `iss`: Must be present. The issuer is used to locate the key for verification.
- `sub`: May be present, but is not validated.
- `exp`: Expired tokens are not valid.
- `nbf`: Tokens processed before this time are not valid.
- `aud`: Token aud claim strings must match the configured id to be considered valid.
- `iat`: May be present, but is not validated.
- `cdniv`: Must be missing or 1.
- `cdniuc`: Validated last, after key verificationD. **Only `regex` is supported!**
Expand All @@ -129,8 +136,6 @@ The following claims are understood:

These claims are not supported. If they are present, the token will not validate:

- `aud`
- `nbf`
- `jti`
- `cdnicrit`
- `cdniip`
Expand Down
4 changes: 4 additions & 0 deletions plugins/experimental/uri_signing/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* limitations under the License.
*/

#pragma once

#define PLUGIN_NAME "uri_signing"

#ifdef URI_SIGNING_UNIT_TEST
Expand All @@ -24,6 +26,8 @@

#define PluginDebug(fmt, ...) PrintToStdErr("(%s) %s:%d:%s() " fmt "\n", PLUGIN_NAME, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define PluginError(fmt, ...) PrintToStdErr("(%s) %s:%d:%s() " fmt "\n", PLUGIN_NAME, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define TSmalloc(x) malloc(x)
#define TSfree(p) free(p)
void PrintToStdErr(const char *fmt, ...);

#else
Expand Down
16 changes: 14 additions & 2 deletions plugins/experimental/uri_signing/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
#include "timing.h"
#include "jwt.h"

#include <ts/ts.h>

#include <cjose/cjose.h>
#include <jansson.h>

Expand All @@ -46,6 +44,7 @@ struct config {
struct signer signer;
struct auth_directive *auth_directives;
char *id;
bool strip_token;
};

cjose_jwk_t **
Expand Down Expand Up @@ -87,6 +86,12 @@ config_get_id(struct config *cfg)
return cfg->id;
}

bool
config_strip_token(struct config *cfg)
{
return cfg->strip_token;
}

struct config *
config_new(size_t n)
{
Expand Down Expand Up @@ -114,6 +119,8 @@ config_new(size_t n)
cfg->auth_directives = NULL;
cfg->id = NULL;

cfg->strip_token = false;

PluginDebug("New config object created at %p", cfg);
return cfg;
}
Expand Down Expand Up @@ -284,6 +291,11 @@ read_config(const char *path)
}
json_decref(id_json);

json_t *strip_json = json_object_get(jwks, "strip_token");
if (strip_json) {
cfg->strip_token = json_boolean_value(strip_json);
}

size_t jwks_ct = json_array_size(key_ary);
cjose_jwk_t **jwks = (*jwkis++ = malloc((jwks_ct + 1) * sizeof *jwks));
PluginDebug("Created table with size %d", cfg->issuers->size);
Expand Down
1 change: 1 addition & 0 deletions plugins/experimental/uri_signing/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ struct _cjose_jwk_int **find_keys(struct config *cfg, const char *issuer);
struct _cjose_jwk_int *find_key_by_kid(struct config *cfg, const char *issuer, const char *kid);
bool uri_matches_auth_directive(struct config *cfg, const char *uri, size_t uri_ct);
const char *config_get_id(struct config *cfg);
bool config_strip_token(struct config *cfg);
1 change: 0 additions & 1 deletion plugins/experimental/uri_signing/cookie.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

#include "cookie.h"
#include "common.h"
#include <ts/ts.h>
#include <string.h>

const char *
Expand Down
21 changes: 14 additions & 7 deletions plugins/experimental/uri_signing/jwt.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "jwt.h"
#include "match.h"
#include "normalize.h"
#include "ts/ts.h"
#include <jansson.h>
#include <cjose/cjose.h>
#include <math.h>
Expand Down Expand Up @@ -206,41 +205,49 @@ jwt_check_uri(const char *cdniuc, const char *uri)
int uri_ct = strlen(uri);
int buff_ct = uri_ct + 2;
int err;
char normal_uri[buff_ct];

char *normal_uri = (char *)TSmalloc(buff_ct);
memset(normal_uri, 0, buff_ct);

err = normalize_uri(uri, uri_ct, normal_uri, buff_ct);

if (err) {
return false;
goto fail_jwt;
}

const char *kind = cdniuc, *container = cdniuc;
while (*container && *container != ':') {
++container;
}
if (!*container) {
return false;
goto fail_jwt;
}
++container;

size_t len = container - kind;
bool status;
PluginDebug("Comparing with match kind \"%.*s\" on \"%s\" to normalized URI \"%s\"", (int)len - 1, kind, container, normal_uri);
switch (len) {
case sizeof CONT_URI_HASH_STR:
if (!strncmp(CONT_URI_HASH_STR, kind, len - 1)) {
return match_hash(container, normal_uri);
status = match_hash(container, normal_uri);
TSfree(normal_uri);
return status;
}
PluginDebug("Expected kind %s, but did not find it in \"%.*s\"", CONT_URI_HASH_STR, (int)len - 1, kind);
break;
case sizeof CONT_URI_REGEX_STR:
if (!strncmp(CONT_URI_REGEX_STR, kind, len - 1)) {
return match_regex(container, normal_uri);
status = match_regex(container, normal_uri);
TSfree(normal_uri);
return status;
}
PluginDebug("Expected kind %s, but did not find it in \"%.*s\"", CONT_URI_REGEX_STR, (int)len - 1, kind);
break;
}
PluginDebug("Unknown match kind \"%.*s\"", (int)len - 1, kind);

fail_jwt:
TSfree(normal_uri);
return false;
}

Expand Down
1 change: 0 additions & 1 deletion plugins/experimental/uri_signing/match.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

#include <regex.h>
#include "common.h"
#include "ts/ts.h"
#include <stdbool.h>
#include <string.h>

Expand Down
1 change: 0 additions & 1 deletion plugins/experimental/uri_signing/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include <cjose/cjose.h>
#include <jansson.h>
#include <string.h>
#include <ts/ts.h>
#include <inttypes.h>

cjose_jws_t *
Expand Down
12 changes: 9 additions & 3 deletions plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,22 @@ normalize_uri_helper(const char *uri, const char *expected_normal)
size_t uri_ct = strlen(uri);
int buff_size = uri_ct + 2;
int err;
char uri_normal[buff_size];
char *uri_normal = (char *)malloc(buff_size);
memset(uri_normal, 0, buff_size);

err = normalize_uri(uri, uri_ct, uri_normal, buff_size);

if (err) {
free(uri_normal);
return false;
}

if (expected_normal && strcmp(expected_normal, uri_normal) == 0) {
free(uri_normal);
return true;
}

free(uri_normal);
return false;
}

Expand Down Expand Up @@ -101,8 +104,10 @@ jws_parsing_helper(const char *uri, const char *paramName, const char *expected_
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);

char *uri_strip = (char *)malloc(uri_ct + 1);
memset(uri_strip, 0, uri_ct + 1);

cjose_jws_t *jws = get_jws_from_uri(uri, uri_ct, paramName, uri_strip, uri_ct, &strip_ct);
if (jws) {
resp = true;
Expand All @@ -114,6 +119,7 @@ jws_parsing_helper(const char *uri, const char *paramName, const char *expected_
resp = false;
}
cjose_jws_release(jws);
free(uri_strip);
return resp;
}

Expand Down
Loading