/** * Look at the request to see if Caucho should handle it. */ static int cse_dispatch(request_rec *r) { config_t *config = cse_get_module_config(r); const char *host = ap_get_server_name(r); const char *uri = r->uri; unsigned int now = r->request_time; LOG(("CONF: %p\n", config)); if (config == NULL) return DECLINED; /* cse_update_config(config, r->request_time); */ if (config->enable_caucho_status && strstr(uri, "/caucho-status")) { r->handler = "caucho-status"; return OK; } /* Check for exact virtual host match */ if (cse_match_request(config, host, ap_get_server_port(r), uri, 0, now) || r->handler && ! strcmp(r->handler, "caucho-request")) { r->handler = "caucho-request"; LOG(("[%d] match %s:%s\n", getpid(), host ? host : "null", uri)); return OK; } LOG(("[%d] mismatch %s:%s\n", getpid(), host ? host : "null", uri)); return DECLINED; }
// Get the full URI of the request_rec's request location // clean_params specifies whether or not all openid.* and modauthopenid.* params should be cleared static void full_uri(request_rec *r, std::string& result, modauthopenid_config *s_cfg, bool clean_params=false) { std::string hostname(r->hostname); std::string uri(r->uri); apr_port_t i_port = ap_get_server_port(r); // Fetch the APR function for determining if we are looking at an https URL APR_OPTIONAL_FN_TYPE(ssl_is_https) *using_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https); std::string prefix = (using_https != NULL && using_https(r->connection)) ? "https://" : "http://"; char *port = apr_psprintf(r->pool, "%lu", (unsigned long) i_port); std::string s_port = (i_port == 80 || i_port == 443) ? "" : ":" + std::string(port); std::string args; if(clean_params) { opkele::params_t params; if(r->args != NULL) params = modauthopenid::parse_query_string(std::string(r->args)); modauthopenid::remove_openid_vars(params); args = params.append_query("", ""); } else { args = (r->args == NULL) ? "" : "?" + std::string(r->args); } if(s_cfg->server_name == NULL) result = prefix + hostname + s_port + uri + args; else result = std::string(s_cfg->server_name) + uri + args; }
CAMLprim value netcgi2_apache_request_port(value rv) { CAMLparam1(rv); request_rec *r = Request_rec_val (rv); CAMLreturn(Val_int(ap_get_server_port(r))); }
/** * Look at the request to see if Resin should handle it. */ static int cse_dispatch(request_rec *r) { config_t *config = cse_get_module_config(r); const char *host_name = ap_get_server_name(r); int port = ap_get_server_port(r); const char *uri = r->uri; resin_host_t *host; unsigned int now; int len; if (config == NULL || ! uri) return DECLINED; now = time(0); LOG(("%s:%d:cse_dispatch(): [%d] host %s\n", __FILE__, __LINE__, getpid(), host_name ? host_name : "null")); len = strlen(uri); /* move back below host */ if (config->enable_caucho_status && len >= sizeof("/caucho-status") - 1 && ! strcmp(uri + len - sizeof("/caucho-status") + 1, "/caucho-status")) { r->handler = "caucho-status"; return caucho_status(r); } /* Check for exact virtual host match */ host = cse_match_request(config, host_name, port, uri, 0, now); if (host || (r->handler && ! strcmp(r->handler, "caucho-request"))) { LOG(("%s:%d:cse_dispatch(): [%d] match %s:%s\n", __FILE__, __LINE__, getpid(), host_name ? host_name : "null", uri)); return caucho_request(r, config, host, now); } else if (r->handler && ! strcmp(r->handler, "caucho-status")) { return caucho_status(r); } if (config->session_url_prefix) { return cse_strip(r); } return DECLINED; }
static int check_request_acl(request_rec *r, int req_access) { char *dir_path, *acl_path; apr_finfo_t acl_finfo; const char *req_uri, *dir_uri, *acl_uri, *access; const char *port, *par_uri, *req_file; librdf_world *rdf_world = NULL; librdf_storage *rdf_storage = NULL; librdf_model *rdf_model = NULL; librdf_parser *rdf_parser = NULL; librdf_uri *rdf_uri_acl = NULL, *rdf_uri_base = NULL; int ret = HTTP_FORBIDDEN; // dir_path: parent directory of request filename // acl_path: absolute path to request ACL dir_path = ap_make_dirstr_parent(r->pool, r->filename); acl_path = ap_make_full_path(r->pool, dir_path, WEBID_ACL_FNAME); if (apr_filepath_merge(&acl_path, NULL, acl_path, APR_FILEPATH_NOTRELATIVE, r->pool) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "Module bug? Request filename path %s is invalid or " "or not absolute for uri %s", r->filename, r->uri); return HTTP_FORBIDDEN; } // acl_path: 403 if missing if ((apr_stat(&acl_finfo, acl_path, APR_FINFO_TYPE, r->pool) != APR_SUCCESS) || (acl_finfo.filetype != APR_REG)) { return HTTP_FORBIDDEN; } // req_uri: fully qualified URI of request filename // dir_uri: fully qualified URI of request filename parent // acl_uri: fully qualified URI of request filename ACL // access: ACL URI of requested access port = ap_is_default_port(ap_get_server_port(r), r) ? "" : apr_psprintf(r->pool, ":%u", ap_get_server_port(r)); req_uri = apr_psprintf(r->pool, "%s://%s%s%s%s", ap_http_scheme(r), ap_get_server_name(r), port, (*r->uri == '/') ? "" : "/", r->uri); par_uri = ap_make_dirstr_parent(r->pool, r->uri); dir_uri = apr_psprintf(r->pool, "%s://%s%s%s%s", ap_http_scheme(r), ap_get_server_name(r), port, (*par_uri == '/') ? "" : "/", par_uri); acl_uri = ap_make_full_path(r->pool, dir_uri, WEBID_ACL_FNAME); if (req_access == WEBID_ACCESS_READ) { access = "Read"; } else if (req_access == WEBID_ACCESS_WRITE) { if ((req_file = strrchr(r->filename, '/')) != NULL && strcmp(++req_file, WEBID_ACL_FNAME) == 0) access = "Control"; else access = "Write"; } else { access = "Control"; } ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "[ACL] %s (%s) %s | URI: %s | DIR: %s (%s) | ACL: %s (%s) | status: %d", r->method, access, r->uri, req_uri, dir_uri, dir_path, acl_uri, acl_path, r->status); if ((rdf_world = librdf_new_world()) != NULL) { librdf_world_open(rdf_world); if ((rdf_storage = librdf_new_storage(rdf_world, "memory", NULL, NULL)) != NULL) { if ((rdf_model = librdf_new_model(rdf_world, rdf_storage, NULL)) != NULL) { if ((rdf_parser = librdf_new_parser(rdf_world, "turtle", NULL, NULL)) != NULL) { if ((rdf_uri_base = librdf_new_uri(rdf_world, (unsigned char*)acl_uri)) != NULL) { if ((rdf_uri_acl = librdf_new_uri_from_filename(rdf_world, acl_path)) != NULL) { if (!librdf_parser_parse_into_model(rdf_parser, rdf_uri_acl, rdf_uri_base, rdf_model)) { //log_stream_prefix(r, librdf_model_as_stream(rdf_model), "[ACL] [model]"); if (query_results(r, rdf_world, rdf_model, apr_psprintf(r->pool, SPARQL_URI_MODE_AGENT, "accessTo", req_uri, access, r->user)) > 0 || \ query_results(r, rdf_world, rdf_model, apr_psprintf(r->pool, SPARQL_URI_MODE_AGENTCLASS, "accessTo", req_uri, access, r->user)) > 0 || \ query_results(r, rdf_world, rdf_model, apr_psprintf(r->pool, SPARQL_URI_MODE_WORLD, "accessTo", req_uri, access)) > 0 || \ ( ( query_results(r, rdf_world, rdf_model, apr_psprintf(r->pool, SPARQL_URI_ACL_EXISTS, "accessTo", req_uri )) == 0 ) && ( query_results(r, rdf_world, rdf_model, apr_psprintf(r->pool, SPARQL_URI_MODE_AGENT, "defaultForNew", dir_uri, access, r->user)) > 0 || \ query_results(r, rdf_world, rdf_model, apr_psprintf(r->pool, SPARQL_URI_MODE_AGENTCLASS, "defaultForNew", dir_uri, access, r->user)) > 0 || \ query_results(r, rdf_world, rdf_model, apr_psprintf(r->pool, SPARQL_URI_MODE_WORLD, "defaultForNew", dir_uri, access)) > 0 ) ) ) { apr_table_set(r->headers_out, "Link", apr_psprintf(r->pool, "%s; rel=meta", acl_uri)); ret = OK; } } else ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "librdf_parser_parse_into_model failed"); librdf_free_uri(rdf_uri_acl); } else ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "librdf_new_uri_from_filename returned NULL"); librdf_free_uri(rdf_uri_base); } else ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "librdf_new_uri returned NULL"); librdf_free_parser(rdf_parser); } else ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "librdf_new_parser returned NULL"); librdf_free_model(rdf_model); } else ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "librdf_new_model returned NULL"); librdf_free_storage(rdf_storage); } else ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "librdf_new_storage returned NULL"); librdf_free_world(rdf_world); } else ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "librdf_new_world returned NULL"); return ret; }
/* This function parses the http-response headers from a backend system. We want to find out if the response-header has a a) Set-Cookie header which should be stored to the session store b) Set-Cookie header which is configured as "free" cookie c) Set-Cookie header which has a special meaning to us (Auth=ok) */ static apr_status_t mod_but_output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) { apr_int64_t i; int shmoffsetnew; char *pshm_offset_number; apr_port_t port = 0; char *host = NULL; char *all_shm_space_used_url = NULL; const char *protocol, *ssl_session_id, *ssl_cipher; request_rec *r = f->r; mod_but_server_t *config = ap_get_module_config(r->server->module_config, &but_module); cookie_res *cr = apr_palloc(r->pool, sizeof(cookie_res)); cr->r = r; cr->cookie = NULL; apr_int64_t num_set_cookie; port = ap_get_server_port (r); if ((port != 80) && (port != 443)) { /* because of multiple passes through don't use r->hostname() */ host = (char *)apr_psprintf(r->pool, "%s:%d", ap_get_server_name (r), port); } else { host = (char *)apr_psprintf(r->pool, "%s", ap_get_server_name (r)); } protocol = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r, apr_pstrdup(r->pool, "SSL_PROTOCOL") ); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: SSL_PROTOCOL [%s]", protocol); ssl_session_id = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r, apr_pstrdup(r->pool, "SSL_SESSION_ID") ); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: SSL_SESSION_ID [%s]", ssl_session_id); ssl_cipher = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r, apr_pstrdup(r->pool, "SSL_CIPHER") ); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: SSL_CIPHER [%s]", ssl_cipher); /* This checks if the response has a Set-Cookie set. There could be a) NO Set-Cookie in response-header b) LOGON Set-Cookie in response-header c) FREE COOKIE in response-header d) Other's Cookies in response-header (belonging into session store) */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: Calling apr_table_do(mod_but_analyze_response_headers)"); /* Do Header Parsing for all Response Headers. We are looking for a) MOD_BUT SESSION b) FREE COOKIES c) SERVICE_LIST COOKIES d) OTHER COOKIES */ apr_table_set(r->notes, "NUM_SET_COOKIE", "0"); apr_table_do(mod_but_analyze_response_headers, cr, r->headers_out, NULL); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED MOD_BUT_ANALYZE_RESPONSE_HEADER"); /* Unsetting all Set-Cookie Headers from Response (All but MOD_BUT_SESSION) */ apr_table_unset(r->headers_out, "Set-Cookie"); apr_table_unset(r->err_headers_out, "Set-Cookie"); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: P1: UNSETTING ALL RESPONSE HEADERS"); /* Setting FREE Cookies into the Response Header manually */ num_set_cookie = apr_atoi64(apr_table_get(r->notes, "NUM_SET_COOKIE")); for (i = 1; i <= num_set_cookie; i++) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: FOR LOOP -- NUM_SET_COOKIE IS [%s]", apr_table_get(r->notes, "NUM_SET_COOKIE")); ap_log_rerror(PC_LOG_INFO, r, "mod_but: VALUE IS [%s]", apr_table_get(r->notes, apr_itoa(r->pool, i))); apr_table_set(r->headers_out, "Set-Cookie", apr_table_get(r->notes, apr_itoa(r->pool, i))); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: P2: SETTING FREE COOKIES INTO THE RESPONSE"); } /* If apr_table_do detected a LOGON=ok Set-Cookie Header, There will be a r->notes about it. Otherwise r->notes is empty. */ if (apr_table_get(r->notes, "LOGON_STATUS") != NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: LOGON STATUS = [%s]", apr_table_get(r->notes, "LOGON_STATUS")); i = apr_atoi64(apr_table_get(r->notes, "SHMOFFSET")); ap_log_rerror(PC_LOG_INFO, r, "mod_but: VOR renew_mod_but_session in mod_but.c"); shmoffsetnew = renew_mod_but_session(i, r); if (shmoffsetnew == -1) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with SHM Creation, DECLINED"); apr_table_unset(r->headers_out, "Set-Cookie"); apr_table_unset(r->err_headers_out, "Set-Cookie"); if (apr_strnatcmp(ssl_session_id,"")){ all_shm_space_used_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->all_shm_space_used_url ); } else { all_shm_space_used_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->all_shm_space_used_url ); } apr_table_setn(r->err_headers_out, "Location", all_shm_space_used_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED ALL_SHM_SPACE_USED"); r->content_type = NULL; return OK; } if (shmoffsetnew == -2) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with SID Creation, DECLINED"); ap_log_rerror(PC_LOG_INFO, r, "mod_but: END OF OUTPUT FILTER"); //return 2400; return OK; } ap_log_rerror(PC_LOG_INFO, r, "mod_but: OUTPUT FILTER: SHMOFFSET BEFORE [%s]", apr_table_get(r->notes, "SHMOFFSET")); /* This is the runtime fix, so that the other stuff will have the correct SHMOFFSET. renew_mod_but_session returned the new SHMOFFST we have to put into r->notes */ pshm_offset_number = apr_itoa(r->pool, shmoffsetnew); apr_table_set(r->notes, "SHMOFFSET", pshm_offset_number); ap_log_rerror(PC_LOG_INFO, r, "mod_but: END OF OUTPUT FILTER"); } if (apr_table_get(r->notes, "CS_SHM") != NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with SHM Cookie Store - ALERT - No space left in SHM Cookiestore to include a processing header"); } ap_log_rerror(PC_LOG_CRIT, r, "mod_but: P3: BEFORE REMOVE OUTPUT FILTER"); ap_remove_output_filter(f); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: P4: AFTER REMOVE OUTPUT FILTER & BEFORE AP_PASS_BRIGADE"); return ap_pass_brigade(f->next, bb_in); }
static int but_access(request_rec *r) { // pcre (is session free url) pcre *re = NULL; // the regular expression const char *error; // error text for the failed regex compilation int error_offset; // offset of the regex compilation error, if any int rc = 0; // return code of pcre_exec int re_vector[3072]; // pcre (session_renew in url) pcre *re6 = NULL; // the regular expression const char *error6; // error text for the failed regex compilation int error_offset6; // offset of the regex compilation error, if any int rc6 = 0; // return code of pcre_exec int re_vector6[3072]; // firsturl pcre pcre *re4 = NULL; // the regular expression const char *error4; // error text for the failed regex compilation int error_offset4; // offset of the regex compilation error, if any int rc4 = 0; // return code of pcre_exec int re_vector4[3072]; //firsturl pcre pcre *re5 = NULL; // the regular expression //const char *error5; // error text for the failed regex compilation //int error_offset5; // offset of the regex compilation error, if any int rc5 = 0; // return code of pcre_exec int re_vector5[3072]; // rc = return codes static int rc1 = 0; apr_status_t rc2 = 0; static int rc3 = 0; // shared memory settings int shmoffset = 0; static apr_rmm_t *cs_rmm = NULL; static apr_rmm_off_t *off = NULL; cookie_res *cr; // configuration mod_but const char *cookie_try; char *pshm_offset_number; mod_but_cookie *c; mod_but_dir_t *dconfig; apr_port_t port = 0; char *host = NULL; char *no_cookie_support_url = NULL; char *session_destroy_url = NULL; char *all_shm_space_used_url = NULL; char *default_url = NULL; char *session_expired_url = NULL; char *session_inactivity_timeout_url = NULL; char *session_firsturl = NULL; char *logon_server_url = NULL; char *global_logon_server_url = NULL; char *global_logon_server_url_1 = NULL; char *global_logon_server_url_2 = NULL; char *service_list_error_url = NULL; char *orig_url_before_logon = NULL; char *session_hacking_attempt_url = NULL; ap_log_rerror(PC_LOG_CRIT, r, "mod_but: START"); const char *protocol, *ssl_session_id, *ssl_cipher; mod_but_server_t *config = ap_get_module_config(r->server->module_config, &but_module); if (config == NULL) { return (int)apr_pstrcat(r->pool, "Illegal server record", NULL, NULL); } // get per-directory configuration dconfig = ap_get_module_config(r->per_dir_config, &but_module); if (dconfig == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Illegal Directory Config"); } if (!config->enabled) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: mod_but_enabled is not activated"); return DECLINED; } ap_log_rerror(PC_LOG_INFO, r, "mod_but: ========= START V1.0 =========== mod_but hook is executed by apache core"); ap_log_rerror(PC_LOG_INFO, r, "mod_but: Request %s", r->uri); port = ap_get_server_port (r); if ((port != 80) && (port != 443)) { /* because of multiple passes through don't use r->hostname() */ host = (char *)apr_psprintf(r->pool, "%s:%d", ap_get_server_name (r), port); } else { host = (char *)apr_psprintf(r->pool, "%s", ap_get_server_name (r)); } protocol = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r, apr_pstrdup(r->pool, "SSL_PROTOCOL") ); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: SSL_PROTOCOL [%s]", protocol); ssl_session_id = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r, apr_pstrdup(r->pool, "SSL_SESSION_ID") ); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: SSL_SESSION_ID [%s]", ssl_session_id); ssl_cipher = (char *)ssl_var_lookup(r->pool, r->server, r->connection, r, apr_pstrdup(r->pool, "SSL_CIPHER") ); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: SSL_CIPHER [%s]", ssl_cipher); /****************************** PART 1 ******************************************************* Check if mod_but session is required for the requesting URI */ /* The var session_free_url implements a regexp for all URL's, for which mod_but does not require a valid session */ if(config->session_free_url != NULL){ re = pcre_compile(config->session_free_url, 0, &error, &error_offset, NULL); }else{ ap_log_rerror(PC_LOG_INFO, r, "mod_but: PCRE FREE URL STRING IS NULL"); } if (re == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: return code of pcre_compile is NULL"); } rc = pcre_exec(re, NULL, r->uri, strlen(r->uri), 0, 0, re_vector, 3072); // BUT-0: session required (goto BUT-1) if (rc < 0 && rc != PCRE_ERROR_NOMATCH) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: %s ID is required for this URI = %s", config->cookie_name, r->uri); } if (rc == 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: PCRE output vector too small (%d)", 3072/3-1); ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with the following URI = %s", r->uri); return DECLINED; } // session not required if (rc > 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: SESSION FREE URL [%s] - [%s]", config->cookie_name, r->uri); /* Renew Session if in URI is defined as RENEW_URI */ if(config->session_renew_url != NULL){ re6 = pcre_compile(config->session_renew_url, 0, &error6, &error_offset6, NULL); }else{ ap_log_rerror(PC_LOG_INFO, r, "mod_but: PCRE FREE URL STRING IS NULL"); } if (re6 == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: return code of pcre_compile is NULL"); } rc6 = pcre_exec(re6, NULL, r->uri, strlen(r->uri), 0, 0, re_vector6, 3072); if (rc6 < 0 && rc6 != PCRE_ERROR_NOMATCH) { // renew url not found ap_log_rerror(PC_LOG_INFO, r, "mod_but: Renew URL is not called"); } if (rc6 == 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: PCRE output vector too small (%d)", 3072/3-1); ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with the following URI = %s", r->uri); return DECLINED; } if (rc6 > 0) { // renew url found!! ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: RENEW SESSION, because RENEW URL [%s] - [%s]", config->cookie_name, r->uri); shmoffset = create_new_mod_but_session(r); if (shmoffset == -1) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with SHM Creation, DECLINED"); if (config->all_shm_space_used_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: MOD_BUT_ALL_SHM_SPACE_USED_URL not configured in httpd.conf"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ all_shm_space_used_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->all_shm_space_used_url ); } else { all_shm_space_used_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->all_shm_space_used_url ); } apr_table_setn(r->err_headers_out, "Location", all_shm_space_used_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED ALL_SHM_SPACE_USED_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (shmoffset == -2) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with SID Creation, DECLINED"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ default_url = (char *)apr_psprintf(r->pool, "https://%s/", host); } else { default_url = (char *)apr_psprintf(r->pool, "http://%s/", host); } apr_table_setn(r->err_headers_out, "Location", default_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED DEFAULT_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED RENEW URL"); return DECLINED; } /****************************** PART 2 ******************************************************* Check of the mod_but session a) mod_but session is not sent by client b) mod_but session sent is invalid c) mod_but session sent is ok The code below will only be executed, if the requesting URI requires a mod_but session (status regexp < 0) */ /* BUT-1 (comming from BUT-0) -> session is required Here we will first parse the request headers for a) MOD_BUT_SESSION (will be unset, because we don't want to have it in the backend) b) FREE COOKIES (will be accepted, if configured in httpd.conf) c) OTHER COOKIES (will be unset) */ if (apr_table_get(r->notes, config->cookie_name)) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: GET SESSION FROM r->notes [%s]", apr_table_get(r->notes, config->cookie_name)); } else { ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: DO INITIAL HEADER PARSING r->notes [%s]", apr_table_get(r->notes, config->cookie_name)); cr = apr_palloc(r->pool, sizeof(cookie_res)); cr->r = r; cr->cookie = NULL; apr_table_do(mod_but_analyze_request_headers, cr, r->headers_in, NULL); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: mod_but_analyze_request_headers finished"); } ap_log_rerror(PC_LOG_INFO, r, "mod_but: SESSION [%s]", apr_table_get(r->notes, config->cookie_name)); if (apr_table_get(r->notes, config->cookie_name) == NULL) { /* This is PART 2 a) mod_but session is not sent by client */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE: CLIENT DID NOT SEND MOD_BUT_SESSION)"); shmoffset = create_new_mod_but_session(r); if (shmoffset == -1) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with SHM Creation, DECLINED"); if (config->all_shm_space_used_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: MOD_BUT_ALL_SHM_SPACE_USED_URL not configured in httpd.conf"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ all_shm_space_used_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->all_shm_space_used_url ); } else { all_shm_space_used_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->all_shm_space_used_url ); } apr_table_setn(r->err_headers_out, "Location", all_shm_space_used_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED ALL_SHM_SPACE_USED_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (shmoffset == -2) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with SID Creation, DECLINED"); return HTTP_INTERNAL_SERVER_ERROR; } /* If client did not send a MOD_BUT session return code rc1 of analyze_request_arguments_for_cookie_test(r) 9900: first client request without __cookie_try in query 9901: second client request with __cookie_try=1 in query 9902: third client request with __cookie_try=2 in query 9903: fouth client request with __cookie_try=3 in query, Redirect to error page 9904: DECLINED */ rc1 = analyze_request_arguments_for_cookie_test(r); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: RETURN VALUE OF COOKIE_TEST ROUTINE %d", rc1); cookie_try = NULL; ap_log_rerror(PC_LOG_INFO, r, "mod_but: rc1 is %d", rc1); // NO COOKIE_TRY in URL if (rc1 == 9900){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: rc1 = 9900 aufgerufen"); //TODO BUT: Use absolute URI for redirection re5 = pcre_compile("\r\n", 0, &error4, &error_offset4, NULL); if (re5 == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: return code of pcre_compile is NULL"); } rc5 = pcre_exec(re5, NULL, r->uri, strlen(r->uri), 0, 0, re_vector5, 3072); if (rc5 < 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: r->uri does not contain CR/LF [%s]", r->uri); if (apr_strnatcmp(ssl_session_id,"")){ cookie_try = (char *)apr_psprintf(r->pool, "https://%s%s?__cookie_try=1", host, r->uri); // uri starts with a "/" } else { cookie_try = (char *)apr_psprintf(r->pool, "http://%s%s?__cookie_try=1", host, r->uri); // uri starts with a "/" } apr_table_setn(r->err_headers_out, "Location", cookie_try); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED COOKIE_TRY; CLIENT SENT R WITHOUT SESSION; REDIRECT TO COOKIE_TRY"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (rc5 < 0 && rc5 != PCRE_ERROR_NOMATCH) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: r->uri does not contain CR/LF [%s]", r->uri); } if (rc5 == 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: PCRE output vector too small (%d)", 3072/3-1); ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with pcre CRLF = %s", r->uri); return DECLINED; } if (rc5 > 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: ATTACK!!!! r->uri contains CR/LF [%s]", r->uri); apr_table_setn(r->err_headers_out, "Location", "file:///C:\\<script>alert('Hacking?')</script>"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } } // 1 COOKIE_TRY in URL if (rc1 == 9901){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: rc1 = 9901 aufgerufen"); //TODO BUT: Use absolute URI for redirection if (apr_strnatcmp(ssl_session_id,"")){ cookie_try = (char *)apr_psprintf(r->pool, "https://%s%s?__cookie_try=2", host, r->uri); // uri starts with a "/" } else { cookie_try = (char *)apr_psprintf(r->pool, "http://%s%s?__cookie_try=2", host, r->uri); // uri starts with a "/" } //cookie_try = (char *)apr_psprintf(r->pool, "%s?__cookie_try=2", r->uri); apr_table_setn(r->err_headers_out, "Location", cookie_try); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED COOKIE_TRY=2"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } // 2 COOKIE_TRY in URL if (rc1 == 9902){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: rc1 = 9902 aufgerufen"); //TODO BUT: Use absolute URI for redirection if (apr_strnatcmp(ssl_session_id,"")){ cookie_try = (char *)apr_psprintf(r->pool, "https://%s%s?__cookie_try=3", host, r->uri); // uri starts with a "/" } else { cookie_try = (char *)apr_psprintf(r->pool, "http://%s%s?__cookie_try=3", host, r->uri); // uri starts with a "/" } //cookie_try = (char *)apr_psprintf(r->pool, "%s?__cookie_try=3", r->uri); apr_table_setn(r->err_headers_out, "Location", cookie_try); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED COOKIE_TRY=3"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } // 3 COOKIE_TRY in URL if (rc1 == 9903){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: rc1 = 9903 aufgerufen"); if (apr_strnatcmp(ssl_session_id,"")){ no_cookie_support_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->client_refuses_cookies_url ); } else { no_cookie_support_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->client_refuses_cookies_url ); } apr_table_setn(r->err_headers_out, "Location", no_cookie_support_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED NO_COOKIE_SUPPORT_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } // DECLINED if (rc1 == 9904){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: rc1 = 9904 aufgerufen"); return DECLINED; } }else{ /* If we are here, the client has sent a mod_but session (valid or invalid) */ /* Check if Client Cookie is valid (and in SHM) */ int shm_offset_number = validation_of_client_sent_session(r); ap_log_rerror(PC_LOG_INFO, r, "mod_but: Offset Number is %d", shm_offset_number); if (shm_offset_number == -5540){ /* In this case, the sent session has reached its time out */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: Session timeout reached"); if (config->session_expired_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: MOD_BUT_SESSION_TIMEOUT_URL not configured in httpd.conf"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ session_expired_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->session_expired_url ); } else { session_expired_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->session_expired_url ); } apr_table_setn(r->err_headers_out, "Location", session_expired_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED SESSION_EXPIRED"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (shm_offset_number == -5541){ /* In this case, the sent session has reached its inactivity timeout */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: Session inactivity timeout reached"); if (config->session_inactivity_timeout_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: MOD_BUT_SESSION_INACTIVITY_TIMEOUT_URL not configured in httpd.conf"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ session_inactivity_timeout_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->session_inactivity_timeout_url ); } else { session_inactivity_timeout_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->session_inactivity_timeout_url ); } apr_table_setn(r->err_headers_out, "Location", session_inactivity_timeout_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED SESSION_INACTIVITY_TIMEOUT_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (shm_offset_number == -5542){ /* In this case, the sent session was in the history cache */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: Session found in history"); if (config->session_expired_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: MOD_BUT_SESSION_TIMEOUT_URL not configured in httpd.conf"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ session_expired_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->session_expired_url ); } else { session_expired_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->session_expired_url); } apr_table_setn(r->err_headers_out, "Location", session_expired_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED_SESSION_EXPIRED_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (shm_offset_number == -5543){ /* In this case, the sent session by the client is invalid, guessed, hacked or a shm error on our side */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: -5543 Invalid Session sent by the client"); ap_log_rerror(PC_LOG_INFO, r, "mod_but: config->session_hacking_attempt_url = [%s]", config->session_hacking_attempt_url); if (config->session_hacking_attempt_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: MOD_BUT_SESSION_HACKING_ATTEMPT_URL not configured in httpd.conf"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ session_hacking_attempt_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->session_hacking_attempt_url ); } else { session_hacking_attempt_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->session_hacking_attempt_url); } apr_table_setn(r->err_headers_out, "Location", session_hacking_attempt_url); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (shm_offset_number < 0){ /* In this case, something went wrong with the return code */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: CRITICAL ERROR shm_offset_number < 0 "); if (config->session_hacking_attempt_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: MOD_BUT_SESSION_HACKING_ATTEMPT_URL not configured in httpd.conf"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ session_hacking_attempt_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->session_hacking_attempt_url ); } else { session_hacking_attempt_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->session_hacking_attempt_url); } apr_table_setn(r->err_headers_out, "Location", session_hacking_attempt_url); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } /* If we are here, the client has sent a valid mod_but session */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: CLIENT SENT VALID MOD_BUT_SESSION"); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: CLIENT SENT VALID MOD_BUT SESSION"); /* We will first check, if the requesting URI asks for the session destroy function This implements the "logout" functionality. */ rc2 = analyze_request_uri_for_session_destroy(r); if (rc2 == 8800){ ap_log_rerror(PC_LOG_INFO, r, "mod_but.c: destroy pattern was not in URI = %s", r->uri); } if (rc2 == 8801){ ap_log_rerror(PC_LOG_INFO, r, "mod_but.c: Problems with the following URI = %s", r->uri); } if (rc2 == 8802){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: SESSION will be destroyed"); delete_mod_but_session(shm_offset_number, r); if (apr_strnatcmp(ssl_session_id,"")){ session_destroy_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->session_destroy_url); } else { session_destroy_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->session_destroy_url); } apr_table_setn(r->err_headers_out, "Location", session_destroy_url); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } /* If we are here, the requesting URI does not want to be destroyed and we analyze the request for the cookie_tests. If we are still in the cookie test phase, we have to give the client the Original URI (from the first request) as redirect */ pshm_offset_number = apr_itoa(r->pool, shm_offset_number); if (pshm_offset_number == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: pshm_offset_number is null!!!"); return HTTP_INTERNAL_SERVER_ERROR; } ap_log_rerror(PC_LOG_INFO, r, "mod_but: WRITE APR: r->notes SHMOFFSET [%s]", pshm_offset_number); apr_table_set(r->notes, "SHMOFFSET", pshm_offset_number); ap_log_rerror(PC_LOG_INFO, r, "mod_but: VOR analyze_request_arguments_for_cookie_test"); rc1 = analyze_request_arguments_for_cookie_test(r); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: RETURN VALUE OF COOKIE_TEST ROUTINE WHEN SESSION IS VALID %d", rc1); ap_log_rerror(PC_LOG_INFO, r, "mod_but: NACH analyze_request_arguments_for_cookie_test"); cs_rmm = find_cs_rmm(); off = find_cs_rmm_off(); c = apr_rmm_addr_get(cs_rmm, off[shm_offset_number]); // cookie is sent by the client, it is a valid session and the requesting URL contains a COOKIE TRY parameter if ((rc1 == 9901)||(rc1 == 9902)||(rc1 == 9903)){ if (c->session_firsturl == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: c->session_firsturl is empty"); return HTTP_INTERNAL_SERVER_ERROR; } ap_log_rerror(PC_LOG_CRIT, r, "mod_but: CLIENT SESSION IS VALID AND COOKIE_TRY IN URL"); re4 = pcre_compile("\r\n", 0, &error4, &error_offset4, NULL); if (re4 == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: return code of pcre_compile is NULL"); } rc4 = pcre_exec(re4, NULL, r->uri, strlen(r->uri), 0, 0, re_vector4, 3072); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: Rc4 contains %d",rc4); if (rc4 < 0) { ap_log_rerror(PC_LOG_CRIT, r, "mod_but: r->uri does not contain CR/LF [%s]", r->uri); if (apr_strnatcmp(ssl_session_id,"")){ session_firsturl = (char *)apr_psprintf(r->pool, "https://%s%s", host, c->session_firsturl); } else { session_firsturl = (char *)apr_psprintf(r->pool, "http://%s%s", host, c->session_firsturl); } apr_table_setn(r->err_headers_out, "Location", session_firsturl); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED_SESSION_FIRSTURL"); r->content_type = NULL; ap_log_rerror(PC_LOG_CRIT, r, "mod_but: AAAAAAAAAAAAAAAA FURSTURL %s", session_firsturl); return HTTP_MOVED_TEMPORARILY; } if (rc4 < 0 && rc4 != PCRE_ERROR_NOMATCH) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: r->uri does not contain CR/LF [%s]", r->uri); if (apr_strnatcmp(ssl_session_id,"")){ session_firsturl = (char *)apr_psprintf(r->pool, "https://%s%s", host, c->session_firsturl); } else { session_firsturl = (char *)apr_psprintf(r->pool, "http://%s%s", host, c->session_firsturl); } apr_table_setn(r->err_headers_out, "Location", session_firsturl); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED_SESSION_FIRSTURL"); r->content_type = NULL; ap_log_rerror(PC_LOG_CRIT, r, "mod_but: AAAAAAAAAAAAAAAA FURSTURL %s", session_firsturl); return HTTP_MOVED_TEMPORARILY; } if (rc4 == 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: PCRE output vector too small (%d)", 3072/3-1); ap_log_rerror(PC_LOG_INFO, r, "mod_but: Problems with pcre CRLF = %s", r->uri); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: BBBBBBBBBBBBBBBBBB"); return DECLINED; } if (rc4 > 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: ATTACK!!!! r->uri contains CR/LF [%s]", r->uri); apr_cpystrn(c->session_firsturl, "ATTACK", sizeof(c->session_firsturl)); apr_table_setn(r->err_headers_out, "Location", session_firsturl); r->content_type = NULL; ap_log_rerror(PC_LOG_CRIT, r, "mod_but: CCCCCCCCCCCCCCCCC"); return HTTP_MOVED_TEMPORARILY; } } ap_log_rerror(PC_LOG_CRIT, r, "mod_but: IF WE ARE HERE, THE REQUEST WILL BE AUTHORIZED (NO COOKIE TRY IN URL)"); /* Now let's do the authorization stuff, if enabled by config */ if (config->authorization_enabled) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Authorization checks are enabled"); rc3 = do_authorization(shm_offset_number, r); /* if return code 7700: client not logged in yet 7701: client is properly authenticated 7702: authentication is not required for this url 7703: client is properly authenticated, but not authorized 7704: client is properly authenticated, but with too low auth_strength (1) 7705: client is properly authenticated, but with too low auth_strength (2) 7706: DECLINED */ if (rc3 == 7700) { /* If we are here, the requesting URI requires authentication and the client is not logged in yet. */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: URI requres auth, but user not logged in yet"); ap_log_rerror(PC_LOG_INFO, r, "mod_but: Client is not logged in"); ap_log_rerror(PC_LOG_INFO, r, "mod_but: orig_url [%s]", c->orig_url_before_logon); apr_cpystrn(c->orig_url_before_logon, r->uri, sizeof(c->orig_url_before_logon)); ap_log_rerror(PC_LOG_INFO, r, "mod_but: CORE SET ORIG_URL TO %s", c->orig_url_before_logon); c->logon_flag=1; ap_log_rerror(PC_LOG_INFO, r, "mod_but: Set logon_flag to[%d]", c->logon_flag); if (dconfig->logon_server_url){ /* If we are here, a Login SERVER is configured for this Location */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: Our Dir Config is [%s]", dconfig->logon_server_url); if (dconfig->logon_server_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: dconfig->logon_server_url is empty"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ logon_server_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, dconfig->logon_server_url); } else { logon_server_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, dconfig->logon_server_url); } apr_table_setn(r->err_headers_out, "Location", logon_server_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED LOGON_SERVER_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; }else{ /* If we are here, no LOGIN SERVER is configured for this Location */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: NULL Our Dir Config is [%s]", dconfig->logon_server_url); if (config->global_logon_server_url == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: config->global_logon_server_url is empty"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ global_logon_server_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->global_logon_server_url); } else { global_logon_server_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->global_logon_server_url); } apr_table_setn(r->err_headers_out, "Location", global_logon_server_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED GLOBAL_LOGON_SERVER_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } } if (rc3 == 7701) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: client is properly authenticated"); } if (rc3 == 7702) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: authentication is not required for this url"); } if (rc3 == 7703) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Client ist properly authenticated, but not allowed to request the url"); if (apr_strnatcmp(ssl_session_id,"")){ service_list_error_url = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->service_list_error_url); } else { service_list_error_url = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->service_list_error_url); } apr_table_setn(r->err_headers_out, "Location", service_list_error_url); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED SERVICE_LIST_ERROR_URL"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (rc3 == 7704) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Client authenticated, but auth_strength is too low"); if (config->global_logon_server_url_1 == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: config->global_logon_server_url_1 is empty"); return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ global_logon_server_url_1 = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->global_logon_server_url_1); } else { global_logon_server_url_1 = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->global_logon_server_url_1); } apr_table_setn(r->err_headers_out, "Location", global_logon_server_url_1); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED GLOBAL_LOGON_SERVER_URL 1"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (rc3 == 7705) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: Client authenticated, but auth_strength is too low"); if (config->global_logon_server_url_2 == NULL ){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: config->global_logon_server_url_2 is empty"); r->content_type = NULL; return HTTP_INTERNAL_SERVER_ERROR; } if (apr_strnatcmp(ssl_session_id,"")){ global_logon_server_url_2 = (char *)apr_psprintf(r->pool, "https://%s%s", host, config->global_logon_server_url_2); } else { global_logon_server_url_2 = (char *)apr_psprintf(r->pool, "http://%s%s", host, config->global_logon_server_url_2); } apr_table_setn(r->err_headers_out, "Location", global_logon_server_url_2); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED GLOBAL_LOGON_SERVER_URL 2"); r->content_type = NULL; return HTTP_MOVED_TEMPORARILY; } if (rc3 == 7706) { ap_log_rerror(PC_LOG_INFO, r, "mod_but: service_list PCRE output vector too small"); return DECLINED; } }else{ ap_log_rerror(PC_LOG_INFO, r, "mod_but: Authorization checks are disabled or LOGON is not required"); } /* If we are here, the client is properly authenticated and we start proceeding the request. */ /* This is the callback function, if the user was previously successfully authenticated and the c->logon_flag = 1. The flag was set to 1 couple of lines above, if uri requires authentication but is not authenticated yet. we need to redirect the client to the OrigURL (initial uri, before authentication) */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: LOGON_FLAG [%d]", c->logon_flag); ap_log_rerror(PC_LOG_INFO, r, "mod_but: LOGON_STATE [%d]", c->logon_state); if (c->logon_flag == 1 && c->logon_state == 1){ if (c->orig_url_before_logon != NULL){ ap_log_rerror(PC_LOG_INFO, r, "mod_but: SEND REDIRECT AFTER SUCCESSFUL LOGON"); ap_log_rerror(PC_LOG_INFO, r, "mod_but: REDIRECT TO OrigURL: [%s]", c->orig_url_before_logon); if (apr_strnatcmp(ssl_session_id,"")){ orig_url_before_logon = (char *)apr_psprintf(r->pool, "https://%s%s", host, c->orig_url_before_logon); } else { orig_url_before_logon = (char *)apr_psprintf(r->pool, "http://%s%s", host, c->orig_url_before_logon); } apr_table_setn(r->err_headers_out, "Location", orig_url_before_logon); ap_log_rerror(PC_LOG_CRIT, r, "mod_but: FINISHED ORIG_URL BEFORE LOGON"); r->content_type = NULL; c->logon_flag=0; return HTTP_MOVED_TEMPORARILY; }else{ ap_log_rerror(PC_LOG_INFO, r, "mod_but: PROBLEM: ORIG_URL is empty"); } }else{ ap_log_rerror(PC_LOG_INFO, r, "mod_but: LOGON_FLAG or LOGON_STATE 0"); } /* If the cookiestore has some "values", we will include them into the request header ADD Headers into the backend request */ if (c->link_to_cookiestore != -1){ add_headers_into_request_from_cookiestore(r, c->link_to_cookiestore); // now all cookies from the cookiestore are within the r->notes REQUEST_COOKIES if (apr_table_get(r->notes, "REQUEST_COOKIES") != NULL) { apr_table_set(r->headers_in, "Cookie", apr_table_get(r->notes, "REQUEST_COOKIES")); } } /* Ok now we will proceed with the request */ ap_log_rerror(PC_LOG_INFO, r, "mod_but: ========= STOP =========== mod_but hook is executed by apache core"); return OK; } return OK; }
static void vhost_alias_interpolate(request_rec *r, mva_sconf_t *conf, const char *name, const char *map, const char *uri) { /* 0..9 9..0 */ enum { MAXDOTS = 19 }; const char *dots[MAXDOTS+1]; int ndots; char buf[HUGE_STRING_LEN]; char *dest; const char *docroot; int N, M, Np, Mp, Nd, Md; const char *start, *end; const char *p; ndots = 0; dots[ndots++] = name-1; /* slightly naughty */ for (p = name; *p; ++p){ if (*p == '.' && ndots < MAXDOTS) { dots[ndots++] = p; } } dots[ndots] = p; r->filename = NULL; dest = buf; while (*map) { if (*map != '%') { /* normal characters */ vhost_alias_checkspace(r, buf, &dest, 1); *dest++ = *map++; continue; } /* we are in a format specifier */ ++map; /* %% -> % */ if (*map == '%') { ++map; vhost_alias_checkspace(r, buf, &dest, 1); *dest++ = '%'; continue; } /* port number */ if (*map == 'p') { ++map; /* no. of decimal digits in a short plus one */ vhost_alias_checkspace(r, buf, &dest, 7); dest += apr_snprintf(dest, 7, "%d", ap_get_server_port(r)); continue; } /* deal with %-N+.-M+ -- syntax is already checked */ M = 0; /* value */ Np = Mp = 0; /* is there a plus? */ Nd = Md = 0; /* is there a dash? */ if (*map == '-') ++map, Nd = 1; N = *map++ - '0'; if (*map == '+') ++map, Np = 1; if (*map == '.') { ++map; if (*map == '-') { ++map, Md = 1; } M = *map++ - '0'; if (*map == '+') { ++map, Mp = 1; } } /* note that N and M are one-based indices, not zero-based */ start = dots[0]+1; /* ptr to the first character */ end = dots[ndots]; /* ptr to the character after the last one */ if (N != 0) { if (N > ndots) { start = "_"; end = start+1; } else if (!Nd) { start = dots[N-1]+1; if (!Np) { end = dots[N]; } } else { if (!Np) { start = dots[ndots-N]+1; } end = dots[ndots-N+1]; } } if (M != 0) { if (M > end - start) { start = "_"; end = start+1; } else if (!Md) { start = start+M-1; if (!Mp) { end = start+1; } } else { if (!Mp) { start = end-M; } end = end-M+1; } } vhost_alias_checkspace(r, buf, &dest, end - start); for (p = start; p < end; ++p) { *dest++ = apr_tolower(*p); } } /* no double slashes */ if (dest - buf > 0 && dest[-1] == '/') { --dest; } *dest = '\0'; /* * A this point we either have a document root which points to something * on disk - or not. * * If the document root doesn't exist on disk we can *attempt* to remap * that to the real file. * * If this remapping fails we don't care as the result will be a 404, * and that would have happened anyway. * */ { struct stat buffer; /** * If we have: * * A document root * Which doesn't exist. * * Then: * * Attempt to fix. * */ if ( ( NULL != buf ) && ( stat( buf, &buffer ) < 0 ) ) { /** * Here we strip out the first part of the name * after the /srv prefix which will result in * a request being rewritten from (for example) * * /srv/test.example.com/public/htdocs * * to: * * /srv/example.com/public/htdocs * */ update_vhost_request( buf ); } } if (r->filename) docroot = apr_pstrcat(r->pool, r->filename, buf, NULL); else docroot = apr_pstrdup(r->pool, buf); r->filename = apr_pstrcat(r->pool, docroot, uri, NULL); ap_set_context_info(r, NULL, docroot); ap_set_document_root(r, docroot); }
static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, const char *uri, apr_uri_t *parsed_uri, const char **key) { cache_server_conf *conf; char *port_str, *hn, *lcs; const char *hostname, *scheme; int i; const char *path; char *querystring; if (*key) { /* * We have been here before during the processing of this request. */ return APR_SUCCESS; } /* * Get the module configuration. We need this for the CacheIgnoreQueryString * option below. */ conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, &cache_module); /* * Use the canonical name to improve cache hit rate, but only if this is * not a proxy request or if this is a reverse proxy request. * We need to handle both cases in the same manner as for the reverse proxy * case we have the following situation: * * If a cached entry is looked up by mod_cache's quick handler r->proxyreq * is still unset in the reverse proxy case as it only gets set in the * translate name hook (either by ProxyPass or mod_rewrite) which is run * after the quick handler hook. This is different to the forward proxy * case where it gets set before the quick handler is run (in the * post_read_request hook). * If a cache entry is created by the CACHE_SAVE filter we always have * r->proxyreq set correctly. * So we must ensure that in the reverse proxy case we use the same code * path and using the canonical name seems to be the right thing to do * in the reverse proxy case. */ if (!r->proxyreq || (r->proxyreq == PROXYREQ_REVERSE)) { if (conf->base_uri && conf->base_uri->hostname) { hostname = conf->base_uri->hostname; } else { /* Use _default_ as the hostname if none present, as in mod_vhost */ hostname = ap_get_server_name(r); if (!hostname) { hostname = "_default_"; } } } else if (parsed_uri->hostname) { /* Copy the parsed uri hostname */ hn = apr_pstrdup(p, parsed_uri->hostname); ap_str_tolower(hn); /* const work-around */ hostname = hn; } else { /* We are a proxied request, with no hostname. Unlikely * to get very far - but just in case */ hostname = "_default_"; } /* * Copy the scheme, ensuring that it is lower case. If the parsed uri * contains no string or if this is not a proxy request get the http * scheme for this request. As r->parsed_uri.scheme is not set if this * is a reverse proxy request, it is ensured that the cases * "no proxy request" and "reverse proxy request" are handled in the same * manner (see above why this is needed). */ if (r->proxyreq && parsed_uri->scheme) { /* Copy the scheme and lower-case it */ lcs = apr_pstrdup(p, parsed_uri->scheme); ap_str_tolower(lcs); /* const work-around */ scheme = lcs; } else { if (conf->base_uri && conf->base_uri->scheme) { scheme = conf->base_uri->scheme; } else { scheme = ap_http_scheme(r); } } /* * If this is a proxy request, but not a reverse proxy request (see comment * above why these cases must be handled in the same manner), copy the * URI's port-string (which may be a service name). If the URI contains * no port-string, use apr-util's notion of the default port for that * scheme - if available. Otherwise use the port-number of the current * server. */ if (r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) { if (parsed_uri->port_str) { port_str = apr_pcalloc(p, strlen(parsed_uri->port_str) + 2); port_str[0] = ':'; for (i = 0; parsed_uri->port_str[i]; i++) { port_str[i + 1] = apr_tolower(parsed_uri->port_str[i]); } } else if (apr_uri_port_of_scheme(scheme)) { port_str = apr_psprintf(p, ":%u", apr_uri_port_of_scheme(scheme)); } else { /* No port string given in the AbsoluteUri, and we have no * idea what the default port for the scheme is. Leave it * blank and live with the inefficiency of some extra cached * entities. */ port_str = ""; } } else { if (conf->base_uri && conf->base_uri->port_str) { port_str = conf->base_uri->port_str; } else if (conf->base_uri && conf->base_uri->hostname) { port_str = ""; } else { /* Use the server port */ port_str = apr_psprintf(p, ":%u", ap_get_server_port(r)); } } /* * Check if we need to ignore session identifiers in the URL and do so * if needed. */ path = uri; querystring = parsed_uri->query; if (conf->ignore_session_id->nelts) { int i; char **identifier; identifier = (char **) conf->ignore_session_id->elts; for (i = 0; i < conf->ignore_session_id->nelts; i++, identifier++) { int len; const char *param; len = strlen(*identifier); /* * Check that we have a parameter separator in the last segment * of the path and that the parameter matches our identifier */ if ((param = ap_strrchr_c(path, ';')) && !strncmp(param + 1, *identifier, len) && (*(param + len + 1) == '=') && !ap_strchr_c(param + len + 2, '/')) { path = apr_pstrndup(p, path, param - path); continue; } /* * Check if the identifier is in the querystring and cut it out. */ if (querystring) { /* * First check if the identifier is at the beginning of the * querystring and followed by a '=' */ if (!strncmp(querystring, *identifier, len) && (*(querystring + len) == '=')) { param = querystring; } else { char *complete; /* * In order to avoid subkey matching (PR 48401) prepend * identifier with a '&' and append a '=' */ complete = apr_pstrcat(p, "&", *identifier, "=", NULL); param = strstr(querystring, complete); /* If we found something we are sitting on the '&' */ if (param) { param++; } } if (param) { const char *amp; if (querystring != param) { querystring = apr_pstrndup(p, querystring, param - querystring); } else { querystring = ""; } if ((amp = ap_strchr_c(param + len + 1, '&'))) { querystring = apr_pstrcat(p, querystring, amp + 1, NULL); } else { /* * If querystring is not "", then we have the case * that the identifier parameter we removed was the * last one in the original querystring. Hence we have * a trailing '&' which needs to be removed. */ if (*querystring) { querystring[strlen(querystring) - 1] = '\0'; } } } } } } /* Key format is a URI, optionally without the query-string */ if (conf->ignorequerystring) { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, path, "?", NULL); } else { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, path, "?", querystring, NULL); } /* * Store the key in the request_config for the cache as r->parsed_uri * might have changed in the time from our first visit here triggered by the * quick handler and our possible second visit triggered by the CACHE_SAVE * filter (e.g. r->parsed_uri got unescaped). In this case we would save the * resource in the cache under a key where it is never found by the quick * handler during following requests. */ ap_log_rerror( APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(00698) "cache: Key for entity %s?%s is %s", uri, parsed_uri->query, *key); return APR_SUCCESS; }
AP_DECLARE(void) ap_add_common_vars(request_rec *r) { apr_table_t *e; server_rec *s = r->server; conn_rec *c = r->connection; core_dir_config *conf = (core_dir_config *)ap_get_core_module_config(r->per_dir_config); const char *env_temp; const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in); const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts; int i; apr_port_t rport; char *q; /* use a temporary apr_table_t which we'll overlap onto * r->subprocess_env later * (exception: if r->subprocess_env is empty at the start, * write directly into it) */ if (apr_is_empty_table(r->subprocess_env)) { e = r->subprocess_env; } else { e = apr_table_make(r->pool, 25 + hdrs_arr->nelts); } /* First, add environment vars from headers... this is as per * CGI specs, though other sorts of scripting interfaces see * the same vars... */ for (i = 0; i < hdrs_arr->nelts; ++i) { if (!hdrs[i].key) { continue; } /* A few headers are special cased --- Authorization to prevent * rogue scripts from capturing passwords; content-type and -length * for no particular reason. */ if (!strcasecmp(hdrs[i].key, "Content-type")) { apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val); } else if (!strcasecmp(hdrs[i].key, "Content-length")) { apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val); } /* * You really don't want to disable this check, since it leaves you * wide open to CGIs stealing passwords and people viewing them * in the environment with "ps -e". But, if you must... */ #ifndef SECURITY_HOLE_PASS_AUTHORIZATION else if (!strcasecmp(hdrs[i].key, "Authorization") || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) { if (conf->cgi_pass_auth == AP_CGI_PASS_AUTH_ON) { add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val); } } #endif else add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val); } env_temp = apr_table_get(r->subprocess_env, "PATH"); if (env_temp == NULL) { env_temp = getenv("PATH"); } if (env_temp == NULL) { env_temp = DEFAULT_PATH; } apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp)); #if defined(WIN32) env2env(e, "SystemRoot"); env2env(e, "COMSPEC"); env2env(e, "PATHEXT"); env2env(e, "WINDIR"); #elif defined(OS2) env2env(e, "COMSPEC"); env2env(e, "ETC"); env2env(e, "DPATH"); env2env(e, "PERLLIB_PREFIX"); #elif defined(BEOS) env2env(e, "LIBRARY_PATH"); #elif defined(DARWIN) env2env(e, "DYLD_LIBRARY_PATH"); #elif defined(_AIX) env2env(e, "LIBPATH"); #elif defined(__HPUX__) /* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */ env2env(e, "SHLIB_PATH"); env2env(e, "LD_LIBRARY_PATH"); #else /* Some Unix */ env2env(e, "LD_LIBRARY_PATH"); #endif apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r)); apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner()); apr_table_addn(e, "SERVER_NAME", ap_escape_html(r->pool, ap_get_server_name_for_url(r))); apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */ apr_table_addn(e, "SERVER_PORT", apr_psprintf(r->pool, "%u", ap_get_server_port(r))); add_unless_null(e, "REMOTE_HOST", ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL)); apr_table_addn(e, "REMOTE_ADDR", r->useragent_ip); apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */ apr_table_setn(e, "REQUEST_SCHEME", ap_http_scheme(r)); apr_table_addn(e, "CONTEXT_PREFIX", ap_context_prefix(r)); apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r)); apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */ if (apr_table_get(r->notes, "proxy-noquery") && (q = ap_strchr(r->filename, '?'))) { *q = '\0'; apr_table_addn(e, "SCRIPT_FILENAME", apr_pstrdup(r->pool, r->filename)); *q = '?'; } else { apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */ } rport = c->client_addr->port; apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport)); if (r->user) { apr_table_addn(e, "REMOTE_USER", r->user); } else if (r->prev) { request_rec *back = r->prev; while (back) { if (back->user) { apr_table_addn(e, "REDIRECT_REMOTE_USER", back->user); break; } back = back->prev; } } add_unless_null(e, "AUTH_TYPE", r->ap_auth_type); env_temp = ap_get_remote_logname(r); if (env_temp) { apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, env_temp)); } /* Apache custom error responses. If we have redirected set two new vars */ if (r->prev) { /* PR#57785: reconstruct full URL here */ apr_uri_t *uri = &r->prev->parsed_uri; if (!uri->scheme) { uri->scheme = (char*)ap_http_scheme(r->prev); } if (!uri->port) { uri->port = ap_get_server_port(r->prev); uri->port_str = apr_psprintf(r->pool, "%u", uri->port); } if (!uri->hostname) { uri->hostname = (char*)ap_get_server_name_for_url(r->prev); } add_unless_null(e, "REDIRECT_QUERY_STRING", r->prev->args); add_unless_null(e, "REDIRECT_URL", apr_uri_unparse(r->pool, uri, 0)); } if (e != r->subprocess_env) { apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET); } }
API_EXPORT(void) ap_add_common_vars(request_rec *r) { table *e; server_rec *s = r->server; conn_rec *c = r->connection; const char *rem_logname; char *env_path; #if defined(WIN32) || defined(OS2) char *env_temp; #endif const char *host; array_header *hdrs_arr = ap_table_elts(r->headers_in); table_entry *hdrs = (table_entry *) hdrs_arr->elts; int i; char servbuf[NI_MAXSERV]; /* use a temporary table which we'll overlap onto * r->subprocess_env later */ e = ap_make_table(r->pool, 25 + hdrs_arr->nelts); /* First, add environment vars from headers... this is as per * CGI specs, though other sorts of scripting interfaces see * the same vars... */ for (i = 0; i < hdrs_arr->nelts; ++i) { if (!hdrs[i].key) { continue; } /* A few headers are special cased --- Authorization to prevent * rogue scripts from capturing passwords; content-type and -length * for no particular reason. */ if (!strcasecmp(hdrs[i].key, "Content-type")) { ap_table_addn(e, "CONTENT_TYPE", hdrs[i].val); } else if (!strcasecmp(hdrs[i].key, "Content-length")) { ap_table_addn(e, "CONTENT_LENGTH", hdrs[i].val); } /* * You really don't want to disable this check, since it leaves you * wide open to CGIs stealing passwords and people viewing them * in the environment with "ps -e". But, if you must... */ #ifndef SECURITY_HOLE_PASS_AUTHORIZATION else if (!strcasecmp(hdrs[i].key, "Authorization") || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) { continue; } #endif else { ap_table_addn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val); } } if (!(env_path = ap_pstrdup(r->pool, getenv("PATH")))) { env_path = DEFAULT_PATH; } #ifdef WIN32 if (env_temp = getenv("SystemRoot")) { ap_table_addn(e, "SystemRoot", env_temp); } if (env_temp = getenv("COMSPEC")) { ap_table_addn(e, "COMSPEC", env_temp); } if (env_temp = getenv("WINDIR")) { ap_table_addn(e, "WINDIR", env_temp); } #endif #ifdef OS2 if ((env_temp = getenv("COMSPEC")) != NULL) { ap_table_addn(e, "COMSPEC", env_temp); } if ((env_temp = getenv("ETC")) != NULL) { ap_table_addn(e, "ETC", env_temp); } if ((env_temp = getenv("DPATH")) != NULL) { ap_table_addn(e, "DPATH", env_temp); } if ((env_temp = getenv("PERLLIB_PREFIX")) != NULL) { ap_table_addn(e, "PERLLIB_PREFIX", env_temp); } #endif ap_table_addn(e, "PATH", env_path); ap_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r)); ap_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version()); ap_table_addn(e, "SERVER_NAME", ap_escape_html(r->pool,ap_get_server_name(r))); ap_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */ ap_table_addn(e, "SERVER_PORT", ap_psprintf(r->pool, "%u", ap_get_server_port(r))); host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST); if (host) { ap_table_addn(e, "REMOTE_HOST", host); } ap_table_addn(e, "REMOTE_ADDR", c->remote_ip); ap_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */ ap_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */ ap_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */ servbuf[0] = '\0'; if (!getnameinfo((struct sockaddr *)&c->remote_addr, #ifndef HAVE_SOCKADDR_LEN SA_LEN((struct sockaddr *)&c->remote_addr), #else c->remote_addr.ss_len, #endif NULL, 0, servbuf, sizeof(servbuf), NI_NUMERICSERV)){ ap_table_addn(e, "REMOTE_PORT", ap_pstrdup(r->pool, servbuf)); } if (c->user) { ap_table_addn(e, "REMOTE_USER", c->user); } if (c->ap_auth_type) { ap_table_addn(e, "AUTH_TYPE", c->ap_auth_type); } rem_logname = ap_get_remote_logname(r); if (rem_logname) { ap_table_addn(e, "REMOTE_IDENT", ap_pstrdup(r->pool, rem_logname)); } /* Apache custom error responses. If we have redirected set two new vars */ if (r->prev) { if (r->prev->args) { ap_table_addn(e, "REDIRECT_QUERY_STRING", r->prev->args); } if (r->prev->uri) { ap_table_addn(e, "REDIRECT_URL", r->prev->uri); } } ap_overlap_tables(r->subprocess_env, e, AP_OVERLAP_TABLES_SET); }
/** * Writes request parameters to srun. */ static void write_env(stream_t *s, request_rec *r, char *session_id) { char buf[4096]; int ch; int i; conn_rec *c = r->connection; const char *host; int port; int is_sub_request = 1; char *uri; /* * is_sub_request is always true, since we can't detect mod_rewrite * and mod_rewrite doesn't change the unparsed_uri. */ if (is_sub_request) uri = r->uri; /* for mod_rewrite */ else uri = r->unparsed_uri; /* #937 */ for (i = 0; (ch = uri[i]) && ch != '?' && i + 1 < sizeof(buf); i++) buf[i] = ch; if (session_id) { buf[i++] = *s->config->session_url_prefix; for (session_id++; *session_id && i + 1 < sizeof(buf); i++) buf[i] = *session_id++; } buf[i] = 0; cse_write_string(s, HMUX_URL, buf); cse_write_string(s, HMUX_METHOD, r->method); if (*s->config->alt_session_url_prefix && r->request_config) { char *suburi = ap_get_module_config(r->request_config, &caucho_module); if (suburi) uri = suburi; } cse_write_string(s, CSE_PROTOCOL, r->protocol); if (r->args) cse_write_string(s, CSE_QUERY_STRING, r->args); /* Gets the server name */ host = ap_get_server_name(r); port = ap_get_server_port(r); cse_write_string(s, HMUX_SERVER_NAME, host); cse_write_string(s, CSE_SERVER_PORT, ap_psprintf(r->pool, "%u", port)); host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST); if (host) cse_write_string(s, CSE_REMOTE_HOST, host); else cse_write_string(s, CSE_REMOTE_HOST, c->remote_ip); cse_write_string(s, CSE_REMOTE_ADDR, c->remote_ip); cse_write_string(s, CSE_REMOTE_PORT, ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port))); if (c->user) cse_write_string(s, CSE_REMOTE_USER, c->user); if (c->ap_auth_type) cse_write_string(s, CSE_AUTH_TYPE, c->ap_auth_type); }
static void vhost_alias_interpolate(request_rec *r, const char *name, const char *map, const char *uri) { /* 0..9 9..0 */ enum { MAXDOTS = 19 }; const char *dots[MAXDOTS+1]; int ndots; char buf[HUGE_STRING_LEN]; char *dest, last; int N, M, Np, Mp, Nd, Md; const char *start, *end; const char *p; ndots = 0; dots[ndots++] = name-1; /* slightly naughty */ for (p = name; *p; ++p){ if (*p == '.' && ndots < MAXDOTS) { dots[ndots++] = p; } } dots[ndots] = p; r->filename = NULL; dest = buf; last = '\0'; while (*map) { if (*map != '%') { /* normal characters */ vhost_alias_checkspace(r, buf, &dest, 1); last = *dest++ = *map++; continue; } /* we are in a format specifier */ ++map; /* can't be a slash */ last = '\0'; /* %% -> % */ if (*map == '%') { ++map; vhost_alias_checkspace(r, buf, &dest, 1); *dest++ = '%'; continue; } /* port number */ if (*map == 'p') { ++map; /* no. of decimal digits in a short plus one */ vhost_alias_checkspace(r, buf, &dest, 7); dest += apr_snprintf(dest, 7, "%d", ap_get_server_port(r)); continue; } /* deal with %-N+.-M+ -- syntax is already checked */ N = M = 0; /* value */ Np = Mp = 0; /* is there a plus? */ Nd = Md = 0; /* is there a dash? */ if (*map == '-') ++map, Nd = 1; N = *map++ - '0'; if (*map == '+') ++map, Np = 1; if (*map == '.') { ++map; if (*map == '-') { ++map, Md = 1; } M = *map++ - '0'; if (*map == '+') { ++map, Mp = 1; } } /* note that N and M are one-based indices, not zero-based */ start = dots[0]+1; /* ptr to the first character */ end = dots[ndots]; /* ptr to the character after the last one */ if (N != 0) { if (N > ndots) { start = "_"; end = start+1; } else if (!Nd) { start = dots[N-1]+1; if (!Np) { end = dots[N]; } } else { if (!Np) { start = dots[ndots-N]+1; } end = dots[ndots-N+1]; } } if (M != 0) { if (M > end - start) { start = "_"; end = start+1; } else if (!Md) { start = start+M-1; if (!Mp) { end = start+1; } } else { if (!Mp) { start = end-M; } end = end-M+1; } } vhost_alias_checkspace(r, buf, &dest, end - start); for (p = start; p < end; ++p) { *dest++ = apr_tolower(*p); } } *dest = '\0'; /* no double slashes */ if (last == '/') { ++uri; } if (r->filename) { r->filename = apr_pstrcat(r->pool, r->filename, buf, uri, NULL); } else { r->filename = apr_pstrcat(r->pool, buf, uri, NULL); } }
/* * This handles http:// URLs, and other URLs using a remote proxy over http * If proxyhost is NULL, then contact the server directly, otherwise * go via the proxy. * Note that if a proxy is used, then URLs other than http: can be accessed, * also, if we have trouble which is clearly specific to the proxy, then * we return DECLINED so that we can try another proxy. (Or the direct * route.) */ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, const char *proxyhost, int proxyport) { const char *strp; char *strp2; const char *err, *desthost; int i, j, sock,/* len,*/ backasswards; table *req_hdrs, *resp_hdrs; array_header *reqhdrs_arr; table_entry *reqhdrs_elts; BUFF *f; char buffer[HUGE_STRING_LEN]; char portstr[32]; pool *p = r->pool; int chunked = 0, destport = 0; char *destportstr = NULL; const char *urlptr = NULL; const char *datestr, *urlstr; struct addrinfo hints, *res, *res0; int error; int result, major, minor; const char *content_length; const char *peer; int destportstrtonum; const char *errstr; void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; int nocache = 0; if (conf->cache.root == NULL) nocache = 1; /* We break the URL into host, port, path-search */ urlptr = strstr(url, "://"); if (urlptr == NULL) return HTTP_BAD_REQUEST; destport = DEFAULT_HTTP_PORT; urlptr += 3; ap_hook_use("ap::mod_proxy::http::handler::set_destport", AP_HOOK_SIG2(int,ptr), AP_HOOK_TOPMOST, &destport, r); ap_snprintf(portstr, sizeof(portstr), "%d", destport); destportstr = portstr; strp = strchr(urlptr, '/'); if (strp == NULL) { desthost = ap_pstrdup(p, urlptr); urlptr = "/"; } else { char *q = ap_palloc(p, strp - urlptr + 1); memcpy(q, urlptr, strp - urlptr); q[strp - urlptr] = '\0'; urlptr = strp; desthost = q; } if (*desthost == '['){ char *u = strrchr(desthost+1, ']'); if (u){ desthost++; *u = '\0'; if (*(u+1) == ':'){ /* [host]:xx */ strp2 = u+1; } else if (*(u+1) == '\0'){ /* [host] */ strp2 = NULL; } else return HTTP_BAD_REQUEST; } else return HTTP_BAD_REQUEST; } else strp2 = strrchr(desthost, ':'); if (strp2 != NULL) { *(strp2++) = '\0'; if (ap_isdigit(*strp2)) destportstr = strp2; } /* Make sure peer is always set to prevent a segfault in the SSL handler */ peer = desthost; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; error = getaddrinfo(desthost, destportstr, &hints, &res0); if (error && proxyhost == NULL) { return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, gai_strerror(error)); /* give up */ } /* check if ProxyBlock directive on this host */ for (i = 0; i < conf->noproxies->nelts; i++) { int fail; struct sockaddr_in *sin; fail = 0; if (npent[i].name != NULL && strstr(desthost, npent[i].name)) fail++; if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0) fail++; for (res = res0; res; res = res->ai_next) { switch (res->ai_family) { case AF_INET: sin = (struct sockaddr_in *)res->ai_addr; if (sin->sin_addr.s_addr == npent[i].addr.s_addr) fail++; break; } } if (fail) { if (res0 != NULL) freeaddrinfo(res0); return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } } if (proxyhost != NULL) { char pbuf[10]; if (res0 != NULL) freeaddrinfo(res0); ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; error = getaddrinfo(proxyhost, pbuf, &hints, &res0); if (error) return DECLINED; /* try another */ } /* check if ProxyBlock directive on this host */ for (i = 0; i < conf->noproxies->nelts; i++) { peer = ap_psprintf(p, "%s:%s", desthost, destportstr); } /* * we have worked out who exactly we are going to connect to, now make * that connection... */ sock = i = -1; for (res = res0; res; res = res->ai_next) { sock = ap_psocket(p, res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) continue; if (conf->recv_buffer_size) { if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (const char *)&conf->recv_buffer_size, sizeof(int)) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } } i = ap_proxy_doconnect(sock, res->ai_addr, r); if (i == 0) break; ap_pclosesocket(p, sock); } freeaddrinfo(res0); if (i == -1) { if (proxyhost != NULL) return DECLINED; /* try again another way */ else return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, "Could not connect to remote machine: ", strerror(errno), NULL)); } /* record request_time for HTTP/1.1 age calculation */ c->req_time = time(NULL); /* * build upstream-request headers by stripping r->headers_in from * connection specific headers. We must not remove the Connection: header * from r->headers_in, we still have to react to Connection: close */ req_hdrs = ap_copy_table(r->pool, r->headers_in); ap_proxy_clear_connection(r->pool, req_hdrs); /* * At this point, we start sending the HTTP/1.1 request to the remote * server (proxy or otherwise). */ f = ap_bcreate(p, B_RDWR | B_SOCKET); ap_bpushfd(f, sock, sock); { char *errmsg = NULL; ap_hook_use("ap::mod_proxy::http::handler::new_connection", AP_HOOK_SIG4(ptr,ptr,ptr,ptr), AP_HOOK_DECLINE(NULL), &errmsg, r, f, peer); if (errmsg != NULL) return ap_proxyerror(r, HTTP_BAD_GATEWAY, errmsg); } ap_hard_timeout("proxy send", r); ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF, NULL); { int rc = DECLINED; ap_hook_use("ap::mod_proxy::http::handler::write_host_header", AP_HOOK_SIG6(int,ptr,ptr,ptr,ptr,ptr), AP_HOOK_DECLINE(DECLINED), &rc, r, f, desthost, destportstr, destportstr); if (rc == DECLINED) { destportstrtonum = strtonum(destportstr, 0, 65535, &errstr); if (errstr) errx(1, "The destination port is %s: %s", errstr, destportstr); if (destportstr != NULL && destportstrtonum != destport) ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL); else ap_bvputs(f, "Host: ", desthost, CRLF, NULL); } } if (conf->viaopt == via_block) { /* Block all outgoing Via: headers */ ap_table_unset(req_hdrs, "Via"); } else if (conf->viaopt != via_off) { /* Create a "Via:" request header entry and merge it */ i = ap_get_server_port(r); if (ap_is_default_port(i, r)) { strlcpy(portstr, "", sizeof(portstr)); } else { ap_snprintf(portstr, sizeof portstr, ":%d", i); } /* Generate outgoing Via: header with/without server comment: */ ap_table_mergen(req_hdrs, "Via", (conf->viaopt == via_full) ? ap_psprintf(p, "%d.%d %s%s (%s)", HTTP_VERSION_MAJOR(r->proto_num), HTTP_VERSION_MINOR(r->proto_num), ap_get_server_name(r), portstr, SERVER_BASEVERSION) : ap_psprintf(p, "%d.%d %s%s", HTTP_VERSION_MAJOR(r->proto_num), HTTP_VERSION_MINOR(r->proto_num), ap_get_server_name(r), portstr) ); } /* the X-* headers are only added if we are a reverse * proxy, otherwise we would be giving away private information. */ if (r->proxyreq == PROXY_PASS) { const char *buf; /* * Add X-Forwarded-For: so that the upstream has a chance to determine, * where the original request came from. */ ap_table_mergen(req_hdrs, "X-Forwarded-For", r->connection->remote_ip); /* Add X-Forwarded-Host: so that upstream knows what the * original request hostname was. */ if ((buf = ap_table_get(r->headers_in, "Host"))) { ap_table_mergen(req_hdrs, "X-Forwarded-Host", buf); } /* Add X-Forwarded-Server: so that upstream knows what the * name of this proxy server is (if there are more than one) * XXX: This duplicates Via: - do we strictly need it? */ ap_table_mergen(req_hdrs, "X-Forwarded-Server", r->server->server_hostname); } /* we don't yet support keepalives - but we will soon, I promise! */ ap_table_set(req_hdrs, "Connection", "close"); reqhdrs_arr = ap_table_elts(req_hdrs); reqhdrs_elts = (table_entry *)reqhdrs_arr->elts; for (i = 0; i < reqhdrs_arr->nelts; i++) { if (reqhdrs_elts[i].key == NULL || reqhdrs_elts[i].val == NULL /* * Clear out hop-by-hop request headers not to send: RFC2616 13.5.1 * says we should strip these headers: */ || !strcasecmp(reqhdrs_elts[i].key, "Host") /* Already sent */ || !strcasecmp(reqhdrs_elts[i].key, "Keep-Alive") || !strcasecmp(reqhdrs_elts[i].key, "TE") || !strcasecmp(reqhdrs_elts[i].key, "Trailer") || !strcasecmp(reqhdrs_elts[i].key, "Transfer-Encoding") || !strcasecmp(reqhdrs_elts[i].key, "Upgrade") /* * XXX: @@@ FIXME: "Proxy-Authorization" should *only* be suppressed * if THIS server requested the authentication, not when a frontend * proxy requested it! * * The solution to this problem is probably to strip out the * Proxy-Authorisation header in the authorisation code itself, not * here. This saves us having to signal somehow whether this request * was authenticated or not. */ || !strcasecmp(reqhdrs_elts[i].key, "Proxy-Authorization")) continue; ap_bvputs(f, reqhdrs_elts[i].key, ": ", reqhdrs_elts[i].val, CRLF, NULL); } /* the obligatory empty line to mark the end of the headers */ ap_bputs(CRLF, f); /* and flush the above away */ ap_bflush(f); /* and kill the send timeout */ ap_kill_timeout(r); /* read the request data, and pass it to the backend. * we might encounter a stray 100-continue reponse from a PUT or POST, * if this happens we ignore the 100 continue status line and read the * response again. */ { /* send the request data, if any. */ ap_hard_timeout("proxy receive request data", r); if (ap_should_client_block(r)) { while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) { ap_reset_timeout(r); ap_bwrite(f, buffer, i); } } ap_bflush(f); ap_kill_timeout(r); /* then, read a response line */ ap_hard_timeout("proxy receive response status line", r); result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor); ap_kill_timeout(r); /* trap any errors */ if (result != OK) { ap_bclose(f); return result; } /* if this response was 100-continue, a stray response has been caught. * read the line again for the real response */ if (r->status == 100) { ap_hard_timeout("proxy receive response status line", r); result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor); ap_kill_timeout(r); /* trap any errors */ if (result != OK) { ap_bclose(f); return result; } } } /* * We have our response status line from the convoluted code above, * now we read the headers to continue. */ ap_hard_timeout("proxy receive response headers", r); /* * Is it an HTTP/1 response? Do some sanity checks on the response. (This * is buggy if we ever see an HTTP/1.10) */ if (backasswards == 0) { /* read the response headers. */ /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ /* Also, take care with headers with multiple occurences. */ resp_hdrs = ap_proxy_read_headers(r, buffer, sizeof(buffer), f); if (resp_hdrs == NULL) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server, "proxy: Bad HTTP/%d.%d header returned by %s (%s)", major, minor, r->uri, r->method); resp_hdrs = ap_make_table(p, 20); nocache = 1; /* do not cache this broken file */ } /* handle Via header in the response */ if (conf->viaopt != via_off && conf->viaopt != via_block) { /* Create a "Via:" response header entry and merge it */ i = ap_get_server_port(r); if (ap_is_default_port(i, r)) { strlcpy(portstr, "", sizeof(portstr)); } else { ap_snprintf(portstr, sizeof portstr, ":%d", i); } ap_table_mergen((table *)resp_hdrs, "Via", (conf->viaopt == via_full) ? ap_psprintf(p, "%d.%d %s%s (%s)", major, minor, ap_get_server_name(r), portstr, SERVER_BASEVERSION) : ap_psprintf(p, "%d.%d %s%s", major, minor, ap_get_server_name(r), portstr) ); } /* is this content chunked? */ chunked = ap_find_last_token(r->pool, ap_table_get(resp_hdrs, "Transfer-Encoding"), "chunked"); /* strip hop-by-hop headers defined by Connection and RFC2616 */ ap_proxy_clear_connection(p, resp_hdrs); content_length = ap_table_get(resp_hdrs, "Content-Length"); if (content_length != NULL) { c->len = ap_strtol(content_length, NULL, 10); if (c->len < 0) { ap_kill_timeout(r); return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, "Invalid Content-Length from remote server", NULL)); } } } else { /* an http/0.9 response */ /* no headers */ resp_hdrs = ap_make_table(p, 20); } ap_kill_timeout(r); /* * HTTP/1.1 requires us to accept 3 types of dates, but only generate one * type */ /* * we SET the dates here, obliterating possible multiple dates, as only * one of each date makes sense in each response. */ if ((datestr = ap_table_get(resp_hdrs, "Date")) != NULL) ap_table_set(resp_hdrs, "Date", ap_proxy_date_canon(p, datestr)); if ((datestr = ap_table_get(resp_hdrs, "Last-Modified")) != NULL) ap_table_set(resp_hdrs, "Last-Modified", ap_proxy_date_canon(p, datestr)); if ((datestr = ap_table_get(resp_hdrs, "Expires")) != NULL) ap_table_set(resp_hdrs, "Expires", ap_proxy_date_canon(p, datestr)); /* handle the ProxyPassReverse mappings */ if ((urlstr = ap_table_get(resp_hdrs, "Location")) != NULL) ap_table_set(resp_hdrs, "Location", proxy_location_reverse_map(r, urlstr)); if ((urlstr = ap_table_get(resp_hdrs, "URI")) != NULL) ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, urlstr)); if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL) ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr)); /* check if NoCache directive on this host */ { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; if (nocache == 0) { for (i = 0; i < conf->nocaches->nelts; i++) { if (ncent[i].name != NULL && (ncent[i].name[0] == '*' || strstr(desthost, ncent[i].name) != NULL)) { nocache = 1; break; } switch (res->ai_addr->sa_family) { case AF_INET: sin = (struct sockaddr_in *)res->ai_addr; if (sin->sin_addr.s_addr == ncent[i].addr.s_addr) { nocache = 1; break; } } } /* update the cache file, possibly even fulfilling the request if * it turns out a conditional allowed us to serve the object from the * cache... */ i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); if (i != DECLINED) { ap_bclose(f); return i; } /* write status line and headers to the cache file */ ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs); } } /* Setup the headers for our client from upstreams response-headers */ ap_proxy_table_replace(r->headers_out, resp_hdrs); /* Add X-Cache header - be careful not to obliterate any upstream headers */ ap_table_mergen(r->headers_out, "X-Cache", ap_pstrcat(r->pool, "MISS from ", ap_get_server_name(r), NULL)); /* The Content-Type of this response is the upstream one. */ r->content_type = ap_table_get(r->headers_out, "Content-Type"); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Content-Type: %s", r->content_type); /* finally output the headers to the client */ ap_send_http_header(r); /* * Is it an HTTP/0.9 respose? If so, send the extra data we read from * upstream as the start of the reponse to client */ /* FIXME: This code is broken: we try and write a buffer and length that * were never intelligently initialised. Rather have a bit of broken protocol * handling for now than broken code. */ /* if (backasswards) { ap_hard_timeout("proxy send assbackward", r); ap_bwrite(r->connection->client, buffer, len); if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, "proxy: error writing extra data to %s", c->tempfile); c = ap_proxy_cache_error(c); } ap_kill_timeout(r); } */ /* send body */ /* if header only, then cache will be NULL */ /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */ /* XXX CHANGEME: We want to eventually support keepalives, which means * we must read content-length bytes... */ if (!r->header_only) { /* we need to set this for ap_proxy_send_fb()... */ c->cache_completion = conf->cache.cache_completion; /* XXX CHECKME: c->len should be the expected content length, or -1 if the * content length is not known. We need to make 100% sure c->len is always * set correctly before we get here to correctly do keepalive. */ ap_proxy_send_fb(f, r, c, c->len, 0, chunked, conf->io_buffer_size); } /* ap_proxy_send_fb() closes the socket f for us */ ap_proxy_cache_tidy(c); ap_proxy_garbage_coll(r); return OK; }
/* This function must remain safe to use for a non-SSL connection. */ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var) { SSLModConfigRec *mc = myModConfig(s); const char *result; BOOL resdup; apr_time_exp_t tm; result = NULL; resdup = TRUE; /* * When no pool is given try to find one */ if (p == NULL) { if (r != NULL) p = r->pool; else if (c != NULL) p = c->pool; else p = mc->pPool; } /* * Request dependent stuff */ if (r != NULL) { switch (var[0]) { case 'H': case 'h': if (strcEQ(var, "HTTP_USER_AGENT")) result = apr_table_get(r->headers_in, "User-Agent"); else if (strcEQ(var, "HTTP_REFERER")) result = apr_table_get(r->headers_in, "Referer"); else if (strcEQ(var, "HTTP_COOKIE")) result = apr_table_get(r->headers_in, "Cookie"); else if (strcEQ(var, "HTTP_FORWARDED")) result = apr_table_get(r->headers_in, "Forwarded"); else if (strcEQ(var, "HTTP_HOST")) result = apr_table_get(r->headers_in, "Host"); else if (strcEQ(var, "HTTP_PROXY_CONNECTION")) result = apr_table_get(r->headers_in, "Proxy-Connection"); else if (strcEQ(var, "HTTP_ACCEPT")) result = apr_table_get(r->headers_in, "Accept"); else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5)) /* all other headers from which we are still not know about */ result = apr_table_get(r->headers_in, var+5); break; case 'R': case 'r': if (strcEQ(var, "REQUEST_METHOD")) result = r->method; else if (strcEQ(var, "REQUEST_SCHEME")) result = ap_http_scheme(r); else if (strcEQ(var, "REQUEST_URI")) result = r->uri; else if (strcEQ(var, "REQUEST_FILENAME")) result = r->filename; else if (strcEQ(var, "REMOTE_ADDR")) result = r->useragent_ip; else if (strcEQ(var, "REMOTE_HOST")) result = ap_get_useragent_host(r, REMOTE_NAME, NULL); else if (strcEQ(var, "REMOTE_IDENT")) result = ap_get_remote_logname(r); else if (strcEQ(var, "REMOTE_USER")) result = r->user; break; case 'S': case 's': if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */ if (strcEQ(var, "SERVER_ADMIN")) result = r->server->server_admin; else if (strcEQ(var, "SERVER_NAME")) result = ap_get_server_name_for_url(r); else if (strcEQ(var, "SERVER_PORT")) result = apr_psprintf(p, "%u", ap_get_server_port(r)); else if (strcEQ(var, "SERVER_PROTOCOL")) result = r->protocol; else if (strcEQ(var, "SCRIPT_FILENAME")) result = r->filename; break; default: if (strcEQ(var, "PATH_INFO")) result = r->path_info; else if (strcEQ(var, "QUERY_STRING")) result = r->args; else if (strcEQ(var, "IS_SUBREQ")) result = (r->main != NULL ? "true" : "false"); else if (strcEQ(var, "DOCUMENT_ROOT")) result = ap_document_root(r); else if (strcEQ(var, "AUTH_TYPE")) result = r->ap_auth_type; else if (strcEQ(var, "THE_REQUEST")) result = r->the_request; else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { result = apr_table_get(r->notes, var+4); if (result == NULL) result = apr_table_get(r->subprocess_env, var+4); } break; } } /* * Connection stuff */ if (result == NULL && c != NULL) { SSLConnRec *sslconn = ssl_get_effective_config(c); if (strlen(var) > 4 && strcEQn(var, "SSL_", 4) && sslconn && sslconn->ssl) result = ssl_var_lookup_ssl(p, sslconn, r, var+4); else if (strcEQ(var, "HTTPS")) { if (sslconn && sslconn->ssl) result = "on"; else result = "off"; } } /* * Totally independent stuff */ if (result == NULL) { if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12)) result = ssl_var_lookup_ssl_version(p, var+12); else if (strcEQ(var, "SERVER_SOFTWARE")) result = ap_get_server_banner(); else if (strcEQ(var, "API_VERSION")) { result = apr_itoa(p, MODULE_MAGIC_NUMBER_MAJOR); resdup = FALSE; } else if (strcEQ(var, "TIME_YEAR")) { apr_time_exp_lt(&tm, apr_time_now()); result = apr_psprintf(p, "%02d%02d", (tm.tm_year / 100) + 19, tm.tm_year % 100); resdup = FALSE; } #define MKTIMESTR(format, tmfield) \ apr_time_exp_lt(&tm, apr_time_now()); \ result = apr_psprintf(p, format, tm.tmfield); \ resdup = FALSE; else if (strcEQ(var, "TIME_MON")) { MKTIMESTR("%02d", tm_mon+1) } else if (strcEQ(var, "TIME_DAY")) { MKTIMESTR("%02d", tm_mday) } else if (strcEQ(var, "TIME_HOUR")) { MKTIMESTR("%02d", tm_hour) } else if (strcEQ(var, "TIME_MIN")) { MKTIMESTR("%02d", tm_min) } else if (strcEQ(var, "TIME_SEC")) { MKTIMESTR("%02d", tm_sec) } else if (strcEQ(var, "TIME_WDAY")) { MKTIMESTR("%d", tm_wday) } else if (strcEQ(var, "TIME")) { apr_time_exp_lt(&tm, apr_time_now()); result = apr_psprintf(p, "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19, (tm.tm_year % 100), tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); resdup = FALSE; } /* all other env-variables from the parent Apache process */ else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { result = getenv(var+4); } } if (result != NULL && resdup) result = apr_pstrdup(p, result); if (result == NULL) result = ""; return (char *)result; }
/** * Handle a request. */ static int caucho_request(request_rec *r, config_t *config, resin_host_t *host, unsigned int now) { stream_t s; int retval; int code = -1; int session_index; int backup_index = 0; char *ip; srun_t *srun; if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) return retval; session_index = get_session_index(config, r, &backup_index); ip = r->connection->REMOTE_IP; if (host) { } else if (config->manual_host) { host = config->manual_host; } else { host = cse_match_host(config, ap_get_server_name(r), ap_get_server_port(r), now); } LOG(("%s:%d:caucho_request(): session index: %d\n", __FILE__, __LINE__, session_index)); if (! host) { ERR(("%s:%d:caucho_request(): no host: %p\n", __FILE__, __LINE__, host)); return HTTP_SERVICE_UNAVAILABLE; } else if (! cse_open_connection(&s, &host->cluster, session_index, backup_index, now, r->pool)) { ERR(("%s:%d:caucho_request(): no connection: cluster(%p)\n", __FILE__, __LINE__, &host->cluster)); return HTTP_SERVICE_UNAVAILABLE; } srun = s.cluster_srun->srun; apr_thread_mutex_lock(srun->lock); srun->active_sockets++; apr_thread_mutex_unlock(srun->lock); code = write_request(&s, r, config, session_index, backup_index); apr_thread_mutex_lock(srun->lock); srun->active_sockets--; apr_thread_mutex_unlock(srun->lock); /* on failure, do not failover but simply fail */ if (code == HMUX_QUIT) cse_free_idle(&s, now); else cse_close(&s, "no reuse"); if (code != HMUX_QUIT && code != HMUX_EXIT) { ERR(("%s:%d:caucho_request(): protocol failure code:%d\n", __FILE__, __LINE__, code)); return HTTP_SERVICE_UNAVAILABLE; } else if (r->status == HTTP_SERVICE_UNAVAILABLE) { cse_close(&s, "close from 503"); cse_srun_unavail(srun, now); return HTTP_SERVICE_UNAVAILABLE; } else { /* * See pages like jms/index.xtp int status = r->status; r->status = HTTP_OK; return status; */ return OK; } }
/** * Writes request parameters to srun. */ static void write_env(stream_t *s, request_rec *r) { char buf[4096]; int ch; int i, j; conn_rec *c = r->connection; const char *host; const char *uri; int port; int is_sub_request = 1; /* for mod_rewrite */ /* * is_sub_request is always true, since we can't detect mod_rewrite * and mod_rewrite doesn't change the unparsed_uri. */ if (is_sub_request) uri = r->uri; else uri = r->unparsed_uri; /* #937 */ j = 0; for (i = 0; (ch = uri[i]) && ch != '?' && j + 2 < sizeof(buf); i++) { if (ch == '%') { /* #1661 */ buf[j++] = '%'; buf[j++] = '2'; buf[j++] = '5'; } else buf[j++] = ch; } buf[j] = 0; cse_write_string(s, HMUX_URL, buf); cse_write_string(s, HMUX_METHOD, r->method); cse_write_string(s, CSE_PROTOCOL, r->protocol); if (r->args) cse_write_string(s, CSE_QUERY_STRING, r->args); /* Gets the server name */ host = ap_get_server_name(r); port = ap_get_server_port(r); cse_write_string(s, HMUX_SERVER_NAME, host); sprintf(buf, "%u", port); cse_write_string(s, CSE_SERVER_PORT, buf); if (c->remote_host) cse_write_string(s, CSE_REMOTE_HOST, c->remote_host); else cse_write_string(s, CSE_REMOTE_HOST, c->REMOTE_IP); cse_write_string(s, CSE_REMOTE_ADDR, c->REMOTE_IP); sprintf(buf, "%u", ntohs(c->REMOTE_ADDR->port)); cse_write_string(s, CSE_REMOTE_PORT, buf); if (r->user) cse_write_string(s, CSE_REMOTE_USER, r->user); if (r->ap_auth_type) cse_write_string(s, CSE_AUTH_TYPE, r->ap_auth_type); /* mod_ssl */ if (g_ssl_lookup) { static char *vars[] = { "SSL_CLIENT_S_DN", "SSL_CIPHER", "SSL_CIPHER_EXPORT", "SSL_PROTOCOL", "SSL_CIPHER_USEKEYSIZE", "SSL_CIPHER_ALGKEYSIZE", 0}; char *var; int i; if ((var = g_ssl_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_CERT"))) { cse_write_string(s, CSE_CLIENT_CERT, var); } for (i = 0; vars[i]; i++) { if ((var = g_ssl_lookup(r->pool, r->server, r->connection, r, vars[i]))) { cse_write_string(s, HMUX_HEADER, vars[i]); cse_write_string(s, HMUX_STRING, var); } } } }
/** * Handle a request. */ static int caucho_request(request_rec *r) { config_t *config = cse_get_module_config(r); resin_host_t *host = 0; stream_t s; int retval; int keepalive = 0; int reuse; int session_index; int backup_index; char *ip; time_t now = r->request_time; char *session_id = 0; if (! config) return HTTP_SERVICE_UNAVAILABLE; if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) return retval; /* ap_soft_timeout("servlet request", r); */ if (r->request_config && ! *config->alt_session_url_prefix && ((session_id = ap_get_module_config(r->request_config, &caucho_module)) || r->prev && (session_id = ap_get_module_config(r->prev->request_config, &caucho_module)))) { /* *session_id = *config->session_url_prefix; */ } session_index = get_session_index(config, r, &backup_index); ip = r->connection->remote_ip; if (host) { } else if (config->manual_host) host = config->manual_host; else { host = cse_match_host(config, ap_get_server_name(r), ap_get_server_port(r), now); } if (! host || ! cse_open_connection(&s, &host->cluster, session_index, backup_index, now, r->pool)) { return HTTP_SERVICE_UNAVAILABLE; } reuse = write_request(&s, r, config, &host->cluster, &keepalive, session_index, backup_index, ip, session_id); /* ap_kill_timeout(r); */ ap_rflush(r); if (reuse == HMUX_QUIT) cse_recycle(&s, now); else cse_close(&s, "no reuse"); if (reuse == HTTP_SERVICE_UNAVAILABLE) return reuse; else return OK; }
AP_DECLARE(void) ap_add_common_vars(request_rec *r) { apr_table_t *e; server_rec *s = r->server; conn_rec *c = r->connection; const char *rem_logname; char *env_path; #if defined(WIN32) || defined(OS2) || defined(BEOS) char *env_temp; #endif const char *host; const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in); const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts; int i; apr_port_t rport; /* use a temporary apr_table_t which we'll overlap onto * r->subprocess_env later * (exception: if r->subprocess_env is empty at the start, * write directly into it) */ if (apr_is_empty_table(r->subprocess_env)) { e = r->subprocess_env; } else { e = apr_table_make(r->pool, 25 + hdrs_arr->nelts); } /* First, add environment vars from headers... this is as per * CGI specs, though other sorts of scripting interfaces see * the same vars... */ for (i = 0; i < hdrs_arr->nelts; ++i) { if (!hdrs[i].key) { continue; } /* A few headers are special cased --- Authorization to prevent * rogue scripts from capturing passwords; content-type and -length * for no particular reason. */ if (!strcasecmp(hdrs[i].key, "Content-type")) { apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val); } else if (!strcasecmp(hdrs[i].key, "Content-length")) { apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val); } /* * You really don't want to disable this check, since it leaves you * wide open to CGIs stealing passwords and people viewing them * in the environment with "ps -e". But, if you must... */ #ifndef SECURITY_HOLE_PASS_AUTHORIZATION else if (!strcasecmp(hdrs[i].key, "Authorization") || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) { continue; } #endif else { apr_table_addn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val); } } if (!(env_path = getenv("PATH"))) { env_path = DEFAULT_PATH; } apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_path)); #ifdef WIN32 if ((env_temp = getenv("SystemRoot")) != NULL) { apr_table_addn(e, "SystemRoot", env_temp); } if ((env_temp = getenv("COMSPEC")) != NULL) { apr_table_addn(e, "COMSPEC", env_temp); } if ((env_temp = getenv("PATHEXT")) != NULL) { apr_table_addn(e, "PATHEXT", env_temp); } if ((env_temp = getenv("WINDIR")) != NULL) { apr_table_addn(e, "WINDIR", env_temp); } #endif #ifdef OS2 if ((env_temp = getenv("COMSPEC")) != NULL) { apr_table_addn(e, "COMSPEC", env_temp); } if ((env_temp = getenv("ETC")) != NULL) { apr_table_addn(e, "ETC", env_temp); } if ((env_temp = getenv("DPATH")) != NULL) { apr_table_addn(e, "DPATH", env_temp); } if ((env_temp = getenv("PERLLIB_PREFIX")) != NULL) { apr_table_addn(e, "PERLLIB_PREFIX", env_temp); } #endif #ifdef BEOS if ((env_temp = getenv("LIBRARY_PATH")) != NULL) { apr_table_addn(e, "LIBRARY_PATH", env_temp); } #endif apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r)); apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner()); apr_table_addn(e, "SERVER_NAME", ap_escape_html(r->pool, ap_get_server_name(r))); apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */ apr_table_addn(e, "SERVER_PORT", apr_psprintf(r->pool, "%u", ap_get_server_port(r))); host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL); if (host) { apr_table_addn(e, "REMOTE_HOST", host); } apr_table_addn(e, "REMOTE_ADDR", c->remote_ip); apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */ apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */ apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */ rport = c->remote_addr->port; apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport)); if (r->user) { apr_table_addn(e, "REMOTE_USER", r->user); } else if (r->prev) { request_rec *back = r->prev; while (back) { if (back->user) { apr_table_addn(e, "REDIRECT_REMOTE_USER", back->user); break; } back = back->prev; } } if (r->ap_auth_type) { apr_table_addn(e, "AUTH_TYPE", r->ap_auth_type); } rem_logname = ap_get_remote_logname(r); if (rem_logname) { apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, rem_logname)); } /* Apache custom error responses. If we have redirected set two new vars */ if (r->prev) { if (r->prev->args) { apr_table_addn(e, "REDIRECT_QUERY_STRING", r->prev->args); } if (r->prev->uri) { apr_table_addn(e, "REDIRECT_URL", r->prev->uri); } } if (e != r->subprocess_env) { apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET); } }
static int ipp_handler(request_rec *r) { papi_attribute_t **request = NULL, **response = NULL; IPPListenerConfig *config; papi_status_t status; int ret; /* Really, IPP is all POST requests */ if (r->method_number != M_POST) return (DECLINED); #ifndef APACHE2 /* * An IPP request must have a MIME type of "application/ipp" * (RFC-2910, Section 4, page 19). If it doesn't match this * MIME type, we should decline the request and let someone else * try and handle it. */ if (r->headers_in != NULL) { char *mime_type = (char *)ap_table_get(r->headers_in, "Content-Type"); if ((mime_type == NULL) || (strcasecmp(mime_type, "application/ipp") != 0)) return (DECLINED); } #endif /* CHUNKED_DECHUNK might not work right for IPP? */ if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) return (ret); if (!ap_should_client_block(r)) return (HTTP_INTERNAL_SERVER_ERROR); #ifndef APACHE2 ap_soft_timeout("ipp_module: read/reply request ", r); #endif /* read the IPP request off the network */ status = ipp_read_message(read_data, r, &request, IPP_TYPE_REQUEST); if (status != PAPI_OK) _log_rerror(APLOG_MARK, APLOG_ERR, r, "read failed: %s\n", papiStatusString(status)); #ifdef DEBUG papiAttributeListPrint(stderr, request, "request (%d) ", getpid()); #endif (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "originating-host", (char *) #ifdef APACHE2 ap_get_remote_host (r->connection, r->per_dir_config, REMOTE_NAME, NULL)); #else ap_get_remote_host (r->connection, r->per_dir_config, REMOTE_NAME)); #endif (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, "uri-port", ap_get_server_port(r)); if (r->headers_in != NULL) { char *host = (char *)ap_table_get(r->headers_in, "Host"); if ((host == NULL) || (host[0] == '\0')) host = (char *)ap_get_server_name(r); (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "uri-host", host); } (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "uri-path", r->uri); config = ap_get_module_config(r->per_dir_config, &ipp_module); if (config != NULL) { (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, "conformance", config->conformance); (void) papiAttributeListAddCollection(&request, PAPI_ATTR_EXCL, "operations", config->operations); if (config->default_user != NULL) (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "default-user", config->default_user); if (config->default_svc != NULL) (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "default-service", config->default_svc); } /* * For Trusted Solaris, pass the fd number of the socket connection * to the backend so the it can be forwarded to the backend print * service to retrieve the sensativity label off of a multi-level * port. */ (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, "peer-socket", ap_bfileno(r->connection->client, B_RD)); /* process the request */ status = ipp_process_request(request, &response, read_data, r); if (status != PAPI_OK) { errno = 0; _log_rerror(APLOG_MARK, APLOG_ERR, r, "request failed: %s\n", papiStatusString(status)); discard_data(r); } #ifdef DEBUG fprintf(stderr, "processing result: %s\n", papiStatusString(status)); papiAttributeListPrint(stderr, response, "response (%d) ", getpid()); #endif /* * If the client is using chunking and we have not yet received the * final "0" sized chunk, we need to discard any data that may * remain in the post request. */ if ((r->read_chunked != 0) && (ap_table_get(r->headers_in, "Content-Length") == NULL)) discard_data(r); /* write an IPP response back to the network */ r->content_type = "application/ipp"; #ifndef APACHE2 ap_send_http_header(r); #endif status = ipp_write_message(write_data, r, response); if (status != PAPI_OK) _log_rerror(APLOG_MARK, APLOG_ERR, r, "write failed: %s\n", papiStatusString(status)); #ifdef DEBUG fprintf(stderr, "write result: %s\n", papiStatusString(status)); fflush(stderr); #endif papiAttributeListFree(request); papiAttributeListFree(response); #ifndef APACHE2 ap_kill_timeout(r); if (ap_rflush(r) < 0) _log_rerror(APLOG_MARK, APLOG_ERR, r, "flush failed, response may not have been sent"); #endif return (OK); }