/** * 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; }
/* Calculate the cookie parameters. * * Parameters: * request_rec *r The request we should set the cookie in. * * Returns: * The cookie parameters as a string. */ static const char *am_cookie_params(request_rec *r) { int secure_cookie; int http_only_cookie; const char *cookie_domain = ap_get_server_name(r); const char *cookie_path = "/"; am_dir_cfg_rec *cfg = am_get_dir_cfg(r); if (cfg->cookie_domain) { cookie_domain = cfg->cookie_domain; } if (cfg->cookie_path) { cookie_path = cfg->cookie_path; } secure_cookie = cfg->secure; http_only_cookie = cfg->http_only; return apr_psprintf(r->pool, "Version=1; Path=%s; Domain=%s%s%s;", cookie_path, cookie_domain, http_only_cookie ? "; HttpOnly" : "", secure_cookie ? "; secure" : ""); }
static int mva_translate(request_rec *r) { mva_sconf_t *conf; const char *name, *map, *uri; mva_mode_e mode; const char *cgi; conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config, &vhost_bytemark_module); cgi = NULL; if (conf->cgi_root) { cgi = strstr(r->uri, "cgi-bin/"); if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) { cgi = NULL; } } if (cgi) { mode = conf->cgi_root_mode; map = conf->cgi_root; uri = cgi + strlen("cgi-bin"); } else if (r->uri[0] == '/') { mode = conf->doc_root_mode; map = conf->doc_root; uri = r->uri; } else { return DECLINED; } if (mode == VHOST_ALIAS_NAME) { name = ap_get_server_name(r); } else if (mode == VHOST_ALIAS_IP) { name = r->connection->local_ip; } else { return DECLINED; } /* ### There is an optimization available here to determine the * absolute portion of the path from the server config phase, * through the first % segment, and note that portion of the path * canonical_path buffer. */ r->canonical_filename = ""; vhost_alias_interpolate(r, conf, name, map, uri); if (cgi) { /* see is_scriptaliased() in mod_cgi */ r->handler = "cgi-script"; apr_table_setn(r->notes, "alias-forced-type", r->handler); ap_set_context_info(r, "/cgi-bin", NULL); } return OK; }
/* A bit like mod_status: add a location: <Location /svn-status> SetHandler svn-status </Location> and then point a browser at http://server/svn-status. */ int dav_svn__status(request_rec *r) { svn_cache__info_t *info; svn_string_t *text_stats; apr_array_header_t *lines; int i; if (r->method_number != M_GET || strcmp(r->handler, "svn-status")) return DECLINED; info = svn_cache__membuffer_get_global_info(r->pool); text_stats = svn_cache__format_info(info, FALSE, r->pool); lines = svn_cstring_split(text_stats->data, "\n", FALSE, r->pool); ap_set_content_type(r, "text/html; charset=ISO-8859-1"); ap_rvputs(r, DOCTYPE_HTML_3_2 "<html><head>\n" "<title>Apache SVN Status</title>\n" "</head><body>\n" "<h1>Apache SVN Cache Status for ", ap_escape_html(r->pool, ap_get_server_name(r)), " (via ", r->connection->local_ip, ")</h1>\n<dl>\n<dt>Server Version: ", ap_get_server_description(), "</dt>\n<dt>Current Time: ", ap_ht_time(r->pool, apr_time_now(), DEFAULT_TIME_FORMAT, 0), "</dt>\n", SVN_VA_NULL); #if defined(WIN32) || (defined(HAVE_UNISTD_H) && defined(HAVE_GETPID)) /* On Unix the server is generally multiple processes and this request only shows the status of the single process that handles the request. Ideally we would iterate over all processes but that would need some MPM support, so we settle for simply showing the process ID. */ ap_rprintf(r, "<dt>Server process id: %d</dt>\n", (int)getpid()); #endif for (i = 0; i < lines->nelts; ++i) { const char *line = APR_ARRAY_IDX(lines, i, const char *); ap_rvputs(r, "<dt>", line, "</dt>\n", SVN_VA_NULL); } ap_rvputs(r, "</dl></body></html>\n", SVN_VA_NULL); return 0; }
static int mva_translate(request_rec *r) { mva_sconf_t *conf; const char *name, *map, *uri; mva_mode_e mode; const char *cgi; conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config, &vhost_alias_module); cgi = NULL; if (conf->cgi_root) { cgi = strstr(r->uri, "cgi-bin/"); if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) { cgi = NULL; } } if (cgi) { mode = conf->cgi_root_mode; map = conf->cgi_root; uri = cgi + strlen("cgi-bin"); } else if (r->uri[0] == '/') { mode = conf->doc_root_mode; map = conf->doc_root; uri = r->uri; } else { return DECLINED; } if (mode == VHOST_ALIAS_NAME) { name = ap_get_server_name(r); } else if (mode == VHOST_ALIAS_IP) { name = r->connection->local_ip; } else { return DECLINED; } vhost_alias_interpolate(r, name, map, uri); if (cgi) { /* see is_scriptaliased() in mod_cgi */ r->handler = "cgi-script"; ap_table_setn(r->notes, "alias-forced-type", r->handler); } return OK; }
/** * 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 void populate_log_entry(request_rec* r, LogEntry* msg) { SET_BYTES(remote_address, r->connection->remote_ip); SET_BYTES(local_address, r->connection->local_ip); SET_BYTES(remote_logname, (char*) ap_get_remote_logname(r)); SET_BYTES(remote_user, r->user); SET_BYTES(filename, r->filename); SET_BYTES(unparsed_uri, r->unparsed_uri); SET_BYTES(method, (char*) r->method); SET_BYTES(protocol, (char*) r->protocol); msg->status = r->status; msg->has_status = 1; SET_BYTES(handler, (char*) r->handler); msg->has_bytes_sent = 1; msg->bytes_sent = r->bytes_sent; SET_BYTES(cookies, (char*) apr_table_get(r->headers_in, kCookieHeader)); SET_BYTES(user_agent, (char*) apr_table_get(r->headers_in, kUserAgentHeader)); SET_BYTES(virtual_host, r->server->server_hostname); SET_BYTES(server_name, (char*) ap_get_server_name(r)); msg->request_time = r->request_time; msg->has_request_time = 1; SET_BYTES(referrer, (char*) apr_table_get(r->headers_in, kReferrerHeader)); /* Try 'em both, just in case... */ if (msg->referrer.len == 0) { SET_BYTES(referrer, (char*) apr_table_get(r->headers_in, kRefererHeader)); } }
/* 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 ruid_set_perm (request_rec *r, const char *from_func) { ruid_config_t *conf = ap_get_module_config(r->server->module_config, &ruid2_module); ruid_dir_config_t *dconf = ap_get_module_config(r->per_dir_config, &ruid2_module); int retval = DECLINED; gid_t gid; uid_t uid; gid_t groups[RUID_MAXGROUPS]; int groupsnr; cap_t cap; cap_value_t capval[3]; cap=cap_get_proc(); capval[0]=CAP_SETUID; capval[1]=CAP_SETGID; cap_set_flag(cap,CAP_EFFECTIVE,2,capval,CAP_SET); if (cap_set_proc(cap)!=0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s>%s:cap_set_proc failed before setuid", MODULE_NAME, from_func, __func__); } cap_free(cap); if (dconf->ruid_mode==RUID_MODE_STAT) { /* set uid,gid to uid,gid of file * if file does not exist, finfo.user and finfo.group is set to uid,gid of parent directory */ gid=r->finfo.group; uid=r->finfo.user; /* if uid of filename is less than conf->min_uid then set to conf->default_uid */ if (uid < conf->min_uid) { uid=conf->default_uid; } if (gid < conf->min_gid) { gid=conf->default_gid; } } else { gid=(dconf->ruid_gid == UNSET) ? ap_unixd_config.group_id : dconf->ruid_gid; uid=(dconf->ruid_uid == UNSET) ? ap_unixd_config.user_id : dconf->ruid_uid; } /* set supplementary groups */ if ((dconf->groupsnr == UNSET) && (startup_groupsnr > 0)) { memcpy(groups, startup_groups, sizeof(groups)); groupsnr = startup_groupsnr; } else if (dconf->groupsnr > 0) { for (groupsnr = 0; groupsnr < dconf->groupsnr; groupsnr++) { groups[groupsnr] = dconf->groups[groupsnr]; } } else { groupsnr = 0; } setgroups(groupsnr, groups); /* final set[ug]id */ if (setgid(gid) != 0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s %s %s %s>%s:setgid(%d) failed. getgid=%d getuid=%d", MODULE_NAME, ap_get_server_name(r), r->the_request, from_func, __func__, dconf->ruid_gid, getgid(), getuid()); retval = HTTP_FORBIDDEN; } else { if (setuid(uid) != 0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s %s %s %s>%s:setuid(%d) failed. getuid=%d", MODULE_NAME, ap_get_server_name(r), r->the_request, from_func, __func__, dconf->ruid_uid, getuid()); retval = HTTP_FORBIDDEN; } } /* set httpd process dumpable after setuid */ if (coredump) { prctl(PR_SET_DUMPABLE,1); } /* clear capabilties from effective set */ cap=cap_get_proc(); capval[0]=CAP_SETUID; capval[1]=CAP_SETGID; capval[2]=CAP_DAC_READ_SEARCH; cap_set_flag(cap,CAP_EFFECTIVE,3,capval,CAP_CLEAR); if (cap_set_proc(cap)!=0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s>%s:cap_set_proc failed after setuid", MODULE_NAME, from_func, __func__); retval = HTTP_FORBIDDEN; } cap_free(cap); return retval; }
/** * 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; }
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 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; }
static apr_status_t ajp_marshal_into_msgb(ajp_msg_t *msg, request_rec *r, apr_uri_t *uri) { int method; apr_uint32_t i, num_headers = 0; apr_byte_t is_ssl; char *remote_host; const char *session_route, *envvar; const apr_array_header_t *arr = apr_table_elts(r->subprocess_env); const apr_table_entry_t *elts = (const apr_table_entry_t *)arr->elts; ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, "Into ajp_marshal_into_msgb"); if ((method = sc_for_req_method_by_id(r)) == UNKNOWN_METHOD) { ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, APLOGNO(02437) "ajp_marshal_into_msgb - Sending unknown method %s as request attribute", r->method); method = SC_M_JK_STORED; } is_ssl = (apr_byte_t) ap_proxy_conn_is_https(r->connection); if (r->headers_in && apr_table_elts(r->headers_in)) { const apr_array_header_t *t = apr_table_elts(r->headers_in); num_headers = t->nelts; } remote_host = (char *)ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_HOST, NULL); ajp_msg_reset(msg); if (ajp_msg_append_uint8(msg, CMD_AJP13_FORWARD_REQUEST) || ajp_msg_append_uint8(msg, (apr_byte_t) method) || ajp_msg_append_string(msg, r->protocol) || ajp_msg_append_string(msg, uri->path) || ajp_msg_append_string(msg, r->useragent_ip) || ajp_msg_append_string(msg, remote_host) || ajp_msg_append_string(msg, ap_get_server_name(r)) || ajp_msg_append_uint16(msg, (apr_uint16_t)r->connection->local_addr->port) || ajp_msg_append_uint8(msg, is_ssl) || ajp_msg_append_uint16(msg, (apr_uint16_t) num_headers)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00968) "ajp_marshal_into_msgb: " "Error appending the message beginning"); return APR_EGENERAL; } for (i = 0 ; i < num_headers ; i++) { int sc; const apr_array_header_t *t = apr_table_elts(r->headers_in); const apr_table_entry_t *elts = (apr_table_entry_t *)t->elts; if ((sc = sc_for_req_header(elts[i].key)) != UNKNOWN_METHOD) { if (ajp_msg_append_uint16(msg, (apr_uint16_t)sc)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00969) "ajp_marshal_into_msgb: " "Error appending the header name"); return AJP_EOVERFLOW; } } else { if (ajp_msg_append_string(msg, elts[i].key)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00970) "ajp_marshal_into_msgb: " "Error appending the header name"); return AJP_EOVERFLOW; } } if (ajp_msg_append_string(msg, elts[i].val)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00971) "ajp_marshal_into_msgb: " "Error appending the header value"); return AJP_EOVERFLOW; } ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "ajp_marshal_into_msgb: Header[%d] [%s] = [%s]", i, elts[i].key, elts[i].val); } /* XXXX need to figure out how to do this if (s->secret) { if (ajp_msg_append_uint8(msg, SC_A_SECRET) || ajp_msg_append_string(msg, s->secret)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Error ajp_marshal_into_msgb - " "Error appending secret"); return APR_EGENERAL; } } */ if (r->user) { if (ajp_msg_append_uint8(msg, SC_A_REMOTE_USER) || ajp_msg_append_string(msg, r->user)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00972) "ajp_marshal_into_msgb: " "Error appending the remote user"); return AJP_EOVERFLOW; } } if (r->ap_auth_type) { if (ajp_msg_append_uint8(msg, SC_A_AUTH_TYPE) || ajp_msg_append_string(msg, r->ap_auth_type)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00973) "ajp_marshal_into_msgb: " "Error appending the auth type"); return AJP_EOVERFLOW; } } /* XXXX ebcdic (args converted?) */ if (uri->query) { if (ajp_msg_append_uint8(msg, SC_A_QUERY_STRING) || ajp_msg_append_string(msg, uri->query)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00974) "ajp_marshal_into_msgb: " "Error appending the query string"); return AJP_EOVERFLOW; } } if ((session_route = apr_table_get(r->notes, "session-route"))) { if (ajp_msg_append_uint8(msg, SC_A_JVM_ROUTE) || ajp_msg_append_string(msg, session_route)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00975) "ajp_marshal_into_msgb: " "Error appending the jvm route"); return AJP_EOVERFLOW; } } /* XXX: Is the subprocess_env a right place? * <Location /examples> * ProxyPass ajp://remote:8009/servlets-examples * SetEnv SSL_SESSION_ID CUSTOM_SSL_SESSION_ID * </Location> */ /* * Only lookup SSL variables if we are currently running HTTPS. * Furthermore ensure that only variables get set in the AJP message * that are not NULL and not empty. */ if (is_ssl) { if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r, AJP13_SSL_CLIENT_CERT_INDICATOR)) && envvar[0]) { if (ajp_msg_append_uint8(msg, SC_A_SSL_CERT) || ajp_msg_append_string(msg, envvar)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00976) "ajp_marshal_into_msgb: " "Error appending the SSL certificates"); return AJP_EOVERFLOW; } } if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r, AJP13_SSL_CIPHER_INDICATOR)) && envvar[0]) { if (ajp_msg_append_uint8(msg, SC_A_SSL_CIPHER) || ajp_msg_append_string(msg, envvar)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00977) "ajp_marshal_into_msgb: " "Error appending the SSL ciphers"); return AJP_EOVERFLOW; } } if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r, AJP13_SSL_SESSION_INDICATOR)) && envvar[0]) { if (ajp_msg_append_uint8(msg, SC_A_SSL_SESSION) || ajp_msg_append_string(msg, envvar)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00978) "ajp_marshal_into_msgb: " "Error appending the SSL session"); return AJP_EOVERFLOW; } } /* ssl_key_size is required by Servlet 2.3 API */ if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r, AJP13_SSL_KEY_SIZE_INDICATOR)) && envvar[0]) { if (ajp_msg_append_uint8(msg, SC_A_SSL_KEY_SIZE) || ajp_msg_append_uint16(msg, (unsigned short) atoi(envvar))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00979) "ajp_marshal_into_msgb: " "Error appending the SSL key size"); return APR_EGENERAL; } } } /* If the method was unrecognized, encode it as an attribute */ if (method == SC_M_JK_STORED) { if (ajp_msg_append_uint8(msg, SC_A_STORED_METHOD) || ajp_msg_append_string(msg, r->method)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02438) "ajp_marshal_into_msgb: " "Error appending the method '%s' as request attribute", r->method); return AJP_EOVERFLOW; } } /* Forward the remote port information, which was forgotten * from the builtin data of the AJP 13 protocol. * Since the servlet spec allows to retrieve it via getRemotePort(), * we provide the port to the Tomcat connector as a request * attribute. Modern Tomcat versions know how to retrieve * the remote port from this attribute. */ { const char *key = SC_A_REQ_REMOTE_PORT; char *val = apr_itoa(r->pool, r->useragent_addr->port); if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) || ajp_msg_append_string(msg, key) || ajp_msg_append_string(msg, val)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00980) "ajp_marshal_into_msgb: " "Error appending attribute %s=%s", key, val); return AJP_EOVERFLOW; } } /* Forward the local ip address information, which was forgotten * from the builtin data of the AJP 13 protocol. * Since the servlet spec allows to retrieve it via getLocalAddr(), * we provide the address to the Tomcat connector as a request * attribute. Modern Tomcat versions know how to retrieve * the local address from this attribute. */ { const char *key = SC_A_REQ_LOCAL_ADDR; char *val = r->connection->local_ip; if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) || ajp_msg_append_string(msg, key) || ajp_msg_append_string(msg, val)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02646) "ajp_marshal_into_msgb: " "Error appending attribute %s=%s", key, val); return AJP_EOVERFLOW; } } /* Use the environment vars prefixed with AJP_ * and pass it to the header striping that prefix. */ for (i = 0; i < (apr_uint32_t)arr->nelts; i++) { if (!strncmp(elts[i].key, "AJP_", 4)) { if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) || ajp_msg_append_string(msg, elts[i].key + 4) || ajp_msg_append_string(msg, elts[i].val)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00981) "ajp_marshal_into_msgb: " "Error appending attribute %s=%s", elts[i].key, elts[i].val); return AJP_EOVERFLOW; } } } if (ajp_msg_append_uint8(msg, SC_A_ARE_DONE)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00982) "ajp_marshal_into_msgb: " "Error appending the message end"); return AJP_EOVERFLOW; } ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, "ajp_marshal_into_msgb: Done"); return APR_SUCCESS; }
/* Routine to perform the actual construction and execution of the relevant * INSERT statements. */ static int log_sql_transaction(request_rec *orig) { char **ptrptr, **ptrptr2; logsql_state *cls = ap_get_module_config(orig->server->module_config, &log_sql_module); const char *access_query; request_rec *r; const char *transfer_tablename = cls->transfer_table_name; const char *notes_tablename = cls->notes_table_name; const char *hout_tablename = cls->hout_table_name; const char *hin_tablename = cls->hin_table_name; const char *cookie_tablename = cls->cookie_table_name; if (global_config.driver == NULL) { return OK; } /* We handle mass virtual hosting differently. Dynamically determine the name * of the table from the virtual server's name, and flag it for creation. */ if (global_config.massvirtual) { /* TODO: Make these configurable? */ char *access_base = "access_"; char *notes_base = "notes_"; char *hout_base = "headout_"; char *hin_base = "headin_"; char *cookie_base = "cookies_"; /* Determine the hostname and convert it to all lower-case; */ char *servername = apr_pstrdup(orig->pool,(char *)ap_get_server_name(orig)); char *p=servername; while (*p) { *p = apr_tolower(*p); if (*p == '.') *p = '_'; if (*p == '-') *p = '_'; ++p; } /* Find memory long enough to hold the table name + \0. */ transfer_tablename = apr_pstrcat(orig->pool, access_base, servername, NULL); notes_tablename = apr_pstrcat(orig->pool, notes_base, servername, NULL); hin_tablename = apr_pstrcat(orig->pool, hin_base, servername, NULL); hout_tablename = apr_pstrcat(orig->pool, hout_base, servername, NULL); cookie_tablename = apr_pstrcat(orig->pool, cookie_base, servername, NULL); /* Tell this virtual server its transfer table name, and * turn on create_tables, which is implied by massvirtual. */ global_config.createtables = 1; } /* Do we have enough info to log? */ if (!transfer_tablename) { return DECLINED; } else { const char *thehost; const char *theitem; char *fields = "", *values = ""; char *itemsets = ""; char *note_query = NULL; char *hin_query = NULL; char *hout_query = NULL; char *cookie_query = NULL; const char *unique_id; const char *formatted_item; int i,length; int proceed; for (r = orig; r->next; r = r->next) { continue; } /* The following is a stolen upsetting mess of pointers, I'm sorry. * Anyone with the motiviation and/or the time should feel free * to make this cleaner. :) */ ptrptr2 = (char **) (cls->transfer_accept_list->elts + (cls->transfer_accept_list->nelts * cls->transfer_accept_list->elt_size)); /* Go through each element of the accept list and compare it to the * request_uri. If we don't get a match, return without logging */ if ((r->uri) && (cls->transfer_accept_list->nelts)) { proceed = 0; for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size)) if (ap_strstr(r->uri, *ptrptr)) { proceed = 1; break; } if (!proceed) return OK; } /* Go through each element of the ignore list and compare it to the * request_uri. If we get a match, return without logging */ ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); if (r->uri) { for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) if (ap_strstr(r->uri, *ptrptr)) { return OK; } } /* Go through each element of the ignore list and compare it to the * remote host. If we get a match, return without logging */ ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size)); thehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); if (thehost) { for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size)) if (ap_strstr(thehost, *ptrptr)) { return OK; } } /* Iterate through the format characters and set up the INSERT string according to * what the user has configured. */ length = strlen(cls->transfer_log_format); for (i = 0; i<length; i++) { logsql_item *item = cls->parsed_log_format[i]; if (item==NULL) { log_error(APLOG_MARK, APLOG_ERR, 0, orig->server, "Log Format '%c' unknown",cls->transfer_log_format[i]); continue; } /* Yes, this key is one of the configured keys. * Call the key's function and put the returned value into 'formatted_item' */ formatted_item = item->func(item->want_orig_default ? orig : r, ""); /* Massage 'formatted_item' for proper SQL eligibility... */ if (!formatted_item) { formatted_item = ""; } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !item->string_contents) { /* If apache tried to log a '-' character for a numeric field, convert that to a zero * because the database expects a numeral and will reject the '-' character. */ formatted_item = "0"; } /* Append the fieldname and value-to-insert to the appropriate strings, quoting stringvals with ' as appropriate */ fields = apr_pstrcat(r->pool, fields, (i ? "," : ""), item->sql_field_name, NULL); values = apr_pstrcat(r->pool, values, (i ? "," : ""), global_config.driver->escape(formatted_item, r->pool,&global_config.db), NULL); } /* Work through the list of notes defined by LogSQLWhichNotes */ i = 0; unique_id = extract_unique_id(r, ""); ptrptr2 = (char **) (cls->notes_list->elts + (cls->notes_list->nelts * cls->notes_list->elt_size)); for (ptrptr = (char **) cls->notes_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->notes_list->elt_size)) { /* If the specified note (*ptrptr) exists for the current request... */ if ((theitem = apr_table_get(r->notes, *ptrptr))) { itemsets = apr_pstrcat(r->pool, itemsets, (i > 0 ? "," : ""), "(", global_config.driver->escape(unique_id, r->pool, &global_config.db), ",", global_config.driver->escape(*ptrptr, r->pool,&global_config.db), ",", global_config.driver->escape(theitem, r->pool,&global_config.db), ")", NULL); i++; } } if ( *itemsets != '\0' ) { note_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", /*global_config.insertdelayed?"delayed":*/"", notes_tablename, itemsets); log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: note string: %s", note_query); } /* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/ i = 0; itemsets = ""; ptrptr2 = (char **) (cls->hout_list->elts + (cls->hout_list->nelts * cls->hout_list->elt_size)); for (ptrptr = (char **) cls->hout_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hout_list->elt_size)) { /* If the specified header (*ptrptr) exists for the current request... */ if ((theitem = apr_table_get(r->headers_out, *ptrptr))) { itemsets = apr_pstrcat(r->pool, itemsets, (i > 0 ? "," : ""), "(", global_config.driver->escape(unique_id, r->pool, &global_config.db), ",", global_config.driver->escape(*ptrptr, r->pool,&global_config.db), ",", global_config.driver->escape(theitem, r->pool,&global_config.db), ")", NULL); i++; } } if ( *itemsets != '\0' ) { hout_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", /*global_config.insertdelayed?"delayed":*/"", hout_tablename, itemsets); log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_out string: %s", hout_query); } /* Work through the list of headers-in defined by LogSQLWhichHeadersIn */ i = 0; itemsets = ""; ptrptr2 = (char **) (cls->hin_list->elts + (cls->hin_list->nelts * cls->hin_list->elt_size)); for (ptrptr = (char **) cls->hin_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hin_list->elt_size)) { /* If the specified header (*ptrptr) exists for the current request... */ if ((theitem = apr_table_get(r->headers_in, *ptrptr))) { itemsets = apr_pstrcat(r->pool, itemsets, (i > 0 ? "," : ""), "(", global_config.driver->escape(unique_id, r->pool, &global_config.db), ",", global_config.driver->escape(*ptrptr, r->pool,&global_config.db), ",", global_config.driver->escape(theitem, r->pool,&global_config.db), ")", NULL); i++; } } if ( *itemsets != '\0' ) { hin_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", /*global_config.insertdelayed?"delayed":*/"", hin_tablename, itemsets); log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_in string: %s", hin_query); } /* Work through the list of cookies defined by LogSQLWhichCookies */ i = 0; itemsets = ""; ptrptr2 = (char **) (cls->cookie_list->elts + (cls->cookie_list->nelts * cls->cookie_list->elt_size)); for (ptrptr = (char **) cls->cookie_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->cookie_list->elt_size)) { /* If the specified cookie (*ptrptr) exists for the current request... */ if ( strncmp((theitem = extract_specific_cookie(r, *ptrptr)), "-", 1) ) { itemsets = apr_pstrcat(r->pool, itemsets, (i > 0 ? "," : ""), "(", global_config.driver->escape(unique_id, r->pool, &global_config.db), ",", global_config.driver->escape(*ptrptr, r->pool,&global_config.db), ",", global_config.driver->escape(theitem, r->pool,&global_config.db), ")", NULL); i++; } } if ( *itemsets != '\0' ) { cookie_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", /*global_config.insertdelayed?"delayed":*/"", cookie_tablename, itemsets); log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: cookie string: %s", cookie_query); } /* Set up the actual INSERT statement */ access_query = apr_psprintf(r->pool, "insert %s into %s (%s) values (%s)", /*global_config.insertdelayed?"delayed":*/"", transfer_tablename, fields, values); log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"mod_log_sql: access string: %s", access_query); /* If the person activated force-preserve, go ahead and push all the entries * into the preserve file, then return. */ if (global_config.forcepreserve) { log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: preservation forced"); preserve_entry(orig, access_query); if ( note_query != NULL ) preserve_entry(orig, note_query); if ( hin_query != NULL ) preserve_entry(orig, hin_query); if ( hout_query != NULL ) preserve_entry(orig, hout_query); if ( cookie_query != NULL ) preserve_entry(orig, cookie_query); return OK; } /* How's our mysql link integrity? */ if (!global_config.db.connected) { if (!global_config.forcepreserve) { /* Make a try to establish the link */ log_sql_opendb_link(r->server); } if (!global_config.db.connected) { /* Unable to re-establish a DB link, so assume that it's really * gone and send the entry to the preserve file instead. * This short-circuits safe_sql_query() during a db outage and therefore * we don't keep logging the db error over and over. */ preserve_entry(orig, access_query); if ( note_query != NULL ) preserve_entry(orig, note_query); if ( hin_query != NULL ) preserve_entry(orig, hin_query); if ( hout_query != NULL ) preserve_entry(orig, hout_query); if ( cookie_query != NULL ) preserve_entry(orig, cookie_query); return OK; } else { /* Whew, we got the DB link back */ log_error(APLOG_MARK,APLOG_NOTICE,0, orig->server,"mod_log_sql: child established database connection"); } } /* ---> So as of here we have a non-null value of mysql_log. <--- */ /* ---> i.e. we have a good MySQL connection. <--- */ /* Make the access-table insert */ safe_sql_insert(orig,LOGSQL_TABLE_ACCESS,transfer_tablename,access_query); /* Log the optional notes, headers, etc. */ if (note_query) safe_sql_insert(orig, LOGSQL_TABLE_NOTES,notes_tablename,note_query); if (hout_query) safe_sql_insert(orig, LOGSQL_TABLE_HEADERSOUT,hout_tablename,hout_query); if (hin_query) safe_sql_insert(orig, LOGSQL_TABLE_HEADERSIN,hin_tablename,hin_query); if (cookie_query) safe_sql_insert(orig, LOGSQL_TABLE_COOKIES,cookie_tablename,cookie_query); return OK; } }
/* * 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 respects the setting of UseCanonicalName so that * the dynamic mass virtual hosting trick works better. */ static const char *log_server_name(request_rec *r, char *a) { return ap_get_server_name(r); }
/** * 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; } }
/** * Extended internal log helper function. Use msr_log instead. If fixup is * true, the message will be stripped of any trailing newline and any * required bytes will be escaped. */ static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec *msr, int level, int fixup, const char *text, va_list ap) { apr_size_t nbytes, nbytes_written; apr_file_t *debuglog_fd = NULL; int filter_debug_level = 0; char *remote = NULL; char *parse_remote = NULL; char *saved = NULL; char *str = NULL; char str1[1024] = ""; char str2[1256] = ""; /* Find the logging FD and determine the logging level from configuration. */ if (dcfg != NULL) { if ((dcfg->debuglog_fd != NULL)&&(dcfg->debuglog_fd != NOT_SET_P)) { debuglog_fd = dcfg->debuglog_fd; } if (dcfg->debuglog_level != NOT_SET) { filter_debug_level = dcfg->debuglog_level; } } /* Return immediately if we don't have where to write * or if the log level of the message is higher than * wanted in the log. */ if ((level > 3)&&( (debuglog_fd == NULL) || (level > filter_debug_level) )) return; /* Construct the message. */ apr_vsnprintf(str1, sizeof(str1), text, ap); if (fixup) { int len = strlen(str1); /* Strip line ending. */ if (len && str1[len - 1] == '\n') { str1[len - 1] = '\0'; } if (len > 1 && str1[len - 2] == '\r') { str1[len - 2] = '\0'; } } /* Construct the log entry. */ apr_snprintf(str2, sizeof(str2), "[%s] [%s/sid#%pp][rid#%pp][%s][%d] %s\n", current_logtime(msr->mp), ap_get_server_name(r), (r->server), r, ((r->uri == NULL) ? "" : log_escape_nq(msr->mp, r->uri)), level, (fixup ? log_escape_nq(msr->mp, str1) : str1)); /* Write to the debug log. */ if ((debuglog_fd != NULL)&&(level <= filter_debug_level)) { nbytes = strlen(str2); apr_file_write_full(debuglog_fd, str2, nbytes, &nbytes_written); } /* Send message levels 1-3 to the Apache error log and * add it to the message list in the audit log. */ if (level <= 3) { char *unique_id = (char *)get_env_var(r, "UNIQUE_ID"); char *hostname = (char *)msr->hostname; if (unique_id != NULL) { unique_id = apr_psprintf(msr->mp, " [unique_id \"%s\"]", log_escape(msr->mp, unique_id)); } else unique_id = ""; if (hostname != NULL) { hostname = apr_psprintf(msr->mp, " [hostname \"%s\"]", log_escape(msr->mp, hostname)); } else hostname = ""; #if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2 ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "[client %s] ModSecurity: %s%s [uri \"%s\"]%s", r->useragent_ip ? r->useragent_ip : r->connection->client_ip, str1, hostname, log_escape(msr->mp, r->uri), unique_id); #else ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server, "[client %s] ModSecurity: %s%s [uri \"%s\"]%s", msr->remote_addr ? msr->remote_addr : r->connection->remote_ip, str1, hostname, log_escape(msr->mp, r->uri), unique_id); #endif /* Add this message to the list. */ if (msr != NULL) { /* Force relevency if this is an alert */ msr->is_relevant++; *(const char **)apr_array_push(msr->alerts) = apr_pstrdup(msr->mp, str1); } } return; }
static int webid_auth_checker(request_rec *r) { int is_initial_req, req_access, req_method, ret; const char *req_dest; request_rec *r_dest; apr_uri_t apr_uri; if (r->filename == NULL) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "Module bug? Request filename is missing for URI %s", r->uri); return http_status_code(r, OK); } if (r->user == NULL || strlen(r->user) == 0) { return http_status_code(r, HTTP_FORBIDDEN); } // req_access: Read, Write, or Control is_initial_req = ap_is_initial_req(r); req_access = WEBID_ACCESS_INVALID; req_method = (AP_METHOD_BIT << r->method_number); if (is_initial_req && r->method_number == M_COPY) { // allow COPY of a readonly source URI // - target URI check happens by subrequest req_access = WEBID_ACCESS_READ; } else if (req_method == (req_method & WEBID_M_READ)) { // check the acl:Read method bitmask req_access = WEBID_ACCESS_READ; } else if (req_method == (req_method & WEBID_M_WRITE)) { // check the acl:Write method bitmask // - writes to ACL URIs are acl:Control (handled internally) req_access = WEBID_ACCESS_WRITE; } else { // unhandled methods require acl:Control req_access = WEBID_ACCESS_CONTROL; } ret = HTTP_FORBIDDEN; if (is_initial_req && (r->method_number == M_COPY || r->method_number == M_MOVE)) { req_dest = apr_table_get(r->headers_in, "Destination"); if (req_dest == NULL) { const char *nscp_host = apr_table_get(r->headers_in, "Host"); const char *nscp_path = apr_table_get(r->headers_in, "New-uri"); if (nscp_host != NULL && nscp_path != NULL) req_dest = apr_psprintf(r->pool, "http://%s%s", nscp_host, nscp_path); } if (req_dest != NULL) { if ((apr_uri_parse(r->pool, req_dest, &apr_uri) == APR_SUCCESS) && (apr_uri.scheme != NULL && strcmp(apr_uri.scheme, ap_http_scheme(r)) == 0) && (apr_uri.hostname != NULL && strcmp(apr_uri.hostname, ap_get_server_name(r)) == 0)) { req_dest = apr_uri_unparse(r->pool, &apr_uri, APR_URI_UNP_OMITSITEPART); r_dest = ap_sub_req_method_uri(r->method, req_dest, r, NULL); if ((ret = check_request_acl(r, req_access)) == OK) ret = check_request_acl(r_dest, WEBID_ACCESS_WRITE); } else { ret = HTTP_BAD_GATEWAY; } } } else { ret = check_request_acl(r, req_access); } return http_status_code(r, ret); }
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; }
/* run in post_read_request hook */ static int ruid_setup (request_rec *r) { /* We decline when we are in a subrequest. The ruid_setup function was * already executed in the main request. */ if (!ap_is_initial_req(r)) { return DECLINED; } ruid_config_t *conf = ap_get_module_config (r->server->module_config, &ruid2_module); ruid_dir_config_t *dconf = ap_get_module_config(r->per_dir_config, &ruid2_module); core_server_config *core = (core_server_config *) ap_get_module_config(r->server->module_config, &core_module); int ncap=0; cap_t cap; cap_value_t capval[2]; if (dconf->ruid_mode==RUID_MODE_STAT) capval[ncap++] = CAP_DAC_READ_SEARCH; if (root_handle != UNSET) capval[ncap++] = CAP_SYS_CHROOT; if (ncap) { cap=cap_get_proc(); cap_set_flag(cap, CAP_EFFECTIVE, ncap, capval, CAP_SET); if (cap_set_proc(cap)!=0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed", MODULE_NAME, __func__); } cap_free(cap); } /* do chroot trick only if chrootdir is defined */ if (conf->chroot_dir) { old_root = ap_document_root(r); core->ap_document_root = conf->document_root; if (chdir(conf->chroot_dir) != 0) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"%s %s %s chdir to %s failed", MODULE_NAME, ap_get_server_name (r), r->the_request, conf->chroot_dir); return HTTP_FORBIDDEN; } if (chroot(conf->chroot_dir) != 0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL,"%s %s %s chroot to %s failed", MODULE_NAME, ap_get_server_name (r), r->the_request, conf->chroot_dir); return HTTP_FORBIDDEN; } cap = cap_get_proc(); capval[0] = CAP_SYS_CHROOT; cap_set_flag(cap, CAP_EFFECTIVE, 1, capval, CAP_CLEAR); if (cap_set_proc(cap) != 0 ) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed", MODULE_NAME, __func__); } cap_free(cap); } /* register suidback function */ apr_pool_cleanup_register(r->pool, r, ruid_suidback, apr_pool_cleanup_null); if (dconf->ruid_mode==RUID_MODE_CONF) { return ruid_set_perm(r, __func__); } else { return DECLINED; } }
/** * 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); } } } }
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); }
/* Manages the loadfactors and member status */ static int balancer_handler(request_rec *r) { void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); proxy_balancer *balancer, *bsel = NULL; proxy_worker *worker, *wsel = NULL; apr_table_t *params = apr_table_make(r->pool, 10); int access_status; int i, n; const char *name; /* is this for us? */ if (strcmp(r->handler, "balancer-manager")) return DECLINED; r->allowed = (AP_METHOD_BIT << M_GET); if (r->method_number != M_GET) return DECLINED; if (r->args) { char *args = apr_pstrdup(r->pool, r->args); char *tok, *val; while (args && *args) { if ((val = ap_strchr(args, '='))) { *val++ = '\0'; if ((tok = ap_strchr(val, '&'))) *tok++ = '\0'; /* * Special case: workers are allowed path information */ if ((access_status = ap_unescape_url(val)) != OK) if (strcmp(args, "w") || (access_status != HTTP_NOT_FOUND)) return access_status; apr_table_setn(params, args, val); args = tok; } else return HTTP_BAD_REQUEST; } } /* Check that the supplied nonce matches this server's nonce; * otherwise ignore all parameters, to prevent a CSRF attack. */ if ((name = apr_table_get(params, "nonce")) == NULL || strcmp(balancer_nonce, name) != 0) { apr_table_clear(params); } if ((name = apr_table_get(params, "b"))) bsel = ap_proxy_get_balancer(r->pool, conf, apr_pstrcat(r->pool, "balancer://", name, NULL)); if ((name = apr_table_get(params, "w"))) { proxy_worker *ws; ws = ap_proxy_get_worker(r->pool, conf, name); if (bsel && ws) { worker = (proxy_worker *)bsel->workers->elts; for (n = 0; n < bsel->workers->nelts; n++) { if (strcasecmp(worker->name, ws->name) == 0) { wsel = worker; break; } ++worker; } } } /* First set the params */ /* * Note that it is not possible set the proxy_balancer because it is not * in shared memory. */ if (wsel) { const char *val; if ((val = apr_table_get(params, "lf"))) { int ival = atoi(val); if (ival >= 1 && ival <= 100) { wsel->s->lbfactor = ival; if (bsel) recalc_factors(bsel); } } if ((val = apr_table_get(params, "wr"))) { if (strlen(val) && strlen(val) < PROXY_WORKER_MAX_ROUTE_SIZ) strcpy(wsel->s->route, val); else *wsel->s->route = '\0'; } if ((val = apr_table_get(params, "rr"))) { if (strlen(val) && strlen(val) < PROXY_WORKER_MAX_ROUTE_SIZ) strcpy(wsel->s->redirect, val); else *wsel->s->redirect = '\0'; } if ((val = apr_table_get(params, "dw"))) { if (!strcasecmp(val, "Disable")) wsel->s->status |= PROXY_WORKER_DISABLED; else if (!strcasecmp(val, "Enable")) wsel->s->status &= ~PROXY_WORKER_DISABLED; } if ((val = apr_table_get(params, "ls"))) { int ival = atoi(val); if (ival >= 0 && ival <= 99) { wsel->s->lbset = ival; } } } if (apr_table_get(params, "xml")) { ap_set_content_type(r, "text/xml"); ap_rputs("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n", r); ap_rputs("<httpd:manager xmlns:httpd=\"http://httpd.apache.org\">\n", r); ap_rputs(" <httpd:balancers>\n", r); balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { ap_rputs(" <httpd:balancer>\n", r); ap_rvputs(r, " <httpd:name>", balancer->name, "</httpd:name>\n", NULL); ap_rputs(" <httpd:workers>\n", r); worker = (proxy_worker *)balancer->workers->elts; for (n = 0; n < balancer->workers->nelts; n++) { ap_rputs(" <httpd:worker>\n", r); ap_rvputs(r, " <httpd:scheme>", worker->scheme, "</httpd:scheme>\n", NULL); ap_rvputs(r, " <httpd:hostname>", worker->hostname, "</httpd:hostname>\n", NULL); ap_rprintf(r, " <httpd:loadfactor>%d</httpd:loadfactor>\n", worker->s->lbfactor); ap_rputs(" </httpd:worker>\n", r); ++worker; } ap_rputs(" </httpd:workers>\n", r); ap_rputs(" </httpd:balancer>\n", r); ++balancer; } ap_rputs(" </httpd:balancers>\n", r); ap_rputs("</httpd:manager>", r); } else { ap_set_content_type(r, "text/html; charset=ISO-8859-1"); ap_rputs(DOCTYPE_HTML_3_2 "<html><head><title>Balancer Manager</title></head>\n", r); ap_rputs("<body><h1>Load Balancer Manager for ", r); ap_rvputs(r, ap_get_server_name(r), "</h1>\n\n", NULL); ap_rvputs(r, "<dl><dt>Server Version: ", ap_get_server_description(), "</dt>\n", NULL); ap_rvputs(r, "<dt>Server Built: ", ap_get_server_built(), "\n</dt></dl>\n", NULL); balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { ap_rputs("<hr />\n<h3>LoadBalancer Status for ", r); ap_rvputs(r, balancer->name, "</h3>\n\n", NULL); ap_rputs("\n\n<table border=\"0\" style=\"text-align: left;\"><tr>" "<th>StickySession</th><th>Timeout</th><th>FailoverAttempts</th><th>Method</th>" "</tr>\n<tr>", r); if (balancer->sticky) { ap_rvputs(r, "<td>", balancer->sticky, NULL); } else { ap_rputs("<td> - ", r); } ap_rprintf(r, "</td><td>%" APR_TIME_T_FMT "</td>", apr_time_sec(balancer->timeout)); ap_rprintf(r, "<td>%d</td>\n", balancer->max_attempts); ap_rprintf(r, "<td>%s</td>\n", balancer->lbmethod->name); ap_rputs("</table>\n<br />", r); ap_rputs("\n\n<table border=\"0\" style=\"text-align: left;\"><tr>" "<th>Worker URL</th>" "<th>Route</th><th>RouteRedir</th>" "<th>Factor</th><th>Set</th><th>Status</th>" "<th>Elected</th><th>To</th><th>From</th>" "</tr>\n", r); worker = (proxy_worker *)balancer->workers->elts; for (n = 0; n < balancer->workers->nelts; n++) { char fbuf[50]; ap_rvputs(r, "<tr>\n<td><a href=\"", r->uri, "?b=", balancer->name + sizeof("balancer://") - 1, "&w=", ap_escape_uri(r->pool, worker->name), "&nonce=", balancer_nonce, "\">", NULL); ap_rvputs(r, worker->name, "</a></td>", NULL); ap_rvputs(r, "<td>", ap_escape_html(r->pool, worker->s->route), NULL); ap_rvputs(r, "</td><td>", ap_escape_html(r->pool, worker->s->redirect), NULL); ap_rprintf(r, "</td><td>%d</td>", worker->s->lbfactor); ap_rprintf(r, "<td>%d</td><td>", worker->s->lbset); if (worker->s->status & PROXY_WORKER_DISABLED) ap_rputs("Dis ", r); if (worker->s->status & PROXY_WORKER_IN_ERROR) ap_rputs("Err ", r); if (worker->s->status & PROXY_WORKER_STOPPED) ap_rputs("Stop ", r); if (worker->s->status & PROXY_WORKER_HOT_STANDBY) ap_rputs("Stby ", r); if (PROXY_WORKER_IS_USABLE(worker)) ap_rputs("Ok", r); if (!PROXY_WORKER_IS_INITIALIZED(worker)) ap_rputs("-", r); ap_rputs("</td>", r); ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>", worker->s->elected); ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r); ap_rputs("</td><td>", r); ap_rputs(apr_strfsize(worker->s->read, fbuf), r); ap_rputs("</td></tr>\n", r); ++worker; } ap_rputs("</table>\n", r); ++balancer; } ap_rputs("<hr />\n", r); if (wsel && bsel) { ap_rputs("<h3>Edit worker settings for ", r); ap_rvputs(r, wsel->name, "</h3>\n", NULL); ap_rvputs(r, "<form method=\"GET\" action=\"", NULL); ap_rvputs(r, r->uri, "\">\n<dl>", NULL); ap_rputs("<table><tr><td>Load factor:</td><td><input name=\"lf\" type=text ", r); ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbfactor); ap_rputs("<tr><td>LB Set:</td><td><input name=\"ls\" type=text ", r); ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbset); ap_rputs("<tr><td>Route:</td><td><input name=\"wr\" type=text ", r); ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->route), NULL); ap_rputs("\"></td></tr>\n", r); ap_rputs("<tr><td>Route Redirect:</td><td><input name=\"rr\" type=text ", r); ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->redirect), NULL); ap_rputs("\"></td></tr>\n", r); ap_rputs("<tr><td>Status:</td><td>Disabled: <input name=\"dw\" value=\"Disable\" type=radio", r); if (wsel->s->status & PROXY_WORKER_DISABLED) ap_rputs(" checked", r); ap_rputs("> | Enabled: <input name=\"dw\" value=\"Enable\" type=radio", r); if (!(wsel->s->status & PROXY_WORKER_DISABLED)) ap_rputs(" checked", r); ap_rputs("></td></tr>\n", r); ap_rputs("<tr><td colspan=2><input type=submit value=\"Submit\"></td></tr>\n", r); ap_rvputs(r, "</table>\n<input type=hidden name=\"w\" ", NULL); ap_rvputs(r, "value=\"", ap_escape_uri(r->pool, wsel->name), "\">\n", NULL); ap_rvputs(r, "<input type=hidden name=\"b\" ", NULL); ap_rvputs(r, "value=\"", bsel->name + sizeof("balancer://") - 1, "\">\n", NULL); ap_rvputs(r, "<input type=hidden name=\"nonce\" value=\"", balancer_nonce, "\">\n", NULL); ap_rvputs(r, "</form>\n", NULL); ap_rputs("<hr />\n", r); } ap_rputs(ap_psignature("",r), r); ap_rputs("</body></html>\n", r); } 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); } }
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); }
static logsql_query_ret safe_sql_insert(request_rec *r, logsql_tabletype table_type, const char *table_name, const char *query) { logsql_query_ret result; logsql_state *cls = ap_get_module_config(r->server->module_config, &log_sql_module); if (!global_config.db.connected || global_config.driver == NULL) { /* preserve query */ return LOGSQL_QUERY_NOLINK; } result = global_config.driver->insert(r,&global_config.db,query); /* If we ran the query and it returned an error, try to be robust. * (After all, the module thought it had a valid mysql_log connection but the query * could have failed for a number of reasons, so we have to be extra-safe and check.) */ switch (result) { case LOGSQL_QUERY_SUCCESS: return LOGSQL_QUERY_SUCCESS; case LOGSQL_QUERY_NOLINK: return LOGSQL_QUERY_FAIL; /* TODO: What do we do here */ case LOGSQL_QUERY_FAIL: global_config.driver->disconnect(&global_config.db); global_config.db.connected = 0; /* re-open the connection and try again */ if (log_sql_opendb_link(r->server) != LOGSQL_OPENDB_FAIL) { log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,"db reconnect successful"); # if defined(WITH_APACHE20) apr_sleep(apr_time_from_sec(0.25)); /* pause for a quarter second */ # elif defined(WITH_APACHE13) # if defined(WIN32) Sleep((DWORD)0.25); # else { struct timespec delay, remainder; int nanoret; delay.tv_sec = 0; delay.tv_nsec = 250000000; /* pause for a quarter second */ nanoret = nanosleep(&delay, &remainder); if (nanoret && errno != EINTR) { log_error(APLOG_MARK,APLOG_ERR, errno, r->server,"nanosleep unsuccessful"); } } # endif /* win32 */ # endif result = global_config.driver->insert(r,&global_config.db,query); if (result == LOGSQL_QUERY_SUCCESS) { return LOGSQL_QUERY_SUCCESS; } else { log_error(APLOG_MARK,APLOG_ERR,0,r->server,"second attempt failed"); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } } else { log_error(APLOG_MARK,APLOG_ERR,0,r->server, "reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); log_error(APLOG_MARK,APLOG_ERR,0,r->server, "log entries are being preserved in %s",cls->preserve_file); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } break; case LOGSQL_QUERY_NOTABLE: if (global_config.createtables) { log_error(APLOG_MARK,APLOG_ERR,0,r->server, "table doesn't exist...creating now"); if ((result = global_config.driver->create_table(r, &global_config.db, table_type, table_name))!=LOGSQL_TABLE_SUCCESS) { log_error(APLOG_MARK,APLOG_ERR,result,r->server, "child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r)); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } else { log_error(APLOG_MARK,APLOG_ERR,result, r->server, "tables successfully created - retrying query"); if ((result = global_config.driver->insert(r,&global_config.db,query))!=LOGSQL_QUERY_SUCCESS) { log_error(APLOG_MARK,APLOG_ERR,result, r->server, "giving up, preserving query"); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } else { log_error(APLOG_MARK,APLOG_NOTICE,0, r->server, "query successful after table creation"); return LOGSQL_QUERY_SUCCESS; } } } else { log_error(APLOG_MARK,APLOG_ERR,0,r->server, "table doesn't exist, creation denied by configuration, preserving query"); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } break; default: log_error(APLOG_MARK,APLOG_ERR,0, r->server, "Invalid return code from mog_log_query"); return LOGSQL_QUERY_FAIL; break; } return LOGSQL_QUERY_FAIL; }
static int xlate_name(request_rec *r) { int i; const char *name; char *backend; apr_dbm_t *db; apr_status_t rv; apr_datum_t key, val; struct proxy_alias *ralias; proxy_dir_conf *dconf; express_server_conf *sconf; sconf = ap_get_module_config(r->server->module_config, &proxy_express_module); dconf = ap_get_module_config(r->per_dir_config, &proxy_module); if (!sconf->enabled) { return DECLINED; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01001) "proxy_express: Enabled"); if (!sconf->dbmfile || (r->filename && strncmp(r->filename, "proxy:", 6) == 0)) { /* it should be go on as an internal proxy request */ return DECLINED; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01002) "proxy_express: Opening DBM file: %s (%s)", sconf->dbmfile, sconf->dbmtype); rv = apr_dbm_open_ex(&db, sconf->dbmtype, sconf->dbmfile, APR_DBM_READONLY, APR_OS_DEFAULT, r->pool); if (rv != APR_SUCCESS) { return DECLINED; } name = ap_get_server_name(r); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01003) "proxy_express: looking for %s", name); key.dptr = (char *)name; key.dsize = strlen(key.dptr); rv = apr_dbm_fetch(db, key, &val); apr_dbm_close(db); if (rv != APR_SUCCESS) { return DECLINED; } backend = apr_pstrmemdup(r->pool, val.dptr, val.dsize); if (!backend) { return DECLINED; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01004) "proxy_express: found %s -> %s", name, backend); r->filename = apr_pstrcat(r->pool, "proxy:", backend, r->uri, NULL); r->handler = "proxy-server"; r->proxyreq = PROXYREQ_REVERSE; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01005) "proxy_express: rewritten as: %s", r->filename); ralias = (struct proxy_alias *)dconf->raliases->elts; /* * See if we have already added a ProxyPassReverse entry * for this host... If so, don't do it again. */ /* * NOTE: dconf is process specific so this wil only * work as long as we maintain that this process * or thread is handling the backend */ for (i = 0; i < dconf->raliases->nelts; i++, ralias++) { if (strcasecmp(backend, ralias->real) == 0) { ralias = NULL; break; } } /* Didn't find one... add it */ if (!ralias) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01006) "proxy_express: adding PPR entry"); ralias = apr_array_push(dconf->raliases); ralias->fake = "/"; ralias->real = apr_pstrdup(dconf->raliases->pool, backend); ralias->flags = 0; } return OK; }
static int aclr_handler(request_rec *r) { int rc; const char *idhead; char *real_uri; const char *docroot; size_t docroot_len; ap_filter_t *f, *nextf; char iredirect[MAX_STRING_LEN]; aclr_dir_config *cfg = (aclr_dir_config *)ap_get_module_config (r->per_dir_config, &aclr_module); if (cfg->state != ACLR_ENABLED) { return DECLINED; } if (!ap_is_initial_req(r)) { return DECLINED; } idhead = apr_table_get(r->headers_in, xa_int_name); if (idhead == NULL) { return DECLINED; } #ifdef DEBUG const char *server_name = ap_get_server_name(r); #endif docroot = ap_document_root(r); docroot_len = strlen(docroot); /* obtain real URI from filename - for rewrited URIs */ if (strncmp(r->filename, docroot, docroot_len) != 0) { if (cfg->redirect_outside_of_docroot != ACLR_ENABLED) { aclr_debug(2, r->server, "file \"%s\" is outside of " "DocumentRoot \"%s\": %s%s", r->filename, docroot, server_name, r->uri); return DECLINED; } real_uri = r->uri; } else { real_uri = r->filename; real_uri += docroot_len; } snprintf(iredirect, sizeof(iredirect), "%s%s", idhead, real_uri); aclr_debug(3, r->server, "trying to process request: %s%s -> %s", server_name, r->uri, iredirect); aclr_debug(3, r->server, "r->filename: %s", r->filename); aclr_debug(3, r->server, "r->uri: %s", r->uri); aclr_debug(3, r->server, "docroot: %s", docroot); aclr_debug(3, r->server, "real_uri: %s", real_uri); if ((rc = ap_discard_request_body(r)) != OK) { return rc; } apr_table_set(r->headers_out, xa_ver_name, ACLR_VERSION); if ((r->method_number != M_GET) || (r->header_only)) { aclr_debug(2, r->server, "request method is not GET: %s%s", server_name, r->uri); return DECLINED; } if (r->finfo.filetype != APR_REG) { aclr_debug(2, r->server, "request file not found " "or is not regular file: %s%s", server_name, r->uri); return DECLINED; } if (cfg->fsize != UNSET && r->finfo.size < cfg->fsize) { aclr_debug(2, r->server, "file size %lu < minsize %lu: %s%s", r->finfo.size, cfg->fsize, server_name, r->uri); return DECLINED; } f = r->output_filters; do { nextf = f->next; aclr_debug(3, r->server, "output filter: %s", f->frec->name); if (strcmp(f->frec->name, "includes") == 0) { aclr_debug(2, r->server, "request uses INCLUDES filter: %s%s", server_name, r->uri); return DECLINED; } f = nextf; } while (f && f != r->proto_output_filters); apr_table_set(r->headers_out, xa_redir_name, iredirect); r->header_only = 0; ap_update_mtime(r, r->finfo.mtime); aclr_debug(1, r->server, "request %s%s redirected to %s", server_name, r->uri, iredirect); return OK; }
/* This respects the setting of UseCanonicalName so that * the dynamic mass virtual hosting trick works better. */ static const char *log_server_name(request_rec *r, char *a) { return ap_escape_logitem(r->pool, ap_get_server_name(r)); }