You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2014/04/20 21:21:07 UTC
[50/50] [abbrv] git commit: TS-2732 Run the code through indent,
to follow our coding standards
TS-2732 Run the code through indent, to follow our coding standards
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/4f2dc70f
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/4f2dc70f
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/4f2dc70f
Branch: refs/heads/master
Commit: 4f2dc70f0e5b3a2969cb70bac77523d259a95610
Parents: 634ba75
Author: Leif Hedstrom <zw...@apache.org>
Authored: Sun Apr 20 13:19:30 2014 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Sun Apr 20 13:19:30 2014 -0600
----------------------------------------------------------------------
plugins/experimental/url_sig/url_sig.c | 836 ++++++++++++++--------------
plugins/experimental/url_sig/url_sig.h | 16 +-
2 files changed, 436 insertions(+), 416 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4f2dc70f/plugins/experimental/url_sig/url_sig.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/url_sig/url_sig.c b/plugins/experimental/url_sig/url_sig.c
index 0cde9d3..be85524 100644
--- a/plugins/experimental/url_sig/url_sig.c
+++ b/plugins/experimental/url_sig/url_sig.c
@@ -34,423 +34,443 @@
#include <ts/ts.h>
#include <ts/remap.h>
-static const char* PLUGIN_NAME = "url_sig";
-
-struct config {
- char *map_from;
- char *map_to;
- TSHttpStatus err_status;
- char *err_url;
- char keys[MAX_KEY_NUM][MAX_KEY_LEN];
+static const char *PLUGIN_NAME = "url_sig";
+
+struct config
+{
+ char *map_from;
+ char *map_to;
+ TSHttpStatus err_status;
+ char *err_url;
+ char keys[MAX_KEY_NUM][MAX_KEY_LEN];
};
-TSReturnCode TSRemapInit(TSRemapInterface* api_info, char *errbuf, int errbuf_size) {
- if (!api_info) {
- strncpy(errbuf, "[tsremap_init] - Invalid TSRemapInterface argument", (size_t) (errbuf_size - 1));
- return TS_ERROR;
- }
-
- if (api_info->tsremap_version < TSREMAP_VERSION) {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapInit] - Incorrect API version %ld.%ld", api_info->tsremap_version >> 16,
- (api_info->tsremap_version & 0xffff));
- return TS_ERROR;
- }
-
- TSDebug(PLUGIN_NAME, "plugin is succesfully initialized");
- return TS_SUCCESS;
+TSReturnCode
+TSRemapInit(TSRemapInterface * api_info, char *errbuf, int errbuf_size)
+{
+ if (!api_info) {
+ strncpy(errbuf, "[tsremap_init] - Invalid TSRemapInterface argument", (size_t) (errbuf_size - 1));
+ return TS_ERROR;
+ }
+
+ if (api_info->tsremap_version < TSREMAP_VERSION) {
+ snprintf(errbuf, errbuf_size - 1, "[TSRemapInit] - Incorrect API version %ld.%ld", api_info->tsremap_version >> 16,
+ (api_info->tsremap_version & 0xffff));
+ return TS_ERROR;
+ }
+
+ TSDebug(PLUGIN_NAME, "plugin is succesfully initialized");
+ return TS_SUCCESS;
}
// To force a config file reload touch remap.config and do a "traffic_line -x"
-TSReturnCode TSRemapNewInstance(int argc, char* argv[], void** ih, char* errbuf, int errbuf_size) {
- char config_file[PATH_MAX];
- struct config *cfg;
-
- cfg = TSmalloc(sizeof(struct config));
- *ih = (void *) cfg;
-
- int i = 0;
- for (i = 0; i < MAX_KEY_NUM; i++) {
- cfg->keys[i][0] = '\0';
- }
-
- if (argc != 3) {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapNewKeyInstance] - Argument count wrong (%d)... Need exactly two pparam= (config file name).",
- argc);
- return TS_ERROR;
- }
- TSDebug(PLUGIN_NAME, "Initializing remap function of %s -> %s with config from %s", argv[0], argv[1], argv[2]);
- cfg->map_from = TSstrndup( argv[0], strlen(argv[0]));
- cfg->map_to = TSstrndup( argv[0], strlen(argv[1]));
-
- const char* install_dir = TSInstallDirGet();
- snprintf(config_file, sizeof(config_file), "%s/%s/%s", install_dir, "etc/trafficserver", argv[2]);
- TSDebug(PLUGIN_NAME, "config file name: %s", config_file);
- FILE *file = fopen(config_file, "r");
- if (file == NULL ) {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Error opening file %s.", config_file);
- return TS_ERROR;
- }
-
- char line[260];
- int line_no = 0;
- int keynum;
- while (fgets(line, sizeof(line), file) != NULL ) {
- TSDebug(PLUGIN_NAME, "LINE: %s (%d)", line, (int) strlen(line));
- line_no++;
- if (line[0] == '#' || strlen(line) <= 1)
- continue;
- char *pos = strchr(line, '=');
- if (pos == NULL ) {
- TSError("Error parsing line %d of file %s (%s).", line_no, config_file, line);
- }
- *pos = '\0';
- char *value = pos + 1;
- while (isspace(*value)) // remove whitespace
- value++;
- pos = strchr(value, '\n'); // remove the new line, terminate the string
- if (pos != NULL ) {
- *pos = '\0';
- } else {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Maximum line (%d) exceeded on line %d.", MAX_KEY_LEN, line_no);
- return TS_ERROR;
- }
- if (strncmp(line, "key", 3) == 0) {
- if (value != NULL ) {
- if (strncmp((char *) (line + 3), "0", 1) == 0) {
- keynum = 0;
- } else {
- TSDebug(PLUGIN_NAME, ">>> %s <<<", line +3);
- keynum = atoi((char *) (line + 3));
- if (keynum == 0) {
- keynum = -1; // Not a Number
- }
- }
- TSDebug(PLUGIN_NAME, "key number %d == %s", keynum, value);
- if (keynum > MAX_KEY_NUM || keynum == -1) {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Key number (%d) > MAX_KEY_NUM (%d) or NaN.", keynum, MAX_KEY_NUM);
- return TS_ERROR;
- }
- strcpy(&cfg->keys[keynum][0], value);
- }
- } else if (strncmp(line, "error_url", 9) == 0) {
- if (atoi(value)) {
- cfg->err_status = atoi(value);
- }
- value += 3;
- while (isspace(*value))
- value++;
-// if (strncmp(value, "http://", strlen("http://")) != 0) {
-// snprintf(errbuf, errbuf_size - 1,
-// "[TSRemapNewInstance] - Invalid config, err_status == 302, but err_url does not start with \"http://\"");
-// return TS_ERROR;
-// }
- if (cfg->err_status == TS_HTTP_STATUS_MOVED_TEMPORARILY)
- cfg->err_url = TSstrndup(value, strlen(value));
- else cfg->err_url = NULL;
- } else {
- TSError("Error parsing line %d of file %s (%s).", line_no, config_file, line);
- }
- }
-
- switch (cfg->err_status) {
- case TS_HTTP_STATUS_MOVED_TEMPORARILY:
- if (cfg->err_url == NULL ) {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Invalid config, err_status == 302, but err_url == NULL");
- return TS_ERROR;
- }
- printf("[url_sig] mapping {%s -> %s} with status %d and err url %s\n", argv[0], argv[1], cfg->err_status, cfg->err_url);
- break;
- case TS_HTTP_STATUS_FORBIDDEN:
- if (cfg->err_url != NULL ) {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Invalid config, err_status == 403, but err_url != NULL");
- return TS_ERROR;
- }
- printf("[url_sig] mapping {%s -> %s} with status %d\n", argv[0], argv[1], cfg->err_status);
- break;
- default:
- snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Return code %d not supported.", cfg->err_status);
- return TS_ERROR;
-
- }
-
- i = 0;
- for (i = 0; i < MAX_KEY_NUM; i++) {
- if (cfg->keys[i] != NULL && strlen(cfg->keys[i]) > 0)
- printf("[url_sig] shared secret key[%d] = %s\n", i, cfg->keys[i]);
- }
- fclose(file);
- printf("%s version %s initialized.\n", PLUGIN_NAME, VERSION);
- return TS_SUCCESS;
+TSReturnCode
+TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_size)
+{
+ char config_file[PATH_MAX];
+ struct config *cfg;
+
+ cfg = TSmalloc(sizeof(struct config));
+ *ih = (void *) cfg;
+
+ int i = 0;
+ for (i = 0; i < MAX_KEY_NUM; i++) {
+ cfg->keys[i][0] = '\0';
+ }
+
+ if (argc != 3) {
+ snprintf(errbuf, errbuf_size - 1,
+ "[TSRemapNewKeyInstance] - Argument count wrong (%d)... Need exactly two pparam= (config file name).",
+ argc);
+ return TS_ERROR;
+ }
+ TSDebug(PLUGIN_NAME, "Initializing remap function of %s -> %s with config from %s", argv[0], argv[1], argv[2]);
+ cfg->map_from = TSstrndup(argv[0], strlen(argv[0]));
+ cfg->map_to = TSstrndup(argv[0], strlen(argv[1]));
+
+ const char *install_dir = TSInstallDirGet();
+ snprintf(config_file, sizeof(config_file), "%s/%s/%s", install_dir, "etc/trafficserver", argv[2]);
+ TSDebug(PLUGIN_NAME, "config file name: %s", config_file);
+ FILE *file = fopen(config_file, "r");
+ if (file == NULL) {
+ snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Error opening file %s.", config_file);
+ return TS_ERROR;
+ }
+
+ char line[260];
+ int line_no = 0;
+ int keynum;
+ while (fgets(line, sizeof(line), file) != NULL) {
+ TSDebug(PLUGIN_NAME, "LINE: %s (%d)", line, (int) strlen(line));
+ line_no++;
+ if (line[0] == '#' || strlen(line) <= 1)
+ continue;
+ char *pos = strchr(line, '=');
+ if (pos == NULL) {
+ TSError("Error parsing line %d of file %s (%s).", line_no, config_file, line);
+ }
+ *pos = '\0';
+ char *value = pos + 1;
+ while (isspace(*value)) // remove whitespace
+ value++;
+ pos = strchr(value, '\n'); // remove the new line, terminate the string
+ if (pos != NULL) {
+ *pos = '\0';
+ } else {
+ snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Maximum line (%d) exceeded on line %d.", MAX_KEY_LEN,
+ line_no);
+ return TS_ERROR;
+ }
+ if (strncmp(line, "key", 3) == 0) {
+ if (value != NULL) {
+ if (strncmp((char *) (line + 3), "0", 1) == 0) {
+ keynum = 0;
+ } else {
+ TSDebug(PLUGIN_NAME, ">>> %s <<<", line + 3);
+ keynum = atoi((char *) (line + 3));
+ if (keynum == 0) {
+ keynum = -1; // Not a Number
+ }
+ }
+ TSDebug(PLUGIN_NAME, "key number %d == %s", keynum, value);
+ if (keynum > MAX_KEY_NUM || keynum == -1) {
+ snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Key number (%d) > MAX_KEY_NUM (%d) or NaN.", keynum,
+ MAX_KEY_NUM);
+ return TS_ERROR;
+ }
+ strcpy(&cfg->keys[keynum][0], value);
+ }
+ } else if (strncmp(line, "error_url", 9) == 0) {
+ if (atoi(value)) {
+ cfg->err_status = atoi(value);
+ }
+ value += 3;
+ while (isspace(*value))
+ value++;
+// if (strncmp(value, "http://", strlen("http://")) != 0) {
+// snprintf(errbuf, errbuf_size - 1,
+// "[TSRemapNewInstance] - Invalid config, err_status == 302, but err_url does not start with \"http://\"");
+// return TS_ERROR;
+// }
+ if (cfg->err_status == TS_HTTP_STATUS_MOVED_TEMPORARILY)
+ cfg->err_url = TSstrndup(value, strlen(value));
+ else
+ cfg->err_url = NULL;
+ } else {
+ TSError("Error parsing line %d of file %s (%s).", line_no, config_file, line);
+ }
+ }
+
+ switch (cfg->err_status) {
+ case TS_HTTP_STATUS_MOVED_TEMPORARILY:
+ if (cfg->err_url == NULL) {
+ snprintf(errbuf, errbuf_size - 1,
+ "[TSRemapNewInstance] - Invalid config, err_status == 302, but err_url == NULL");
+ return TS_ERROR;
+ }
+ printf("[url_sig] mapping {%s -> %s} with status %d and err url %s\n", argv[0], argv[1], cfg->err_status,
+ cfg->err_url);
+ break;
+ case TS_HTTP_STATUS_FORBIDDEN:
+ if (cfg->err_url != NULL) {
+ snprintf(errbuf, errbuf_size - 1,
+ "[TSRemapNewInstance] - Invalid config, err_status == 403, but err_url != NULL");
+ return TS_ERROR;
+ }
+ printf("[url_sig] mapping {%s -> %s} with status %d\n", argv[0], argv[1], cfg->err_status);
+ break;
+ default:
+ snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Return code %d not supported.", cfg->err_status);
+ return TS_ERROR;
+
+ }
+
+ i = 0;
+ for (i = 0; i < MAX_KEY_NUM; i++) {
+ if (cfg->keys[i] != NULL && strlen(cfg->keys[i]) > 0)
+ printf("[url_sig] shared secret key[%d] = %s\n", i, cfg->keys[i]);
+ }
+ fclose(file);
+ printf("%s version %s initialized.\n", PLUGIN_NAME, VERSION);
+ return TS_SUCCESS;
}
-void TSRemapDeleteInstance(void* ih) {
- struct config *cfg;
- cfg = (struct config *) ih;
-
- TSError("Cleaning up...");
- TSfree(cfg->map_from);
- TSfree(cfg->map_to);
- TSfree(cfg->err_url);
- TSfree(cfg);
+void
+TSRemapDeleteInstance(void *ih)
+{
+ struct config *cfg;
+ cfg = (struct config *) ih;
+
+ TSError("Cleaning up...");
+ TSfree(cfg->map_from);
+ TSfree(cfg->map_to);
+ TSfree(cfg->err_url);
+ TSfree(cfg);
}
-void err_log(char *url, char *msg) {
- if (msg && url) {
- TSDebug(PLUGIN_NAME, "[URL=%s]: %s", url, msg);
- TSError("[URL=%s]: %s", url, msg); // This goes to error.log
- } else {
- TSError("Invalid err_log request");
- }
+void
+err_log(char *url, char *msg)
+{
+ if (msg && url) {
+ TSDebug(PLUGIN_NAME, "[URL=%s]: %s", url, msg);
+ TSError("[URL=%s]: %s", url, msg); // This goes to error.log
+ } else {
+ TSError("Invalid err_log request");
+ }
}
-TSRemapStatus TSRemapDoRemap(void* ih, TSHttpTxn txnp, TSRemapRequestInfo *rri) {
- struct config *cfg;
- cfg = (struct config *) ih;
-
- int url_len = 0;
- time_t expiration = 0;
- int algorithm = -1;
- int keyindex = -1;
- int cmp_res;
- int rval;
- int i = 0;
- int j = 0;
- unsigned int sig_len = 0;
-
- /* all strings are locally allocated except url... about 25k per instance*/
- char *url;
- char signed_part[8192] = { '\0' }; // this initializes the whole array and is needed
- char urltokstr[8192] = { '\0' };
- char client_ip[CIP_STRLEN] = { '\0' };
- char ipstr[CIP_STRLEN] = { '\0' };
- unsigned char sig[MAX_SIG_SIZE + 1];
- char sig_string[2 * MAX_SIG_SIZE + 1];
-
- /* these are just pointers into other allocations */
- char *signature = NULL;
- char *parts = NULL;
- char *part = NULL;
- char *p = NULL, *pp = NULL;
- char *query = NULL;
-
- int retval, sockfd;
- socklen_t peer_len;
- struct sockaddr_in peer;
-
- url = TSUrlStringGet(rri->requestBufp, rri->requestUrl, &url_len);
-
- if (url_len >= MAX_REQ_LEN - 1) {
- err_log(url, "URL string too long.");
- goto deny;
- }
-
- TSDebug(PLUGIN_NAME, "%s", url);
-
- query = strstr(url, "?");
- if (query == NULL ) {
- err_log(url, "Has no query string.");
- goto deny;
- }
-
- if (strncmp(url, "http://", strlen("http://")) != 0) {
- err_log(url, "Invalid URL scheme - only http supported.");
- goto deny;
- }
-
- /* first, parse the query string */
- query++; /* get rid of the ? */
- TSDebug(PLUGIN_NAME, "Query string is:%s", query);
-
- // Client IP - this one is optional
- p = strstr(query, CIP_QSTRING"=");
- if (p != NULL ) {
-
- p += strlen(CIP_QSTRING + 1);
- pp = strstr(p, "&");
- if ((pp - p) > CIP_STRLEN - 1 || (pp - p) < 4) {
- err_log(url, "IP address string too long or short.");
- goto deny;
- }
- strncpy(client_ip, p + strlen(CIP_QSTRING) + 1, (pp - p - (strlen(CIP_QSTRING) + 1)));
- client_ip[pp - p - (strlen(CIP_QSTRING) + 1)] = '\0';
- TSDebug(PLUGIN_NAME, "CIP: -%s-", client_ip);
- retval = TSHttpTxnClientFdGet(txnp, &sockfd);
- if (retval != TS_SUCCESS) {
- err_log(url, "Error getting sockfd.");
- goto deny;
- }
- peer_len = sizeof(peer);
- if (getpeername(sockfd, (struct sockaddr*) &peer, &peer_len) != 0) {
- perror("Can't get peer address:");
- }
- struct sockaddr_in *s = (struct sockaddr_in *) &peer;
- inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
- TSDebug(PLUGIN_NAME, "Peer address: -%s-", ipstr);
- if (strcmp(ipstr, client_ip) != 0) {
- err_log(url, "Client IP doesn't match signature.");
- goto deny;
- }
- }
- // Expiration
- p = strstr(query, EXP_QSTRING"=");
- if (p != NULL ) {
- p += strlen(EXP_QSTRING) + 1;
- expiration = atoi(p);
- if (expiration == 0 || expiration < time(NULL )) {
- err_log(url, "Invalid expiration, or expired.");
- goto deny;
- }
- TSDebug(PLUGIN_NAME, "Exp: %d", (int) expiration);
- } else {
- err_log(url, "Expiration query string not found.");
- goto deny;
- }
- // Algorithm
- p = strstr(query, ALG_QSTRING"=");
- if (p != NULL ) {
- p += strlen(ALG_QSTRING) + 1;
- algorithm = atoi(p);
- // The check for a valid algorithm is later.
- TSDebug(PLUGIN_NAME, "Algorithm: %d", algorithm);
- } else {
- err_log(url, "Algorithm query string not found.");
- goto deny;
- }
- // Key index
- p = strstr(query, KIN_QSTRING"=");
- if (p != NULL ) {
- p += strlen(KIN_QSTRING) + 1;
- keyindex = atoi(p);
- if (keyindex == -1) {
- err_log(url, "Invalid key index.");
- goto deny;
- }
- TSDebug(PLUGIN_NAME, "Key Index: %d", keyindex);
- } else {
- err_log(url, "KeyIndex query string not found.");
- goto deny;
- }
- // Parts
- p = strstr(query, PAR_QSTRING"=");
- if (p != NULL ) {
- p += strlen(PAR_QSTRING) + 1;
- parts = p; // NOTE parts is not NULL terminated it is terminated by "&" of next param
- p = strstr(parts, "&");
- TSDebug(PLUGIN_NAME, "Parts: %.*s", (int) (p - parts), parts);
- } else {
- err_log(url, "PartsSigned query string not found.");
- goto deny;
- }
- // And finally, the sig (has to be last)
- p = strstr(query, SIG_QSTRING"=");
- if (p != NULL ) {
- p += strlen(SIG_QSTRING) + 1;
- signature = p; // NOTE sig is not NULL terminated, it has to be 20 chars
- if ((algorithm == USIG_HMAC_SHA1 && strlen(signature) < SHA1_SIG_SIZE) || (algorithm == USIG_HMAC_MD5 && strlen(signature) < MD5_SIG_SIZE)) {
- err_log(url, "Signature query string too short (< 20).");
- goto deny;
- }
- } else {
- err_log(url, "Signature query string not found.");
- goto deny;
- }
-
- /* have the query string, and parameters passed initial checks */
- TSDebug(PLUGIN_NAME, "Found all needed parameters: C=%s E=%d A=%d K=%d P=%s S=%s", client_ip, (int) expiration, algorithm, keyindex, parts,
- signature);
-
- /* find the string that was signed - cycle through the parts letters, adding the part of the fqdn/path if it is 1 */
- p = strstr(url, "?");
- memcpy(urltokstr, &url[strlen("http://")], p - url - strlen("http://"));
- part = strtok_r(urltokstr, "/", &p);
- while (part != NULL ) {
- if (parts[j] == '1') {
- strcpy(signed_part + strlen(signed_part), part);
- strcpy(signed_part + strlen(signed_part), "/");
- }
- if (parts[j + 1] == '0' || parts[j + 1] == '1') // This remembers the last part, meaning, if there are no more valid letters in parts
- j++; // will keep repeating the value of the last one
- part = strtok_r(NULL, "/", &p);
- }
-
- signed_part[strlen(signed_part) - 1] = '?'; // chop off the last /, replace with '?'
- p = strstr(query, SIG_QSTRING"=");
- strncat(signed_part, query, (p - query) + strlen(SIG_QSTRING) + 1);
-
- TSDebug(PLUGIN_NAME, "Signed string=\"%s\"", signed_part);
-
- /* calculate the expected the signature with the right algorithm */
- switch (algorithm) {
- case USIG_HMAC_SHA1:
- HMAC(EVP_sha1(), (const unsigned char *) cfg->keys[keyindex], strlen(cfg->keys[keyindex]), (const unsigned char *) signed_part,
- strlen(signed_part), sig, &sig_len);
- if (sig_len != SHA1_SIG_SIZE) {
- TSDebug(PLUGIN_NAME, "sig_len: %d", sig_len);
- err_log(url, "Calculated sig len != SHA1_SIG_SIZE !");
- goto deny;
- }
-
- break;
- case USIG_HMAC_MD5:
- HMAC(EVP_md5(), (const unsigned char *) cfg->keys[keyindex], strlen(cfg->keys[keyindex]), (const unsigned char *) signed_part,
- strlen(signed_part), sig, &sig_len);
- if (sig_len != MD5_SIG_SIZE) {
- TSDebug(PLUGIN_NAME, "sig_len: %d", sig_len);
- err_log(url, "Calculated sig len != MD5_SIG_SIZE !");
- goto deny;
- }
- break;
- default:
- err_log(url, "Algorithm not supported.");
- goto deny;
- }
-
- for (i = 0; i < sig_len; i++) {
- sprintf(&(sig_string[i * 2]), "%02x", sig[i]);
- }
-
- TSDebug(PLUGIN_NAME, "Expected signature: %s", sig_string);
-
- /* and compare to signature that was sent */
- cmp_res = strncmp(sig_string, signature, sig_len * 2);
- if (cmp_res != 0) {
- err_log(url, "Signature check failed.");
- goto deny;
- } else {
- TSDebug(PLUGIN_NAME, "Signature check passed.");
- goto allow;
- }
-
- /* ********* Deny ********* */
- deny: if (url)
- TSfree(url);
- switch (cfg->err_status) {
- case TS_HTTP_STATUS_MOVED_TEMPORARILY:
- TSDebug(PLUGIN_NAME, "Redirecting to %s", cfg->err_url);
- char *start, *end;
- start = cfg->err_url;
- end = start + strlen(cfg->err_url);
- if (TSUrlParse(rri->requestBufp, rri->requestUrl, (const char **) &start, end) != TS_PARSE_DONE) {
- err_log("url", "Error inn TSUrlParse!");
- }
- rri->redirect = 1;
- break;
- case TS_HTTP_STATUS_FORBIDDEN:
- default:
- /* set status and body to be 403 */
- TSHttpTxnSetHttpRetStatus(txnp, TS_HTTP_STATUS_FORBIDDEN);
- TSHttpTxnErrorBodySet(txnp, TSstrdup("Authorization Denied"), strlen("Authorization Denied") - 1, TSstrdup("text/plain"));
- break;
- }
- return TSREMAP_DID_REMAP;
-
- /* ********* Allow ********* */
- allow: if (url)
- TSfree(url);
- /* drop the query string so we can cache-hit */
- rval = TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, NULL, 0);
- if (rval != TS_SUCCESS) {
- TSError("Error stripping query string: %d.", rval);
- }
- return TSREMAP_NO_REMAP;
+TSRemapStatus
+TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo * rri)
+{
+ struct config *cfg;
+ cfg = (struct config *) ih;
+
+ int url_len = 0;
+ time_t expiration = 0;
+ int algorithm = -1;
+ int keyindex = -1;
+ int cmp_res;
+ int rval;
+ int i = 0;
+ int j = 0;
+ unsigned int sig_len = 0;
+
+ /* all strings are locally allocated except url... about 25k per instance */
+ char *url;
+ char signed_part[8192] = { '\0' }; // this initializes the whole array and is needed
+ char urltokstr[8192] = { '\0' };
+ char client_ip[CIP_STRLEN] = { '\0' };
+ char ipstr[CIP_STRLEN] = { '\0' };
+ unsigned char sig[MAX_SIG_SIZE + 1];
+ char sig_string[2 * MAX_SIG_SIZE + 1];
+
+ /* these are just pointers into other allocations */
+ char *signature = NULL;
+ char *parts = NULL;
+ char *part = NULL;
+ char *p = NULL, *pp = NULL;
+ char *query = NULL;
+
+ int retval, sockfd;
+ socklen_t peer_len;
+ struct sockaddr_in peer;
+
+ url = TSUrlStringGet(rri->requestBufp, rri->requestUrl, &url_len);
+
+ if (url_len >= MAX_REQ_LEN - 1) {
+ err_log(url, "URL string too long.");
+ goto deny;
+ }
+
+ TSDebug(PLUGIN_NAME, "%s", url);
+
+ query = strstr(url, "?");
+ if (query == NULL) {
+ err_log(url, "Has no query string.");
+ goto deny;
+ }
+
+ if (strncmp(url, "http://", strlen("http://")) != 0) {
+ err_log(url, "Invalid URL scheme - only http supported.");
+ goto deny;
+ }
+
+ /* first, parse the query string */
+ query++; /* get rid of the ? */
+ TSDebug(PLUGIN_NAME, "Query string is:%s", query);
+
+ // Client IP - this one is optional
+ p = strstr(query, CIP_QSTRING "=");
+ if (p != NULL) {
+
+ p += strlen(CIP_QSTRING + 1);
+ pp = strstr(p, "&");
+ if ((pp - p) > CIP_STRLEN - 1 || (pp - p) < 4) {
+ err_log(url, "IP address string too long or short.");
+ goto deny;
+ }
+ strncpy(client_ip, p + strlen(CIP_QSTRING) + 1, (pp - p - (strlen(CIP_QSTRING) + 1)));
+ client_ip[pp - p - (strlen(CIP_QSTRING) + 1)] = '\0';
+ TSDebug(PLUGIN_NAME, "CIP: -%s-", client_ip);
+ retval = TSHttpTxnClientFdGet(txnp, &sockfd);
+ if (retval != TS_SUCCESS) {
+ err_log(url, "Error getting sockfd.");
+ goto deny;
+ }
+ peer_len = sizeof(peer);
+ if (getpeername(sockfd, (struct sockaddr *) &peer, &peer_len) != 0) {
+ perror("Can't get peer address:");
+ }
+ struct sockaddr_in *s = (struct sockaddr_in *) &peer;
+ inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
+ TSDebug(PLUGIN_NAME, "Peer address: -%s-", ipstr);
+ if (strcmp(ipstr, client_ip) != 0) {
+ err_log(url, "Client IP doesn't match signature.");
+ goto deny;
+ }
+ }
+ // Expiration
+ p = strstr(query, EXP_QSTRING "=");
+ if (p != NULL) {
+ p += strlen(EXP_QSTRING) + 1;
+ expiration = atoi(p);
+ if (expiration == 0 || expiration < time(NULL)) {
+ err_log(url, "Invalid expiration, or expired.");
+ goto deny;
+ }
+ TSDebug(PLUGIN_NAME, "Exp: %d", (int) expiration);
+ } else {
+ err_log(url, "Expiration query string not found.");
+ goto deny;
+ }
+ // Algorithm
+ p = strstr(query, ALG_QSTRING "=");
+ if (p != NULL) {
+ p += strlen(ALG_QSTRING) + 1;
+ algorithm = atoi(p);
+ // The check for a valid algorithm is later.
+ TSDebug(PLUGIN_NAME, "Algorithm: %d", algorithm);
+ } else {
+ err_log(url, "Algorithm query string not found.");
+ goto deny;
+ }
+ // Key index
+ p = strstr(query, KIN_QSTRING "=");
+ if (p != NULL) {
+ p += strlen(KIN_QSTRING) + 1;
+ keyindex = atoi(p);
+ if (keyindex == -1) {
+ err_log(url, "Invalid key index.");
+ goto deny;
+ }
+ TSDebug(PLUGIN_NAME, "Key Index: %d", keyindex);
+ } else {
+ err_log(url, "KeyIndex query string not found.");
+ goto deny;
+ }
+ // Parts
+ p = strstr(query, PAR_QSTRING "=");
+ if (p != NULL) {
+ p += strlen(PAR_QSTRING) + 1;
+ parts = p; // NOTE parts is not NULL terminated it is terminated by "&" of next param
+ p = strstr(parts, "&");
+ TSDebug(PLUGIN_NAME, "Parts: %.*s", (int) (p - parts), parts);
+ } else {
+ err_log(url, "PartsSigned query string not found.");
+ goto deny;
+ }
+ // And finally, the sig (has to be last)
+ p = strstr(query, SIG_QSTRING "=");
+ if (p != NULL) {
+ p += strlen(SIG_QSTRING) + 1;
+ signature = p; // NOTE sig is not NULL terminated, it has to be 20 chars
+ if ((algorithm == USIG_HMAC_SHA1 && strlen(signature) < SHA1_SIG_SIZE) ||
+ (algorithm == USIG_HMAC_MD5 && strlen(signature) < MD5_SIG_SIZE)) {
+ err_log(url, "Signature query string too short (< 20).");
+ goto deny;
+ }
+ } else {
+ err_log(url, "Signature query string not found.");
+ goto deny;
+ }
+
+ /* have the query string, and parameters passed initial checks */
+ TSDebug(PLUGIN_NAME, "Found all needed parameters: C=%s E=%d A=%d K=%d P=%s S=%s", client_ip, (int) expiration,
+ algorithm, keyindex, parts, signature);
+
+ /* find the string that was signed - cycle through the parts letters, adding the part of the fqdn/path if it is 1 */
+ p = strstr(url, "?");
+ memcpy(urltokstr, &url[strlen("http://")], p - url - strlen("http://"));
+ part = strtok_r(urltokstr, "/", &p);
+ while (part != NULL) {
+ if (parts[j] == '1') {
+ strcpy(signed_part + strlen(signed_part), part);
+ strcpy(signed_part + strlen(signed_part), "/");
+ }
+ if (parts[j + 1] == '0' || parts[j + 1] == '1') // This remembers the last part, meaning, if there are no more valid letters in parts
+ j++; // will keep repeating the value of the last one
+ part = strtok_r(NULL, "/", &p);
+ }
+
+ signed_part[strlen(signed_part) - 1] = '?'; // chop off the last /, replace with '?'
+ p = strstr(query, SIG_QSTRING "=");
+ strncat(signed_part, query, (p - query) + strlen(SIG_QSTRING) + 1);
+
+ TSDebug(PLUGIN_NAME, "Signed string=\"%s\"", signed_part);
+
+ /* calculate the expected the signature with the right algorithm */
+ switch (algorithm) {
+ case USIG_HMAC_SHA1:
+ HMAC(EVP_sha1(), (const unsigned char *) cfg->keys[keyindex], strlen(cfg->keys[keyindex]),
+ (const unsigned char *) signed_part, strlen(signed_part), sig, &sig_len);
+ if (sig_len != SHA1_SIG_SIZE) {
+ TSDebug(PLUGIN_NAME, "sig_len: %d", sig_len);
+ err_log(url, "Calculated sig len != SHA1_SIG_SIZE !");
+ goto deny;
+ }
+
+ break;
+ case USIG_HMAC_MD5:
+ HMAC(EVP_md5(), (const unsigned char *) cfg->keys[keyindex], strlen(cfg->keys[keyindex]),
+ (const unsigned char *) signed_part, strlen(signed_part), sig, &sig_len);
+ if (sig_len != MD5_SIG_SIZE) {
+ TSDebug(PLUGIN_NAME, "sig_len: %d", sig_len);
+ err_log(url, "Calculated sig len != MD5_SIG_SIZE !");
+ goto deny;
+ }
+ break;
+ default:
+ err_log(url, "Algorithm not supported.");
+ goto deny;
+ }
+
+ for (i = 0; i < sig_len; i++) {
+ sprintf(&(sig_string[i * 2]), "%02x", sig[i]);
+ }
+
+ TSDebug(PLUGIN_NAME, "Expected signature: %s", sig_string);
+
+ /* and compare to signature that was sent */
+ cmp_res = strncmp(sig_string, signature, sig_len * 2);
+ if (cmp_res != 0) {
+ err_log(url, "Signature check failed.");
+ goto deny;
+ } else {
+ TSDebug(PLUGIN_NAME, "Signature check passed.");
+ goto allow;
+ }
+
+ /* ********* Deny ********* */
+deny:if (url)
+ TSfree(url);
+ switch (cfg->err_status) {
+ case TS_HTTP_STATUS_MOVED_TEMPORARILY:
+ TSDebug(PLUGIN_NAME, "Redirecting to %s", cfg->err_url);
+ char *start, *end;
+ start = cfg->err_url;
+ end = start + strlen(cfg->err_url);
+ if (TSUrlParse(rri->requestBufp, rri->requestUrl, (const char **) &start, end) != TS_PARSE_DONE) {
+ err_log("url", "Error inn TSUrlParse!");
+ }
+ rri->redirect = 1;
+ break;
+ case TS_HTTP_STATUS_FORBIDDEN:
+ default:
+ /* set status and body to be 403 */
+ TSHttpTxnSetHttpRetStatus(txnp, TS_HTTP_STATUS_FORBIDDEN);
+ TSHttpTxnErrorBodySet(txnp, TSstrdup("Authorization Denied"), strlen("Authorization Denied") - 1,
+ TSstrdup("text/plain"));
+ break;
+ }
+ return TSREMAP_DID_REMAP;
+
+ /* ********* Allow ********* */
+allow:if (url)
+ TSfree(url);
+ /* drop the query string so we can cache-hit */
+ rval = TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, NULL, 0);
+ if (rval != TS_SUCCESS) {
+ TSError("Error stripping query string: %d.", rval);
+ }
+ return TSREMAP_NO_REMAP;
}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4f2dc70f/plugins/experimental/url_sig/url_sig.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/url_sig/url_sig.h b/plugins/experimental/url_sig/url_sig.h
index c495b4b..dd24cc7 100644
--- a/plugins/experimental/url_sig/url_sig.h
+++ b/plugins/experimental/url_sig/url_sig.h
@@ -21,21 +21,21 @@
#define VERSION "1.0"
/* in the query string that we add to sign the url: */
-#define CIP_QSTRING "C" /* C=24.0.33.12 designates the client IP address */
-#define EXP_QSTRING "E" /* E=1356128799 means expires at (seconds since Unix epoch) */
-#define ALG_QSTRING "A" /* A=1 means hashing algorithm 1 */
-#define KIN_QSTRING "K" /* K=3 means use key number 3 */
-#define PAR_QSTRING "P" /* P=1110 means use parts 0, 1 and 2 (and no more) for the hashing of the url after removing the 'http://' */
+#define CIP_QSTRING "C" /* C=24.0.33.12 designates the client IP address */
+#define EXP_QSTRING "E" /* E=1356128799 means expires at (seconds since Unix epoch) */
+#define ALG_QSTRING "A" /* A=1 means hashing algorithm 1 */
+#define KIN_QSTRING "K" /* K=3 means use key number 3 */
+#define PAR_QSTRING "P" /* P=1110 means use parts 0, 1 and 2 (and no more) for the hashing of the url after removing the 'http://' */
/* and making the parts by doing a split("/") */
-#define SIG_QSTRING "S" /* S=9e2828d570a4bee3c964f698b0985ee58b9f6b64 means 9e2828d570a4bee3c964f698b0985ee58b9f6b64 is the sig
- This one has to be the last one of the string */
+#define SIG_QSTRING "S" /* S=9e2828d570a4bee3c964f698b0985ee58b9f6b64 means 9e2828d570a4bee3c964f698b0985ee58b9f6b64 is the sig
+ This one has to be the last one of the string */
#define CIP_STRLEN 20
#define EXP_STRLEN 16
#define PAR_STRLEN 16
#define MAX_PARTS 32
-#define MAX_HTTP_REQUEST_SIZE 8192 //
+#define MAX_HTTP_REQUEST_SIZE 8192 //
#define MAX_SIG_SIZE 20
#define SHA1_SIG_SIZE 20