/* Translate the URL into a 'filename' */ CStr qEnvApache::MapFullPath(const char *path) { char *p; if (path && (*path != '/') && (p = strrchr(myReq->filename,DIRSEP))) { // relative path map should be easy int len = p - myReq->filename; CStr mapped(myReq->filename,len+1); mapped << path; return mapped; } else { // root path map is complex, easier way in API? int was = IsAuth; IsAuth = 1; #ifdef APACHE2 request_rec *r = ap_sub_req_lookup_uri(path, myReq, NULL); #else request_rec *r = ap_sub_req_lookup_uri(path, myReq); #endif IsAuth = was; CStr mapped = r->filename; ap_destroy_sub_req(r); return mapped; } }
/* do a sub-request to fetch properties for the target resource's URI. */ static void dav_do_prop_subreq(dav_propdb *propdb) { /* perform a "GET" on the resource's URI (note that the resource may not correspond to the current request!). */ propdb->subreq = ap_sub_req_lookup_uri(propdb->resource->uri, propdb->r, NULL); }
/* This is the special environment used for running the "exec cmd=" * variety of SSI directives. */ static void add_ssi_vars(request_rec *r) { apr_table_t *e = r->subprocess_env; if (r->path_info && r->path_info[0] != '\0') { request_rec *pa_req; apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info)); pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, NULL); if (pa_req->filename) { apr_table_setn(e, "PATH_TRANSLATED", apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL)); } ap_destroy_sub_req(pa_req); } if (r->args) { char *arg_copy = apr_pstrdup(r->pool, r->args); apr_table_setn(e, "QUERY_STRING", r->args); ap_unescape_url(arg_copy); apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy)); } }
AP_DECLARE(void) ap_add_cgi_vars(request_rec *r) { apr_table_t *e = r->subprocess_env; apr_table_setn(e, "GATEWAY_INTERFACE", "CGI/1.1"); apr_table_setn(e, "SERVER_PROTOCOL", r->protocol); apr_table_setn(e, "REQUEST_METHOD", r->method); apr_table_setn(e, "QUERY_STRING", r->args ? r->args : ""); apr_table_setn(e, "REQUEST_URI", original_uri(r)); /* Note that the code below special-cases scripts run from includes, * because it "knows" that the sub_request has been hacked to have the * args and path_info of the original request, and not any that may have * come with the script URI in the include command. Ugh. */ if (!strcmp(r->protocol, "INCLUDED")) { apr_table_setn(e, "SCRIPT_NAME", r->uri); if (r->path_info && *r->path_info) { apr_table_setn(e, "PATH_INFO", r->path_info); } } else if (!r->path_info || !*r->path_info) { apr_table_setn(e, "SCRIPT_NAME", r->uri); } else { int path_info_start = ap_find_path_info(r->uri, r->path_info); apr_table_setn(e, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, path_info_start)); apr_table_setn(e, "PATH_INFO", r->path_info); } if (r->path_info && r->path_info[0]) { /* * To get PATH_TRANSLATED, treat PATH_INFO as a URI path. * Need to re-escape it for this, since the entire URI was * un-escaped before we determined where the PATH_INFO began. */ request_rec *pa_req; pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, NULL); if (pa_req->filename) { char *pt = apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL); #ifdef WIN32 /* We need to make this a real Windows path name */ apr_filepath_merge(&pt, "", pt, APR_FILEPATH_NATIVE, r->pool); #endif apr_table_setn(e, "PATH_TRANSLATED", pt); } ap_destroy_sub_req(pa_req); } }
static request_rec *php_apache_lookup_uri(char *filename) { php_struct *ctx = SG(server_context); if (!filename || !ctx || !ctx->r) { return NULL; } return ap_sub_req_lookup_uri(filename, ctx->r, ctx->r->output_filters); }
/* do a sub-request to fetch properties for the target resource's URI. */ static void dav_do_prop_subreq(dav_propdb *propdb) { /* need to escape the uri that's in the resource struct because during * the property walker it's not encoded. */ const char *e_uri = ap_escape_uri(propdb->resource->pool, propdb->resource->uri); /* perform a "GET" on the resource's URI (note that the resource may not correspond to the current request!). */ propdb->subreq = ap_sub_req_lookup_uri(e_uri, propdb->r, NULL); }
/*============================================================================ *============================================================================ * This is the beginning of the cgi filter code moved from mod_include. This * is the code required to handle the "exec" SSI directive. *============================================================================ *============================================================================*/ static apr_status_t include_cgi(include_ctx_t *ctx, ap_filter_t *f, apr_bucket_brigade *bb, char *s) { request_rec *r = f->r; request_rec *rr = ap_sub_req_lookup_uri(s, r, f->next); int rr_status; if (rr->status != HTTP_OK) { ap_destroy_sub_req(rr); return APR_EGENERAL; } /* No hardwired path info or query allowed */ if ((rr->path_info && rr->path_info[0]) || rr->args) { ap_destroy_sub_req(rr); return APR_EGENERAL; } if (rr->finfo.filetype != APR_REG) { ap_destroy_sub_req(rr); return APR_EGENERAL; } /* Script gets parameters of the *document*, for back compatibility */ rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */ rr->args = r->args; /* Force sub_req to be treated as a CGI request, even if ordinary * typing rules would have called it something else. */ ap_set_content_type(rr, CGI_MAGIC_TYPE); /* Run it. */ rr_status = ap_run_sub_req(rr); if (ap_is_HTTP_REDIRECT(rr_status)) { const char *location = apr_table_get(rr->headers_out, "Location"); if (location) { char *buffer; location = ap_escape_html(rr->pool, location); buffer = apr_pstrcat(ctx->pool, "<a href=\"", location, "\">", location, "</a>", NULL); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(buffer, strlen(buffer), ctx->pool, f->c->bucket_alloc)); } } ap_destroy_sub_req(rr); return APR_SUCCESS; }
/* little helper function to get the original request path code borrowed from request.c and util_script.c */ static const char *ap_xsendfile_get_orginal_path(request_rec *rec) { const char *rv = rec->the_request, *last; int dir = 0; size_t uri_len; /* skip method && spaces */ while (*rv && !apr_isspace(*rv)) { ++rv; } while (apr_isspace(*rv)) { ++rv; } /* first space is the request end */ last = rv; while (*last && !apr_isspace(*last)) { ++last; } uri_len = last - rv; if (!uri_len) { return NULL; } /* alright, lets see if the request_uri changed! */ if (strncmp(rv, rec->uri, uri_len) == 0) { rv = apr_pstrdup(rec->pool, rec->filename); dir = rec->finfo.filetype == APR_DIR; } else { /* need to lookup the url again as it changed */ request_rec *sr = ap_sub_req_lookup_uri( apr_pstrmemdup(rec->pool, rv, uri_len), rec, NULL ); if (!sr) { return NULL; } rv = apr_pstrdup(rec->pool, sr->filename); dir = rec->finfo.filetype == APR_DIR; ap_destroy_sub_req(sr); } /* now we need to truncate so we only have the directory */ if (!dir && (last = ap_strrchr(rv, '/')) != NULL) { *((char*)last + 1) = '\0'; } return rv; }
static int is_contenttype_ignored(dosdetector_dir_config *cfg, request_rec *r) { const char *content_type; content_type = ap_sub_req_lookup_uri(r->uri, r, NULL)->content_type; ap_regmatch_t regmatch[AP_MAX_REG_MATCH]; ap_regex_t **contenttype_regexp = (ap_regex_t **) cfg->contenttype_regexp->elts; int i, ignore = 0; for (i = 0; i < cfg->contenttype_regexp->nelts; i++) { if(!ap_regexec(contenttype_regexp[i], content_type, AP_MAX_REG_MATCH, regmatch, 0)) { ignore = 1; break; } } DEBUGLOG_R("content-type=%s, result=%s", content_type, (ignore ? "ignored":"processed")); return ignore; }
/* XXX: Is there is still an O(n^2) attack possible here? Please detail. */ BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType) { isapi_cid *cid = (isapi_cid *)hConn; request_rec *r = cid->r; request_rec *subreq; switch (dwHSERequest) { case 1: /* HSE_REQ_SEND_URL_REDIRECT_RESP */ /* Set the status to be returned when the HttpExtensionProc() * is done. * WARNING: Microsoft now advertises HSE_REQ_SEND_URL_REDIRECT_RESP * and HSE_REQ_SEND_URL as equivalant per the Jan 2000 SDK. * They most definately are not, even in their own samples. */ ap_table_set(r->headers_out, "Location", lpvBuffer); cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = HTTP_MOVED_TEMPORARILY; return TRUE; case 2: /* HSE_REQ_SEND_URL */ /* Soak up remaining input (there should be none) */ if (r->remaining > 0) { char argsbuffer[HUGE_STRING_LEN]; while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0); } /* Reset the method to GET */ r->method = ap_pstrdup(r->pool, "GET"); r->method_number = M_GET; /* Don't let anyone think there's still data */ ap_table_unset(r->headers_in, "Content-Length"); /* AV fault per PR3598 - redirected path is lost! */ (char*)lpvBuffer = ap_pstrdup(r->pool, (char*)lpvBuffer); ap_internal_redirect((char*)lpvBuffer, r); return TRUE; case 3: /* HSE_REQ_SEND_RESPONSE_HEADER */ { /* Parse them out, or die trying */ DWORD statlen = 0, headlen = 0; if (lpvBuffer) statlen = strlen((char*) lpvBuffer); if (lpdwDataType) headlen = strlen((char*) lpdwDataType); return SendResponseHeaderEx(cid, (char*) lpvBuffer, (char*) lpdwDataType, statlen, headlen); } case 4: /* HSE_REQ_DONE_WITH_SESSION */ /* Do nothing... since we don't support async I/O, they'll * return from HttpExtensionProc soon */ return TRUE; case 1001: /* HSE_REQ_MAP_URL_TO_PATH */ { /* Map a URL to a filename */ char *file = (char *)lpvBuffer; DWORD len; subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, file, *lpdwSize), r); len = ap_cpystrn(file, subreq->filename, *lpdwSize) - file; /* IIS puts a trailing slash on directories, Apache doesn't */ if (S_ISDIR (subreq->finfo.st_mode)) { if (len < *lpdwSize - 1) { file[len++] = '\\'; file[len] = '\0'; } } *lpdwSize = len; return TRUE; } case 1002: /* HSE_REQ_GET_SSPI_INFO */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction HSE_REQ_GET_SSPI_INFO " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1003: /* HSE_APPEND_LOG_PARAMETER */ /* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field * This code will do for now... */ ap_table_set(r->notes, "isapi-parameter", (char*) lpvBuffer); if (AppendLogToQuery) { if (r->args) r->args = ap_pstrcat(r->pool, r->args, (char*) lpvBuffer, NULL); else r->args = ap_pstrdup(r->pool, (char*) lpvBuffer); } if (AppendLogToErrors) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r, "ISAPI %s: %s", cid->r->filename, (char*) lpvBuffer); return TRUE; /* We don't support all this async I/O, Microsoft-specific stuff */ case 1005: /* HSE_REQ_IO_COMPLETION */ case 1006: /* HSE_REQ_TRANSMIT_FILE */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI asynchronous I/O not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1007: /* HSE_REQ_REFRESH_ISAPI_ACL */ /* Since we don't override the user ID and access, we can't reset. */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_REFRESH_ISAPI_ACL " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1008: /* HSE_REQ_IS_KEEP_CONN */ *((LPBOOL) lpvBuffer) = (r->connection->keepalive == 1); return TRUE; case 1010: /* HSE_REQ_ASYNC_READ_CLIENT */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI asynchronous I/O not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1011: /* HSE_REQ_GET_IMPERSONATION_TOKEN Added in ISAPI 4.0 */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_GET_IMPERSONATION_TOKEN " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; #ifdef HSE_REQ_MAP_URL_TO_PATH_EX case 1012: /* HSE_REQ_MAP_URL_TO_PATH_EX */ { /* Map a URL to a filename */ LPHSE_URL_MAPEX_INFO info = (LPHSE_URL_MAPEX_INFO) lpdwDataType; char* test_uri = ap_pstrndup(r->pool, (char *)lpvBuffer, *lpdwSize); subreq = ap_sub_req_lookup_uri(test_uri, r); info->cchMatchingURL = strlen(test_uri); info->cchMatchingPath = ap_cpystrn(info->lpszPath, subreq->filename, MAX_PATH) - info->lpszPath; /* Mapping started with assuming both strings matched. * Now roll on the path_info as a mismatch and handle * terminating slashes for directory matches. */ if (subreq->path_info && *subreq->path_info) { ap_cpystrn(info->lpszPath + info->cchMatchingPath, subreq->path_info, MAX_PATH - info->cchMatchingPath); info->cchMatchingURL -= strlen(subreq->path_info); if (S_ISDIR(subreq->finfo.st_mode) && info->cchMatchingPath < MAX_PATH - 1) { /* roll forward over path_info's first slash */ ++info->cchMatchingPath; ++info->cchMatchingURL; } } else if (S_ISDIR(subreq->finfo.st_mode) && info->cchMatchingPath < MAX_PATH - 1) { /* Add a trailing slash for directory */ info->lpszPath[info->cchMatchingPath++] = '/'; info->lpszPath[info->cchMatchingPath] = '\0'; } /* If the matched isn't a file, roll match back to the prior slash */ if (!subreq->finfo.st_mode) { while (info->cchMatchingPath && info->cchMatchingURL) { if (info->lpszPath[info->cchMatchingPath - 1] == '/') break; --info->cchMatchingPath; --info->cchMatchingURL; } } /* Paths returned with back slashes */ for (test_uri = info->lpszPath; *test_uri; ++test_uri) if (*test_uri == '/') *test_uri = '\\'; /* is a combination of: * HSE_URL_FLAGS_READ 0x001 Allow read * HSE_URL_FLAGS_WRITE 0x002 Allow write * HSE_URL_FLAGS_EXECUTE 0x004 Allow execute * HSE_URL_FLAGS_SSL 0x008 Require SSL * HSE_URL_FLAGS_DONT_CACHE 0x010 Don't cache (VRoot only) * HSE_URL_FLAGS_NEGO_CERT 0x020 Allow client SSL cert * HSE_URL_FLAGS_REQUIRE_CERT 0x040 Require client SSL cert * HSE_URL_FLAGS_MAP_CERT 0x080 Map client SSL cert to account * HSE_URL_FLAGS_SSL128 0x100 Require 128-bit SSL cert * HSE_URL_FLAGS_SCRIPT 0x200 Allow script execution * * XxX: As everywhere, EXEC flags could use some work... * and this could go further with more flags, as desired. */ info->dwFlags = (subreq->finfo.st_mode & _S_IREAD ? 0x001 : 0) | (subreq->finfo.st_mode & _S_IWRITE ? 0x002 : 0) | (subreq->finfo.st_mode & _S_IEXEC ? 0x204 : 0); return TRUE; } #endif case 1014: /* HSE_REQ_ABORTIVE_CLOSE */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE" " is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1015: /* HSE_REQ_GET_CERT_INFO_EX Added in ISAPI 4.0 */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_GET_CERT_INFO_EX " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; #ifdef HSE_REQ_SEND_RESPONSE_HEADER_EX case 1016: /* HSE_REQ_SEND_RESPONSE_HEADER_EX Added in ISAPI 4.0 */ { LPHSE_SEND_HEADER_EX_INFO shi = (LPHSE_SEND_HEADER_EX_INFO) lpvBuffer; /* XXX: ignore shi->fKeepConn? We shouldn't need the advise */ /* r->connection->keepalive = shi->fKeepConn; */ return SendResponseHeaderEx(cid, shi->pszStatus, shi->pszHeader, shi->cchStatus, shi->cchHeader); } #endif case 1017: /* HSE_REQ_CLOSE_CONNECTION Added after ISAPI 4.0 */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_CLOSE_CONNECTION " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1018: /* HSE_REQ_IS_CONNECTED Added after ISAPI 4.0 */ /* Returns True if client is connected c.f. MSKB Q188346 * XXX: That statement is very ambigious... assuming the * identical return mechanism as HSE_REQ_IS_KEEP_CONN. */ *((LPBOOL) lpvBuffer) = (r->connection->aborted == 0); return TRUE; case 1020: /* HSE_REQ_EXTENSION_TRIGGER Added after ISAPI 4.0 */ /* Undocumented - defined by the Microsoft Jan '00 Platform SDK */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_EXTENSION_TRIGGER " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; default: if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction (%d) not supported: " "%s", dwHSERequest, r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } }
static int dosdetector_handler(request_rec *r) { //DEBUGLOG("dosdetector_handler is called"); dosdetector_dir_config *cfg = (dosdetector_dir_config *) ap_get_module_config(r->per_dir_config, &dosdetector_module); if(cfg->detection) return DECLINED; if (!ap_is_initial_req(r)) return DECLINED; //char **ignore_contenttype = (char **) cfg->ignore_contenttype->elts; const char *content_type; const char *address_tmp; const char *address = NULL; int i; content_type = ap_sub_req_lookup_uri(r->uri, r, NULL)->content_type; if (!content_type) { #if (AP_SERVER_MINORVERSION_NUMBER > 2) content_type = DefaultContentType; #else content_type = ap_default_type(r); #endif } if (cfg->forwarded){ if ((address_tmp = apr_table_get(r->headers_in, "X-Forwarded-For")) != NULL){ const char *i = address_tmp; while(*i != 0 && *i != ',') i++; address = apr_pstrndup(r->pool, address_tmp, i - address_tmp); } } if (address == NULL) { #if (AP_SERVER_MINORVERSION_NUMBER > 2) address = r->connection->client_ip; #else address = r->connection->remote_ip; #endif } ap_regmatch_t regmatch[AP_MAX_REG_MATCH]; ap_regex_t **contenttype_regexp = (ap_regex_t **) cfg->contenttype_regexp->elts; for (i = 0; i < cfg->contenttype_regexp->nelts; i++) { if(!ap_regexec(contenttype_regexp[i], content_type, AP_MAX_REG_MATCH, regmatch, 0)){ //ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, 0, "ignoring content-type: %s", content_type); return OK; } } DEBUGLOG("dosdetector: processing content-type: %s", content_type); struct in_addr addr; if(!cfg->forwarded) { #if (AP_SERVER_MINORVERSION_NUMBER > 2) addr = r->connection->client_addr->sa.sin.sin_addr; #else addr = r->connection->remote_addr->sa.sin.sin_addr; #endif } if(cfg->forwarded || addr.s_addr == 0){ if (inet_aton(address, &addr) == 0) { TRACELOG("dosdetector: '%s' is not a valid IP addresss", address); return DECLINED; } } if (lock) apr_global_mutex_lock(lock); client_t *client = get_client(client_list, addr, cfg->period); if (lock) apr_global_mutex_unlock(lock); #ifdef _DEBUG int last_count = client->count; #endif count_increment(client, cfg->threshold); DEBUGLOG("dosdetector: %s, count: %d -> %d, interval: %d", address, last_count, client->count, (int)client->interval); //DEBUGLOG("dosdetector: %s, count: %d -> %d, interval: %d on tid %d, pid %d", address, last_count, client->count, (int)client->interval, gettid(), getpid()); time_t now = time((time_t *)0); if(client->suspected > 0 && client->suspected + cfg->ban_period > now){ apr_table_setn(r->subprocess_env, "SuspectDoS", "1"); //apr_table_setn(r->notes, "SuspectDoS", "1"); DEBUGLOG("dosdetector: '%s' has been still suspected as DoS attack! (suspected %d sec ago)", address, now - client->suspected); if(client->count > cfg->ban_threshold){ if(client->hard_suspected == 0) TRACELOG("dosdetector: '%s' is suspected as Hard DoS attack! (counter: %d)", address, client->count); client->hard_suspected = now; apr_table_setn(r->subprocess_env, "SuspectHardDoS", "1"); //apr_table_setn(r->notes, "SuspectHardDoS", "1"); } } else { if(client->suspected > 0){ client->suspected = 0; client->hard_suspected = 0; client->count = 0; } //int last_count = client->count; //client->count = client->count - client->interval * cfg->threshold; //if(client->count < 0) // client->count = 0; //client->count ++; //DEBUGLOG("client address: %s, count: %d -> %d, interval: %d", address, last_count, client->count, client->interval); if(client->count > cfg->threshold){ client->suspected = now; apr_table_setn(r->subprocess_env, "SuspectDoS", "1"); //apr_table_setn(r->notes, "SuspectDoS", "1"); TRACELOG("dosdetector: '%s' is suspected as DoS attack! (counter: %d)", address, client->count); } } return DECLINED; }