static int mag_auth(request_rec *req) { const char *type; struct mag_config *cfg; const char *auth_header; char *auth_header_type; char *auth_header_value; int ret = HTTP_UNAUTHORIZED; gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; gss_ctx_id_t *pctx; gss_buffer_desc input = GSS_C_EMPTY_BUFFER; gss_buffer_desc output = GSS_C_EMPTY_BUFFER; gss_buffer_desc name = GSS_C_EMPTY_BUFFER; gss_name_t client = GSS_C_NO_NAME; gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL; gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL; uint32_t flags; uint32_t vtime; uint32_t maj, min; char *reply; size_t replen; char *clientname; gss_OID mech_type = GSS_C_NO_OID; gss_buffer_desc lname = GSS_C_EMPTY_BUFFER; struct mag_conn *mc = NULL; type = ap_auth_type(req); if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) { return DECLINED; } /* ignore auth for subrequests */ if (!ap_is_initial_req(req)) { return OK; } cfg = ap_get_module_config(req->per_dir_config, &auth_gssapi_module); if (cfg->ssl_only) { if (!mag_conn_is_https(req->connection)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "Not a TLS connection, refusing to authenticate!"); goto done; } } if (cfg->gss_conn_ctx) { mc = (struct mag_conn *)ap_get_module_config( req->connection->conn_config, &auth_gssapi_module); if (!mc) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, req, "Failed to retrieve connection context!"); goto done; } } /* if available, session always supersedes connection bound data */ mag_check_session(req, cfg, &mc); if (mc) { /* register the context in the memory pool, so it can be freed * when the connection/request is terminated */ apr_pool_userdata_set(mc, "mag_conn_ptr", mag_conn_destroy, mc->parent); if (mc->established) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, req, "Already established context found!"); apr_table_set(req->subprocess_env, "GSS_NAME", mc->gss_name); req->ap_auth_type = apr_pstrdup(req->pool, "Negotiate"); req->user = apr_pstrdup(req->pool, mc->user_name); ret = OK; goto done; } pctx = &mc->ctx; } else { pctx = &ctx; } auth_header = apr_table_get(req->headers_in, "Authorization"); if (!auth_header) goto done; auth_header_type = ap_getword_white(req->pool, &auth_header); if (!auth_header_type) goto done; if (strcasecmp(auth_header_type, "Negotiate") != 0) goto done; auth_header_value = ap_getword_white(req->pool, &auth_header); if (!auth_header_value) goto done; input.length = apr_base64_decode_len(auth_header_value) + 1; input.value = apr_pcalloc(req->pool, input.length); if (!input.value) goto done; input.length = apr_base64_decode(input.value, auth_header_value); #ifdef HAVE_GSS_ACQUIRE_CRED_FROM if (cfg->use_s4u2proxy) { maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, 0, GSS_C_NO_OID_SET, GSS_C_BOTH, cfg->cred_store, &acquired_cred, NULL, NULL); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s", mag_error(req, "gss_acquire_cred_from() failed", maj, min)); goto done; } } #endif maj = gss_accept_sec_context(&min, pctx, acquired_cred, &input, GSS_C_NO_CHANNEL_BINDINGS, &client, &mech_type, &output, &flags, &vtime, &delegated_cred); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s", mag_error(req, "gss_accept_sec_context() failed", maj, min)); goto done; } if (maj == GSS_S_CONTINUE_NEEDED) { if (!mc) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "Mechanism needs continuation but neither " "GssapiConnectionBound nor " "GssapiUseSessions are available"); gss_delete_sec_context(&min, pctx, GSS_C_NO_BUFFER); gss_release_buffer(&min, &output); output.length = 0; } /* auth not complete send token and wait next packet */ goto done; } req->ap_auth_type = apr_pstrdup(req->pool, "Negotiate"); /* Always set the GSS name in an env var */ maj = gss_display_name(&min, client, &name, NULL); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s", mag_error(req, "gss_accept_sec_context() failed", maj, min)); goto done; } clientname = apr_pstrndup(req->pool, name.value, name.length); apr_table_set(req->subprocess_env, "GSS_NAME", clientname); #ifdef HAVE_GSS_STORE_CRED_INTO if (cfg->deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL) { char *ccachefile = NULL; mag_store_deleg_creds(req, cfg->deleg_ccache_dir, clientname, delegated_cred, &ccachefile); if (ccachefile) { apr_table_set(req->subprocess_env, "KRB5CCNAME", ccachefile); } } #endif if (cfg->map_to_local) { maj = gss_localname(&min, client, mech_type, &lname); if (maj != GSS_S_COMPLETE) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s", mag_error(req, "gss_localname() failed", maj, min)); goto done; } req->user = apr_pstrndup(req->pool, lname.value, lname.length); } else { req->user = clientname; } if (mc) { mc->user_name = apr_pstrdup(mc->parent, req->user); mc->gss_name = apr_pstrdup(mc->parent, clientname); mc->established = true; if (vtime == GSS_C_INDEFINITE || vtime < MIN_SESS_EXP_TIME) { vtime = MIN_SESS_EXP_TIME; } mc->expiration = time(NULL) + vtime; mag_attempt_session(req, cfg, mc); } ret = OK; done: if (ret == HTTP_UNAUTHORIZED) { if (output.length != 0) { replen = apr_base64_encode_len(output.length) + 1; reply = apr_pcalloc(req->pool, 10 + replen); if (reply) { memcpy(reply, "Negotiate ", 10); apr_base64_encode(&reply[10], output.value, output.length); apr_table_add(req->err_headers_out, "WWW-Authenticate", reply); } } else { apr_table_add(req->err_headers_out, "WWW-Authenticate", "Negotiate"); } } gss_release_cred(&min, &delegated_cred); gss_release_buffer(&min, &output); gss_release_name(&min, &client); gss_release_buffer(&min, &name); gss_release_buffer(&min, &lname); return ret; }
static apr_status_t substitute_filter(ap_filter_t *f, apr_bucket_brigade *bb) { apr_size_t bytes; apr_size_t len; apr_size_t fbytes; const char *buff; const char *nl = NULL; char *bflat; apr_bucket *b; apr_bucket *tmp_b; apr_bucket_brigade *tmp_bb = NULL; apr_status_t rv; subst_dir_conf *cfg = (subst_dir_conf *) ap_get_module_config(f->r->per_dir_config, &substitute_module); substitute_module_ctx *ctx = f->ctx; /* * First time around? Create the saved bb that we used for each pass * through. Note that we can also get here when we explicitly clear ctx, * for error handling */ if (!ctx) { f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx)); /* * Create all the temporary brigades we need and reuse them to avoid * creating them over and over again from r->pool which would cost a * lot of memory in some cases. */ ctx->linebb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); ctx->linesbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); ctx->pattbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); /* * Everything to be passed to the next filter goes in * here, our pass brigade. */ ctx->passbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); /* Create our temporary pool only once */ apr_pool_create(&(ctx->tpool), f->r->pool); apr_table_unset(f->r->headers_out, "Content-Length"); } /* * Shortcircuit processing */ if (APR_BRIGADE_EMPTY(bb)) return APR_SUCCESS; /* * Here's the concept: * Read in the data and look for newlines. Once we * find a full "line", add it to our working brigade. * If we've finished reading the brigade and we have * any left over data (not a "full" line), store that * for the next pass. * * Note: anything stored in ctx->linebb for sure does not have * a newline char, so we don't concat that bb with the * new bb, since we would spending time searching for the newline * in data we know it doesn't exist. So instead, we simply scan * our current bb and, if we see a newline, prepend ctx->linebb * to the front of it. This makes the code much less straight- * forward (otherwise we could APR_BRIGADE_CONCAT(ctx->linebb, bb) * and just scan for newlines and not bother with needing to know * when ctx->linebb needs to be reset) but also faster. We'll take * the speed. * * Note: apr_brigade_split_line would be nice here, but we * really can't use it since we need more control and we want * to re-use already read bucket data. * * See mod_include if still confused :) */ while ((b = APR_BRIGADE_FIRST(bb)) && (b != APR_BRIGADE_SENTINEL(bb))) { if (APR_BUCKET_IS_EOS(b)) { /* * if we see the EOS, then we need to pass along everything we * have. But if the ctx->linebb isn't empty, then we need to add * that to the end of what we'll be passing. */ if (!APR_BRIGADE_EMPTY(ctx->linebb)) { rv = apr_brigade_pflatten(ctx->linebb, &bflat, &fbytes, ctx->tpool); if (rv != APR_SUCCESS) goto err; if (fbytes > cfg->max_line_length) { rv = APR_ENOMEM; goto err; } tmp_b = apr_bucket_transient_create(bflat, fbytes, f->r->connection->bucket_alloc); rv = do_pattmatch(f, tmp_b, ctx->pattbb, ctx->tpool); if (rv != APR_SUCCESS) goto err; APR_BRIGADE_CONCAT(ctx->passbb, ctx->pattbb); apr_brigade_cleanup(ctx->linebb); } APR_BUCKET_REMOVE(b); APR_BRIGADE_INSERT_TAIL(ctx->passbb, b); } /* * No need to handle FLUSH buckets separately as we call * ap_pass_brigade anyway at the end of the loop. */ else if (APR_BUCKET_IS_METADATA(b)) { APR_BUCKET_REMOVE(b); APR_BRIGADE_INSERT_TAIL(ctx->passbb, b); } else { /* * We have actual "data" so read in as much as we can and start * scanning and splitting from our read buffer */ rv = apr_bucket_read(b, &buff, &bytes, APR_BLOCK_READ); if (rv != APR_SUCCESS || bytes == 0) { apr_bucket_delete(b); } else { int num = 0; while (bytes > 0) { nl = memchr(buff, APR_ASCII_LF, bytes); if (nl) { len = (apr_size_t) (nl - buff) + 1; /* split *after* the newline */ apr_bucket_split(b, len); /* * We've likely read more data, so bypass rereading * bucket data and continue scanning through this * buffer */ bytes -= len; buff += len; /* * we need b to be updated for future potential * splitting */ tmp_b = APR_BUCKET_NEXT(b); APR_BUCKET_REMOVE(b); /* * Hey, we found a newline! Don't forget the old * stuff that needs to be added to the front. So we * add the split bucket to the end, flatten the whole * bb, morph the whole shebang into a bucket which is * then added to the tail of the newline bb. */ if (!APR_BRIGADE_EMPTY(ctx->linebb)) { APR_BRIGADE_INSERT_TAIL(ctx->linebb, b); rv = apr_brigade_pflatten(ctx->linebb, &bflat, &fbytes, ctx->tpool); if (rv != APR_SUCCESS) goto err; if (fbytes > cfg->max_line_length) { /* Avoid pflattening further lines, we will * abort later on anyway. */ rv = APR_ENOMEM; goto err; } b = apr_bucket_transient_create(bflat, fbytes, f->r->connection->bucket_alloc); apr_brigade_cleanup(ctx->linebb); } rv = do_pattmatch(f, b, ctx->pattbb, ctx->tpool); if (rv != APR_SUCCESS) goto err; /* * Count how many buckets we have in ctx->passbb * so far. Yes, this is correct we count ctx->passbb * and not ctx->pattbb as we do not reset num on every * iteration. */ for (b = APR_BRIGADE_FIRST(ctx->pattbb); b != APR_BRIGADE_SENTINEL(ctx->pattbb); b = APR_BUCKET_NEXT(b)) { num++; } APR_BRIGADE_CONCAT(ctx->passbb, ctx->pattbb); /* * If the number of buckets in ctx->passbb reaches an * "insane" level, we consume much memory for all the * buckets as such. So lets flush them down the chain * in this case and thus clear ctx->passbb. This frees * the buckets memory for further processing. * Usually this condition should not become true, but * it is a safety measure for edge cases. */ if (num > AP_MAX_BUCKETS) { b = apr_bucket_flush_create( f->r->connection->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->passbb, b); rv = ap_pass_brigade(f->next, ctx->passbb); apr_brigade_cleanup(ctx->passbb); num = 0; apr_pool_clear(ctx->tpool); if (rv != APR_SUCCESS) goto err; } b = tmp_b; } else { /* * no newline in whatever is left of this buffer so * tuck data away and get next bucket */ APR_BUCKET_REMOVE(b); APR_BRIGADE_INSERT_TAIL(ctx->linebb, b); bytes = 0; } } } } if (!APR_BRIGADE_EMPTY(ctx->passbb)) { rv = ap_pass_brigade(f->next, ctx->passbb); apr_brigade_cleanup(ctx->passbb); if (rv != APR_SUCCESS) goto err; } apr_pool_clear(ctx->tpool); } /* Anything left we want to save/setaside for the next go-around */ if (!APR_BRIGADE_EMPTY(ctx->linebb)) { /* * Provide ap_save_brigade with an existing empty brigade * (ctx->linesbb) to avoid creating a new one. */ ap_save_brigade(f, &(ctx->linesbb), &(ctx->linebb), f->r->pool); tmp_bb = ctx->linebb; ctx->linebb = ctx->linesbb; ctx->linesbb = tmp_bb; } return APR_SUCCESS; err: if (rv == APR_ENOMEM) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01328) "Line too long, URI %s", f->r->uri); apr_pool_clear(ctx->tpool); return rv; }
static int open_entity(cache_handle_t *h, request_rec *r, const char *key) { apr_uint32_t format; apr_size_t len; const char *nkey; apr_status_t rc; static int error_logged = 0; disk_cache_conf *conf = ap_get_module_config(r->server->module_config, &disk_cache_module); apr_finfo_t finfo; cache_object_t *obj; cache_info *info; disk_cache_object_t *dobj; int flags; h->cache_obj = NULL; /* Look up entity keyed to 'url' */ if (conf->cache_root == NULL) { if (!error_logged) { error_logged = 1; ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "disk_cache: Cannot cache files to disk without a CacheRoot specified."); } return DECLINED; } /* Create and init the cache object */ h->cache_obj = obj = apr_pcalloc(r->pool, sizeof(cache_object_t)); obj->vobj = dobj = apr_pcalloc(r->pool, sizeof(disk_cache_object_t)); info = &(obj->info); /* Open the headers file */ dobj->prefix = NULL; /* Save the cache root */ dobj->root = apr_pstrndup(r->pool, conf->cache_root, conf->cache_root_len); dobj->root_len = conf->cache_root_len; dobj->hdrsfile = header_file(r->pool, conf, dobj, key); flags = APR_READ|APR_BINARY|APR_BUFFERED; rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool); if (rc != APR_SUCCESS) { return DECLINED; } /* read the format from the cache file */ len = sizeof(format); apr_file_read_full(dobj->hfd, &format, len, &len); if (format == VARY_FORMAT_VERSION) { apr_array_header_t* varray; apr_time_t expire; len = sizeof(expire); apr_file_read_full(dobj->hfd, &expire, len, &len); varray = apr_array_make(r->pool, 5, sizeof(char*)); rc = read_array(r, varray, dobj->hfd); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, "disk_cache: Cannot parse vary header file: %s", dobj->hdrsfile); return DECLINED; } apr_file_close(dobj->hfd); nkey = regen_key(r->pool, r->headers_in, varray, key); dobj->hashfile = NULL; dobj->prefix = dobj->hdrsfile; dobj->hdrsfile = header_file(r->pool, conf, dobj, nkey); flags = APR_READ|APR_BINARY|APR_BUFFERED; rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool); if (rc != APR_SUCCESS) { return DECLINED; } } else if (format != DISK_FORMAT_VERSION) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "cache_disk: File '%s' has a version mismatch. File had version: %d.", dobj->hdrsfile, format); return DECLINED; } else { apr_off_t offset = 0; /* This wasn't a Vary Format file, so we must seek to the * start of the file again, so that later reads work. */ apr_file_seek(dobj->hfd, APR_SET, &offset); nkey = key; } obj->key = nkey; dobj->key = nkey; dobj->name = key; dobj->datafile = data_file(r->pool, conf, dobj, nkey); dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); /* Open the data file */ flags = APR_READ|APR_BINARY; #ifdef APR_SENDFILE_ENABLED flags |= APR_SENDFILE_ENABLED; #endif rc = apr_file_open(&dobj->fd, dobj->datafile, flags, 0, r->pool); if (rc != APR_SUCCESS) { /* XXX: Log message */ return DECLINED; } rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, dobj->fd); if (rc == APR_SUCCESS) { dobj->file_size = finfo.size; } /* Read the bytes to setup the cache_info fields */ rc = file_cache_recall_mydata(dobj->hfd, info, dobj, r); if (rc != APR_SUCCESS) { /* XXX log message */ return DECLINED; } /* Initialize the cache_handle callback functions */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Recalled cached URL info header %s", dobj->name); return OK; }
/* CONNECT handler */ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, proxy_server_conf *conf, char *url, const char *proxyname, apr_port_t proxyport) { apr_pool_t *p = r->pool; apr_socket_t *sock; apr_status_t err, rv; apr_size_t i, o, nbytes; char buffer[HUGE_STRING_LEN]; apr_socket_t *client_socket = ap_get_module_config(r->connection->conn_config, &core_module); int failed; apr_pollset_t *pollset; apr_pollfd_t pollfd; const apr_pollfd_t *signalled; apr_int32_t pollcnt, pi; apr_int16_t pollevent; apr_sockaddr_t *uri_addr, *connect_addr; apr_uri_t uri; const char *connectname; int connectport = 0; /* is this for us? */ if (r->method_number != M_CONNECT) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: declining URL %s", url); return DECLINED; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: serving URL %s", url); /* * Step One: Determine Who To Connect To * * Break up the URL to determine the host to connect to */ /* we break the URL into host, port, uri */ if (APR_SUCCESS != apr_uri_parse_hostinfo(p, url, &uri)) { return ap_proxyerror(r, HTTP_BAD_REQUEST, apr_pstrcat(p, "URI cannot be parsed: ", url, NULL)); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: connecting %s to %s:%d", url, uri.hostname, uri.port); /* do a DNS lookup for the destination host */ err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, 0, p); /* are we connecting directly, or via a proxy? */ if (proxyname) { connectname = proxyname; connectport = proxyport; err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC, proxyport, 0, p); } else { connectname = uri.hostname; connectport = uri.port; connect_addr = uri_addr; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: connecting to remote proxy %s on port %d", connectname, connectport); /* check if ProxyBlock directive on this host */ if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) { return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } /* Check if it is an allowed port */ if (conf->allowed_connect_ports->nelts == 0) { /* Default setting if not overridden by AllowCONNECT */ switch (uri.port) { case APR_URI_HTTPS_DEFAULT_PORT: case APR_URI_SNEWS_DEFAULT_PORT: break; default: /* XXX can we call ap_proxyerror() here to get a nice log message? */ return HTTP_FORBIDDEN; } } else if(!allowed_port(conf, uri.port)) { /* XXX can we call ap_proxyerror() here to get a nice log message? */ return HTTP_FORBIDDEN; } /* * Step Two: Make the Connection * * We have determined who to connect to. Now make the connection. */ /* get all the possible IP addresses for the destname and loop through them * until we get a successful connection */ if (APR_SUCCESS != err) { return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p, "DNS lookup failure for: ", connectname, NULL)); } /* * At this point we have a list of one or more IP addresses of * the machine to connect to. If configured, reorder this * list so that the "best candidate" is first try. "best * candidate" could mean the least loaded server, the fastest * responding server, whatever. * * For now we do nothing, ie we get DNS round robin. * XXX FIXME */ failed = ap_proxy_connect_to_backend(&sock, "CONNECT", connect_addr, connectname, conf, r->server, r->pool); /* handle a permanent error from the above loop */ if (failed) { if (proxyname) { return DECLINED; } else { return HTTP_BAD_GATEWAY; } } /* * Step Three: Send the Request * * Send the HTTP/1.1 CONNECT request to the remote server */ /* we are acting as a tunnel - the output filter stack should * be completely empty, because when we are done here we are done completely. * We add the NULL filter to the stack to do this... */ r->output_filters = NULL; r->connection->output_filters = NULL; /* If we are connecting through a remote proxy, we need to pass * the CONNECT request on to it. */ if (proxyport) { /* FIXME: Error checking ignored. */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: sending the CONNECT request to the remote proxy"); nbytes = apr_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, r->uri); apr_socket_send(sock, buffer, &nbytes); nbytes = apr_snprintf(buffer, sizeof(buffer), "Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); apr_socket_send(sock, buffer, &nbytes); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: Returning 200 OK Status"); nbytes = apr_snprintf(buffer, sizeof(buffer), "HTTP/1.0 200 Connection Established" CRLF); ap_xlate_proto_to_ascii(buffer, nbytes); apr_socket_send(client_socket, buffer, &nbytes); nbytes = apr_snprintf(buffer, sizeof(buffer), "Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); ap_xlate_proto_to_ascii(buffer, nbytes); apr_socket_send(client_socket, buffer, &nbytes); #if 0 /* This is safer code, but it doesn't work yet. I'm leaving it * here so that I can fix it later. */ r->status = HTTP_OK; r->header_only = 1; apr_table_set(r->headers_out, "Proxy-agent: %s", ap_get_server_banner()); ap_rflush(r); #endif } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: setting up poll()"); /* * Step Four: Handle Data Transfer * * Handle two way transfer of data over the socket (this is a tunnel). */ /* r->sent_bodyct = 1;*/ if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) { apr_socket_close(sock); ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: CONNECT: error apr_pollset_create()"); return HTTP_INTERNAL_SERVER_ERROR; } /* Add client side to the poll */ pollfd.p = r->pool; pollfd.desc_type = APR_POLL_SOCKET; pollfd.reqevents = APR_POLLIN; pollfd.desc.s = client_socket; pollfd.client_data = NULL; apr_pollset_add(pollset, &pollfd); /* Add the server side to the poll */ pollfd.desc.s = sock; apr_pollset_add(pollset, &pollfd); while (1) { /* Infinite loop until error (one side closes the connection) */ if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) != APR_SUCCESS) { apr_socket_close(sock); ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: CONNECT: error apr_poll()"); return HTTP_INTERNAL_SERVER_ERROR; } #ifdef DEBUGGING ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: woke from select(), i=%d", pollcnt); #endif for (pi = 0; pi < pollcnt; pi++) { const apr_pollfd_t *cur = &signalled[pi]; if (cur->desc.s == sock) { pollevent = cur->rtnevents; if (pollevent & APR_POLLIN) { #ifdef DEBUGGING ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: sock was set"); #endif nbytes = sizeof(buffer); rv = apr_socket_recv(sock, buffer, &nbytes); if (rv == APR_SUCCESS) { o = 0; i = nbytes; while(i > 0) { nbytes = i; /* This is just plain wrong. No module should ever write directly * to the client. For now, this works, but this is high on my list of * things to fix. The correct line is: * if ((nbytes = ap_rwrite(buffer + o, nbytes, r)) < 0) * rbb */ rv = apr_socket_send(client_socket, buffer + o, &nbytes); if (rv != APR_SUCCESS) break; o += nbytes; i -= nbytes; } } else break; } else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) break; } else if (cur->desc.s == client_socket) { pollevent = cur->rtnevents; if (pollevent & APR_POLLIN) { #ifdef DEBUGGING ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: client was set"); #endif nbytes = sizeof(buffer); rv = apr_socket_recv(client_socket, buffer, &nbytes); if (rv == APR_SUCCESS) { o = 0; i = nbytes; #ifdef DEBUGGING ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: read %d from client", i); #endif while(i > 0) { nbytes = i; rv = apr_socket_send(sock, buffer + o, &nbytes); if (rv != APR_SUCCESS) break; o += nbytes; i -= nbytes; } } else break; } else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { rv = APR_EOF; break; } } else break; } if (rv != APR_SUCCESS) { break; } } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: finished with poll() - cleaning up"); /* * Step Five: Clean Up * * Close the socket and clean up */ apr_socket_close(sock); return OK; }
/** * Performs the make, if necessary */ static int make_fixup(request_rec *r) { if (!r) return HTTP_INTERNAL_SERVER_ERROR; if (r->prev) return DECLINED; // We're running in a sub-request, ignore. dir_cfg* cfg=ap_get_module_config(r->per_dir_config,&make_module); if (!cfg->onoff) // Is module turned on? return DECLINED; const char* docroot=ap_document_root(r); if (cfg->debug) { ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:onoff:%d",cfg->onoff); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:sourceRoot:%s",cfg->sourceRoot); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makefileName:%s",cfg->makefileName); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makeProgram:%s",cfg->makeProgram); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makeOptions:%s",cfg->makeOptions); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:includeFileTypes:%s",cfg->includeFileTypes); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:excludeFileTypes:%s",cfg->excludeFileTypes); // ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:excludeRegex:%s",cfg->excludeRegex); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:errorURI:%s",cfg->errorURI); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:errorCSS:%s",cfg->errorCSS); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: DocumentRoot:%s",docroot); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: URI:%s",r->uri); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Canonical Filename:%s",r->canonical_filename); } // Determine if this is a request I care about, i.e., the following is true: // The file type is in MakeIncludeFileTypes (if specified) and is not in MakeExcludeFileTypes (if specified) if (cfg->includeFileTypes || cfg->excludeFileTypes) { // Get file extension char* fname=basename(r->canonical_filename); char* ext=strchr(fname,'.'); if (ext) { if (cfg->includeFileTypes && !strcasestr(cfg->includeFileTypes,ext)) { return DECLINED; } if (cfg->excludeFileTypes && strcasestr(cfg->excludeFileTypes,ext)) { return DECLINED; } } } // Locate Makefile: The Makefile should be in SourceRoot/REL_PATH/Makefile char relpath[256]; char makefile[256]; char make_target[256]; // Determine the relative path part of r->canonical_filename, i.e., the part with the DocumentRoot removed strncpy(relpath,r->canonical_filename+strlen(docroot),sizeof(relpath)-1); // Truncate it before the basename char* p=strrchr(relpath,'/'); if (p) *++p='\0'; else { relpath[0]='/'; relpath[1]='\0'; } if (cfg->debug) { ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: relpath:%s",relpath); } int bFoundMakefile=FALSE; int bGiveUp=FALSE; do { // Determine the make target, i.e., the basename of r->canonical_filename strncpy(make_target,r->canonical_filename+strlen(docroot)+strlen(relpath),sizeof(make_target)-1); make_target[sizeof(make_target)-1]='\0'; if (strlen(cfg->sourceRoot)) strncpy(makefile,cfg->sourceRoot,sizeof(makefile)-1); else strncpy(makefile,docroot,sizeof(makefile)-1); strncat(makefile,relpath,sizeof(makefile)-strlen(makefile)-1); strncat(makefile,cfg->makefileName,sizeof(makefile)-strlen(makefile)-1); makefile[sizeof(makefile)-1]='\0'; // If Makefile not found, ignore it (we only care if there •is* a Makefile) struct stat ss; if (!stat(makefile,&ss)) bFoundMakefile=TRUE; else { if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Makefile not found:%s. Trying parent directory...",makefile); // Go up one dir until we find a Makefile (but don't go past cfg->sourceRoot) // Take a directory off relpath, move it to the start of make_target and retry looking for the Makefile // Find 2nd-to-last / in relpath, that's the start of the last directory name char* p=strrchr(relpath,'/'); if (p) { do --p; while (p>=relpath && *p!='/'); if (p>=relpath) *(p+1)='\0'; else bGiveUp=TRUE; } else bGiveUp=TRUE; } } while (bFoundMakefile==FALSE && bGiveUp==FALSE); if (bFoundMakefile==FALSE) // Never found a Makefile { if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Unable to find a Makefile named:%s",cfg->makefileName); return DECLINED; } if (cfg->debug) { ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: relpath:%s",relpath); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: makefile:%s",makefile); ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make_target:%s",make_target); } // Build make command char* cmd=apr_psprintf(r->pool,"WWWDOCROOT=%s WWWRELPATH=%s %s -f %s -C %s %s %s 2>&1", docroot, relpath, cfg->makeProgram, cfg->makefileName, (const char*)dirname(makefile), cfg->makeOptions, make_target); if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cmd:%s",cmd); // Run Makefile to make target FILE* makep=popen(cmd,"r"); if (!makep) { // If launching make fails, output errors from make and return HTTP error if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: failed to popen:%s",cmd); return HTTP_INTERNAL_SERVER_ERROR; } // Compile regex regex_t regex; char* regexstr=apr_psprintf(r->pool, "^make:[[:space:]]+\\*\\*\\*[[:space:]]+No[[:space:]]+rule[[:space:]]+to[[:space:]]+make[[:space:]]+target[[:space:]]+`%s'\\.[[:space:]]+Stop\\.", make_target ); if (regcomp(®ex,regexstr,REG_EXTENDED)) { if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: regcomp failed"); return HTTP_INTERNAL_SERVER_ERROR; } int bSilentFail=FALSE; // Read output of make size_t make_output_size=10240; // TODO: allow the buffer to grow beyond 10K char* make_output=apr_palloc(r->pool,make_output_size); make_output[0]='\0'; make_output_size--; p=make_output; // reuse p do { const char* newp=fgets(p,make_output_size,makep); if (newp) { if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make output:%s",newp); make_output_size-=strlen(newp); p+=strlen(newp); if (regexec(®ex,newp,0,0,0)==0) { if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: regex match:%s",newp); bSilentFail=TRUE; } } } while (!feof(makep) && make_output_size>1); if (!make_output_size) { if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make output exceeded max length"); // TODO: add appropriate message to make_output } int ret=pclose(makep); if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make exit code:%d",WEXITSTATUS(ret)); if (WEXITSTATUS(ret)) {// make did not complete successfully, output make's output and tell Apache to stop. if (bSilentFail) { if (cfg->debug) ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: silently failing."); return DECLINED; } // Store make_output in request_rec so that the handler can display it apr_table_set(r->notes,"make_output",make_output); // Redirect to our own content handler ap_internal_redirect(cfg->errorURI,r); return OK; } return DECLINED; }
static int check_speling(request_rec *r) { spconfig *cfg; char *good, *bad, *postgood, *url; apr_finfo_t dirent; int filoc, dotloc, urlen, pglen; apr_array_header_t *candidates = NULL; apr_dir_t *dir; cfg = ap_get_module_config(r->per_dir_config, &speling_module); if (!cfg->enabled) { return DECLINED; } /* We only want to worry about GETs */ if (r->method_number != M_GET) { return DECLINED; } /* We've already got a file of some kind or another */ if (r->finfo.filetype != APR_NOFILE) { return DECLINED; } /* Not a file request */ if (r->proxyreq || !r->filename) { return DECLINED; } /* This is a sub request - don't mess with it */ if (r->main) { return DECLINED; } /* * The request should end up looking like this: * r->uri: /correct-url/mispelling/more * r->filename: /correct-file/mispelling r->path_info: /more * * So we do this in steps. First break r->filename into two pieces */ filoc = ap_rind(r->filename, '/'); /* * Don't do anything if the request doesn't contain a slash, or * requests "/" */ if (filoc == -1 || strcmp(r->uri, "/") == 0) { return DECLINED; } /* good = /correct-file */ good = apr_pstrndup(r->pool, r->filename, filoc); /* bad = mispelling */ bad = apr_pstrdup(r->pool, r->filename + filoc + 1); /* postgood = mispelling/more */ postgood = apr_pstrcat(r->pool, bad, r->path_info, NULL); urlen = strlen(r->uri); pglen = strlen(postgood); /* Check to see if the URL pieces add up */ if (strcmp(postgood, r->uri + (urlen - pglen))) { return DECLINED; } /* url = /correct-url */ url = apr_pstrndup(r->pool, r->uri, (urlen - pglen)); /* Now open the directory and do ourselves a check... */ if (apr_dir_open(&dir, good, r->pool) != APR_SUCCESS) { /* Oops, not a directory... */ return DECLINED; } candidates = apr_array_make(r->pool, 2, sizeof(misspelled_file)); dotloc = ap_ind(bad, '.'); if (dotloc == -1) { dotloc = strlen(bad); } while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dir) == APR_SUCCESS) { sp_reason q; /* * If we end up with a "fixed" URL which is identical to the * requested one, we must have found a broken symlink or some such. * Do _not_ try to redirect this, it causes a loop! */ if (strcmp(bad, dirent.name) == 0) { apr_dir_close(dir); return OK; } /* * miscapitalization errors are checked first (like, e.g., lower case * file, upper case request) */ else if (strcasecmp(bad, dirent.name) == 0) { misspelled_file *sp_new; sp_new = (misspelled_file *) apr_array_push(candidates); sp_new->name = apr_pstrdup(r->pool, dirent.name); sp_new->quality = SP_MISCAPITALIZED; } /* * simple typing errors are checked next (like, e.g., * missing/extra/transposed char) */ else if ((cfg->check_case_only == 0) && ((q = spdist(bad, dirent.name)) != SP_VERYDIFFERENT)) { misspelled_file *sp_new; sp_new = (misspelled_file *) apr_array_push(candidates); sp_new->name = apr_pstrdup(r->pool, dirent.name); sp_new->quality = q; } /* * The spdist() should have found the majority of the misspelled * requests. It is of questionable use to continue looking for * files with the same base name, but potentially of totally wrong * type (index.html <-> index.db). * * If you're using MultiViews, and have a file named foobar.html, * which you refer to as "foobar", and someone tried to access * "Foobar", without CheckBasenameMatch, mod_speling won't find it, * because it won't find anything matching that spelling. * With the extension-munging, it would locate "foobar.html". */ else if ((cfg->check_case_only == 0) && (cfg->check_basename_match == 1)) { /* * Okay... we didn't find anything. Now we take out the hard-core * power tools. There are several cases here. Someone might have * entered a wrong extension (.htm instead of .html or vice * versa) or the document could be negotiated. At any rate, now * we just compare stuff before the first dot. If it matches, we * figure we got us a match. This can result in wrong things if * there are files of different content types but the same prefix * (e.g. foo.gif and foo.html) This code will pick the first one * it finds. Better than a Not Found, though. */ int entloc = ap_ind(dirent.name, '.'); if (entloc == -1) { entloc = strlen(dirent.name); } if ((dotloc == entloc) && !strncasecmp(bad, dirent.name, dotloc)) { misspelled_file *sp_new; sp_new = (misspelled_file *) apr_array_push(candidates); sp_new->name = apr_pstrdup(r->pool, dirent.name); sp_new->quality = SP_VERYDIFFERENT; } } } apr_dir_close(dir); if (candidates->nelts != 0) { /* Wow... we found us a mispelling. Construct a fixed url */ char *nuri; const char *ref; misspelled_file *variant = (misspelled_file *) candidates->elts; int i; ref = apr_table_get(r->headers_in, "Referer"); qsort((void *) candidates->elts, candidates->nelts, sizeof(misspelled_file), sort_by_quality); /* * Conditions for immediate redirection: * a) the first candidate was not found by stripping the suffix * AND b) there exists only one candidate OR the best match is not * ambiguous * then return a redirection right away. */ if (variant[0].quality != SP_VERYDIFFERENT && (candidates->nelts == 1 || variant[0].quality != variant[1].quality)) { nuri = ap_escape_uri(r->pool, apr_pstrcat(r->pool, url, variant[0].name, r->path_info, NULL)); if (r->parsed_uri.query) nuri = apr_pstrcat(r->pool, nuri, "?", r->parsed_uri.query, NULL); apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, nuri, r)); ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, ref ? "Fixed spelling: %s to %s from %s" : "Fixed spelling: %s to %s%s", r->uri, nuri, (ref ? ref : "")); return HTTP_MOVED_PERMANENTLY; } /* * Otherwise, a "[300] Multiple Choices" list with the variants is * returned. */ else { apr_pool_t *p; apr_table_t *notes; apr_pool_t *sub_pool; apr_array_header_t *t; apr_array_header_t *v; if (r->main == NULL) { p = r->pool; notes = r->notes; } else { p = r->main->pool; notes = r->main->notes; } if (apr_pool_create(&sub_pool, p) != APR_SUCCESS) return DECLINED; t = apr_array_make(sub_pool, candidates->nelts * 8 + 8, sizeof(char *)); v = apr_array_make(sub_pool, candidates->nelts * 5, sizeof(char *)); /* Generate the response text. */ *(const char **)apr_array_push(t) = "The document name you requested (<code>"; *(const char **)apr_array_push(t) = ap_escape_html(sub_pool, r->uri); *(const char **)apr_array_push(t) = "</code>) could not be found on this server.\n" "However, we found documents with names similar " "to the one you requested.<p>" "Available documents:\n<ul>\n"; for (i = 0; i < candidates->nelts; ++i) { char *vuri; const char *reason; reason = sp_reason_str[(int) (variant[i].quality)]; /* The format isn't very neat... */ vuri = apr_pstrcat(sub_pool, url, variant[i].name, r->path_info, (r->parsed_uri.query != NULL) ? "?" : "", (r->parsed_uri.query != NULL) ? r->parsed_uri.query : "", NULL); *(const char **)apr_array_push(v) = "\""; *(const char **)apr_array_push(v) = ap_escape_uri(sub_pool, vuri); *(const char **)apr_array_push(v) = "\";\""; *(const char **)apr_array_push(v) = reason; *(const char **)apr_array_push(v) = "\""; *(const char **)apr_array_push(t) = "<li><a href=\""; *(const char **)apr_array_push(t) = ap_escape_uri(sub_pool, vuri); *(const char **)apr_array_push(t) = "\">"; *(const char **)apr_array_push(t) = ap_escape_html(sub_pool, vuri); *(const char **)apr_array_push(t) = "</a> ("; *(const char **)apr_array_push(t) = reason; *(const char **)apr_array_push(t) = ")\n"; /* * when we have printed the "close matches" and there are * more "distant matches" (matched by stripping the suffix), * then we insert an additional separator text to suggest * that the user LOOK CLOSELY whether these are really the * files she wanted. */ if (i > 0 && i < candidates->nelts - 1 && variant[i].quality != SP_VERYDIFFERENT && variant[i + 1].quality == SP_VERYDIFFERENT) { *(const char **)apr_array_push(t) = "</ul>\nFurthermore, the following related " "documents were found:\n<ul>\n"; } } *(const char **)apr_array_push(t) = "</ul>\n"; /* If we know there was a referring page, add a note: */ if (ref != NULL) { *(const char **)apr_array_push(t) = "Please consider informing the owner of the " "<a href=\""; *(const char **)apr_array_push(t) = ap_escape_uri(sub_pool, ref); *(const char **)apr_array_push(t) = "\">referring page</a> " "about the broken link.\n"; } /* Pass our apr_table_t to http_protocol.c (see mod_negotiation): */ apr_table_setn(notes, "variant-list", apr_array_pstrcat(p, t, 0)); apr_table_mergen(r->subprocess_env, "VARIANTS", apr_array_pstrcat(p, v, ',')); apr_pool_destroy(sub_pool); ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, ref ? "Spelling fix: %s: %d candidates from %s" : "Spelling fix: %s: %d candidates%s", r->uri, candidates->nelts, (ref ? ref : "")); return HTTP_MULTIPLE_CHOICES; } } return OK; }
static int reverseproxy_modify_connection(request_rec *r) { conn_rec *c = r->connection; reverseproxy_config_t *config = (reverseproxy_config_t *) ap_get_module_config(r->server->module_config, &reverseproxy_module); if (!config->enable_module) return DECLINED; reverseproxy_conn_t *conn; #ifdef REMOTEIP_OPTIMIZED apr_sockaddr_t temp_sa_buff; apr_sockaddr_t *temp_sa = &temp_sa_buff; #else apr_sockaddr_t *temp_sa; #endif apr_status_t rv; char *remote = (char *) apr_table_get(r->headers_in, config->header_name); char *proxy_ips = NULL; char *parse_remote; char *eos; unsigned char *addrbyte; void *internal = NULL; apr_pool_userdata_get((void*)&conn, "mod_reverseproxy-conn", c->pool); if (conn) { if (remote && (strcmp(remote, conn->prior_remote) == 0)) { /* TODO: Recycle r-> overrides from previous request */ goto ditto_request_rec; } else { /* TODO: Revert connection from previous request */ #if AP_MODULE_MAGIC_AT_LEAST(20111130,0) c->client_addr = conn->orig_addr; c->client_ip = (char *) conn->orig_ip; #else c->remote_addr = conn->orig_addr; c->remote_ip = (char *) conn->orig_ip; #endif } } remote = apr_pstrdup(r->pool, remote); #if AP_MODULE_MAGIC_AT_LEAST(20111130,0) #ifdef REMOTEIP_OPTIMIZED memcpy(temp_sa, c->client_addr, sizeof(*temp_sa)); temp_sa->pool = r->pool; #else temp_sa = c->client_addr; #endif #else #ifdef REMOTEIP_OPTIMIZED memcpy(temp_sa, c->remote_addr, sizeof(*temp_sa)); temp_sa->pool = r->pool; #else temp_sa = c->remote_addr; #endif #endif while (remote) { /* verify c->client_addr is trusted if there is a trusted proxy list */ if (config->proxymatch_ip) { int i; reverseproxy_proxymatch_t *match; match = (reverseproxy_proxymatch_t *)config->proxymatch_ip->elts; for (i = 0; i < config->proxymatch_ip->nelts; ++i) { #if AP_MODULE_MAGIC_AT_LEAST(20111130,0) if (apr_ipsubnet_test(match[i].ip, c->client_addr)) { internal = match[i].internal; break; } #else if (apr_ipsubnet_test(match[i].ip, c->remote_addr)) { internal = match[i].internal; break; } #endif } } if ((parse_remote = strrchr(remote, ',')) == NULL) { parse_remote = remote; remote = NULL; } else { *(parse_remote++) = '\0'; } while (*parse_remote == ' ') ++parse_remote; eos = parse_remote + strlen(parse_remote) - 1; while (eos >= parse_remote && *eos == ' ') *(eos--) = '\0'; if (eos < parse_remote) { if (remote) *(remote + strlen(remote)) = ','; else remote = parse_remote; break; } #ifdef REMOTEIP_OPTIMIZED /* Decode client_addr - sucks; apr_sockaddr_vars_set isn't 'public' */ if (inet_pton(AF_INET, parse_remote, &temp_sa->sa.sin.sin_addr) > 0) { apr_sockaddr_vars_set(temp_sa, APR_INET, temp_sa.port); } #if APR_HAVE_IPV6 else if (inet_pton(AF_INET6, parse_remote, &temp_sa->sa.sin6.sin6_addr) > 0) { apr_sockaddr_vars_set(temp_sa, APR_INET6, temp_sa.port); } #endif else { rv = apr_get_netos_error(); #else /* !REMOTEIP_OPTIMIZED */ /* We map as IPv4 rather than IPv6 for equivilant host names * or IPV4OVERIPV6 */ rv = apr_sockaddr_info_get(&temp_sa, parse_remote, APR_UNSPEC, temp_sa->port, APR_IPV4_ADDR_OK, r->pool); if (rv != APR_SUCCESS) { #endif ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, "RemoteIP: Header %s value of %s cannot be parsed " "as a client IP", config->header_name, parse_remote); if (remote) *(remote + strlen(remote)) = ','; else remote = parse_remote; break; } addrbyte = (unsigned char *) &temp_sa->sa.sin.sin_addr; /* For intranet (Internal proxies) ignore all restrictions below */ if (!internal && ((temp_sa->family == APR_INET /* For internet (non-Internal proxies) deny all * RFC3330 designated local/private subnets: * 10.0.0.0/8 169.254.0.0/16 192.168.0.0/16 * 127.0.0.0/8 172.16.0.0/12 */ && (addrbyte[0] == 10 || addrbyte[0] == 127 || (addrbyte[0] == 169 && addrbyte[1] == 254) || (addrbyte[0] == 172 && (addrbyte[1] & 0xf0) == 16) || (addrbyte[0] == 192 && addrbyte[1] == 168))) #if APR_HAVE_IPV6 || (temp_sa->family == APR_INET6 /* For internet (non-Internal proxies) we translated * IPv4-over-IPv6-mapped addresses as IPv4, above. * Accept only Global Unicast 2000::/3 defined by RFC4291 */ && ((temp_sa->sa.sin6.sin6_addr.s6_addr[0] & 0xe0) != 0x20)) #endif )) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, "RemoteIP: Header %s value of %s appears to be " "a private IP or nonsensical. Ignored", config->header_name, parse_remote); if (remote) *(remote + strlen(remote)) = ','; else remote = parse_remote; break; } #if AP_MODULE_MAGIC_AT_LEAST(20111130,0) if (!conn) { conn = (reverseproxy_conn_t *) apr_palloc(c->pool, sizeof(*conn)); apr_pool_userdata_set(conn, "mod_reverseproxy-conn", NULL, c->pool); conn->orig_addr = c->client_addr; conn->orig_ip = c->client_ip; } /* Set remote_ip string */ if (!internal) { if (proxy_ips) proxy_ips = apr_pstrcat(r->pool, proxy_ips, ", ", c->client_ip, NULL); else proxy_ips = c->client_ip; } c->client_addr = temp_sa; apr_sockaddr_ip_get(&c->client_ip, c->client_addr); } /* Nothing happened? */ if (!conn || (c->client_addr == conn->orig_addr)) return OK; /* Fixups here, remote becomes the new Via header value, etc * In the heavy operations above we used request scope, to limit * conn pool memory growth on keepalives, so here we must scope * the final results to the connection pool lifetime. * To limit memory growth, we keep recycling the same buffer * for the final apr_sockaddr_t in the remoteip conn rec. */ c->client_ip = apr_pstrdup(c->pool, c->client_ip); conn->proxied_ip = c->client_ip; r->useragent_ip = c->client_ip; r->useragent_addr = c->client_addr; memcpy(&conn->proxied_addr, temp_sa, sizeof(*temp_sa)); conn->proxied_addr.pool = c->pool; c->client_addr = &conn->proxied_addr; #else if (!conn) { conn = (reverseproxy_conn_t *) apr_palloc(c->pool, sizeof(*conn)); apr_pool_userdata_set(conn, "mod_reverseproxy-conn", NULL, c->pool); conn->orig_addr = c->remote_addr; conn->orig_ip = c->remote_ip; } /* Set remote_ip string */ if (!internal) { if (proxy_ips) proxy_ips = apr_pstrcat(r->pool, proxy_ips, ", ", c->remote_ip, NULL); else proxy_ips = c->remote_ip; } c->remote_addr = temp_sa; apr_sockaddr_ip_get(&c->remote_ip, c->remote_addr); } /* Nothing happened? */ if (!conn || (c->remote_addr == conn->orig_addr)) return OK; /* Fixups here, remote becomes the new Via header value, etc * In the heavy operations above we used request scope, to limit * conn pool memory growth on keepalives, so here we must scope * the final results to the connection pool lifetime. * To limit memory growth, we keep recycling the same buffer * for the final apr_sockaddr_t in the remoteip conn rec. */ c->remote_ip = apr_pstrdup(c->pool, c->remote_ip); conn->proxied_ip = c->remote_ip; memcpy(&conn->proxied_addr, temp_sa, sizeof(*temp_sa)); conn->proxied_addr.pool = c->pool; c->remote_addr = &conn->proxied_addr; #endif if (remote) remote = apr_pstrdup(c->pool, remote); conn->proxied_remote = remote; conn->prior_remote = apr_pstrdup(c->pool, apr_table_get(r->headers_in, config->header_name)); if (proxy_ips) proxy_ips = apr_pstrdup(c->pool, proxy_ips); conn->proxy_ips = proxy_ips; /* Unset remote_host string DNS lookups */ c->remote_host = NULL; c->remote_logname = NULL; ditto_request_rec: if (conn->proxy_ips) { apr_table_setn(r->notes, "reverseproxy-proxy-ip-list", conn->proxy_ips); if (config->proxies_header_name) apr_table_setn(r->headers_in, config->proxies_header_name, conn->proxy_ips); } ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, conn->proxy_ips ? "Using %s as client's IP by proxies %s" : "Using %s as client's IP by internal proxies", conn->proxied_ip, conn->proxy_ips); return OK; }
/* * initialize the memcache struct to a number of memcache servers */ static int oidc_cache_memcache_post_config(server_rec *s) { oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(s->module_config, &auth_openidc_module); if (cfg->cache_cfg != NULL) return APR_SUCCESS; oidc_cache_cfg_memcache_t *context = oidc_cache_memcache_cfg_create( s->process->pool); cfg->cache_cfg = context; apr_status_t rv = APR_SUCCESS; int nservers = 0; char* split; char* tok; apr_pool_t *p = s->process->pool; if (cfg->cache_memcache_servers == NULL) { oidc_serror(s, "cache type is set to \"memcache\", but no valid OIDCMemCacheServers setting was found"); return HTTP_INTERNAL_SERVER_ERROR; } /* loop over the provided memcache servers to find out the number of servers configured */ char *cache_config = apr_pstrdup(p, cfg->cache_memcache_servers); split = apr_strtok(cache_config, " ", &tok); while (split) { nservers++; split = apr_strtok(NULL, " ", &tok); } /* allocated space for the number of servers */ rv = apr_memcache_create(p, nservers, 0, &context->cache_memcache); if (rv != APR_SUCCESS) { oidc_serror(s, "failed to create memcache object of '%d' size", nservers); return HTTP_INTERNAL_SERVER_ERROR; } /* loop again over the provided servers */ cache_config = apr_pstrdup(p, cfg->cache_memcache_servers); split = apr_strtok(cache_config, " ", &tok); while (split) { apr_memcache_server_t* st; char* host_str; char* scope_id; apr_port_t port; /* parse out host and port */ rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); if (rv != APR_SUCCESS) { oidc_serror(s, "failed to parse cache server: '%s'", split); return HTTP_INTERNAL_SERVER_ERROR; } if (host_str == NULL) { oidc_serror(s, "failed to parse cache server, no hostname specified: '%s'", split); return HTTP_INTERNAL_SERVER_ERROR; } if (port == 0) port = 11211; /* create the memcache server struct */ // TODO: tune this rv = apr_memcache_server_create(p, host_str, port, 0, 1, 1, 60, &st); if (rv != APR_SUCCESS) { oidc_serror(s, "failed to create cache server: %s:%d", host_str, port); return HTTP_INTERNAL_SERVER_ERROR; } /* add the memcache server struct to the list */ rv = apr_memcache_add_server(context->cache_memcache, st); if (rv != APR_SUCCESS) { oidc_serror(s, "failed to add cache server: %s:%d", host_str, port); return HTTP_INTERNAL_SERVER_ERROR; } /* go to the next entry */ split = apr_strtok(NULL, " ", &tok); } return OK; }
// command for setting the url for group data requests static const char *lmmpset_group_data_url_cmd(cmd_parms * cmd, void *dummy, const char* arg) { moon_svr_cfg * cfg = ap_get_module_config(cmd->server->module_config, &moon_module); cfg->group_data_url = arg; return NULL; }
CACHE_DECLARE(int) ap_cache_check_freshness(cache_handle_t *h, request_rec *r) { apr_int64_t age, maxage_req, maxage_cresp, maxage, smaxage, maxstale; apr_int64_t minfresh; const char *cc_cresp, *cc_req; const char *pragma; const char *agestr = NULL; const char *expstr = NULL; char *val; apr_time_t age_c = 0; cache_info *info = &(h->cache_obj->info); cache_server_conf *conf = (cache_server_conf *)ap_get_module_config(r->server->module_config, &cache_module); /* * We now want to check if our cached data is still fresh. This depends * on a few things, in this order: * * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache. no-cache in * either the request or the cached response means that we must * revalidate the request unconditionally, overriding any expiration * mechanism. It's equivalent to max-age=0,must-revalidate. * * - RFC2616 14.32 Pragma: no-cache This is treated the same as * Cache-Control: no-cache. * * - RFC2616 14.9.3 Cache-Control: max-stale, must-revalidate, * proxy-revalidate if the max-stale request header exists, modify the * stale calculations below so that an object can be at most <max-stale> * seconds stale before we request a revalidation, _UNLESS_ a * must-revalidate or proxy-revalidate cached response header exists to * stop us doing this. * * - RFC2616 14.9.3 Cache-Control: s-maxage the origin server specifies the * maximum age an object can be before it is considered stale. This * directive has the effect of proxy|must revalidate, which in turn means * simple ignore any max-stale setting. * * - RFC2616 14.9.4 Cache-Control: max-age this header can appear in both * requests and responses. If both are specified, the smaller of the two * takes priority. * * - RFC2616 14.21 Expires: if this request header exists in the cached * entity, and it's value is in the past, it has expired. * */ /* This value comes from the client's initial request. */ cc_req = apr_table_get(r->headers_in, "Cache-Control"); pragma = apr_table_get(r->headers_in, "Pragma"); if (ap_cache_liststr(NULL, pragma, "no-cache", NULL) || ap_cache_liststr(NULL, cc_req, "no-cache", NULL)) { if (!conf->ignorecachecontrol) { /* Treat as stale, causing revalidation */ return 0; } ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "Incoming request is asking for a uncached version of " "%s, but we know better and are ignoring it", r->unparsed_uri); } /* These come from the cached entity. */ cc_cresp = apr_table_get(h->resp_hdrs, "Cache-Control"); expstr = apr_table_get(h->resp_hdrs, "Expires"); if (ap_cache_liststr(NULL, cc_cresp, "no-cache", NULL)) { /* * The cached entity contained Cache-Control: no-cache, so treat as * stale causing revalidation */ return 0; } if ((agestr = apr_table_get(h->resp_hdrs, "Age"))) { age_c = apr_atoi64(agestr); } /* calculate age of object */ age = ap_cache_current_age(info, age_c, r->request_time); /* extract s-maxage */ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val) && val != NULL) { smaxage = apr_atoi64(val); } else { smaxage = -1; } /* extract max-age from request */ if (!conf->ignorecachecontrol && cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val) && val != NULL) { maxage_req = apr_atoi64(val); } else { maxage_req = -1; } /* extract max-age from response */ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val) && val != NULL) { maxage_cresp = apr_atoi64(val); } else { maxage_cresp = -1; } /* * if both maxage request and response, the smaller one takes priority */ if (maxage_req == -1) { maxage = maxage_cresp; } else if (maxage_cresp == -1) { maxage = maxage_req; } else { maxage = MIN(maxage_req, maxage_cresp); } /* extract max-stale */ if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-stale", &val)) { if(val != NULL) { maxstale = apr_atoi64(val); } else { /* * If no value is assigned to max-stale, then the client is willing * to accept a stale response of any age (RFC2616 14.9.3). We will * set it to one year in this case as this situation is somewhat * similar to a "never expires" Expires header (RFC2616 14.21) * which is set to a date one year from the time the response is * sent in this case. */ maxstale = APR_INT64_C(86400*365); } } else { maxstale = 0; } /* extract min-fresh */ if (!conf->ignorecachecontrol && cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val) && val != NULL) { minfresh = apr_atoi64(val); } else { minfresh = 0; } /* override maxstale if must-revalidate or proxy-revalidate */ if (maxstale && ((cc_cresp && ap_cache_liststr(NULL, cc_cresp, "must-revalidate", NULL)) || (cc_cresp && ap_cache_liststr(NULL, cc_cresp, "proxy-revalidate", NULL)))) { maxstale = 0; } /* handle expiration */ if (((smaxage != -1) && (age < (smaxage - minfresh))) || ((maxage != -1) && (age < (maxage + maxstale - minfresh))) || ((smaxage == -1) && (maxage == -1) && (info->expire != APR_DATE_BAD) && (age < (apr_time_sec(info->expire - info->date) + maxstale - minfresh)))) { const char *warn_head; warn_head = apr_table_get(h->resp_hdrs, "Warning"); /* it's fresh darlings... */ /* set age header on response */ apr_table_set(h->resp_hdrs, "Age", apr_psprintf(r->pool, "%lu", (unsigned long)age)); /* add warning if maxstale overrode freshness calculation */ if (!(((smaxage != -1) && age < smaxage) || ((maxage != -1) && age < maxage) || (info->expire != APR_DATE_BAD && (apr_time_sec(info->expire - info->date)) > age))) { /* make sure we don't stomp on a previous warning */ if ((warn_head == NULL) || ((warn_head != NULL) && (ap_strstr_c(warn_head, "110") == NULL))) { apr_table_merge(h->resp_hdrs, "Warning", "110 Response is stale"); } } /* * If none of Expires, Cache-Control: max-age, or Cache-Control: * s-maxage appears in the response, and the respose header age * calculated is more than 24 hours add the warning 113 */ if ((maxage_cresp == -1) && (smaxage == -1) && (expstr == NULL) && (age > 86400)) { /* Make sure we don't stomp on a previous warning, and don't dup * a 113 marning that is already present. Also, make sure to add * the new warning to the correct *headers_out location. */ if ((warn_head == NULL) || ((warn_head != NULL) && (ap_strstr_c(warn_head, "113") == NULL))) { apr_table_merge(h->resp_hdrs, "Warning", "113 Heuristic expiration"); } } return 1; /* Cache object is fresh (enough) */ } return 0; /* Cache object is stale */ }
static CWX_CONFIG* cwx_get_server_config(server_rec *s){ return (CWX_CONFIG *) ap_get_module_config(s->module_config, &cwinux_module); }
apr_status_t proc_spawn_process(const char *cmdline, fcgid_proc_info *procinfo, fcgid_procnode *procnode) { HANDLE *finish_event, listen_handle; SECURITY_ATTRIBUTES SecurityAttributes; fcgid_server_conf *sconf; apr_procattr_t *proc_attr; apr_status_t rv; apr_file_t *file; const char * const *proc_environ; char sock_path[FCGID_PATH_MAX]; int argc; char const * wargv[APACHE_ARG_MAX + 1], *word; /* For wrapper */ const char *tmp; /* Build wrapper args */ argc = 0; tmp = cmdline; while (1) { word = ap_getword_white(procnode->proc_pool, &tmp); if (word == NULL || *word == '\0') break; if (argc >= APACHE_ARG_MAX) break; wargv[argc++] = word; } wargv[argc] = NULL; memset(&SecurityAttributes, 0, sizeof(SecurityAttributes)); /* Prepare finish event */ finish_event = apr_palloc(procnode->proc_pool, sizeof(HANDLE)); *finish_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (*finish_event == NULL || !SetHandleInformation(*finish_event, HANDLE_FLAG_INHERIT, TRUE)) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), procinfo->main_server, "mod_fcgid: can't create mutex for subprocess"); return APR_ENOLOCK; } apr_pool_cleanup_register(procnode->proc_pool, finish_event, close_finish_event, apr_pool_cleanup_null); /* For proc_kill_gracefully() */ apr_pool_userdata_set(finish_event, FINISH_EVENT_DATA_NAME, NULL, procnode->proc_pool); /* Pass the finish event id to subprocess */ apr_table_setn(procinfo->proc_environ, SHUTDOWN_EVENT_NAME, apr_ltoa(procnode->proc_pool, (long) *finish_event)); /* Prepare the listen namedpipe file name (no check for truncation) */ apr_snprintf(sock_path, sizeof sock_path, "\\\\.\\pipe\\fcgidpipe-%lu.%d", GetCurrentProcessId(), g_process_counter++); /* Prepare the listen namedpipe handle */ SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; listen_handle = CreateNamedPipe(sock_path, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 8192, 8192, 0, &SecurityAttributes); if (listen_handle == INVALID_HANDLE_VALUE) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), procinfo->main_server, "mod_fcgid: can't create namedpipe for subprocess"); return APR_ENOSOCKET; } apr_cpystrn(procnode->socket_path, sock_path, sizeof(procnode->socket_path)); apr_cpystrn(procnode->executable_path, wargv[0], sizeof(procnode->executable_path)); /* Build environment variables */ proc_environ = (const char * const *) ap_create_environment(procnode->proc_pool, procinfo->proc_environ); if (!proc_environ) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), procinfo->main_server, "mod_fcgid: can't build environment variables"); return APR_ENOMEM; } /* Create process now */ if ((rv = apr_procattr_create(&proc_attr, procnode->proc_pool)) != APR_SUCCESS || (rv = apr_procattr_dir_set(proc_attr, ap_make_dirstr_parent(procnode->proc_pool, wargv[0]))) != APR_SUCCESS || (rv = apr_procattr_cmdtype_set(proc_attr, APR_PROGRAM)) != APR_SUCCESS || (rv = apr_procattr_detach_set(proc_attr, 1)) != APR_SUCCESS || (rv = apr_procattr_io_set(proc_attr, APR_NO_PIPE, APR_NO_FILE, APR_NO_FILE)) != APR_SUCCESS || (rv = apr_os_file_put(&file, &listen_handle, 0, procnode->proc_pool)) != APR_SUCCESS || (rv = apr_procattr_child_in_set(proc_attr, file, NULL)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, procinfo->main_server, "mod_fcgid: can't create FastCGI process attribute"); CloseHandle(listen_handle); return APR_ENOPROC; } /* fork and exec now */ rv = apr_proc_create(&(procnode->proc_id), wargv[0], wargv, proc_environ, proc_attr, procnode->proc_pool); /* OK, I created the process, now put it back to idle list */ CloseHandle(listen_handle); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, procinfo->main_server, "mod_fcgid: can't run %s", wargv[0]); return rv; } /* FcgidWin32PreventOrphans feature */ sconf = ap_get_module_config(procinfo->main_server->module_config, &fcgid_module); if (sconf->hJobObjectForAutoCleanup != NULL) { /* Associate cgi process to current process */ if (AssignProcessToJobObject(sconf->hJobObjectForAutoCleanup, procnode->proc_id.hproc) == 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), procinfo->main_server, "mod_fcgid: unable to assign child process to " "job object"); } } 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; } }
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 translate_userdir(request_rec *r) { ap_conf_vector_t *server_conf; const userdir_config *s_cfg; const char *userdirs; const char *user, *dname; char *redirect; apr_finfo_t statbuf; /* * If the URI doesn't match our basic pattern, we've nothing to do with * it. */ if (r->uri[0] != '/' || r->uri[1] != '~') { return DECLINED; } server_conf = r->server->module_config; s_cfg = ap_get_module_config(server_conf, &userdir_module); userdirs = s_cfg->userdir; if (userdirs == NULL) { return DECLINED; } dname = r->uri + 2; user = ap_getword(r->pool, &dname, '/'); /* * The 'dname' funny business involves backing it up to capture the '/' * delimiting the "/~user" part from the rest of the URL, in case there * was one (the case where there wasn't being just "GET /~user HTTP/1.0", * for which we don't want to tack on a '/' onto the filename). */ if (dname[-1] == '/') { --dname; } /* * If there's no username, it's not for us. Ignore . and .. as well. */ if (user[0] == '\0' || (user[1] == '.' && (user[2] == '\0' || (user[2] == '.' && user[3] == '\0')))) { return DECLINED; } /* * Nor if there's an username but it's in the disabled list. */ if (apr_table_get(s_cfg->disabled_users, user) != NULL) { return DECLINED; } /* * If there's a global interdiction on UserDirs, check to see if this * name is one of the Blessed. */ if (s_cfg->globally_disabled == O_DISABLE && apr_table_get(s_cfg->enabled_users, user) == NULL) { return DECLINED; } /* * Special cases all checked, onward to normal substitution processing. */ while (*userdirs) { const char *userdir = ap_getword_conf(r->pool, &userdirs); char *filename = NULL, *prefix = NULL; apr_status_t rv; int is_absolute = ap_os_is_path_absolute(r->pool, userdir); if (ap_strchr_c(userdir, '*')) prefix = ap_getword(r->pool, &userdir, '*'); if (userdir[0] == '\0' || is_absolute) { if (prefix) { #ifdef HAVE_DRIVE_LETTERS /* * Crummy hack. Need to figure out whether we have been * redirected to a URL or to a file on some drive. Since I * know of no protocols that are a single letter, ignore * a : as the first or second character, and assume a file * was specified */ if (strchr(prefix + 2, ':')) #else if (strchr(prefix, ':') && !is_absolute) #endif /* HAVE_DRIVE_LETTERS */ { redirect = apr_pstrcat(r->pool, prefix, user, userdir, dname, NULL); apr_table_setn(r->headers_out, "Location", redirect); return HTTP_MOVED_TEMPORARILY; } else filename = apr_pstrcat(r->pool, prefix, user, userdir, NULL); } else filename = apr_pstrcat(r->pool, userdir, "/", user, NULL); } else if (prefix && ap_strchr_c(prefix, ':')) { redirect = apr_pstrcat(r->pool, prefix, user, dname, NULL); apr_table_setn(r->headers_out, "Location", redirect); return HTTP_MOVED_TEMPORARILY; } else { #if APR_HAS_USER char *homedir; if (apr_uid_homepath_get(&homedir, user, r->pool) == APR_SUCCESS) { filename = apr_pstrcat(r->pool, homedir, "/", userdir, NULL); } #else return DECLINED; #endif } /* * Now see if it exists, or we're at the last entry. If we are at the * last entry, then use the filename generated (if there is one) * anyway, in the hope that some handler might handle it. This can be * used, for example, to run a CGI script for the user. */ if (filename && (!*userdirs || ((rv = apr_stat(&statbuf, filename, APR_FINFO_MIN, r->pool)) == APR_SUCCESS || rv == APR_INCOMPLETE))) { r->filename = apr_pstrcat(r->pool, filename, dname, NULL); ap_set_context_info(r, apr_pstrmemdup(r->pool, r->uri, dname - r->uri), filename); /* XXX: Does this walk us around FollowSymLink rules? * When statbuf contains info on r->filename we can save a syscall * by copying it to r->finfo */ if (*userdirs && dname[0] == 0) r->finfo = statbuf; /* For use in the get_suexec_identity phase */ apr_table_setn(r->notes, "mod_userdir_user", user); return OK; } } return DECLINED; }
// generate content takes the request rec and a file_t pointing to the // already opened file from the request // it adds the html information surrounding the body then loops // over the names in the file and prints their coordinates static int generate_content(request_rec *r, apr_file_t *fd) { // initialization char buf[MAX_BUF_LENGTH]; apr_status_t rv; apr_file_t *name_data; const char * cookies; char * user = NULL; char * groups = NULL; moon_svr_cfg* cfg = ap_get_module_config(r->server->module_config, &moon_module); // get the cookies string from the request, retrieve the data // about a user and set the user and groups strings cookies = get_cookies_from_request(r); if(cookies != NULL) { rv = get_user_info(r, cookies, &user, &groups); if(rv != OK) { return rv; } } // set the reponse content type ap_set_content_type(r, "text/html;charset=ascii"); // send initial html data ap_rputs(DOCTYPE, r); ap_rputs(OPEN_HTML_AND_HEAD, r); ap_rputs(TITLE, r); add_user_css(r, cfg, user); add_group_css(r, cfg, groups); ap_rputs(CLOSE_HEAD_OPEN_BODY, r); // check headers and return cookie, if NULL then no cookie set if(cookies != NULL && user != NULL) { add_user_info(r, user, groups); } else { add_anonymous_info(r); } // loop over file, get the next place // and print information about that place while(1) { rv = get_next_place(r, fd, buf); if(rv != OK) { if(rv==DONE) { break; } else { return rv; } } rv = get_place_coordinates(r, buf); ap_rprintf(r, "\n\t\t<p>\n\t\tCoordinates: %s\t\t</p>", buf); if(rv != OK) { return rv; } } // cleanup and return ap_rputs(CLOSE_HTML, r); return OK; }
static int dbm_check_auth(request_rec *r) { dbm_auth_config_rec *conf = ap_get_module_config(r->per_dir_config, &auth_dbm_module); char *user = r->user; int m = r->method_number; const apr_array_header_t *reqs_arr = ap_requires(r); require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL; register int x; const char *t; char *w; if (!conf->auth_dbmgrpfile) return DECLINED; if (!reqs_arr) return DECLINED; for (x = 0; x < reqs_arr->nelts; x++) { if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) continue; t = reqs[x].requirement; w = ap_getword_white(r->pool, &t); if (!strcmp(w, "group") && conf->auth_dbmgrpfile) { const char *orig_groups, *groups; char *v; if (!(groups = get_dbm_grp(r, user, conf->auth_dbmgrpfile, conf->auth_dbmtype))) { if (!(conf->auth_dbmauthoritative)) return DECLINED; ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "user %s not in DBM group file %s: %s", user, conf->auth_dbmgrpfile, r->filename); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; } orig_groups = groups; while (t[0]) { w = ap_getword_white(r->pool, &t); groups = orig_groups; while (groups[0]) { v = ap_getword(r->pool, &groups, ','); if (!strcmp(v, w)) return OK; } } ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "user %s not in right group: %s", user, r->filename); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; } } return DECLINED; }
// get_user_info uses CURL calls to get the data for a user name and groups associated // with a given opensso cookie static int get_user_info(request_rec *r, const char *cookies, char ** user, char **groups) { CURL *curl_handle; CURLcode ec; curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); long no_cert_flag = 0L; moon_svr_cfg* cfg = ap_get_module_config(r->server->module_config, &moon_module); if(curl_handle==NULL) { return HTTP_INTERNAL_SERVER_ERROR; } apr_file_t *groups_data; apr_file_t *user_data; apr_status_t rv; // opens the file/stream for writing data about user if(rv = open_file(r, &user_data, USER_TEMP_FILE_LOC) != OK) { curl_easy_cleanup(curl_handle); return rv; } // opens the file/stream for writing data about user groups if(rv = open_file(r, &groups_data, GROUPS_TEMP_FILE_LOC) != OK) { curl_easy_cleanup(curl_handle); apr_file_close(user_data); return rv; } // set all options for curl call requesting user data rv = set_curl_options(curl_handle, (char*)cfg->user_data_url, &no_cert_flag, user_data, write_data, cookies); if(rv != OK) { curl_easy_cleanup(curl_handle); apr_file_close(user_data); apr_file_close(groups_data); return rv; } // execute request ec = curl_easy_perform(curl_handle); if(ec != CURLE_WRITE_ERROR && ec != CURLE_OK ) { curl_easy_cleanup(curl_handle); apr_file_close(user_data); apr_file_close(groups_data); return HTTP_INTERNAL_SERVER_ERROR; } double x = 0.0; curl_easy_getinfo(curl_handle,CURLINFO_TOTAL_TIME,&x); ap_rprintf(r,"\n\n<!--\nTime for user data request: %f\n-->\n\n",x); // set all options for curl call requesting groups data rv = set_curl_options(curl_handle, (char*)cfg->group_data_url, &no_cert_flag, groups_data, write_data, cookies); if(rv != OK) { curl_easy_cleanup(curl_handle); apr_file_close(user_data); apr_file_close(groups_data); return rv; } // execute request ec = curl_easy_perform(curl_handle); if(ec != CURLE_WRITE_ERROR && ec != CURLE_OK ) { curl_easy_cleanup(curl_handle); apr_file_close(user_data); apr_file_close(groups_data); return HTTP_INTERNAL_SERVER_ERROR; } curl_easy_getinfo(curl_handle,CURLINFO_TOTAL_TIME,&x); ap_rprintf(r,"\n\n<!--\nTime for group data request: %f\n-->\n\n",x); // parse information from responses get_user(r, user_data, user); get_groups(r, groups_data, groups); // cleanup and return curl_easy_cleanup(curl_handle); apr_file_close(user_data); apr_file_close(groups_data); return OK; }
static const char *reveseproxy_enable(cmd_parms *cmd, void *dummy, int flag) { reverseproxy_config_t *config = ap_get_module_config(cmd->server->module_config, &reverseproxy_module); config->enable_module = flag; return NULL; }
static int process_echo_connection(conn_rec *c) { apr_bucket_brigade *bb; apr_bucket *b; apr_socket_t *csd = NULL; EchoConfig *pConfig = ap_get_module_config(c->base_server->module_config, &echo_module); if (!pConfig->bEnabled) { return DECLINED; } ap_time_process_request(c->sbh, START_PREQUEST); update_echo_child_status(c->sbh, SERVER_BUSY_READ, c, NULL); bb = apr_brigade_create(c->pool, c->bucket_alloc); for ( ; ; ) { apr_status_t rv; /* Get a single line of input from the client */ if (((rv = ap_get_brigade(c->input_filters, bb, AP_MODE_GETLINE, APR_BLOCK_READ, 0)) != APR_SUCCESS)) { apr_brigade_cleanup(bb); if (!APR_STATUS_IS_EOF(rv) && ! APR_STATUS_IS_TIMEUP(rv)) ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01611) "ProtocolEcho: Failure reading from %s", c->client_ip); break; } /* Something horribly wrong happened. Someone didn't block! */ if (APR_BRIGADE_EMPTY(bb)) { apr_brigade_cleanup(bb); ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01612) "ProtocolEcho: Error - read empty brigade from %s!", c->client_ip); break; } if (!csd) { csd = ap_get_conn_socket(c); apr_socket_timeout_set(csd, c->base_server->keep_alive_timeout); } update_echo_child_status(c->sbh, SERVER_BUSY_WRITE, NULL, bb); /* Make sure the data is flushed to the client */ b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); rv = ap_pass_brigade(c->output_filters, bb); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01613) "ProtocolEcho: Failure writing to %s", c->client_ip); break; } apr_brigade_cleanup(bb); /* Announce our intent to loop */ update_echo_child_status(c->sbh, SERVER_BUSY_KEEPALIVE, NULL, NULL); } apr_brigade_destroy(bb); ap_time_process_request(c->sbh, STOP_PREQUEST); update_echo_child_status(c->sbh, SERVER_CLOSING, c, NULL); return OK; }
static const char *load_module(cmd_parms *cmd, void *dummy, const char *modname, const char *filename) { apr_dso_handle_t *modhandle; apr_dso_handle_sym_t modsym; module *modp; const char *szModuleFile = ap_server_root_relative(cmd->pool, filename); so_server_conf *sconf; ap_module_symbol_t *modi; ap_module_symbol_t *modie; int i; const char *error; /* we need to setup this value for dummy to make sure that we don't try * to add a non-existant tree into the build when we return to * execute_now. */ *(ap_directive_t **)dummy = NULL; if (!szModuleFile) { return apr_pstrcat(cmd->pool, "Invalid LoadModule path ", filename, NULL); } /* * check for already existing module * If it already exists, we have nothing to do * Check both dynamically-loaded modules and statically-linked modules. */ sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config, &so_module); modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; for (i = 0; i < sconf->loaded_modules->nelts; i++) { modi = &modie[i]; if (modi->name != NULL && strcmp(modi->name, modname) == 0) { ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, cmd->pool, "module %s is already loaded, skipping", modname); return NULL; } } for (i = 0; ap_preloaded_modules[i]; i++) { const char *preload_name; apr_size_t preload_len; apr_size_t thismod_len; modp = ap_preloaded_modules[i]; /* make sure we're comparing apples with apples * make sure name of preloaded module is mod_FOO.c * make sure name of structure being loaded is FOO_module */ if (memcmp(modp->name, "mod_", 4)) { continue; } preload_name = modp->name + strlen("mod_"); preload_len = strlen(preload_name) - 2; if (strlen(modname) <= strlen("_module")) { continue; } thismod_len = strlen(modname) - strlen("_module"); if (strcmp(modname + thismod_len, "_module")) { continue; } if (thismod_len != preload_len) { continue; } if (!memcmp(modname, preload_name, preload_len)) { return apr_pstrcat(cmd->pool, "module ", modname, " is built-in and can't be loaded", NULL); } } modi = apr_array_push(sconf->loaded_modules); modi->name = modname; /* * Load the file into the Apache address space */ if (apr_dso_load(&modhandle, szModuleFile, cmd->pool) != APR_SUCCESS) { char my_error[256]; return apr_pstrcat(cmd->pool, "Cannot load ", szModuleFile, " into server: ", apr_dso_error(modhandle, my_error, sizeof(my_error)), NULL); } ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool, "loaded module %s", modname); /* * Retrieve the pointer to the module structure through the module name: * First with the hidden variant (prefix `AP_') and then with the plain * symbol name. */ if (apr_dso_sym(&modsym, modhandle, modname) != APR_SUCCESS) { char my_error[256]; return apr_pstrcat(cmd->pool, "Can't locate API module structure `", modname, "' in file ", szModuleFile, ": ", apr_dso_error(modhandle, my_error, sizeof(my_error)), NULL); } modp = (module*) modsym; modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle; modi->modp = modp; /* * Make sure the found module structure is really a module structure * */ if (modp->magic != MODULE_MAGIC_COOKIE) { return apr_pstrcat(cmd->pool, "API module structure `", modname, "' in file ", szModuleFile, " is garbled -" " perhaps this is not an Apache module DSO?", NULL); } /* * Add this module to the Apache core structures */ error = ap_add_loaded_module(modp, cmd->pool); if (error) { return error; } /* * Register a cleanup in the config apr_pool_t (normally pconf). When * we do a restart (or shutdown) this cleanup will cause the * shared object to be unloaded. */ apr_pool_cleanup_register(cmd->pool, modi, unload_module, apr_pool_cleanup_null); /* * Finally we need to run the configuration process for the module */ ap_single_module_configure(cmd->pool, cmd->server, modp); return NULL; }
static void ap_logio_add_bytes_in(conn_rec *c, apr_off_t bytes){ logio_config_t *cf = ap_get_module_config(c->conn_config, &logio_module); cf->bytes_in += bytes; }
static int amagent_auth_handler(request_rec *r) { const char *thisfunc = "amagent_auth_handler():"; int rv; am_request_t d; am_config_t *boot = NULL; amagent_config_t *c = ap_get_module_config(r->server->module_config, &amagent_module); if (c == NULL || !c->enabled || c->error != AM_SUCCESS) { /* amagent module is not enabled for this * server/virtualhost - we are not handling this request **/ return DECLINED; } if (c->error != AM_SUCCESS) { LOG_R(APLOG_ERR, r, "%s is not configured to handle the request " "to %s (unable to load bootstrap configuration from %s, error: %s)", DESCRIPTION, r->uri, c->config, am_strerror(c->error)); return HTTP_FORBIDDEN; } LOG_R(APLOG_DEBUG, r, "amagent_auth_handler(): [%s] [%ld]", c->config, c->config_id); /* register and update instance logger configuration (for already registered * instances - update logging level only */ am_log_register_instance(c->config_id, c->debug_file, c->debug_level, c->audit_file, c->audit_level); am_log_debug(c->config_id, "%s begin", thisfunc); /* fetch agent configuration instance (from cache if available) */ rv = am_get_agent_config(c->config_id, c->config, &boot); if (boot == NULL || rv != AM_SUCCESS) { LOG_R(APLOG_ERR, r, "%s is not configured to handle the request " "to %s (unable to get agent configuration instance, configuration: %s, error: %s)", DESCRIPTION, r->uri, c->config, am_strerror(rv)); am_log_error(c->config_id, "amagent_auth_handler(): failed to get agent configuration instance, error: %s", am_strerror(rv)); return HTTP_FORBIDDEN; } /* set up request processor data structure */ memset(&d, 0, sizeof (am_request_t)); d.conf = boot; d.status = AM_ERROR; d.instance_id = c->config_id; d.ctx = r; d.method = get_method_num(r, c->config_id); d.content_type = apr_table_get(r->headers_in, "Content-Type"); d.cookies = apr_table_get(r->headers_in, "Cookie"); if (ISVALID(d.conf->client_ip_header)) { d.client_ip = (char *) apr_table_get(r->headers_in, d.conf->client_ip_header); } if (!ISVALID(d.client_ip)) { #ifdef APACHE24 d.client_ip = (char *) r->connection->client_ip; #else d.client_ip = (char *) r->connection->remote_ip; #endif } if (ISVALID(d.conf->client_hostname_header)) { d.client_host = (char *) apr_table_get(r->headers_in, d.conf->client_hostname_header); } d.am_get_request_url_f = get_request_url; d.am_get_post_data_f = get_request_body; d.am_set_post_data_f = set_request_body; d.am_set_user_f = set_user; d.am_set_header_in_request_f = set_header_in_request; d.am_add_header_in_response_f = add_header_in_response; d.am_set_cookie_f = set_cookie; d.am_set_custom_response_f = set_custom_response; d.am_set_method_f = set_method; am_process_request(&d); rv = am_status_value(d.status); am_log_debug(c->config_id, "amagent_auth_handler(): exit status: %s (%d)", am_strerror(d.status), d.status); am_config_free(&d.conf); am_request_free(&d); LOG_R(APLOG_DEBUG, r, "amagent_auth_handler(): return status: %d", rv); return rv; }
static apr_off_t ap_logio_get_last_bytes(conn_rec *c) { logio_config_t *cf = ap_get_module_config(c->conn_config, &logio_module); return cf->bytes_last_request; }
static apr_status_t do_pattmatch(ap_filter_t *f, apr_bucket *inb, apr_bucket_brigade *mybb, apr_pool_t *pool) { int i; int force_quick = 0; ap_regmatch_t regm[AP_MAX_REG_MATCH]; apr_size_t bytes; apr_size_t len; const char *buff; struct ap_varbuf vb; apr_bucket *b; apr_bucket *tmp_b; subst_dir_conf *cfg = (subst_dir_conf *) ap_get_module_config(f->r->per_dir_config, &substitute_module); subst_pattern_t *script; APR_BRIGADE_INSERT_TAIL(mybb, inb); ap_varbuf_init(pool, &vb, 0); script = (subst_pattern_t *) cfg->patterns->elts; /* * Simple optimization. If we only have one pattern, then * we can safely avoid the overhead of flattening */ if (cfg->patterns->nelts == 1) { force_quick = 1; } for (i = 0; i < cfg->patterns->nelts; i++) { for (b = APR_BRIGADE_FIRST(mybb); b != APR_BRIGADE_SENTINEL(mybb); b = APR_BUCKET_NEXT(b)) { if (APR_BUCKET_IS_METADATA(b)) { /* * we should NEVER see this, because we should never * be passed any, but "handle" it just in case. */ continue; } if (apr_bucket_read(b, &buff, &bytes, APR_BLOCK_READ) == APR_SUCCESS) { int have_match = 0; vb.strlen = 0; if (script->pattern) { const char *repl; /* * space_left counts how many bytes we have left until the * line length reaches max_line_length. */ apr_size_t space_left = cfg->max_line_length; apr_size_t repl_len = strlen(script->replacement); while ((repl = apr_strmatch(script->pattern, buff, bytes))) { have_match = 1; /* get offset into buff for pattern */ len = (apr_size_t) (repl - buff); if (script->flatten && !force_quick) { /* * We are flattening the buckets here, meaning * that we don't do the fast bucket splits. * Instead we copy over what the buckets would * contain and use them. This is slow, since we * are constanting allocing space and copying * strings. */ if (vb.strlen + len + repl_len > cfg->max_line_length) return APR_ENOMEM; ap_varbuf_strmemcat(&vb, buff, len); ap_varbuf_strmemcat(&vb, script->replacement, repl_len); } else { /* * The string before the match but after the * previous match (if any) has length 'len'. * Check if we still have space for this string and * the replacement string. */ if (space_left < len + repl_len) return APR_ENOMEM; space_left -= len + repl_len; /* * We now split off the string before the match * as its own bucket, then isolate the matched * string and delete it. */ SEDRMPATBCKT(b, len, tmp_b, script->patlen); /* * Finally, we create a bucket that contains the * replacement... */ tmp_b = apr_bucket_transient_create(script->replacement, script->replen, f->r->connection->bucket_alloc); /* ... and insert it */ APR_BUCKET_INSERT_BEFORE(b, tmp_b); } /* now we need to adjust buff for all these changes */ len += script->patlen; bytes -= len; buff += len; } if (have_match) { if (script->flatten && !force_quick) { /* XXX: we should check for AP_MAX_BUCKETS here and * XXX: call ap_pass_brigade accordingly */ char *copy = ap_varbuf_pdup(pool, &vb, NULL, 0, buff, bytes, &len); tmp_b = apr_bucket_pool_create(copy, len, pool, f->r->connection->bucket_alloc); APR_BUCKET_INSERT_BEFORE(b, tmp_b); apr_bucket_delete(b); b = tmp_b; } else { /* * We want the behaviour to be predictable. * Therefore we try to always error out if the * line length is larger than the limit, * regardless of the content of the line. So, * let's check if the remaining non-matching * string does not exceed the limit. */ if (space_left < b->length) return APR_ENOMEM; } } } else if (script->regexp) { int left = bytes; const char *pos = buff; char *repl; apr_size_t space_left = cfg->max_line_length; while (!ap_regexec_len(script->regexp, pos, left, AP_MAX_REG_MATCH, regm, 0)) { apr_status_t rv; have_match = 1; if (script->flatten && !force_quick) { /* check remaining buffer size */ /* Note that the last param in ap_varbuf_regsub below * must stay positive. If it gets 0, it would mean * unlimited space available. */ if (vb.strlen + regm[0].rm_so >= cfg->max_line_length) return APR_ENOMEM; /* copy bytes before the match */ if (regm[0].rm_so > 0) ap_varbuf_strmemcat(&vb, pos, regm[0].rm_so); /* add replacement string, last argument is unsigned! */ rv = ap_varbuf_regsub(&vb, script->replacement, pos, AP_MAX_REG_MATCH, regm, cfg->max_line_length - vb.strlen); if (rv != APR_SUCCESS) return rv; } else { apr_size_t repl_len; /* acount for string before the match */ if (space_left <= regm[0].rm_so) return APR_ENOMEM; space_left -= regm[0].rm_so; rv = ap_pregsub_ex(pool, &repl, script->replacement, pos, AP_MAX_REG_MATCH, regm, space_left); if (rv != APR_SUCCESS) return rv; repl_len = strlen(repl); space_left -= repl_len; len = (apr_size_t) (regm[0].rm_eo - regm[0].rm_so); SEDRMPATBCKT(b, regm[0].rm_so, tmp_b, len); tmp_b = apr_bucket_transient_create(repl, repl_len, f->r->connection->bucket_alloc); APR_BUCKET_INSERT_BEFORE(b, tmp_b); } /* * reset to past what we just did. pos now maps to b * again */ pos += regm[0].rm_eo; left -= regm[0].rm_eo; } if (have_match && script->flatten && !force_quick) { char *copy; /* Copy result plus the part after the last match into * a bucket. */ copy = ap_varbuf_pdup(pool, &vb, NULL, 0, pos, left, &len); tmp_b = apr_bucket_pool_create(copy, len, pool, f->r->connection->bucket_alloc); APR_BUCKET_INSERT_BEFORE(b, tmp_b); apr_bucket_delete(b); b = tmp_b; } } else { ap_assert(0); continue; } } } script++; } ap_varbuf_free(&vb); return APR_SUCCESS; }
static const char *set_cookie_exp(cmd_parms *parms, void *dummy, const char *arg) { cookie_log_state *cls; time_t factor, modifier = 0; time_t num = 0; char *word; cls = ap_get_module_config(parms->server->module_config, &usertrack_module); /* The simple case first - all numbers (we assume) */ if (apr_isdigit(arg[0]) && apr_isdigit(arg[strlen(arg) - 1])) { cls->expires = atol(arg); return NULL; } /* * The harder case - stolen from mod_expires * * CookieExpires "[plus] {<num> <type>}*" */ word = ap_getword_conf(parms->temp_pool, &arg); if (!strncasecmp(word, "plus", 1)) { word = ap_getword_conf(parms->temp_pool, &arg); }; /* {<num> <type>}* */ while (word[0]) { /* <num> */ if (apr_isdigit(word[0])) num = atoi(word); else return "bad expires code, numeric value expected."; /* <type> */ word = ap_getword_conf(parms->temp_pool, &arg); if (!word[0]) return "bad expires code, missing <type>"; if (!strncasecmp(word, "years", 1)) factor = 60 * 60 * 24 * 365; else if (!strncasecmp(word, "months", 2)) factor = 60 * 60 * 24 * 30; else if (!strncasecmp(word, "weeks", 1)) factor = 60 * 60 * 24 * 7; else if (!strncasecmp(word, "days", 1)) factor = 60 * 60 * 24; else if (!strncasecmp(word, "hours", 1)) factor = 60 * 60; else if (!strncasecmp(word, "minutes", 2)) factor = 60; else if (!strncasecmp(word, "seconds", 1)) factor = 1; else return "bad expires code, unrecognized type"; modifier = modifier + factor * num; /* next <num> */ word = ap_getword_conf(parms->temp_pool, &arg); } cls->expires = modifier; return NULL; }
static int geoip_header_parser(request_rec * r) { char *orgorisp; char *ipaddr; char *free_me = NULL; short int country_id; const char *continent_code; const char *country_code; const char *country_name; const char *region_name; geoip_server_config_rec *cfg; unsigned char databaseType; GeoIPRecord *gir; GeoIPRegion *giregion; int i; int netspeed; /* For splitting proxy headers */ char *ipaddr_ptr = NULL; char *comma_ptr; cfg = ap_get_module_config(r->server->module_config, &geoip_module); if (!cfg) return DECLINED; if (!cfg->scanProxyHeaders) { ipaddr = _get_client_ip(r); } else { ap_add_common_vars(r); if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) { ipaddr_ptr = (char *)apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP"); } else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) { ipaddr_ptr = (char *)apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR"); } else if (apr_table_get(r->headers_in, "X-Forwarded-For")) { ipaddr_ptr = (char *)apr_table_get(r->headers_in, "X-Forwarded-For"); } else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) { ipaddr_ptr = (char *)apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR"); } if (!ipaddr_ptr) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR."); ipaddr = _get_client_ip(r); } else { /* Found XFF like header */ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr); if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP) { ipaddr = free_me = _get_ip_from_xff(ipaddr_ptr); if (!ipaddr) ipaddr = _get_client_ip(r); } else { ipaddr = free_me = (char *)calloc(8 * 4 + 7 + 1, sizeof(char)); /* proxyHeaderMode is * GEOIP_PROXY_HEADER_MODE_LAST_IP or GEOIP_PROXY_HEADER_MODE_FIRST_IP */ /* * Check to ensure that the HTTP_CLIENT_IP or * X-Forwarded-For header is not a comma separated * list of addresses, which would cause mod_geoip to * return no country code. If the header is a comma * separated list, return the first IP address in the * list, which is (hopefully!) the real client IP. */ if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_LAST_IP) { comma_ptr = strrchr(ipaddr_ptr, ','); if (comma_ptr) { /* skip over whitespace */ ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t"); } } strncpy(ipaddr, ipaddr_ptr, 8 * 4 + 7); comma_ptr = strchr(ipaddr, ','); if (comma_ptr != 0) *comma_ptr = '\0'; } } } /* this block should be removed! */ #if 1 if (!cfg->gips) { if (cfg->GeoIPFilenames != NULL) { cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles); for (i = 0; i < cfg->numGeoIPFiles; i++) { cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], (cfg->GeoIPFlags2[i] == GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i]); if (cfg->gips[i]) { if (cfg->GeoIPEnableUTF8) { GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8); } } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file %s", cfg->GeoIPFilenames[i]); return DECLINED; } } } else { cfg->gips = malloc(sizeof(GeoIP *)); cfg->gips[0] = GeoIP_new(GEOIP_STANDARD); if (!cfg->gips[0]) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file"); return DECLINED; } cfg->numGeoIPFiles = 1; } } #endif set_geoip_output(cfg, r, "GEOIP_ADDR", ipaddr); for (i = 0; i < cfg->numGeoIPFiles; i++) { /* * skip database handles that can not be opned for some * reason */ if (cfg->gips[i] == NULL) continue; databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1; /* -1 is "magic value" * in case file not * found */ switch (databaseType) { case GEOIP_NETSPEED_EDITION_REV1: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_NETSPEED", orgorisp); break; case GEOIP_NETSPEED_EDITION: netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr); if (netspeed == GEOIP_UNKNOWN_SPEED) { netspeedstring = "unknown"; } else if (netspeed == GEOIP_DIALUP_SPEED) { netspeedstring = "dialup"; } else if (netspeed == GEOIP_CABLEDSL_SPEED) { netspeedstring = "cabledsl"; } else if (netspeed == GEOIP_CORPORATE_SPEED) { netspeedstring = "corporate"; } setn_geoip_output(cfg, r, "GEOIP_NETSPEED", netspeedstring); break; case GEOIP_COUNTRY_EDITION_V6: /* Get the Country ID */ country_id = GeoIP_id_by_addr_v6(cfg->gips[i], ipaddr); if (country_id > 0) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6", continent_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6", country_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6", country_name); } break; case GEOIP_COUNTRY_EDITION: /* Get the Country ID */ country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr); if (country_id > 0) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE", continent_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", country_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", country_name); } break; case GEOIP_REGION_EDITION_REV0: case GEOIP_REGION_EDITION_REV1: giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr); if (giregion != NULL) { region_name = NULL; if (giregion->country_code[0]) { region_name = GeoIP_region_name_by_code (giregion->country_code, giregion->region); set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", giregion->country_code); country_id = GeoIP_id_by_code(giregion->country_code); setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", GeoIP_country_name[country_id]); setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE", GeoIP_country_continent[country_id]); } if (giregion->region[0]) { set_geoip_output(cfg, r, "GEOIP_REGION", giregion->region); } if (region_name != NULL) { set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name); } GeoIPRegion_delete(giregion); } break; case GEOIP_CITY_EDITION_REV0_V6: case GEOIP_CITY_EDITION_REV1_V6: gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr); if (gir != NULL) { if (gir->country_code != NULL) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6", gir->continent_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6", gir->country_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6", gir->country_name); set_geoip_output(cfg, r, "GEOIP_REGION_V6", gir->region); set_geoip_output(cfg, r, "GEOIP_REGION_NAME_V6", region_name); set_geoip_output(cfg, r, "GEOIP_CITY_V6", gir->city); set_geoip_output(cfg, r, "GEOIP_DMA_CODE_V6", metrocodestr); set_geoip_output(cfg, r, "GEOIP_METRO_CODE_V6", metrocodestr); set_geoip_output(cfg, r, "GEOIP_AREA_CODE_V6", areacodestr); sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); set_geoip_output(cfg, r, "GEOIP_LATITUDE_V6", latstr); set_geoip_output(cfg, r, "GEOIP_LONGITUDE_V6", lonstr); set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE_V6", gir->postal_code); GeoIPRecord_delete(gir); } break; case GEOIP_CITY_EDITION_REV0: case GEOIP_CITY_EDITION_REV1: gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr); if (gir != NULL) { if (gir->country_code != NULL) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE", gir->continent_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", gir->country_code); set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", gir->country_name); set_geoip_output(cfg, r, "GEOIP_REGION", gir->region); set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name); set_geoip_output(cfg, r, "GEOIP_CITY", gir->city); set_geoip_output(cfg, r, "GEOIP_DMA_CODE", metrocodestr); set_geoip_output(cfg, r, "GEOIP_METRO_CODE", metrocodestr); set_geoip_output(cfg, r, "GEOIP_AREA_CODE", areacodestr); sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); set_geoip_output(cfg, r, "GEOIP_LATITUDE", latstr); set_geoip_output(cfg, r, "GEOIP_LONGITUDE", lonstr); set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE", gir->postal_code); GeoIPRecord_delete(gir); } break; case GEOIP_ORG_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_ORGANIZATION", orgorisp); break; case GEOIP_ISP_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_ISP", orgorisp); break; case GEOIP_DOMAIN_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); setn_geoip_output(cfg, r, "GEOIP_DOMAIN", orgorisp); break; } } if (free_me) free(free_me); return OK; }
/* The wiki handler */ static int wiki_handler(request_rec *r) { wiki_conf *conf; git_repository *repo; const git_oid *tree_oid; char *path; const git_oid *oid; char hash[41]; hash[40] = '\0'; int ret; int type; MMIOT *doc; if (strcmp(r->handler, "wiki")) { return DECLINED; } if (r->header_only) { return OK; } conf = (wiki_conf *) ap_get_module_config(r->per_dir_config, &wiki_module); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "filename=%s", r->filename); if (conf->basepath) { path = ltrim(conf->basepath, r->parsed_uri.path); } else { path = r->parsed_uri.path + 1; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "path=%s", path); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "r->content_type=%s", r->content_type); if (conf->repo == NULL) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "WikiRepository is not set."); return HTTP_INTERNAL_SERVER_ERROR; } ret = git_repository_open(&repo, conf->repo); if (ret) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Cannot open git repository.(%s)", conf->repo); return HTTP_INTERNAL_SERVER_ERROR; } tree_oid = lookup_master_tree(repo); if (tree_oid == NULL) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Not found master tree."); git_repository_free(repo); } type = lookup_object_oid(r, repo, tree_oid, path, &oid); if (type == WIKI_NOTFOUND) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Object is not found."); git_repository_free(repo); return HTTP_NOT_FOUND; } else if(type == WIKI_DIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Directory listing is not implement yet."); git_repository_free(repo); return HTTP_FORBIDDEN; } else if(type == WIKI_ERROR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Error at lookup."); git_repository_free(repo); return HTTP_NOT_FOUND; } git_oid_fmt(hash, oid); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "object hash=%s", hash); const char *data; size_t size; git_odb *odb; ret = git_repository_odb(&odb, repo); git_odb_object *odb_object; ret = git_odb_read(&odb_object, odb, oid); data = git_odb_object_data(odb_object); size = git_odb_object_size(odb_object); git_odb_object_free(odb_object); // is this safe? if (type == WIKI_FOUND) { ap_rwrite(data, size, r); } else if(type == WIKI_MARKDOWN) { r->content_type = "text/html"; doc = mkd_string(data, size, 0); if (doc == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mkd_string() returned NULL\n"); git_repository_free(repo); return HTTP_INTERNAL_SERVER_ERROR; } wiki_output(doc, r); mkd_cleanup(doc); } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Unknown Error.\n"); git_repository_free(repo); return HTTP_INTERNAL_SERVER_ERROR; } git_repository_free(repo); return OK; }
static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info *info) { disk_cache_conf *conf = ap_get_module_config(r->server->module_config, &disk_cache_module); apr_status_t rv; apr_size_t amt; disk_cache_object_t *dobj = (disk_cache_object_t*) h->cache_obj->vobj; disk_cache_info_t disk_info; struct iovec iov[2]; /* This is flaky... we need to manage the cache_info differently */ h->cache_obj->info = *info; if (r->headers_out) { const char *tmp; tmp = apr_table_get(r->headers_out, "Vary"); if (tmp) { apr_array_header_t* varray; apr_uint32_t format = VARY_FORMAT_VERSION; /* If we were initially opened as a vary format, rollback * that internal state for the moment so we can recreate the * vary format hints in the appropriate directory. */ if (dobj->prefix) { dobj->hdrsfile = dobj->prefix; dobj->prefix = NULL; } mkdir_structure(conf, dobj->hdrsfile, r->pool); rv = apr_file_mktemp(&dobj->tfd, dobj->tempfile, APR_CREATE | APR_WRITE | APR_BINARY | APR_EXCL, r->pool); if (rv != APR_SUCCESS) { return rv; } amt = sizeof(format); apr_file_write(dobj->tfd, &format, &amt); amt = sizeof(info->expire); apr_file_write(dobj->tfd, &info->expire, &amt); varray = apr_array_make(r->pool, 6, sizeof(char*)); tokens_to_array(r->pool, tmp, varray); store_array(dobj->tfd, varray); apr_file_close(dobj->tfd); dobj->tfd = NULL; rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server, "disk_cache: rename tempfile to varyfile failed: %s -> %s", dobj->tempfile, dobj->hdrsfile); apr_file_remove(dobj->tempfile, r->pool); return rv; } dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); tmp = regen_key(r->pool, r->headers_in, varray, dobj->name); dobj->prefix = dobj->hdrsfile; dobj->hashfile = NULL; dobj->datafile = data_file(r->pool, conf, dobj, tmp); dobj->hdrsfile = header_file(r->pool, conf, dobj, tmp); } } rv = apr_file_mktemp(&dobj->hfd, dobj->tempfile, APR_CREATE | APR_WRITE | APR_BINARY | APR_BUFFERED | APR_EXCL, r->pool); if (rv != APR_SUCCESS) { return rv; } disk_info.format = DISK_FORMAT_VERSION; disk_info.date = info->date; disk_info.expire = info->expire; disk_info.entity_version = dobj->disk_info.entity_version++; disk_info.request_time = info->request_time; disk_info.response_time = info->response_time; disk_info.status = info->status; disk_info.name_len = strlen(dobj->name); iov[0].iov_base = (void*)&disk_info; iov[0].iov_len = sizeof(disk_cache_info_t); iov[1].iov_base = (void*)dobj->name; iov[1].iov_len = disk_info.name_len; rv = apr_file_writev(dobj->hfd, (const struct iovec *) &iov, 2, &amt); if (rv != APR_SUCCESS) { return rv; } if (r->headers_out) { apr_table_t *headers_out; headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out, r->server); if (!apr_table_get(headers_out, "Content-Type") && r->content_type) { apr_table_setn(headers_out, "Content-Type", ap_make_content_type(r, r->content_type)); } headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out); rv = store_table(dobj->hfd, headers_out); if (rv != APR_SUCCESS) { return rv; } } /* Parse the vary header and dump those fields from the headers_in. */ /* FIXME: Make call to the same thing cache_select calls to crack Vary. */ if (r->headers_in) { apr_table_t *headers_in; headers_in = ap_cache_cacheable_hdrs_out(r->pool, r->headers_in, r->server); rv = store_table(dobj->hfd, headers_in); if (rv != APR_SUCCESS) { return rv; } } apr_file_close(dobj->hfd); /* flush and close */ /* Remove old file with the same name. If remove fails, then * perhaps we need to create the directory tree where we are * about to write the new headers file. */ rv = apr_file_remove(dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { mkdir_structure(conf, dobj->hdrsfile, r->pool); } rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server, "disk_cache: rename tempfile to hdrsfile failed: %s -> %s", dobj->tempfile, dobj->hdrsfile); apr_file_remove(dobj->tempfile, r->pool); return rv; } dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Stored headers for URL %s", dobj->name); return APR_SUCCESS; }
static int check_auth_cookie(request_rec *r) { const char *cookies = NULL, *auth_line = NULL; char *cookie = NULL; /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "check_auth_cookie called");*/ /* Get config for this directory. */ cookie_auth_config_rec *conf = ap_get_module_config(r->per_dir_config, &auth_cookie_module); /* Check we have been configured. */ if (!conf->cookie_auth_cookie) { return DECLINED; } /* Do not override real auth header, unless config instructs us to. */ if (!conf->cookie_auth_override && apr_table_get(r->headers_in, "Authorization")) { if (conf->cookie_auth_env) { unsetenv(conf->cookie_auth_env); } return DECLINED; } /* todo: protect against xxxCookieNamexxx, regex? */ /* todo: make case insensitive? */ /* Get the cookie (code from mod_log_config). */ if ((cookies = apr_table_get(r->headers_in, "Cookie"))) { char *start_cookie, *end_cookie; if ((start_cookie = ap_strstr_c(cookies, conf->cookie_auth_cookie))) { start_cookie += strlen(conf->cookie_auth_cookie) + 1; cookie = apr_pstrdup(r->pool, start_cookie); /* kill everything in cookie after ';' */ end_cookie = strchr(cookie, ';'); if (end_cookie) { *end_cookie = '\0'; } ap_unescape_url(cookie); } } /* No cookie? Nothing for us to do. */ if (!cookie) { if (conf->cookie_auth_unauth_redirect) { const char* redirect = conf->cookie_auth_unauth_redirect; compose_and_set_redirect(r, redirect); return HTTP_MOVED_TEMPORARILY; } else { return DECLINED; } } /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s=%s", conf->cookie_auth_cookie, cookie);*/ char* aux_auth_info = ""; /* Construct the fake auth_line. */ if (conf->cookie_auth_base64) { char* decoded_cookie = apr_palloc(r->pool, apr_base64_decode_len(cookie)); int decoded_cookie_length = apr_base64_decode(decoded_cookie, cookie); int valid = 1; /* if the cookie is encrypted, decrypt it in place */ if (conf->cookie_auth_encrypt) { MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL); int keysize = strlen(conf->cookie_auth_encrypt); int blocksize = mcrypt_enc_get_block_size(td); // We will copy the iv from the beginning of the cookie. // The iv does not need to be null-terminated, but we will // null-terminate it for convenience. int iv_length = mcrypt_enc_get_iv_size(td); char* iv = (char*) apr_palloc(r->pool, iv_length + 1); memcpy(iv, decoded_cookie, iv_length); iv[iv_length] = '\0'; // Take the iv off the beginning of the cookie decoded_cookie += iv_length; decoded_cookie_length -= iv_length; mcrypt_generic_init( td, conf->cookie_auth_encrypt, keysize, iv); // Encryption in CBC is performed in blocks, so our // decryption string will always be an integral number // of full blocks. char* decrypt_ptr = decoded_cookie; while (decoded_cookie_length >= blocksize) { mdecrypt_generic(td, decrypt_ptr, blocksize); decrypt_ptr += blocksize; decoded_cookie_length -= blocksize; } if (decoded_cookie_length != 0) { valid = 0; } mcrypt_generic_deinit (td); mcrypt_module_close(td); /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mdecrypt(%s)=%s", conf->cookie_auth_cookie, decoded_cookie);*/ } /* if the cookie did not decrypt, then do nothing */ if (valid) { char* end_auth_info = strchr(decoded_cookie, '\t'); if (end_auth_info) { aux_auth_info = decoded_cookie; char* unencoded_cookie = end_auth_info + 1; *end_auth_info = 0; auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, unencoded_cookie), NULL); } else { auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, decoded_cookie), NULL); } } } else { // Aux auth info and cookie encrypt features only available in base64 mode ap_unescape_url(cookie); auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, cookie), NULL); } /* If there is aux auth info, then set the env variable */ if (conf->cookie_auth_env) { apr_table_set(r->subprocess_env, conf->cookie_auth_env, aux_auth_info); } /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Authorization: %s", auth_line);*/ /* If there is no aux auth info, then force a redirect if our conf directives say that we should */ if (conf->cookie_auth_env_redirect && !strlen(aux_auth_info)) { const char* redirect = conf->cookie_auth_env_redirect; compose_and_set_redirect(r, redirect); return HTTP_MOVED_TEMPORARILY; } else { /* Set fake auth_line. */ if (auth_line) { apr_table_set(r->headers_in, "Authorization", auth_line); } } /* Always return DECLINED because we don't authorize, */ /* we just set things up for the next auth module to. */ return DECLINED; }