static int ts_lua_server_request_get_uri(lua_State *L) { char uri[TS_LUA_MAX_URL_LENGTH]; const char *path; int path_len; int uri_len; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx); path = TSUrlPathGet(http_ctx->server_request_bufp, http_ctx->server_request_url, &path_len); uri_len = snprintf(uri, TS_LUA_MAX_URL_LENGTH, "/%.*s", path_len, path); if (uri_len >= TS_LUA_MAX_URL_LENGTH) { lua_pushlstring(L, uri, TS_LUA_MAX_URL_LENGTH - 1); } else { lua_pushlstring(L, uri, uri_len); } return 1; }
static int ts_lua_remap_get_to_uri(lua_State *L) { char uri[TS_LUA_MAX_URL_LENGTH]; const char *path; int path_len; int uri_len; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); if (http_ctx->rri != NULL) { path = TSUrlPathGet(http_ctx->client_request_bufp, http_ctx->rri->mapToUrl, &path_len); uri_len = snprintf(uri, TS_LUA_MAX_URL_LENGTH, "/%.*s", path_len, path); if (uri_len >= TS_LUA_MAX_URL_LENGTH) { lua_pushlstring(L, uri, TS_LUA_MAX_URL_LENGTH - 1); } else { lua_pushlstring(L, uri, uri_len); } } else { lua_pushnil(L); } return 1; }
static int stats_origin(TSCont contp ATS_UNUSED, TSEvent event ATS_UNUSED, void *edata) { TSCont icontp; stats_state *my_state; TSHttpTxn txnp = (TSHttpTxn)edata; TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSEvent reenable = TS_EVENT_HTTP_CONTINUE; TSDebug(PLUGIN_NAME, "in the read stuff"); if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc) != TS_SUCCESS) { goto cleanup; } if (TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc) != TS_SUCCESS) { goto cleanup; } int path_len = 0; const char *path = TSUrlPathGet(reqp, url_loc, &path_len); TSDebug(PLUGIN_NAME, "Path: %.*s", path_len, path); if (!(path_len != 0 && path_len == url_path_len && !memcmp(path, url_path, url_path_len))) { goto notforme; } TSSkipRemappingSet(txnp, 1); // not strictly necessary, but speed is everything these days /* This is us -- register our intercept */ TSDebug(PLUGIN_NAME, "Intercepting request"); icontp = TSContCreate(stats_dostuff, TSMutexCreate()); my_state = (stats_state *)TSmalloc(sizeof(*my_state)); memset(my_state, 0, sizeof(*my_state)); TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); goto cleanup; notforme: cleanup: if (url_loc) { TSHandleMLocRelease(reqp, hdr_loc, url_loc); } if (hdr_loc) { TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); } TSHttpTxnReenable(txnp, reenable); return 0; }
/* Read-request header continuation, used to kick off the server intercept if necessary */ static int health_check_origin(TSCont contp, TSEvent event, void *edata) { TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSCont icontp; HCState *my_state; TSHttpTxn txnp = (TSHttpTxn) edata; HCFileInfo *info = g_config; if ((TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) && (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc))) { int path_len = 0; const char* path = TSUrlPathGet(reqp, url_loc, &path_len); while (info) { if (info->p_len == path_len && !memcmp(info->path, path, path_len)) break; info = info->_next; } if (!info) goto cleanup; TSSkipRemappingSet(txnp, 1); /* not strictly necessary, but speed is everything these days */ /* This is us -- register our intercept */ icontp = TSContCreate(hc_intercept, TSMutexCreate()); my_state = (HCState *)TSmalloc(sizeof(*my_state)); memset(my_state, 0, sizeof(*my_state)); my_state->info = info; my_state->data = info->data; TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); } cleanup: if (url_loc) TSHandleMLocRelease(reqp, hdr_loc, url_loc); if (hdr_loc) TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; }
/* Read-request header continuation, used to kick off the server intercept if necessary */ static int acme_hook(TSCont contp ATS_UNUSED, TSEvent event ATS_UNUSED, void *edata) { TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSCont icontp; AcmeState *my_state; TSHttpTxn txnp = (TSHttpTxn)edata; TSDebug(PLUGIN_NAME, "kicking off ACME hook"); if ((TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) && (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc))) { int path_len = 0; const char *path = TSUrlPathGet(reqp, url_loc, &path_len); /* Short circuit the / path, common case */ if (!path || path_len < (int)(strlen(ACME_WK_PATH) + 2) || *path != '.' || memcmp(path, ACME_WK_PATH, strlen(ACME_WK_PATH))) { TSDebug(PLUGIN_NAME, "skipping URL path = %.*s", path_len, path); goto cleanup; } TSSkipRemappingSet(txnp, 1); /* not strictly necessary, but speed is everything these days */ /* This request is for us -- register our intercept */ icontp = TSContCreate(acme_intercept, TSMutexCreate()); my_state = make_acme_state(); open_acme_file(my_state, path + strlen(ACME_WK_PATH), path_len - strlen(ACME_WK_PATH)); TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); TSDebug(PLUGIN_NAME, "created intercept hook"); } cleanup: if (url_loc) { TSHandleMLocRelease(reqp, hdr_loc, url_loc); } if (hdr_loc) { TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); } TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; }
static int ts_lua_client_request_get_uri(lua_State *L) { char uri[TS_LUA_MAX_URL_LENGTH]; const char *path; int path_len; int uri_len; ts_lua_http_ctx *http_ctx; http_ctx = ts_lua_get_http_ctx(L); path = TSUrlPathGet(http_ctx->client_request_bufp, http_ctx->client_request_url, &path_len); uri_len = snprintf(uri, TS_LUA_MAX_URL_LENGTH, "/%.*s", path_len, path); lua_pushlstring(L, uri, uri_len); return 1; }
static int ts_lua_server_request_get_uri(lua_State *L) { const char *path; int path_len; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx); path = TSUrlPathGet(http_ctx->server_request_bufp, http_ctx->server_request_url, &path_len); lua_pushlstring(L, "/", 1); lua_pushlstring(L, path, path_len >= TS_LUA_MAX_URL_LENGTH - 1 ? TS_LUA_MAX_URL_LENGTH - 2 : path_len); lua_concat(L, 2); return 1; }
TSRemapStatus TSRemapDoRemap(void* ih, TSHttpTxn rh, TSRemapRequestInfo *rri) { hash_remap_struct *hash = (hash_remap_struct*) ih; if (rri == NULL || ih == NULL) { TSError(PLUGIN_NAME "NULL pointer for rri or ih"); return TSREMAP_NO_REMAP; } int req_host_len; int req_path_len; const char* req_host = TSUrlHostGet(rri->requestBufp, rri->requestUrl, &req_host_len); const char* req_path = TSUrlPathGet(rri->requestBufp, rri->requestUrl, &req_path_len); uint32_t hash_value_host = hash_fnv32((char *) req_host, req_host_len); uint64_t hash_value_host_and_path = hash_fnv64((char *) req_host, req_host_len); hash_fnv64_continue((char *) req_path, req_path_len, &hash_value_host_and_path); memset(hash->hash, 0, hash->hash_len); int len = sprintf(hash->hash, "%lx%x.%.*s", hash_value_host_and_path, hash_value_host, hash->isp_name_len, hash->isp_name); if (len > hash->hash_len) { TSError(PLUGIN_NAME "Memory probably corrupt :whistle:"); return TSREMAP_NO_REMAP; } if (TSUrlHostSet(rri->requestBufp, rri->requestUrl, hash->hash, len) != TS_SUCCESS) { /* the request was not modified, TS will use the toURL from the remap rule */ TSError(PLUGIN_NAME "Failed to modify the Host in request URL"); return TSREMAP_NO_REMAP; } TSDebug(PLUGIN_NAME, "host changed from [%.*s] to [%.*s]", req_host_len, req_host, len, hash->hash); // fprintf(stderr, "host changed from [%.*s] to [%.*s/%.*s]\n", req_host_len, req_host, len, hash->hash, req_path_len, req_path); return TSREMAP_DID_REMAP; /* host has been modified */ }
TSRemapStatus TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo* rri) { int i, len; time_t t, e; MD5_CTX ctx; struct sockaddr_in *in; const char *qh, *ph, *ip; unsigned char md[MD5_DIGEST_LENGTH]; secure_link_info *sli = (secure_link_info *)ih; char *token = NULL, *expire = NULL, *path = NULL; char *s, *ptr, *saveptr = NULL, *val, hash[32] = ""; in = (struct sockaddr_in *)TSHttpTxnClientAddrGet(rh); ip = inet_ntoa(in->sin_addr); s = TSUrlStringGet(rri->requestBufp, rri->requestUrl, &len); TSDebug(PLUGIN_NAME, "request [%.*s] from [%s]", len, s, ip); TSfree(s); qh = TSUrlHttpQueryGet(rri->requestBufp, rri->requestUrl, &len); if(qh && len > 0) { s = (char *)TSstrndup(qh, len); if((ptr = strtok_r(s, "&", &saveptr)) != NULL) { do { if((val = strchr(ptr, '=')) != NULL) { *val++ = '\0'; if(strcmp(ptr, "st") == 0) { token = TSstrdup(val); } else if(strcmp(ptr, "ex") == 0) { expire = TSstrdup(val); } } else { TSError("Invalid parameter [%s]", ptr); break; } } while((ptr = strtok_r(NULL, "&", &saveptr)) != NULL); } else { TSError("strtok didn't find a & in the query string"); /* this is just example, so set fake params to prevent plugin crash */ token = TSstrdup("d41d8cd98f00b204e9800998ecf8427e"); expire = TSstrdup("00000000"); } TSfree(s); } else { TSError("TSUrlHttpQueryGet returns empty value"); } ph = TSUrlPathGet(rri->requestBufp, rri->requestUrl, &len); if(ph && len > 0) { s = TSstrndup(ph, len); if((ptr = strrchr(s, '/')) != NULL) { *++ptr = '\0'; } path = TSstrdup(s); TSfree(s); } else { TSError("TSUrlPathGet returns empty value"); /* this is just example, so set fake params to prevent plugin crash */ path = TSstrdup("example/"); } MD5_Init(&ctx); MD5_Update(&ctx, sli->secret, strlen(sli->secret)); MD5_Update(&ctx, ip, strlen(ip)); if (path) MD5_Update(&ctx, path, strlen(path)); if (expire) MD5_Update(&ctx, expire, strlen(expire)); MD5_Final(md, &ctx); for(i = 0; i < MD5_DIGEST_LENGTH; i++) { sprintf(&hash[i * 2], "%02x", md[i]); } time(&t); e = strtol(expire, NULL, 16); i = TSREMAP_DID_REMAP; if(e < t || strcmp(hash, token) != 0) { if(e < t) { TSDebug(PLUGIN_NAME, "link expired: [%lu] vs [%lu]", t, e); } else { TSDebug(PLUGIN_NAME, "tokens mismatch: [%s] vs [%s]", hash, token); } if(sli->strict) { TSDebug(PLUGIN_NAME, "request is DENY"); TSHttpTxnSetHttpRetStatus(rh, TS_HTTP_STATUS_FORBIDDEN); i = TSREMAP_NO_REMAP; } else { TSDebug(PLUGIN_NAME, "request is PASS"); } } if(i == TSREMAP_DID_REMAP) { if(TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, "", -1) == TS_SUCCESS) { s = TSUrlStringGet(rri->requestBufp, rri->requestUrl, &len); TSDebug(PLUGIN_NAME, "new request string is [%.*s]", len, s); TSfree(s); } else { i = TSREMAP_NO_REMAP; } } TSfree(expire); TSfree(token); TSfree(path); return i; }
static void handle_purge(TSHttpTxn txnp, PurgeInstance *purge) { TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; bool should_purge = false; if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) { int method_len = 0; const char *method = TSHttpHdrMethodGet(reqp, hdr_loc, &method_len); if ((TS_HTTP_METHOD_PURGE == method) || ((TS_HTTP_METHOD_GET == method) && purge->allow_get)) { /* First see if we require the "secret" to be passed in a header, and then use that */ if (purge->header) { TSMLoc field_loc = TSMimeHdrFieldFind(reqp, hdr_loc, purge->header, purge->header_len); if (field_loc) { const char *header; int header_len; header = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field_loc, -1, &header_len); TSDebug(PLUGIN_NAME, "Checking for %.*s == %s ?", header_len, header, purge->secret); if (header && (header_len == purge->secret_len) && !memcmp(header, purge->secret, header_len)) { should_purge = true; } TSHandleMLocRelease(reqp, hdr_loc, field_loc); } } else { /* We are matching on the path component instead of a header */ if (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc)) { int path_len = 0; const char *path = TSUrlPathGet(reqp, url_loc, &path_len); TSDebug(PLUGIN_NAME, "Checking PATH = %.*s", path_len, path); if (path && (path_len >= purge->secret_len)) { int s_path = path_len - 1; while ((s_path >= 0) && ('/' != path[s_path])) { /* No memrchr in OSX */ --s_path; } if (!memcmp(s_path > 0 ? path + s_path + 1 : path, purge->secret, purge->secret_len)) { should_purge = true; } } TSHandleMLocRelease(reqp, hdr_loc, url_loc); } } } TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); } /* Setup the continuation to handle this request if appropriate, if not, set the GenID if needed */ if (should_purge) { TSCont cont = TSContCreate(purge_cont, TSMutexCreate()); TSContDataSet(cont, purge); TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, cont); TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, cont); } else if (purge->gen_id > 0) { TSHttpTxnConfigIntSet(txnp, TS_CONFIG_HTTP_CACHE_GENERATION, purge->gen_id); } }
static int astats_origin(TSCont cont, TSEvent event, void *edata) { TSCont icontp; stats_state *my_state; config_t* config; TSHttpTxn txnp = (TSHttpTxn) edata; TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; TSEvent reenable = TS_EVENT_HTTP_CONTINUE; config = get_config(cont); TSDebug(PLUGIN_TAG, "in the read stuff"); if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc) != TS_SUCCESS) goto cleanup; if (TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc) != TS_SUCCESS) goto cleanup; int path_len = 0; const char* path = TSUrlPathGet(reqp,url_loc,&path_len); TSDebug(PLUGIN_TAG,"Path: %.*s",path_len,path); TSDebug(PLUGIN_TAG,"Path: %.*s",path_len,path); if (!(path_len == config->stats_path_len && !memcmp(path, config->stats_path, config->stats_path_len))) { // TSDebug(PLUGIN_TAG, "not right path: %.*s",path_len,path); goto notforme; } const struct sockaddr *addr = TSHttpTxnClientAddrGet(txnp); if(!is_ip_allowed(config, addr)) { TSDebug(PLUGIN_TAG, "not right ip"); goto notforme; } // TSDebug(PLUGIN_TAG,"Path...: %.*s",path_len,path); int query_len; char *query = (char*)TSUrlHttpQueryGet(reqp,url_loc,&query_len); TSDebug(PLUGIN_TAG,"query: %.*s",query_len,query); TSSkipRemappingSet(txnp,1); //not strictly necessary, but speed is everything these days /* This is us -- register our intercept */ TSDebug(PLUGIN_TAG, "Intercepting request"); icontp = TSContCreate(stats_dostuff, TSMutexCreate()); my_state = (stats_state *) TSmalloc(sizeof(*my_state)); memset(my_state, 0, sizeof(*my_state)); my_state->recordTypes = config->recordTypes; if (query_len) { my_state->query = nstrl(query, query_len); TSDebug(PLUGIN_TAG,"new query: %s", my_state->query); stats_fillState(my_state, my_state->query, query_len); } TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); goto cleanup; notforme: cleanup: #if (TS_VERSION_NUMBER < 2001005) if (path) TSHandleStringRelease(reqp, url_loc, path); #endif if (url_loc) TSHandleMLocRelease(reqp, hdr_loc, url_loc); if (hdr_loc) TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); TSHttpTxnReenable(txnp, reenable); return 0; }