static int proxy_fdpass_handler(request_rec *r, proxy_worker *worker, proxy_server_conf *conf, char *url, const char *proxyname, apr_port_t proxyport) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *clientsock; if (strncasecmp(url, "fd://", 5) == 0) { url += 5; } else { return DECLINED; } rv = get_socket_from_path(r->pool, url, &sock); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01152) "Failed to connect to '%s'", url); return HTTP_INTERNAL_SERVER_ERROR; } { int status; const char *flush_method = worker->s->flusher ? worker->s->flusher : "flush"; proxy_fdpass_flush *flush = ap_lookup_provider(PROXY_FDPASS_FLUSHER, flush_method, "0"); if (!flush) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01153) "Unable to find configured flush provider '%s'", flush_method); return HTTP_INTERNAL_SERVER_ERROR; } status = flush->flusher(r); if (status) { return status; } } clientsock = ap_get_conn_socket(r->connection); rv = send_socket(r->pool, sock, clientsock); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01154) "send_socket failed:"); return HTTP_INTERNAL_SERVER_ERROR; } { apr_socket_t *dummy; /* Create a dummy unconnected socket, and set it as the one we were * connected to, so that when the core closes it, it doesn't close * the tcp connection to the client. */ rv = apr_socket_create(&dummy, APR_INET, SOCK_STREAM, APR_PROTO_TCP, r->connection->pool); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01155) "failed to create dummy socket"); return HTTP_INTERNAL_SERVER_ERROR; } ap_set_core_module_config(r->connection->conn_config, dummy); } return OK; }
static apr_status_t triger_filter(ap_filter_t * f, apr_bucket_brigade * bb) { apr_status_t rv = APR_SUCCESS; triger_conf_t *cfg; apr_bucket *b; triger_module_ctx_t *ctx = f->ctx; if (APR_BRIGADE_EMPTY(bb)) return APR_SUCCESS; cfg = ap_get_module_config(f->r->per_dir_config, &triger_module); if (!cfg) goto last; if (!cfg->enabled) goto last; if (!ctx) { f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx)); if (!ctx) goto last; ctx->times = 1; ctx->unknown_start_tag_find = 0; ctx->unknown_end_tag_find = 0; ctx->find = 0; ctx->no_tag_find = 1; ctx->doctype_tag_find = 0; ctx->html_start_tag_find = ctx->head_start_tag_find = ctx->body_start_tag_find = ctx->body_end_tag_find = ctx->html_end_tag_find = 0; ctx->triger_bucket = apr_pcalloc(f->r->pool, sizeof(triger_bucket_t)); if (!ctx->triger_bucket) goto last; ctx->triger_bucket->limit = cfg->chk_len; ctx->head_check = 0; apr_table_unset(f->r->headers_out, "Content-Length"); } else ctx->times++; if (!is_this_html(f->r) || ctx->find) goto last; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "Enter this filter %u times", ctx->times); if (!cfg->full_chk) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "Only check the first and last data buckets"); if (!ctx->head_check) { ctx->head_check = 1; get_data_at_head(f, bb); where_to_insert_html_fragment_at_head(f); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "Find the first data bucket. Content length: %d uri: %s path info: %s positions found: %d (<head>)", (int) ctx->triger_bucket->len, f->r->uri, f->r->path_info, (int) ctx->triger_bucket->head_start_tag_pos); insert_html_fragment_at_head(f, bb, cfg); } if (ctx->find || !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) goto last; get_data_at_tail(f, bb); where_to_insert_html_fragment_at_tail(f); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "Find the last data bucket. Content length: %d uri: %s path info: %s positions found: %d (</body>) %d (/html)", (int) ctx->triger_bucket->len, f->r->uri, f->r->path_info, (int) ctx->triger_bucket->body_end_tag_pos, (int) ctx->triger_bucket->html_end_tag_pos); insert_html_fragment_at_tail(f, bb, cfg); } else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "Check each data bucket"); for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) { if (!APR_BUCKET_IS_METADATA(b)) { get_triger_bucket(f, b); where_to_insert_html_fragment_at_head(f); insert_html_fragment_at_head(f, bb, cfg); } if (!ctx->find && APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { get_data_at_tail(f, bb); where_to_insert_html_fragment_at_tail(f); insert_html_fragment_at_tail(f, bb, cfg); } } } last: rv = ap_pass_brigade(f->next, bb); return rv; }
static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg, const char *action) { int rv; const char *newuri = NULL; int nrows; const char *message; ap_dbd_t *dbd; apr_dbd_prepared_t *query; apr_dbd_results_t *res = NULL; apr_dbd_row_t *row = NULL; if (cfg->query == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01642) "No query configured for %s!", action); return HTTP_INTERNAL_SERVER_ERROR; } dbd = dbd_handle(r); if (dbd == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02902) "No db handle available for %s! " "Check your database access", action); return HTTP_INTERNAL_SERVER_ERROR; } query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING); if (query == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01643) "Error retrieving Query for %s!", action); return HTTP_INTERNAL_SERVER_ERROR; } rv = apr_dbd_pvquery(dbd->driver, r->pool, dbd->handle, &nrows, query, r->user, NULL); if (rv == 0) { if (nrows != 1) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01644) "authz_dbd: %s of user %s updated %d rows", action, r->user, nrows); } } else { message = apr_dbd_error(dbd->driver, dbd->handle, rv); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01645) "authz_dbd: query for %s failed; user %s [%s]", action, r->user, message?message:noerror); return HTTP_INTERNAL_SERVER_ERROR; } if (cfg->redirect == 1) { newuri = apr_table_get(r->headers_in, "Referer"); } if (!newuri && cfg->redir_query) { query = apr_hash_get(dbd->prepared, cfg->redir_query, APR_HASH_KEY_STRING); if (query == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01646) "authz_dbd: no redirect query!"); /* OK, this is non-critical; we can just not-redirect */ } else if ((rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, query, 0, r->user, NULL)) == 0) { for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); rv != -1; rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { if (rv != 0) { message = apr_dbd_error(dbd->driver, dbd->handle, rv); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01647) "authz_dbd in get_row; action=%s user=%s [%s]", action, r->user, message?message:noerror); } else if (newuri == NULL) { newuri = apr_pstrdup(r->pool, apr_dbd_get_entry(dbd->driver, row, 0)); } /* we can't break out here or row won't get cleaned up */ } } else { message = apr_dbd_error(dbd->driver, dbd->handle, rv); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01648) "authz_dbd/redirect for %s of %s [%s]", action, r->user, message?message:noerror); } } if (newuri != NULL) { r->status = HTTP_MOVED_TEMPORARILY; apr_table_set(r->err_headers_out, "Location", newuri); } authz_dbd_run_client_login(r, OK, action); return OK; }
/* The handler. Create a new parser and/or filter context where appropriate * and parse the chunks of data received from the brigade */ static int idlChunkHandler( ap_filter_t *f, apr_bucket_brigade *brigade ) { idlChunkContext* ctx = f->ctx; apr_bucket* currentBucket = NULL; apr_pool_t* pool = f->r->pool; const char* data; apr_size_t len; osrfStringArray* params = NULL; mparams = NULL; /* load the per-dir/location config */ idlChunkConfig* config = ap_get_module_config( f->r->per_dir_config, &idlchunk_module ); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "IDLCHUNK Config:\nContent Type = %s, " "Strip PI = %s, Strip Comments = %s, Doctype = %s", config->contentType, (config->stripPI) ? "yes" : "no", (config->stripComments) ? "yes" : "no", config->doctype); /* set the content type based on the config */ ap_set_content_type(f->r, config->contentType); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "Set content type"); params = apacheParseParms(f->r); /* free me */ mparams = apacheGetParamValues( params, "class" ); /* free me */ all = 1; if (mparams && mparams->size > 0) all = 0; //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "Parsed the params, if any"); /* create the XML parser */ int firstrun = 0; if( parser == NULL ) { firstrun = 1; parser = XML_ParserCreate("UTF-8"); XML_SetUserData(parser, f); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, charHandler); if(!config->stripDoctype) XML_SetStartDoctypeDeclHandler( parser, doctypeHandler ); if(!config->stripPI) XML_SetProcessingInstructionHandler(parser, handlePI); if(!config->stripComments) XML_SetCommentHandler(parser, handleComment); } /* create the filter context */ if( ctx == NULL ) { f->ctx = ctx = apr_pcalloc( pool, sizeof(*ctx)); ctx->brigade = apr_brigade_create( pool, f->c->bucket_alloc ); ctx->parser = parser; } if(firstrun) { /* we haven't started writing the data to the stream yet */ /* go ahead and write the doctype out if we have one defined */ if(config->doctype) { ap_log_rerror( APLOG_MARK, APLOG_DEBUG, 0, f->r, "IDLCHUNK DOCTYPE => %s", config->doctype); _fwrite(f, "%s\n", config->doctype); } } /* cycle through the buckets in the brigade */ while (!APR_BRIGADE_EMPTY(brigade)) { /* grab the next bucket */ currentBucket = APR_BRIGADE_FIRST(brigade); /* clean up when we're done */ if (APR_BUCKET_IS_EOS(currentBucket) || APR_BUCKET_IS_FLUSH(currentBucket)) { APR_BUCKET_REMOVE(currentBucket); APR_BRIGADE_INSERT_TAIL(ctx->brigade, currentBucket); ap_pass_brigade(f->next, ctx->brigade); XML_ParserFree(parser); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); parser = NULL; return APR_SUCCESS; } /* read the incoming data */ int s = apr_bucket_read(currentBucket, &data, &len, APR_NONBLOCK_READ); if( s != APR_SUCCESS ) { ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, f->r, "IDLCHUNK error reading data from filter with status %d", s); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); return s; } if (len > 0) { ap_log_rerror( APLOG_MARK, APLOG_DEBUG, 0, f->r, "IDLCHUNK read %d bytes", (int)len); /* push data into the XML push parser */ if ( XML_Parse(ctx->parser, data, len, 0) == XML_STATUS_ERROR ) { char tmp[len+1]; memcpy(tmp, data, len); tmp[len] = '\0'; /* log and die on XML errors */ ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, f->r, "IDLCHUNK XML Parse Error: %s at line %d: parsing %s: data %s", XML_ErrorString(XML_GetErrorCode(ctx->parser)), (int) XML_GetCurrentLineNumber(ctx->parser), f->r->filename, tmp); XML_ParserFree(parser); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); parser = NULL; return HTTP_INTERNAL_SERVER_ERROR; } } /* so a subrequest doesn't re-read this bucket */ apr_bucket_delete(currentBucket); } apr_brigade_destroy(brigade); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); return APR_SUCCESS; }
static triger_bucket_t *where_to_insert_html_fragment_at_head(ap_filter_t * f) { int in_comments = -1; apr_size_t i = 0, j = 0;; apr_size_t char_counts = 0; triger_module_ctx_t *ctx = f->ctx; triger_bucket_t *rv = ctx->triger_bucket; apr_size_t len = rv->len; const char *data = rv->data; rv->head_start_tag_pos = rv->body_start_tag_pos = -1; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "Look for <head> and <body>"); if (len < 1) return rv; for (; i < len; i++) { if (char_counts > rv->limit) return rv; else char_counts++; if (in_comments != -1) { switch (*(data + i)) { case '>': if (i >= 2) { if (in_comments == html_comment) { if (*(data + i - 1) == '-' && *(data + i - 2) == '-') in_comments = -1; } else if (in_comments == xml_comment) { if (*(data + i - 1) == ']' && *(data + i - 2) == ']') in_comments = -1; } } break; case '<': if (in_comments == microsoft_comment) if (i + 9 < len && *(data + i + 1) == '/' && (*(data + i + 2) == 'c' || *(data + i + 2) == 'C') && (*(data + i + 3) == 'o' || *(data + i + 3) == 'O') && (*(data + i + 4) == 'm' || *(data + i + 4) == 'M') && (*(data + i + 5) == 'm' || *(data + i + 5) == 'M') && (*(data + i + 6) == 'e' || *(data + i + 6) == 'E') && (*(data + i + 7) == 'n' || *(data + i + 7) == 'N') && (*(data + i + 8) == 't' || *(data + i + 8) == 'T') && *(data + i + 9) == '>') { in_comments = -1; i = i + 9; } break; default: continue; } } else { switch (*(data + i)) { case '<': if (i + 14 < len && *(data + i + 1) == '!' && *(data + i + 2) == 'D' && *(data + i + 3) == 'O' && *(data + i + 4) == 'C' && *(data + i + 5) == 'T' && *(data + i + 6) == 'Y' && *(data + i + 7) == 'P' && *(data + i + 8) == 'E' && *(data + i + 9) == ' ' && (*(data + i + 10) == 'h' || *(data + i + 10) == 'H') && (*(data + i + 11) == 't' || *(data + i + 11) == 'T') && (*(data + i + 12) == 'm' || *(data + i + 12) == 'M') && (*(data + i + 13) == 'l' || *(data + i + 13) == 'L') && (*(data + i + 14) == ' ' || *(data + i + 14) == '>')) { if (!ctx->doctype_tag_find) ctx->doctype_tag_find = 1; } else if (i + 5 < len && (*(data + i + 1) == 'h' || *(data + i + 1) == 'H') && (*(data + i + 2) == 't' || *(data + i + 2) == 'T') && (*(data + i + 3) == 'm' || *(data + i + 3) == 'M') && (*(data + i + 4) == 'l' || *(data + i + 4) == 'L') && (*(data + i + 5) == '>' || *(data + i + 5) == ' ')) { for (j = i + 5; *(data + j) != '>' && j < len - 1; j++); if (*(data + j) == '>') { if (ctx->no_tag_find && !ctx->html_start_tag_find) { ctx->html_start_tag_find = 1; ctx->no_tag_find = 0; } else return rv; rv->html_start_tag_pos = j; i = j; } else rv->head_start_tag_pos = -1; } else if (i + 5 < len && (*(data + i + 1) == 'h' || *(data + i + 1) == 'H') && (*(data + i + 2) == 'e' || *(data + i + 2) == 'E') && (*(data + i + 3) == 'a' || *(data + i + 3) == 'A') && (*(data + i + 4) == 'd' || *(data + i + 4) == 'D') && (*(data + i + 5) == '>' || *(data + i + 5) == ' ')) { for (j = i + 5; *(data + j) != '>' && j < len - 1; j++); if (*(data + j) == '>') { if (!ctx->head_start_tag_find) { ctx->head_start_tag_find = 1; ctx->no_tag_find = 0; } else return rv; rv->head_start_tag_pos = j; } else rv->head_start_tag_pos = -1; return rv; } else if (i + 5 < len && (*(data + i + 1) == 'b' || *(data + i + 1) == 'B') && (*(data + i + 2) == 'o' || *(data + i + 2) == 'O') && (*(data + i + 3) == 'd' || *(data + i + 3) == 'D') && (*(data + i + 4) == 'y' || *(data + i + 4) == 'Y') && (*(data + i + 5) == '>' || *(data + i + 5) == ' ')) { for (j = i + 5; *(data + j) != '>' && j < len - 1; j++); if (*(data + j) == '>') { if (!ctx->body_start_tag_find) { ctx->body_start_tag_find = 1; ctx->no_tag_find = 0; } else return rv; rv->body_start_tag_pos = j; i = j; } else rv->body_start_tag_pos = -1; return rv; } else if (i + 3 < len && *(data + i + 1) == '!' && *(data + i + 2) == '-' && *(data + i + 3) == '-') { in_comments = html_comment; i = i + 3; } else if (i + 8 < len && *(data + i + 1) == '!' && *(data + i + 2) == '[' && *(data + i + 3) == 'C' && *(data + i + 4) == 'D' && *(data + i + 5) == 'A' && *(data + i + 6) == 'T' && *(data + i + 7) == 'A' && *(data + i + 8) == '[') { in_comments = xml_comment; i = i + 8; } else if (i + 8 < len && (*(data + i + 1) == 'c' || *(data + i + 1) == 'C') && (*(data + i + 2) == 'o' || *(data + i + 2) == 'O') && (*(data + i + 3) == 'm' || *(data + i + 3) == 'M') && (*(data + i + 4) == 'm' || *(data + i + 4) == 'M') && (*(data + i + 5) == 'e' || *(data + i + 5) == 'E') && (*(data + i + 6) == 'n' || *(data + i + 6) == 'N') && (*(data + i + 7) == 't' || *(data + i + 7) == 'T') && (*(data + i + 8) == '>' || *(data + i + 8) == ' ')) { in_comments = microsoft_comment; i = i + 8; } else { ctx->unknown_start_tag_find = 1; return rv; } break; default: continue; } } } return rv; }
AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f, apr_bucket_brigade *bb) { request_rec *r = f->r; conn_rec *c = r->connection; apr_bucket *e; apr_bucket_brigade *bsend; apr_bucket_brigade *tmpbb; apr_off_t range_start; apr_off_t range_end; apr_off_t clength = 0; apr_status_t rv; int found = 0; int num_ranges; char *boundary = NULL; char *bound_head = NULL; apr_array_header_t *indexes; indexes_t *idx; int i; int original_status; int max_ranges = get_max_ranges(r); /* * Iterate through the brigade until reaching EOS or a bucket with * unknown length. */ for (e = APR_BRIGADE_FIRST(bb); (e != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(e) && e->length != (apr_size_t)-1); e = APR_BUCKET_NEXT(e)) { clength += e->length; } /* * Don't attempt to do byte range work if this brigade doesn't * contain an EOS, or if any of the buckets has an unknown length; * this avoids the cases where it is expensive to perform * byteranging (i.e. may require arbitrary amounts of memory). */ if (!APR_BUCKET_IS_EOS(e) || clength <= 0) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } original_status = r->status; num_ranges = ap_set_byterange(r, clength, &indexes); /* We have nothing to do, get out of the way. */ if (num_ranges == 0 || (max_ranges >= 0 && num_ranges > max_ranges)) { r->status = original_status; ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } /* this brigade holds what we will be sending */ bsend = apr_brigade_create(r->pool, c->bucket_alloc); if (num_ranges < 0) return send_416(f, bsend); if (num_ranges > 1) { /* Is ap_make_content_type required here? */ const char *orig_ct = ap_make_content_type(r, r->content_type); boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx", (apr_uint64_t)r->request_time, c->id); ap_set_content_type(r, apr_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/", "byteranges; boundary=", boundary, NULL)); if (strcasecmp(orig_ct, NO_CONTENT_TYPE)) { bound_head = apr_pstrcat(r->pool, CRLF "--", boundary, CRLF "Content-type: ", orig_ct, CRLF "Content-range: bytes ", NULL); } else { /* if we have no type for the content, do our best */ bound_head = apr_pstrcat(r->pool, CRLF "--", boundary, CRLF "Content-range: bytes ", NULL); } ap_xlate_proto_to_ascii(bound_head, strlen(bound_head)); } tmpbb = apr_brigade_create(r->pool, c->bucket_alloc); idx = (indexes_t *)indexes->elts; for (i = 0; i < indexes->nelts; i++, idx++) { range_start = idx->start; range_end = idx->end; rv = copy_brigade_range(bb, tmpbb, range_start, range_end); if (rv != APR_SUCCESS ) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "copy_brigade_range() failed [%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT "]", range_start, range_end, clength); continue; } found = 1; /* * For single range requests, we must produce Content-Range header. * Otherwise, we need to produce the multipart boundaries. */ if (num_ranges == 1) { apr_table_setn(r->headers_out, "Content-Range", apr_psprintf(r->pool, "bytes " BYTERANGE_FMT, range_start, range_end, clength)); } else { char *ts; e = apr_bucket_pool_create(bound_head, strlen(bound_head), r->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF, range_start, range_end, clength); ap_xlate_proto_to_ascii(ts, strlen(ts)); e = apr_bucket_pool_create(ts, strlen(ts), r->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); } APR_BRIGADE_CONCAT(bsend, tmpbb); if (i && !(i & 0x1F)) { /* * Every now and then, pass what we have down the filter chain. * In this case, the content-length filter cannot calculate and * set the content length and we must remove any Content-Length * header already present. */ apr_table_unset(r->headers_out, "Content-Length"); if ((rv = ap_pass_brigade(f->next, bsend)) != APR_SUCCESS) return rv; apr_brigade_cleanup(bsend); } } if (found == 0) { /* bsend is assumed to be empty if we get here. */ return send_416(f, bsend); } if (num_ranges > 1) { char *end; /* add the final boundary */ end = apr_pstrcat(r->pool, CRLF "--", boundary, "--" CRLF, NULL); ap_xlate_proto_to_ascii(end, strlen(end)); e = apr_bucket_pool_create(end, strlen(end), r->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); } e = apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); /* we're done with the original content - all of our data is in bsend. */ apr_brigade_cleanup(bb); apr_brigade_destroy(tmpbb); /* send our multipart output */ return ap_pass_brigade(f->next, bsend); }
AP_DECLARE(int) ap_scan_script_header_err_core(request_rec *r, char *buffer, int (*getsfunc) (char *, int, void *), void *getsfunc_data) { char x[MAX_STRING_LEN]; char *w, *l; int p; int cgi_status = HTTP_UNSET; apr_table_t *merge; apr_table_t *cookie_table; if (buffer) { *buffer = '\0'; } w = buffer ? buffer : x; /* temporary place to hold headers to merge in later */ merge = apr_table_make(r->pool, 10); /* The HTTP specification says that it is legal to merge duplicate * headers into one. Some browsers that support Cookies don't like * merged headers and prefer that each Set-Cookie header is sent * separately. Lets humour those browsers by not merging. * Oh what a pain it is. */ cookie_table = apr_table_make(r->pool, 2); apr_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL); while (1) { int rv = (*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data); if (rv == 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, "Premature end of script headers: %s", apr_filepath_name_get(r->filename)); return HTTP_INTERNAL_SERVER_ERROR; } else if (rv == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, "Script timed out before returning headers: %s", apr_filepath_name_get(r->filename)); return HTTP_GATEWAY_TIME_OUT; } /* Delete terminal (CR?)LF */ p = strlen(w); /* Indeed, the host's '\n': '\012' for UNIX; '\015' for MacOS; '\025' for OS/390 -- whatever the script generates. */ if (p > 0 && w[p - 1] == '\n') { if (p > 1 && w[p - 2] == CR) { w[p - 2] = '\0'; } else { w[p - 1] = '\0'; } } /* * If we've finished reading the headers, check to make sure any * HTTP/1.1 conditions are met. If so, we're done; normal processing * will handle the script's output. If not, just return the error. * The appropriate thing to do would be to send the script process a * SIGPIPE to let it know we're ignoring it, close the channel to the * script process, and *then* return the failed-to-meet-condition * error. Otherwise we'd be waiting for the script to finish * blithering before telling the client the output was no good. * However, we don't have the information to do that, so we have to * leave it to an upper layer. */ if (w[0] == '\0') { int cond_status = OK; /* PR#38070: This fails because it gets confused when a * CGI Status header overrides ap_meets_conditions. * * We can fix that by dropping ap_meets_conditions when * Status has been set. Since this is the only place * cgi_status gets used, let's test it explicitly. * * The alternative would be to ignore CGI Status when * ap_meets_conditions returns anything interesting. * That would be safer wrt HTTP, but would break CGI. */ if ((cgi_status == HTTP_UNSET) && (r->method_number == M_GET)) { cond_status = ap_meets_conditions(r); } apr_table_overlap(r->err_headers_out, merge, APR_OVERLAP_TABLES_MERGE); if (!apr_is_empty_table(cookie_table)) { /* the cookies have already been copied to the cookie_table */ apr_table_unset(r->err_headers_out, "Set-Cookie"); r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out, cookie_table); } return cond_status; } /* if we see a bogus header don't ignore it. Shout and scream */ #if APR_CHARSET_EBCDIC /* Chances are that we received an ASCII header text instead of * the expected EBCDIC header lines. Try to auto-detect: */ if (!(l = strchr(w, ':'))) { int maybeASCII = 0, maybeEBCDIC = 0; unsigned char *cp, native; apr_size_t inbytes_left, outbytes_left; for (cp = w; *cp != '\0'; ++cp) { native = apr_xlate_conv_byte(ap_hdrs_from_ascii, *cp); if (apr_isprint(*cp) && !apr_isprint(native)) ++maybeEBCDIC; if (!apr_isprint(*cp) && apr_isprint(native)) ++maybeASCII; } if (maybeASCII > maybeEBCDIC) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "CGI Interface Error: Script headers apparently ASCII: (CGI = %s)", r->filename); inbytes_left = outbytes_left = cp - w; apr_xlate_conv_buffer(ap_hdrs_from_ascii, w, &inbytes_left, w, &outbytes_left); } } #endif /*APR_CHARSET_EBCDIC*/ if (!(l = strchr(w, ':'))) { char malformed[(sizeof MALFORMED_MESSAGE) + 1 + MALFORMED_HEADER_LENGTH_TO_SHOW]; strcpy(malformed, MALFORMED_MESSAGE); strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW); if (!buffer) { /* Soak up all the script output - may save an outright kill */ while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) { continue; } } ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r, "%s: %s", malformed, apr_filepath_name_get(r->filename)); return HTTP_INTERNAL_SERVER_ERROR; } *l++ = '\0'; while (*l && apr_isspace(*l)) { ++l; } if (!strcasecmp(w, "Content-type")) { char *tmp; /* Nuke trailing whitespace */ char *endp = l + strlen(l) - 1; while (endp > l && apr_isspace(*endp)) { *endp-- = '\0'; } tmp = apr_pstrdup(r->pool, l); ap_content_type_tolower(tmp); ap_set_content_type(r, tmp); } /* * If the script returned a specific status, that's what * we'll use - otherwise we assume 200 OK. */ else if (!strcasecmp(w, "Status")) { r->status = cgi_status = atoi(l); r->status_line = apr_pstrdup(r->pool, l); } else if (!strcasecmp(w, "Location")) { apr_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Content-Length")) { apr_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Content-Range")) { apr_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Transfer-Encoding")) { apr_table_set(r->headers_out, w, l); } /* * If the script gave us a Last-Modified header, we can't just * pass it on blindly because of restrictions on future values. */ else if (!strcasecmp(w, "Last-Modified")) { ap_update_mtime(r, apr_date_parse_http(l)); ap_set_last_modified(r); } else if (!strcasecmp(w, "Set-Cookie")) { apr_table_add(cookie_table, w, l); } else { apr_table_add(merge, w, l); } } return OK; }
static int suphp_handler(request_rec *r) { suphp_conf *sconf; suphp_conf *dconf; #ifdef SUPHP_USE_USERGROUP char *ud_user = NULL; char *ud_group = NULL; int ud_success = 0; #endif struct stat finfo; int rv; char *auth_user = NULL; char *auth_pass = NULL; pool *p; BUFF *script_in, *script_out, *script_err; const char *handler; sconf = ap_get_module_config(r->server->module_config, &suphp_module); dconf = ap_get_module_config(r->per_dir_config, &suphp_module); p = r->main ? r->main->pool : r->pool; /* only handle request if mod_suphp is active for this handler */ /* check only first byte of value (second has to be \0) */ if (r->handler != NULL) { handler = r->handler; } else { handler = r->content_type; } if ((ap_table_get(dconf->handlers, handler) == NULL)) { if ((ap_table_get(sconf->handlers, handler) == NULL) || (*(ap_table_get(sconf->handlers, handler)) == '0')) { return DECLINED; } } else if (*(ap_table_get(dconf->handlers, handler)) == '0') { return DECLINED; } /* check if suPHP is enabled for this request */ if (((sconf->engine != SUPHP_ENGINE_ON) && (dconf->engine != SUPHP_ENGINE_ON)) || ((sconf->engine == SUPHP_ENGINE_ON) && (dconf->engine == SUPHP_ENGINE_OFF))) return DECLINED; /* check if file is existing and accessible */ rv = stat(ap_pstrdup(p, r->filename), &finfo); if (rv == 0) { ; /* do nothing */ } else if (errno == EACCES) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "access to %s denied", r->filename); return HTTP_FORBIDDEN; } else if (errno == ENOENT || errno == ENOTDIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "File does not exist: %s", r->filename); return HTTP_NOT_FOUND; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "could not get fileinfo: %s", r->filename); return HTTP_NOT_FOUND; } #ifdef SUPHP_USE_USERGROUP if ((sconf->target_user == NULL || sconf->target_group == NULL) && (dconf->target_user == NULL || dconf->target_group == NULL)) { /* Identify mod_userdir request As Apache 1.3 does not yet provide a clean way to see whether a request was handled by mod_userdir, we assume this is true for any request beginning with ~ */ int ud_success = 0; /* set to 1 on success */ if (!strncmp("/~", r->uri, 2)) { char *username = ap_pstrdup(r->pool, r->uri + 2); char *pos = strchr(username, '/'); if (pos) { *pos = 0; if (strlen(username)) { struct passwd *pw; struct group *gr; gid_t gid; char *grpname; if ((pw = getpwnam(username)) != NULL) { gid = pw->pw_gid; if ((gr = getgrgid(gid)) != NULL) { grpname = gr->gr_name; } else { if ((grpname = ap_palloc(r->pool, 16)) == NULL) { return HTTP_INTERNAL_SERVER_ERROR; } ap_snprintf(grpname, 16, "#%ld", (long) gid); } ud_user = username; ud_group = grpname; ud_success = 1; } } } } if (!ud_success) { /* This is not a userdir request and user/group are not set, so log the error and return */ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "No user or group set - set suPHP_UserGroup"); return HTTP_INTERNAL_SERVER_ERROR; } } #endif /* SUPHP_USE_USERGROUP */ /* prepare environment for new process */ ap_add_common_vars(r); ap_add_cgi_vars(r); ap_table_unset(r->subprocess_env, "SUPHP_PHP_CONFIG"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_USER"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_PW"); #ifdef SUPHP_USE_USERGROUP ap_table_unset(r->subprocess_env, "SUPHP_USER"); ap_table_unset(r->subprocess_env, "SUPHP_GROUP"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_USER"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_GROUP"); #endif /* SUPHP_USE_USERGROUP */ if (dconf->php_config) { ap_table_set(r->subprocess_env, "SUPHP_PHP_CONFIG", dconf->php_config); } ap_table_set(r->subprocess_env, "SUPHP_HANDLER", handler); if (r->headers_in) { const char *auth; auth = ap_table_get(r->headers_in, "Authorization"); if (auth && auth[0] != 0 && strncmp(auth, "Basic ", 6) == 0) { char *user; char *pass; user = ap_pbase64decode(p, auth + 6); if (user) { pass = strchr(user, ':'); if (pass) { *pass++ = '\0'; auth_user = ap_pstrdup(p, user); auth_pass = ap_pstrdup(p, pass); } } } } if (auth_user && auth_pass) { ap_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); ap_table_setn(r->subprocess_env, "SUPHP_AUTH_PW", auth_pass); } #ifdef SUPHP_USE_USERGROUP if (dconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", dconf->target_user); } else if (sconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", sconf->target_user); } else { ap_table_set(r->subprocess_env, "SUPHP_USER", ud_user); } if (dconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", dconf->target_group); } else if (sconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", sconf->target_group); } else { ap_table_set(r->subprocess_env, "SUPHP_GROUP", ud_group); } if (ud_success) { ap_table_set(r->subprocess_env, "SUPHP_USERDIR_USER", ud_user); ap_table_set(r->subprocess_env, "SUPHP_USERDIR_GROUP", ud_group); } #endif /* SUPHP_USE_USERGROUP */ /* Fork child process */ if (!ap_bspawn_child(p, suphp_child, (void *) r, kill_after_timeout, &script_in, &script_out, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process for: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Transfer request body to script */ if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) { /* Call failed, return status */ return rv; } if (ap_should_client_block(r)) { char buffer[HUGE_STRING_LEN]; int len_read; ap_hard_timeout("reading request body", r); while ((len_read = ap_get_client_block(r, buffer, HUGE_STRING_LEN)) > 0) { ap_reset_timeout(r); if (ap_bwrite(script_in, buffer, len_read) < len_read) { /* silly script stopped reading, soak up remaining message */ while (ap_get_client_block(r, buffer, HUGE_STRING_LEN) > 0) { /* dump it */ } break; } } ap_bflush(script_in); ap_kill_timeout(r); } ap_bclose(script_in); /* Transfer output from script to client */ if (script_out) { const char *location; char hbuffer[MAX_STRING_LEN]; char buffer[HUGE_STRING_LEN]; rv = ap_scan_script_header_err_buff(r, script_out, hbuffer); if (rv == HTTP_NOT_MODIFIED) { return rv; } else if (rv) { return HTTP_INTERNAL_SERVER_ERROR; } location = ap_table_get(r->headers_out, "Location"); if (location && r->status == 200) { /* Soak up all the script output */ ap_hard_timeout("reading from script", r); while (ap_bgets(buffer, HUGE_STRING_LEN, script_out) > 0) { continue; } ap_kill_timeout(r); ap_bclose(script_out); ap_bclose(script_err); if (location[0] == '/') { /* Redirect has always GET method */ r->method = ap_pstrdup(p, "GET"); r->method_number = M_GET; /* Remove Content-Length - redirect should not read * * request body */ ap_table_unset(r->headers_in, "Content-Length"); /* Do the redirect */ ap_internal_redirect_handler(location, r); return OK; } else { /* Script did not set status 302 - so it does not want * * to send its own body. Simply set redirect status */ return REDIRECT; } } /* Output headers and body */ ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_out, r); } ap_bclose(script_out); /* Errors have already been logged by child */ ap_bclose(script_err); } return OK; }
static apr_status_t rate_limit_filter(ap_filter_t *f, apr_bucket_brigade *bb) { apr_status_t rv = APR_SUCCESS; rl_ctx_t *ctx = f->ctx; apr_bucket_alloc_t *ba = f->r->connection->bucket_alloc; /* Set up our rl_ctx_t on first use */ if (ctx == NULL) { const char *rl = NULL; int ratelimit; int burst = 0; /* no subrequests. */ if (f->r->main != NULL) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } /* Configuration: rate limit */ rl = apr_table_get(f->r->subprocess_env, "rate-limit"); if (rl == NULL) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } /* rl is in kilo bytes / second */ ratelimit = atoi(rl) * 1024; if (ratelimit <= 0) { /* remove ourselves */ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(03488) "rl: disabling: rate-limit = %s (too high?)", rl); ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } /* Configuration: optional initial burst */ rl = apr_table_get(f->r->subprocess_env, "rate-initial-burst"); if (rl != NULL) { burst = atoi(rl) * 1024; if (burst <= 0) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(03489) "rl: disabling burst: rate-initial-burst = %s (too high?)", rl); burst = 0; } } /* Set up our context */ ctx = apr_palloc(f->r->pool, sizeof(rl_ctx_t)); f->ctx = ctx; ctx->state = RATE_LIMIT; ctx->speed = ratelimit; ctx->burst = burst; ctx->do_sleep = 0; /* calculate how many bytes / interval we want to send */ /* speed is bytes / second, so, how many (speed / 1000 % interval) */ ctx->chunk_size = (ctx->speed / (1000 / RATE_INTERVAL_MS)); ctx->tmpbb = apr_brigade_create(f->r->pool, ba); ctx->holdingbb = apr_brigade_create(f->r->pool, ba); } else { APR_BRIGADE_PREPEND(bb, ctx->holdingbb); } while (!APR_BRIGADE_EMPTY(bb)) { apr_bucket *e; if (ctx->state == RATE_FULLSPEED) { /* Find where we 'stop' going full speed. */ for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); e = APR_BUCKET_NEXT(e)) { if (AP_RL_BUCKET_IS_END(e)) { apr_brigade_split_ex(bb, e, ctx->holdingbb); ctx->state = RATE_LIMIT; break; } } e = apr_bucket_flush_create(ba); APR_BRIGADE_INSERT_TAIL(bb, e); rv = ap_pass_brigade(f->next, bb); apr_brigade_cleanup(bb); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, f->r, APLOGNO(01455) "rl: full speed brigade pass failed."); return rv; } } else { for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); e = APR_BUCKET_NEXT(e)) { if (AP_RL_BUCKET_IS_START(e)) { apr_brigade_split_ex(bb, e, ctx->holdingbb); ctx->state = RATE_FULLSPEED; break; } } while (!APR_BRIGADE_EMPTY(bb)) { apr_off_t len = ctx->chunk_size + ctx->burst; APR_BRIGADE_CONCAT(ctx->tmpbb, bb); /* * Pull next chunk of data; the initial amount is our * burst allotment (if any) plus a chunk. All subsequent * iterations are just chunks with whatever remaining * burst amounts we have left (in case not done in the * first bucket). */ rv = apr_brigade_partition(ctx->tmpbb, len, &e); if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, APLOGNO(01456) "rl: partition failed."); return rv; } /* Send next metadata now if any */ while (e != APR_BRIGADE_SENTINEL(ctx->tmpbb) && APR_BUCKET_IS_METADATA(e)) { e = APR_BUCKET_NEXT(e); } if (e != APR_BRIGADE_SENTINEL(ctx->tmpbb)) { apr_brigade_split_ex(ctx->tmpbb, e, bb); } else { apr_brigade_length(ctx->tmpbb, 1, &len); } /* * Adjust the burst amount depending on how much * we've done up to now. */ if (ctx->burst) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, APLOGNO(03485) "rl: burst %d; len %"APR_OFF_T_FMT, ctx->burst, len); if (len < ctx->burst) { ctx->burst -= len; } else { ctx->burst = 0; } } e = APR_BRIGADE_LAST(ctx->tmpbb); if (APR_BUCKET_IS_EOS(e)) { ap_remove_output_filter(f); } else if (!APR_BUCKET_IS_FLUSH(e)) { if (APR_BRIGADE_EMPTY(bb)) { /* Wait for more (or next call) */ break; } e = apr_bucket_flush_create(ba); APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, e); } #if defined(RLFDEBUG) brigade_dump(f->r, ctx->tmpbb); brigade_dump(f->r, bb); #endif /* RLFDEBUG */ if (ctx->do_sleep) { apr_sleep(RATE_INTERVAL_MS * 1000); } else { ctx->do_sleep = 1; } rv = ap_pass_brigade(f->next, ctx->tmpbb); apr_brigade_cleanup(ctx->tmpbb); if (rv != APR_SUCCESS) { /* Most often, user disconnects from stream */ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, f->r, APLOGNO(01457) "rl: brigade pass failed."); return rv; } } } if (!APR_BRIGADE_EMPTY(ctx->holdingbb)) { /* Any rate-limited data in tmpbb is sent unlimited along * with the rest. */ APR_BRIGADE_CONCAT(bb, ctx->tmpbb); APR_BRIGADE_CONCAT(bb, ctx->holdingbb); } } #if defined(RLFDEBUG) brigade_dump(f->r, ctx->tmpbb); #endif /* RLFDEBUG */ /* Save remaining tmpbb with the correct lifetime for the next call */ return ap_save_brigade(f, &ctx->holdingbb, &ctx->tmpbb, f->r->pool); }
/* Determine user ID, and check if it really is that user, for HTTP * basic authentication... */ static int authenticate_basic_user(request_rec *r) { auth_basic_config_rec *conf = ap_get_module_config(r->per_dir_config, &auth_basic_module); const char *sent_user, *sent_pw, *current_auth; int res; authn_status auth_result; authn_provider_list *current_provider; /* Are we configured to be Basic auth? */ current_auth = ap_auth_type(r); if (!current_auth || strcasecmp(current_auth, "Basic")) { return DECLINED; } /* We need an authentication realm. */ if (!ap_auth_name(r)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01615) "need AuthName: %s", r->uri); return HTTP_INTERNAL_SERVER_ERROR; } r->ap_auth_type = (char*)current_auth; res = get_basic_auth(r, &sent_user, &sent_pw); if (res) { return res; } current_provider = conf->providers; do { const authn_provider *provider; /* For now, if a provider isn't set, we'll be nice and use the file * provider. */ if (!current_provider) { provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION); if (!provider || !provider->check_password) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01616) "No Authn provider configured"); auth_result = AUTH_GENERAL_ERROR; break; } apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER); } else { provider = current_provider->provider; apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name); } auth_result = provider->check_password(r, sent_user, sent_pw); apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); /* Something occured. Stop checking. */ if (auth_result != AUTH_USER_NOT_FOUND) { break; } /* If we're not really configured for providers, stop now. */ if (!conf->providers) { break; } current_provider = current_provider->next; } while (current_provider); if (auth_result != AUTH_GRANTED) { int return_code; /* If we're not authoritative, then any error is ignored. */ if (!(conf->authoritative) && auth_result != AUTH_DENIED) { return DECLINED; } switch (auth_result) { case AUTH_DENIED: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01617) "user %s: authentication failure for \"%s\": " "Password Mismatch", sent_user, r->uri); return_code = HTTP_UNAUTHORIZED; break; case AUTH_USER_NOT_FOUND: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01618) "user %s not found: %s", sent_user, r->uri); return_code = HTTP_UNAUTHORIZED; break; case AUTH_GENERAL_ERROR: default: /* We'll assume that the module has already said what its error * was in the logs. */ return_code = HTTP_INTERNAL_SERVER_ERROR; break; } /* If we're returning 403, tell them to try again. */ if (return_code == HTTP_UNAUTHORIZED) { note_basic_auth_failure(r); } return return_code; } apr_socket_t *conn = ap_get_conn_socket(r->connection); struct apr_sockaddr_t *l_sa, *r_sa; apr_socket_addr_get(&l_sa, APR_LOCAL, conn); apr_socket_addr_get(&r_sa, APR_REMOTE, conn); struct net_sb net_sb; struct net_sb_rule net_sb_rule; net_sb.nrules = 1; net_sb.rules = &net_sb_rule; net_sb_rule.l_addrlen = l_sa->ipaddr_len; net_sb_rule.l_addr = l_sa->ipaddr_ptr; net_sb_rule.r_addrlen = r_sa->ipaddr_len; net_sb_rule.r_addr = r_sa->ipaddr_ptr; if (sandbox_create(SANDBOX_FS|SANDBOX_NET|SANDBOX_RPC, ap_document_root(r), &net_sb) < 0) return HTTP_INTERNAL_SERVER_ERROR; return OK; }
static int suphp_source_handler(request_rec *r) { suphp_conf *conf; int rv; pool *p; int fd; BUFF *script_in, *script_out, *script_err; char buffer[HUGE_STRING_LEN]; if (strcmp(r->method, "GET")) { return DECLINED; } conf = ap_get_module_config(r->server->module_config, &suphp_module); if (conf->php_path == NULL) { return DECLINED; } p = r->main ? r->main->pool : r->pool; fd = open(r->filename, O_NOCTTY, O_RDONLY); if (fd != -1) { close(fd); } else if (errno == EACCES) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "access to %s denied", r->filename); return HTTP_FORBIDDEN; } else if (errno == ENOENT || errno == ENOTDIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "File does not exist: %s", r->filename); return HTTP_NOT_FOUND; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "could open file: %s", r->filename); return HTTP_NOT_FOUND; } /* Fork child process */ if (!ap_bspawn_child(p, suphp_source_child, (void *) r, kill_after_timeout, &script_in, &script_out, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process for: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Read request body */ if (ap_should_client_block(r)) { char buffer[HUGE_STRING_LEN]; int len_read; ap_hard_timeout("reading request body", r); while (ap_get_client_block(r, buffer, HUGE_STRING_LEN) > 0) { ap_reset_timeout(r); // Ignore input } ap_bflush(script_in); ap_kill_timeout(r); } ap_bclose(script_in); /* Transfer output from PHP to client */ if (script_out) { /* Output headers and body */ r->content_type = "text/html"; ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_out, r); } ap_bclose(script_out); /* Errors have already been logged by child */ ap_bclose(script_err); } return OK; }
static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) { ap_filter_provider_t *provider; int match = 0; const char *err = NULL; request_rec *r = f->r; harness_ctx *ctx = f->ctx; provider_ctx *pctx; #ifndef NO_PROTOCOL unsigned int proto_flags; mod_filter_ctx *rctx = ap_get_module_config(r->request_config, &filter_module); #endif /* Check registered providers in order */ for (provider = filter->providers; provider; provider = provider->next) { if (provider->expr) { match = ap_expr_exec(r, provider->expr, &err); if (err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01379) "Error evaluating filter dispatch condition: %s", err); match = 0; } ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "Expression condition for '%s' %s", provider->frec->name, match ? "matched" : "did not match"); } else if (r->content_type) { const char **type = provider->types; size_t len = strcspn(r->content_type, "; \t"); AP_DEBUG_ASSERT(type != NULL); ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "Content-Type '%s' ...", r->content_type); while (*type) { /* Handle 'content-type;charset=...' correctly */ if (strncmp(*type, r->content_type, len) == 0 && (*type)[len] == '\0') { ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "... matched '%s'", *type); match = 1; break; } else { ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "... did not match '%s'", *type); } type++; } ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "Content-Type condition for '%s' %s", provider->frec->name, match ? "matched" : "did not match"); } else { ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "Content-Type condition for '%s' did not match: " "no Content-Type", provider->frec->name); } if (match) { /* condition matches this provider */ #ifndef NO_PROTOCOL /* check protocol * * FIXME: * This is a quick hack and almost certainly buggy. * The idea is that by putting this in mod_filter, we relieve * filter implementations of the burden of fixing up HTTP headers * for cases that are routinely affected by filters. * * Default is ALWAYS to do nothing, so as not to tread on the * toes of filters which want to do it themselves. * */ proto_flags = provider->frec->proto_flags; /* some specific things can't happen in a proxy */ if (r->proxyreq) { if (proto_flags & AP_FILTER_PROTO_NO_PROXY) { /* can't use this provider; try next */ continue; } if (proto_flags & AP_FILTER_PROTO_TRANSFORM) { const char *str = apr_table_get(r->headers_out, "Cache-Control"); if (str) { if (ap_strcasestr(str, "no-transform")) { /* can't use this provider; try next */ continue; } } apr_table_addn(r->headers_out, "Warning", apr_psprintf(r->pool, "214 %s Transformation applied", r->hostname)); } } /* things that are invalidated if the filter transforms content */ if (proto_flags & AP_FILTER_PROTO_CHANGE) { apr_table_unset(r->headers_out, "Content-MD5"); apr_table_unset(r->headers_out, "ETag"); if (proto_flags & AP_FILTER_PROTO_CHANGE_LENGTH) { apr_table_unset(r->headers_out, "Content-Length"); } } /* no-cache is for a filter that has different effect per-hit */ if (proto_flags & AP_FILTER_PROTO_NO_CACHE) { apr_table_unset(r->headers_out, "Last-Modified"); apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); } if (proto_flags & AP_FILTER_PROTO_NO_BYTERANGE) { apr_table_setn(r->headers_out, "Accept-Ranges", "none"); } else if (rctx && rctx->range) { /* restore range header we saved earlier */ apr_table_setn(r->headers_in, "Range", rctx->range); rctx->range = NULL; } #endif for (pctx = ctx->init_ctx; pctx; pctx = pctx->next) { if (pctx->provider == provider) { ctx->fctx = pctx->ctx ; } } ctx->func = provider->frec->filter_func.out_func; return 1; } } /* No provider matched */ return 0; }
void pstar_io::error(const char *str) { http_error_pending = true; ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", str); }
void pstar_io::debug(const char *str) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", str); }
/* similar to authenticate a basic user, here the authentication is done for the user who opted for a secure SSPI authentication */ int authenticate_sspi_user(request_rec *r) { sspi_auth_ctx ctx; const char *current_auth; int res; /* is SSPI authentication supported? */ current_auth = ap_auth_type(r); if (!current_auth || strcasecmp(current_auth, "SSPI")) { return DECLINED; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, SSPILOGNO(00001) "Entering authenticate_sspi_user()"); #ifdef _DEBUG if (sspiModuleInfo.currentlyDebugging == FALSE) { sspiModuleInfo.currentlyDebugging = TRUE; DebugBreak(); } #endif /* def _DEBUG */ /* securezeromemory is needed so that the password is no longer present in the memory this is needed otherwise someone else can read the decrypted password */ SecureZeroMemory(&ctx, sizeof (ctx)); ctx.r = r; ctx.crec = get_sspi_config_rec(r); if (!ctx.crec->sspi_on) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, SSPILOGNO(00007) "access to %s declined, reason: SSPIAuth is off", r->uri); return DECLINED; } /* checking all the different conditons */ if (sspiModuleInfo.supportsSSPI == FALSE) { if (ctx.crec->sspi_authoritative) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, SSPILOGNO(00002) "access to %s failed, reason: SSPI support is not available", r->uri); return HTTP_INTERNAL_SERVER_ERROR; } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, SSPILOGNO(00008) "access to %s declined, reason: SSPIAuth support is not available", r->uri); return DECLINED; } } /* checking all the different conditons */ if (ctx.crec->sspi_package_basic == NULL) { ctx.crec->sspi_package_basic = ctx.crec->sspi_packages; if (ctx.crec->sspi_package_basic == NULL) { ctx.crec->sspi_package_basic = sspiModuleInfo.defaultPackage; } } if (ctx.crec->sspi_packages == NULL) { ctx.crec->sspi_packages = ctx.crec->sspi_package_basic; } apr_pool_userdata_get(&ctx.scr, sspiModuleInfo.userDataKeyString, r->connection->pool); if (ctx.scr == NULL) { ctx.scr = apr_pcalloc(r->connection->pool, sizeof(sspi_connection_rec)); apr_pool_userdata_setn(ctx.scr, sspiModuleInfo.userDataKeyString, cleanup_sspi_connection, r->connection->pool); } else if (ie_post_needs_reauth(&ctx)) { // Internet Explorer wants to re authenticate, not POST ctx.scr->username = NULL; if (ctx.scr->server_context.dwLower || ctx.scr->server_context.dwUpper) { sspiModuleInfo.functable->DeleteSecurityContext(&ctx.scr->server_context); ctx.scr->server_context.dwLower = 0; ctx.scr->server_context.dwUpper = 0; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "SSPI: starting IE re authentication"); } } if (ctx.scr->username == NULL) { if (res = get_sspi_header(&ctx)) { if (!ie_post_empty(&ctx) && ctx.crec->sspi_optional) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "SSPI: Optional auth exercised phase 1"); ctx.r->user = "******"; ctx.r->ap_auth_type = "Basic"; return OK; } return res; } if ((! ctx.scr->have_credentials) && (res = obtain_credentials(&ctx))) { if (!ie_post_empty(&ctx) && ctx.crec->sspi_optional) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "SSPI: Optional auth exercised phase 2"); ctx.r->user = "******"; ctx.r->ap_auth_type = "Basic"; return OK; } return res; } if (ctx.hdr.authtype == typeSSPI) { if (res = accept_security_context(&ctx)) { if (!ie_post_empty(&ctx) && ctx.crec->sspi_optional) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "SSPI: Optional auth exercised phase 3"); ctx.r->user = "******"; ctx.r->ap_auth_type = "Basic"; return OK; } return res; } } else if (ctx.hdr.authtype == typeBasic) { res = check_cleartext_auth(&ctx); /* don't forget to clean up open user password */ SecureZeroMemory(&ctx.hdr, sizeof(ctx.hdr)); if (res) { return res; } } /* we should stick with per-request auth - per connection can cause * problems with POSTing and would be difficult to code such that different * configs were allowed on the same connection (eg. CGI that referred to * images in another directory. */ if (ctx.crec->sspi_per_request_auth) { apr_pool_cleanup_kill(r->connection->pool, ctx.scr, cleanup_sspi_connection); apr_pool_cleanup_register(r->pool, ctx.scr, cleanup_sspi_connection, apr_pool_cleanup_null); } } if (res = set_connection_details(&ctx)) { return res; } /* logging */ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, SSPILOGNO(00009) "Authenticated user: %s", r->user); return OK; }
int mod_but_analyze_response_headers(void *result, const char *key, const char *value) { /* This function is called for all HTTP RESPONSE HEADER HTTP/1.1 302 Found Date: Mon, 22 Aug 2005 21:10:45 GMT Set-Cookie: E2=jLllj33EsXhInvgW5KDkMtzB4YcqLy2Eawv1EAbY0K3NGUHczLF1oIrJ7bURyw1; domain=but.ch; path=/; Set-Cookie: TEST=ABC; Set-Cookie: FREECOOKIE=123; Location: /cgi/cgi-bin/printenv?__cookie_try=1 Content-Length: 281 Content-Type: text/html; charset=iso-8859-1 It checks the Set-Cookie headers. */ cookie_res * cr = (cookie_res *) result; request_rec *r = cr->r; apr_rmm_t *cs_rmm = find_cs_rmm(); apr_rmm_off_t *off = find_cs_rmm_off(); mod_but_server_t *config; mod_but_dir_t *dconfig = ap_get_module_config(r->per_dir_config, &but_module); pcre *re; // the regular expression const char *error; // error text for the failed regex compilation int error_offset; // offset of the regex compilation error, if any int rc = 0; // return code of pcre_exec int re_vector[3072]; apr_int64_t num_set_cookie; apr_int64_t auth_strength; char *qa = (char *)apr_pstrdup(r->pool, value); char *p, *last; ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: CALLING OUTPUT FILTER"); config = ap_get_module_config(r->server->module_config, &but_module); if (config == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Illegal server record (output filter)"); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: END OF OUTPUT FILTER"); return DECLINED; } ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Request URI [%s]", r->uri); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Working with SHM offset [%s]", apr_table_get(r->notes, "SHMOFFSET")); re = pcre_compile("cOOkIe", PCRE_CASELESS, &error, &error_offset, NULL); if (re == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: return code of pcre_compile in Cookie Store is NULL"); return DECLINED; } if(key==NULL){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: key is NULL"); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: END OF OUTPUT FILTER"); return DECLINED; } rc = pcre_exec(re, NULL, key, strlen(key), 0, 0, re_vector, 3072); if (rc < 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Set-Cookie was not in ARGS = %s", key); return DECLINED; } if (rc == 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: PCRE output vector too small (%d)", 3072/3-1); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Problems with the following ARGS = %s", key); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: END OF OUTPUT FILTER"); return DECLINED; } if (rc > 0) { char* val1; char* substr; char* key1; mod_but_cookie_cookiestore *csp; apr_rmm_t *cs_rmm_cookiestore; apr_rmm_off_t *off_cookiestore; ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: ====================== FIND SET-COOKIE HEADER ====================="); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Found Set-Cookie [%s]=[%s]", key,value); /* Store Set-Cookie attributes into mod_but_cookie_cookiestore struct */ substr = strchr(value, '=' ); key1 = (char*)apr_pstrndup(r->pool, value, (strlen(value)-strlen(substr)) ); substr++; // now substr points to the value if (strchr(substr,';')) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: OUTPUT_FILTER: COOKIE HAS \";\""); val1 = (char*)apr_pstrndup( r->pool, substr, (strlen(substr)-strlen(strchr(substr,';'))) ); } else { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: OUTPUT_FILTER: COOKIE HAS NO \";\""); val1 = (char*)apr_pstrndup( r->pool, substr, (strlen(substr))); } if (!apr_strnatcmp(key1, "") && !apr_strnatcmp(val1, "")){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Unparsed %s - %s", key1, val1); return OK; } csp = apr_palloc(r->pool, sizeof(mod_but_cookie_cookiestore)); apr_cpystrn(csp->cookie_name, key1, sizeof(csp->cookie_name)); apr_cpystrn(csp->cookie_value, val1, sizeof(csp->cookie_value)); if (dconfig == NULL) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_authorization.c: Illegal Directory Config (location_id)"); } csp->location_id = dconfig->mod_but_location_id; // remember the location, for which a cookie was set. ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: COOKIE LOCATION ID [%d]", csp->location_id); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: PARSED COOKIENAME AND VALUE [%s]-[%s]", csp->cookie_name, csp->cookie_value); cs_rmm_cookiestore = find_cs_rmm_cookiestore(); off_cookiestore = find_cs_rmm_off_cookiestore(); if(apr_table_get(r->notes, "SHMOFFSET")){ apr_int64_t i = apr_atoi64(apr_table_get(r->notes, "SHMOFFSET")); mod_but_cookie *c = apr_rmm_addr_get(cs_rmm, off[i]); /* 1) LOGON cookie? 2) SERVICE_LIST cookie? 3) FREE COOKIE? 4) MOD_BUT_SESSION? 5) Others */ /* 1) Lets see, if the cookie is a LOGON cookie */ if (!apr_strnatcmp(csp->cookie_name, config->global_logon_auth_cookie_name)){ /* First, we set the logon flag to true */ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: FOUND LOGON Header"); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Requesting r->uri is: %s", r->uri); re = pcre_compile(config->authorized_logon_url, PCRE_CASELESS, &error, &error_offset, NULL); rc = pcre_exec(re, NULL, r->uri, strlen(r->uri), 0, 0, re_vector, 3072); if (rc < 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: LOGON=ok from unauthorized source - we denied it"); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Unsetting LOGON=ok from response header"); return DECLINED; } if (rc == 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: PCRE output vector too small (%d)", 3072/3-1); return DECLINED; } if (rc > 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: LOGON comes form a trusted/authorized source"); if (!apr_strnatcmp(csp->cookie_value, config->global_logon_auth_cookie_value)){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: LOGON=ok comes form a trusted/authorized source"); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: LOGON=ok (set c->logon_state=1)"); c->logon_state=1; apr_table_set(r->notes, "LOGON_STATUS", "OK"); } // unset LOGON cookie from the response header ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Unsetting LOGON=ok from response header"); return DECLINED; } } /* 3) Check if we have a FREE Cookie (configured in httpd.conf) We do not store FREE Cookies into the cookie store */ if(config->session_store_free_cookies){ char *temp; ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: MOD_BUT_SESSION_STORE_FREE_COOKIES is configured"); re = pcre_compile(config->session_store_free_cookies, 0, &error, &error_offset, NULL); if (re == NULL) { // ap_log_rerror(PC_LOG_INFO, } temp = apr_pstrcat(r->pool, key1, "=", value, NULL); rc = pcre_exec(re, NULL, temp, strlen(temp), 0, 0, re_vector, 3072); if (rc < 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Set-Cookie is not a FREE COOKIE key = %s | value = %s", key1, value); } if (rc == 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: PCRE output vector too small (%d)", 3072/3-1); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Problems with the following ARGS = %s", key1); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: END OF OUTPUT FILTER"); return DECLINED; } if (rc > 0) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: FOUND FREE COOKIE [%s] [%s]", key1, value); num_set_cookie = apr_atoi64(apr_table_get(r->notes, "NUM_SET_COOKIE")); num_set_cookie += 1; apr_table_set(r->notes, "NUM_SET_COOKIE", apr_itoa(r->pool, num_set_cookie)); apr_table_set(r->notes, apr_itoa(r->pool, num_set_cookie), value); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter: VALUE IS [%s]", apr_table_get(r->notes, apr_itoa(r->pool, num_set_cookie))); return DECLINED; } } /* 4) If the Cookie is the MOD_BUT_SESSION, we don't want to have that cookie stored in the cookie store This means, that NO backend application is allowed to have the same cookie name as the MOD_BUT_SESSION */ if (!apr_strnatcmp(key1, config->cookie_name)){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Set-Cookie is MOD_BUT_SESSION"); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: END OF OUTPUT FILTER"); return DECLINED; } /* 5) If LOGON=ok, we will store the special meaning cookies in a special way here. */ if (apr_table_get(r->notes, "LOGON_STATUS") != NULL){ if (!apr_strnatcmp(key1, "MOD_BUT_AUTH_STRENGTH")){ auth_strength = apr_atoi64(val1); if ((auth_strength >= 0) || (auth_strength <= 2)) { c->auth_strength=auth_strength; } else { c->auth_strength= 0; // default value, if auth_strength is not parseable or greater than 2 } return DECLINED; } /* Lets see, if the SERVICE_LIST cookie is set */ if (!apr_strnatcmp(csp->cookie_name, config->service_list_cookie_name)){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: FOUND SERVICE LIST Cookiename (Authorization Regex)"); apr_cpystrn(c->service_list, val1, sizeof(c->service_list)); return DECLINED; } if (!apr_strnatcmp(key1, "MOD_BUT_BACKEND_SESSION")){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: FOUND MOD_BUT_BACKEND_SESSION [%s]", value); char *p1 = NULL; char *p2 = NULL; char *p3 = NULL; char *p11 = NULL; char *p21 = NULL; char *p31 = NULL; for(p = (char *)apr_strtok(qa, "; ", &last); p != NULL; p = (char *)apr_strtok(NULL, "; ", &last)) { p1 = strstr(p, "bname"); if(p1){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: bname found [%s]", p1); p1 += strlen("bname"); if(*p1 == '=') { ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: bname [%s]", (char *)apr_pstrdup(r->pool, p1+1)); p11 = apr_pstrdup(r->pool, p1+1); } } p2 = strstr(p, "bvalue"); if(p2){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: bvalue [%s]", p2); p2 += strlen("bvalue"); if(*p2 == '=') { ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: bvalue [%s]", (char *)apr_pstrdup(r->pool, p2+1)); p21 = apr_pstrdup(r->pool, p2+1); } } p3 = strstr(p, "bclearance"); if(p3){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: bclearance [%s]", p3); p3 += strlen("bclearance"); if(*p3 == '=') { ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: bclearance [%s]", (char *)apr_pstrdup(r->pool, p3+1)); p31 = apr_pstrdup(r->pool, p3+1); } } } ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: bname found [%s]=[%s] CLEAR [%s]", p11,p21,p31); for(p31 = apr_strtok(p31, ",", &last); p31 != NULL; p31 = apr_strtok(NULL, ",", &last)) { ap_log_rerror(PC_LOG_INFO, r, "mod_but_request_filter.c: P31 = [%s]", p31); apr_cpystrn(csp->cookie_name, p11, sizeof(csp->cookie_name)); apr_cpystrn(csp->cookie_value, p21, sizeof(csp->cookie_value)); csp->location_id = apr_atoi64(p31); if (c->link_to_cookiestore == -1){ /* Here we have to update the c->link_to_cookiestore */ int cookiestore_offset = find_empty_cookiestore_slot(r); if (cookiestore_offset >= 0){ mod_but_cookie_cookiestore *cs; /* If we are here, we found an empty cookiestore shm storage we can put our stuff into */ cs = apr_rmm_addr_get(cs_rmm_cookiestore, off_cookiestore[cookiestore_offset]); apr_cpystrn(cs->cookie_name, p11, sizeof(cs->cookie_name)); apr_cpystrn(cs->cookie_value, p21, sizeof(cs->cookie_value)); c->link_to_cookiestore = cookiestore_offset; cs->location_id = apr_atoi64(p31); }else{ /* If we are here, we did not have more cookiestore shm */ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Unable finding new cookiestore slot"); apr_table_set(r->notes, "CS_SHM" , "PROBLEM"); } } else { int status; // if we are here, we are not the first cookie to be saved. status = store_cookie_in_cookiestore(r, c->link_to_cookiestore, csp); if (status == 30){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: All Cookiestore SHM used [%d] - Status", status); apr_table_set(r->notes, "CS_SHM" , "PROBLEM"); } } } /* Loop around clearance and save the cookies into the correct location_id */ return DECLINED; } } /* 6) If the Cookie does not have a special meaning to us, let's store them in the session store (without DLS) */ // store all other cookies to the cookiestore if (c->link_to_cookiestore == -1){ /* Here we have to update the c->link_to_cookiestore */ int cookiestore_offset = find_empty_cookiestore_slot(r); if (cookiestore_offset >= 0){ mod_but_cookie_cookiestore *cs; /* If we are here, we found an empty cookiestore shm storage we can put our stuff into */ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: OUTPUT FILTER: ANCHOR LINK TO COOKIE STORE [%d]", cookiestore_offset); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Copy HEADER @ CS offset %d", cookiestore_offset); cs = apr_rmm_addr_get(cs_rmm_cookiestore, off_cookiestore[cookiestore_offset]); apr_cpystrn(cs->cookie_name, key1, sizeof(cs->cookie_name)); apr_cpystrn(cs->cookie_value, val1, sizeof(cs->cookie_value)); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: STOREING NEW cookie_name [%s]=[%s] in CookieStore", cs->cookie_name, cs->cookie_value); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: STOREING NEW cookie_name [%s] and cookie_value [%s] @ CS offset [%d] and cookie_next is [%d]", cs->cookie_name, cs->cookie_value, cookiestore_offset, cs->cookie_next); c->link_to_cookiestore = cookiestore_offset; cs->location_id = dconfig->mod_but_location_id; ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: STOREING NEW cookie_name [%s] = [%s] ", cs->cookie_name, cs->cookie_value); ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: STOREING NEW cookie_name [%s] and cookie_value [%s] @ CS offset [%d] and cookie_next is [%d] and cookie_before is [%d]", cs->cookie_name, cs->cookie_value, cookiestore_offset, cs->cookie_next, cs->cookie_before); }else{ /* If we are here, we did not have more cookiestore shm */ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: Unable finding new cookiestore slot"); apr_table_set(r->notes, "CS_SHM" , "PROBLEM"); } } else { int status; // if we are here, we are not the first cookie to be saved. ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: STORE [%s]=[%s]", csp->cookie_name,csp->cookie_value); status = store_cookie_in_cookiestore(r, c->link_to_cookiestore, csp); if (status == 30){ ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: All Cookiestore SHM used [%d] - Status", status); apr_table_set(r->notes, "CS_SHM" , "PROBLEM"); } } } } ap_log_rerror(PC_LOG_INFO, r, "mod_but_output_filter.c: END OF OUTPUT FILTER"); return DECLINED; }
static apr_status_t ap_xsendfile_output_filter(ap_filter_t *f, apr_bucket_brigade *in) { request_rec *r = f->r, *sr = NULL; xsendfile_conf_t *dconf = (xsendfile_conf_t *)ap_get_module_config(r->per_dir_config, &xsendfile_module), *sconf = (xsendfile_conf_t *)ap_get_module_config(r->server->module_config, &xsendfile_module), *conf = xsendfile_config_merge(r->pool, sconf, dconf); core_dir_config *coreconf = (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); apr_status_t rv; apr_bucket *e; apr_file_t *fd = NULL; apr_finfo_t finfo; const char *file = NULL; char *translated = NULL; int errcode; #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: output_filter for %s", r->the_request); #endif /* should we proceed with this request? * sub-requests suck * furthermore default-handled requests suck, as they actually shouldn't be able to set headers */ if ( r->status != HTTP_OK || r->main || (r->handler && strcmp(r->handler, "default-handler") == 0) /* those table-keys are lower-case, right? */ ) { #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: not met [%d]", r->status); #endif ap_remove_output_filter(f); return ap_pass_brigade(f->next, in); } /* alright, look for x-sendfile */ file = apr_table_get(r->headers_out, AP_XSENDFILE_HEADER); apr_table_unset(r->headers_out, AP_XSENDFILE_HEADER); /* cgi/fastcgi will put the stuff into err_headers_out */ if (!file || !*file) { file = apr_table_get(r->err_headers_out, AP_XSENDFILE_HEADER); apr_table_unset(r->err_headers_out, AP_XSENDFILE_HEADER); } /* nothing there :p */ if (!file || !*file) { #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: nothing found"); #endif ap_remove_output_filter(f); return ap_pass_brigade(f->next, in); } /* drop *everything* might be pretty expensive to generate content first that goes straight to the bitbucket, but actually the scripts that might set this flag won't output too much anyway */ while (!APR_BRIGADE_EMPTY(in)) { e = APR_BRIGADE_FIRST(in); apr_bucket_delete(e); } r->eos_sent = 0; rv = ap_xsendfile_get_filepath(r, conf, file, &translated); if (rv != OK) { ap_log_rerror( APLOG_MARK, APLOG_ERR, rv, r, "xsendfile: unable to find file: %s", file ); ap_remove_output_filter(f); ap_die(HTTP_NOT_FOUND, r); return HTTP_NOT_FOUND; } #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: found %s", translated); #endif /* ry open the file */ if ((rv = apr_file_open( &fd, translated, APR_READ | APR_BINARY #if APR_HAS_SENDFILE | (coreconf->enable_sendfile == ENABLE_SENDFILE_ON ? APR_SENDFILE_ENABLED : 0) #endif , 0, r->pool )) != APR_SUCCESS) { ap_log_rerror( APLOG_MARK, APLOG_ERR, rv, r, "xsendfile: cannot open file: %s", translated ); ap_remove_output_filter(f); ap_die(HTTP_NOT_FOUND, r); return HTTP_NOT_FOUND; } #if APR_HAS_SENDFILE && defined(_DEBUG) if (coreconf->enable_sendfile != ENABLE_SENDFILE_ON) { ap_log_error( APLOG_MARK, APLOG_WARNING, 0, r->server, "xsendfile: sendfile configured, but not active %d", coreconf->enable_sendfile ); } #endif /* stat (for etag/cache/content-length stuff) */ if ((rv = apr_file_info_get(&finfo, APR_FINFO_NORM, fd)) != APR_SUCCESS) { ap_log_rerror( APLOG_MARK, APLOG_ERR, rv, r, "xsendfile: unable to stat file: %s", translated ); apr_file_close(fd); ap_remove_output_filter(f); ap_die(HTTP_FORBIDDEN, r); return HTTP_FORBIDDEN; } /* no inclusion of directories! we're serving files! */ if (finfo.filetype != APR_REG) { ap_log_rerror( APLOG_MARK, APLOG_ERR, APR_EBADPATH, r, "xsendfile: not a file %s", translated ); apr_file_close(fd); ap_remove_output_filter(f); ap_die(HTTP_NOT_FOUND, r); return HTTP_NOT_FOUND; } /* need to cheat here a bit as etag generator will use those ;) and we want local_copy and cache */ r->finfo.inode = finfo.inode; r->finfo.size = finfo.size; /* caching? why not :p */ r->no_cache = r->no_local_copy = 0; /* some script (f?cgi) place stuff in err_headers_out */ if ( conf->ignoreLM == XSENDFILE_ENABLED || ( !apr_table_get(r->headers_out, "last-modified") && !apr_table_get(r->headers_out, "last-modified") ) ) { apr_table_unset(r->err_headers_out, "last-modified"); ap_update_mtime(r, finfo.mtime); ap_set_last_modified(r); } if ( conf->ignoreETag == XSENDFILE_ENABLED || ( !apr_table_get(r->headers_out, "etag") && !apr_table_get(r->err_headers_out, "etag") ) ) { apr_table_unset(r->err_headers_out, "etag"); ap_set_etag(r); } apr_table_unset(r->err_headers_out, "content-length"); ap_set_content_length(r, finfo.size); /* as we dropped all the content this field is not valid anymore! */ apr_table_unset(r->headers_out, "Content-Encoding"); apr_table_unset(r->err_headers_out, "Content-Encoding"); /* cache or something? */ if ((errcode = ap_meets_conditions(r)) != OK) { #ifdef _DEBUG ap_log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: met condition %d for %s", errcode, file ); #endif apr_file_close(fd); r->status = errcode; } else { /* For platforms where the size of the file may be larger than * that which can be stored in a single bucket (where the * length field is an apr_size_t), split it into several * buckets: */ if (sizeof(apr_off_t) > sizeof(apr_size_t) && finfo.size > AP_MAX_SENDFILE) { apr_off_t fsize = finfo.size; e = apr_bucket_file_create(fd, 0, AP_MAX_SENDFILE, r->pool, in->bucket_alloc); while (fsize > AP_MAX_SENDFILE) { apr_bucket *ce; apr_bucket_copy(e, &ce); APR_BRIGADE_INSERT_TAIL(in, ce); e->start += AP_MAX_SENDFILE; fsize -= AP_MAX_SENDFILE; } e->length = (apr_size_t)fsize; /* Resize just the last bucket */ } else { e = apr_bucket_file_create(fd, 0, (apr_size_t)finfo.size, r->pool, in->bucket_alloc); } #if APR_HAS_MMAP if (coreconf->enable_mmap == ENABLE_MMAP_ON) { apr_bucket_file_enable_mmap(e, 0); } #if defined(_DEBUG) else { ap_log_error( APLOG_MARK, APLOG_WARNING, 0, r->server, "xsendfile: mmap configured, but not active %d", coreconf->enable_mmap ); } #endif /* _DEBUG */ #endif /* APR_HAS_MMAP */ APR_BRIGADE_INSERT_TAIL(in, e); } e = apr_bucket_eos_create(in->bucket_alloc); APR_BRIGADE_INSERT_TAIL(in, e); /* remove ourselves from the filter chain */ ap_remove_output_filter(f); #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "xsendfile: sending %d bytes", (int)finfo.size); #endif /* send the data up the stack */ return ap_pass_brigade(f->next, in); }
/* Do a query and return the (0,0) value. The query is assumed to be * a select. */ char *do_pg_query(request_rec * r, char *query, pg_auth_config_rec * sec) { PGresult *pg_result; PGconn *pg_conn; char *val; char *result = NULL; pg_errstr[0] = '\0'; #ifdef DEBUG_AUTH_PGSQL ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_auth_pgsql.c] - do_pg_query - going to connect database \"%s\" ", sec->auth_pg_database); #endif /* DEBUG_AUTH_PGSQL */ pg_conn = PQsetdbLogin(sec->auth_pg_host, sec->auth_pg_port, sec->auth_pg_options, NULL, sec->auth_pg_database, sec->auth_pg_user, sec->auth_pg_pwd); if (PQstatus(pg_conn) != CONNECTION_OK) { PQreset(pg_conn); apr_snprintf(pg_errstr, MAX_STRING_LEN, "mod_auth_pgsql database connection error resetting %s", PQerrorMessage(pg_conn)); if (PQstatus(pg_conn) != CONNECTION_OK) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "mod_auth_pgsql database connection error reset failed %s", PQerrorMessage(pg_conn)); PQfinish(pg_conn); return NULL; } } #ifdef DEBUG_AUTH_PGSQL ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_auth_pgsql.c] - do_pg_query - going to execute query \"%s\" ", query); #endif /* DEBUG_AUTH_PGSQL */ pg_result = PQexec(pg_conn, query); if (pg_result == NULL) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "PGSQL 2: %s -- Query: %s ", PQerrorMessage(pg_conn), query); PQfinish(pg_conn); return NULL; } if (PQresultStatus(pg_result) == PGRES_EMPTY_QUERY) { PQclear(pg_result); PQfinish(pg_conn); return NULL; } if (PQresultStatus(pg_result) != PGRES_TUPLES_OK) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "PGSQL 3: %s -- Query: %s", PQerrorMessage(pg_conn), query); PQclear(pg_result); PQfinish(pg_conn); return NULL; } if (PQntuples(pg_result) == 1) { val = PQgetvalue(pg_result, 0, 0); if (val == NULL) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "PGSQL 4: %s", PQerrorMessage(pg_conn)); PQclear(pg_result); PQfinish(pg_conn); return NULL; } if (!(result = (char *) apr_pcalloc(r->pool, strlen(val) + 1))) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "Could not get memory for Postgres query."); PQclear(pg_result); PQfinish(pg_conn); return NULL; } strcpy(result, val); } /* ignore errors here ! */ PQclear(pg_result); PQfinish(pg_conn); return result; }
static int ap_set_byterange(request_rec *r, apr_off_t clength, apr_array_header_t **indexes) { const char *range; const char *if_range; const char *match; const char *ct; char *cur; int num_ranges = 0, unsatisfiable = 0; apr_off_t sum_lengths = 0; indexes_t *idx; int ranges = 1; const char *it; if (r->assbackwards) { return 0; } /* * Check for Range request-header (HTTP/1.1) or Request-Range for * backwards-compatibility with second-draft Luotonen/Franks * byte-ranges (e.g. Netscape Navigator 2-3). * * We support this form, with Request-Range, and (farther down) we * send multipart/x-byteranges instead of multipart/byteranges for * Request-Range based requests to work around a bug in Netscape * Navigator 2-3 and MSIE 3. */ if (!(range = apr_table_get(r->headers_in, "Range"))) { range = apr_table_get(r->headers_in, "Request-Range"); } if (!range || strncasecmp(range, "bytes=", 6) || r->status != HTTP_OK) { return 0; } /* is content already a single range? */ if (apr_table_get(r->headers_out, "Content-Range")) { return 0; } /* is content already a multiple range? */ if ((ct = apr_table_get(r->headers_out, "Content-Type")) && (!strncasecmp(ct, "multipart/byteranges", 20) || !strncasecmp(ct, "multipart/x-byteranges", 22))) { return 0; } /* * Check the If-Range header for Etag or Date. * Note that this check will return false (as required) if either * of the two etags are weak. */ if ((if_range = apr_table_get(r->headers_in, "If-Range"))) { if (if_range[0] == '"') { if (!(match = apr_table_get(r->headers_out, "Etag")) || (strcmp(if_range, match) != 0)) { return 0; } } else if (!(match = apr_table_get(r->headers_out, "Last-Modified")) || (strcmp(if_range, match) != 0)) { return 0; } } range += 6; it = range; while (*it) { if (*it++ == ',') { ranges++; } } it = range; *indexes = apr_array_make(r->pool, ranges, sizeof(indexes_t)); while ((cur = ap_getword(r->pool, &range, ','))) { char *dash; char *errp; apr_off_t number, start, end; if (!*cur) break; /* * Per RFC 2616 14.35.1: If there is at least one syntactically invalid * byte-range-spec, we must ignore the whole header. */ if (!(dash = strchr(cur, '-'))) { return 0; } if (dash == cur) { /* In the form "-5" */ if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) { return 0; } if (number < 1) { return 0; } start = clength - number; end = clength - 1; } else { *dash++ = '\0'; if (apr_strtoff(&number, cur, &errp, 10) || *errp) { return 0; } start = number; if (*dash) { if (apr_strtoff(&number, dash, &errp, 10) || *errp) { return 0; } end = number; if (start > end) { return 0; } } else { /* "5-" */ end = clength - 1; /* * special case: 0- * ignore all other ranges provided * return as a single range: 0- */ if (start == 0) { (*indexes)->nelts = 0; idx = (indexes_t *)apr_array_push(*indexes); idx->start = start; idx->end = end; sum_lengths = clength; num_ranges = 1; break; } } } if (start < 0) { start = 0; } if (start >= clength) { unsatisfiable = 1; continue; } if (end >= clength) { end = clength - 1; } idx = (indexes_t *)apr_array_push(*indexes); idx->start = start; idx->end = end; sum_lengths += end - start + 1; /* new set again */ num_ranges++; } if (num_ranges == 0 && unsatisfiable) { /* If all ranges are unsatisfiable, we should return 416 */ return -1; } if (sum_lengths > clength) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Sum of ranges larger than file, ignoring."); return 0; } r->status = HTTP_PARTIAL_CONTENT; r->range = it; return num_ranges; }
static char *get_pg_grp(request_rec * r, char *group, char *user, pg_auth_config_rec * sec) { char query[MAX_STRING_LEN]; char *safe_user; char *safe_group; int n; safe_user = apr_palloc(r->pool, 1 + 2 * strlen(user)); safe_group = apr_palloc(r->pool, 1 + 2 * strlen(group)); #ifdef DEBUG_AUTH_PGSQL ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_auth_pgsql.c] - get_pg_grp - going to retrieve group for user \"%s\" from database", user); #endif /* DEBUG_AUTH_PGSQL */ query[0] = '\0'; pg_check_string(safe_user, user, strlen(user)); pg_check_string(safe_group, group, strlen(group)); if ((!sec->auth_pg_grp_table) || (!sec->auth_pg_grp_group_field) || (!sec->auth_pg_grp_user_field)) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "PG: Missing parameters for password lookup: %s%s%s", (sec->auth_pg_grp_table ? "" : "Group table name"), (sec-> auth_pg_grp_group_field ? "" : "GroupID field name "), (sec-> auth_pg_grp_user_field ? "" : "Group table user field name ")); return NULL; }; if (sec->auth_pg_lowercaseuid) { /* and force it to lowercase */ n = 0; while (safe_user[n] && n < (MAX_STRING_LEN - 1)) { if (isupper(safe_user[n])) { safe_user[n] = tolower(safe_user[n]); } n++; } } if (sec->auth_pg_uppercaseuid) { /* and force it to uppercase */ n = 0; while (safe_user[n] && n < (MAX_STRING_LEN - 1)) { if (islower(safe_user[n])) { safe_user[n] = toupper(safe_user[n]); } n++; } } n = apr_snprintf(query, MAX_STRING_LEN, "select %s from %s where %s='%s' and %s='%s' %s", sec->auth_pg_grp_group_field, sec->auth_pg_grp_table, sec->auth_pg_grp_user_field, safe_user, sec->auth_pg_grp_group_field, safe_group, sec->auth_pg_grp_whereclause ? sec-> auth_pg_grp_whereclause : ""); if (n < 0 || n > MAX_STRING_LEN) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "PG: Detected SQL-truncation attack. Auth aborted."); return NULL; } return do_pg_query(r, query, sec); }
static int zipread_showfile(request_rec *r, const char *fname) { char *zipfile, *name; ZZIP_DIR *dir; unsigned int itnum; if (!r->path_info) return HTTP_NOT_FOUND; zipfile = r->filename; if (!fname || !*fname) { name = apr_pstrdup(r->pool, r->path_info); } else { name = apr_pstrcat(r->pool, r->path_info, fname, NULL); } r->content_type = zipread_getcontenttype(r, name); if (*name == '/') name++; // ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_zipread showfile: %s - %s - %s", zipfile, fname, name); for(itnum = 0; itnum < 5; itnum++) { dir = zzip_dir_open(zipfile, 0); if (dir) { ZZIP_STAT st; // fetch stat info of filename, before opening it if (zzip_dir_stat(dir, name, &st, 0) != 0) { // check if a directory entry is available for that name. name = apr_pstrcat(r->pool, name, "/", NULL); if (zzip_dir_stat(dir, name, &st, 0) != 0) { zzip_dir_close(dir); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_zipread showfile stat failed: %d - %s", zzip_error(dir), zzip_strerror(zzip_error(dir))); return HTTP_NOT_FOUND; } // found a directory entry, do an external redirect to get the // links in the directory listing right. name = apr_pstrcat(r->pool, r->uri, "/", NULL); apr_table_setn(r->headers_out, "Location", name); // ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_zipread showfile directory entry."); return HTTP_MOVED_PERMANENTLY; } ap_set_content_length(r, st.st_size); // cannot check last-modified date of the file itself here, because // zziplib doesnt extract it. instead we use the zip file's date r->mtime = r->finfo.mtime; ap_set_last_modified(r); if (!r->header_only) { ZZIP_FILE *fp = zzip_file_open(dir, name, 0); if (fp) { int len; char buf[32769]; while ((len = zzip_file_read (fp, buf, 32768))) { ap_rwrite(buf, len, r); } zzip_file_close(fp); zzip_dir_close(dir); return OK; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_zipread showfile file open failed: %d - %s.", zzip_error(dir), zzip_strerror(zzip_error(dir))); if (zzip_dir_stat(dir, name, &st, 0) != 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_zipread showfile after stat failed: %d - %s", zzip_error(dir), zzip_strerror(zzip_error(dir))); break; } zzip_dir_close(dir); continue; } } zzip_dir_close(dir); return OK; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_zipread showfile zip file not open."); return HTTP_NOT_FOUND; } } zzip_dir_close (dir); return HTTP_NOT_FOUND; }
/* Process authentication request from Apache*/ static int pg_authenticate_basic_user(request_rec * r) { pg_auth_config_rec *sec = (pg_auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_pgsql_module); char *val = NULL; char *sent_pw, *real_pw; int res; char *user; if ((res = ap_get_basic_auth_pw(r, (const char **) &sent_pw))) return res; user = r->user; #ifdef DEBUG_AUTH_PGSQL ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_auth_pgsql.c] - pg_authenticate_basic_user - going to auth user \"%s\" pass \"%s\" uri \"%s\"", user, sent_pw, r->unparsed_uri); #endif /* DEBUG_AUTH_PGSQL */ /* if *password* checking is configured in any way, i.e. then * handle it, if not decline and leave it to the next in line.. * We do not check on dbase, group, userid or host name, as it is * perfectly possible to only do group control and leave * user control to the next guy in line. */ if ((!sec->auth_pg_pwd_table) && (!sec->auth_pg_pwd_field)) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_auth_pgsql.c] - missing configuration parameters"); return DECLINED; } pg_errstr[0] = '\0'; if (sec->auth_pg_cache_passwords && (!apr_is_empty_table(sec->cache_pass_table))) { val = (char *) apr_table_get(sec->cache_pass_table, user); if (val) real_pw = val; else real_pw = get_pg_pw(r, user, sec); } else real_pw = get_pg_pw(r, user, sec); if (!real_pw) { if (pg_errstr[0]) { res = HTTP_INTERNAL_SERVER_ERROR; } else { if (sec->auth_pg_authoritative) { /* force error and access denied */ apr_snprintf(pg_errstr, MAX_STRING_LEN, "mod_auth_pgsql: Password for user %s not found (PG-Authoritative)", user); ap_note_basic_auth_failure(r); res = HTTP_UNAUTHORIZED; } else { /* allow fall through to another module */ return DECLINED; } } ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); return res; } /* allow no password, if the flag is set and the password * is empty. But be sure to log this. */ if ((sec->auth_pg_nopasswd) && (!strlen(real_pw))) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "[mod_auth_pgsql.c] - Empty password accepted for user \"%s\"", user); ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); pg_log_auth_user(r, sec, user, sent_pw); return OK; }; /* if the flag is off however, keep that kind of stuff at * an arms length. */ if ((!strlen(real_pw)) || (!strlen(sent_pw))) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "[mod_auth_pgsql.c] - Empty password rejected for user \"%s\"", user); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; }; if (sec->auth_pg_encrypted) switch (sec->auth_pg_hash_type) { case AUTH_PG_HASH_TYPE_MD5: sent_pw = auth_pg_md5(sent_pw); break; case AUTH_PG_HASH_TYPE_CRYPT: sent_pw = (char *) crypt(sent_pw, real_pw); break; case AUTH_PG_HASH_TYPE_BASE64: sent_pw = auth_pg_base64(sent_pw); break; } if (sec->auth_pg_hash_type == AUTH_PG_HASH_TYPE_NETEPI) { char *netepi_pw; if (netepi_pw = netepi_pwd_check(sec, r, real_pw, sent_pw)) goto netepi_ok; apr_snprintf(pg_errstr, MAX_STRING_LEN, "PG user %s: password mismatch", user); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; netepi_ok: sent_pw = netepi_pw; } else if ((sec->auth_pg_hash_type == AUTH_PG_HASH_TYPE_MD5 || sec->auth_pg_hash_type == AUTH_PG_HASH_TYPE_BASE64 || sec->auth_pg_pwdignorecase) ? strcasecmp(real_pw, sent_pw) : strcmp(real_pw, sent_pw)) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "PG user %s: password mismatch", user); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; } /* store password in the cache */ if (sec->auth_pg_cache_passwords && !val && sec->cache_pass_table) { if ((apr_table_elts(sec->cache_pass_table))->nelts >= MAX_TABLE_LEN) { apr_table_clear(sec->cache_pass_table); } apr_table_set(sec->cache_pass_table, user, real_pw); } pg_log_auth_user(r, sec, user, sent_pw); return OK; }
/* This function populates the subprocess environment with data received * from the IdP. * * Parameters: * request_rec *r The request we should add the data to. * am_cache_entry_t *t The session data. * * Returns: * Nothing. */ void am_cache_env_populate(request_rec *r, am_cache_entry_t *t) { am_dir_cfg_rec *d; int i; apr_hash_t *counters; am_envattr_conf_t *env_varname_conf; const char *varname; const char *varname_prefix; const char *value; int *count; int status; d = am_get_dir_cfg(r); /* Check if the user attribute has been set, and set it if it * hasn't been set. */ if (am_cache_entry_slot_is_empty(&t->user)) { for(i = 0; i < t->size; ++i) { varname = am_cache_entry_get_string(t, &t->env[i].varname); if (strcmp(varname, d->userattr) == 0) { value = am_cache_entry_get_string(t, &t->env[i].value); status = am_cache_entry_store_string(t, &t->user, value); if (status != 0) { ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, "Unable to store the user name because there" " is no more space in the session. " "Username = \"%s\".", value); } } } } /* Allocate a set of counters for duplicate variables in the list. */ counters = apr_hash_make(r->pool); /* Populate the subprocess environment with the attributes we * received from the IdP. */ for(i = 0; i < t->size; ++i) { varname = am_cache_entry_get_string(t, &t->env[i].varname); varname_prefix = "MELLON_"; /* Check if we should map this name into another name. */ env_varname_conf = (am_envattr_conf_t *)apr_hash_get( d->envattr, varname, APR_HASH_KEY_STRING); if(env_varname_conf != NULL) { varname = env_varname_conf->name; if (!env_varname_conf->prefixed) { varname_prefix = ""; } } value = am_cache_entry_get_string(t, &t->env[i].value); /* * If we find a variable remapping to MellonUser, use it. */ if (am_cache_entry_slot_is_empty(&t->user) && (strcmp(varname, d->userattr) == 0)) { status = am_cache_entry_store_string(t, &t->user, value); if (status != 0) { ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, "Unable to store the user name because there" " is no more space in the session. " "Username = \"%s\".", value); } } /* Find the number of times this variable has been set. */ count = apr_hash_get(counters, varname, APR_HASH_KEY_STRING); if(count == NULL) { /* This is the first time. Create a counter for this variable. */ count = apr_palloc(r->pool, sizeof(int)); *count = 0; apr_hash_set(counters, varname, APR_HASH_KEY_STRING, count); /* Add the variable without a suffix. */ apr_table_set(r->subprocess_env, apr_pstrcat(r->pool, varname_prefix, varname, NULL), value); } /* Add the variable with a suffix indicating how many times it has * been added before. */ apr_table_set(r->subprocess_env, apr_psprintf(r->pool, "%s%s_%d", varname_prefix, varname, *count), value); /* Increase the count. */ ++(*count); } if (!am_cache_entry_slot_is_empty(&t->user)) { /* We have a user-"name". Set r->user and r->ap_auth_type. */ r->user = apr_pstrdup(r->pool, am_cache_entry_get_string(t, &t->user)); r->ap_auth_type = apr_pstrdup(r->pool, "Mellon"); } else { /* We don't have a user-"name". Log error. */ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, "Didn't find the attribute \"%s\" in the attributes" " which were received from the IdP. Cannot set a user" " for this request without a valid user attribute.", d->userattr); } /* Populate with the session? */ if (d->dump_session) { char *session; const char *srcstr; int srclen, dstlen; srcstr = am_cache_entry_get_string(t, &t->lasso_session); srclen = strlen(srcstr); dstlen = apr_base64_encode_len(srclen); session = apr_palloc(r->pool, dstlen); (void)apr_base64_encode(session, srcstr, srclen); apr_table_set(r->subprocess_env, "MELLON_SESSION", session); } if (d->dump_saml_response) { const char *sr = am_cache_entry_get_string(t, &t->lasso_saml_response); if (sr) { apr_table_set(r->subprocess_env, "MELLON_SAML_RESPONSE", sr); } } }
static int pg_check_auth(request_rec * r) { pg_auth_config_rec *sec = (pg_auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_pgsql_module); char *user = r->user; int m = r->method_number; int group_result = DECLINED; apr_array_header_t *reqs_arr = (apr_array_header_t *) ap_requires(r); require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL; register int x, res; const char *t; char *w; pg_errstr[0] = '\0'; #ifdef DEBUG_AUTH_PGSQL ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_auth_pgsql.c] - pg_check_auth - going to check auth for user \"%s\" ", user); #endif /* DEBUG_AUTH_PGSQL */ /* if we cannot do it; leave it to some other guy */ if ((!sec->auth_pg_grp_table) && (!sec->auth_pg_grp_group_field) && (!sec->auth_pg_grp_user_field)) return DECLINED; if (!reqs_arr) { if (sec->auth_pg_authoritative) { /* force error and access denied */ apr_snprintf(pg_errstr, MAX_STRING_LEN, "mod_auth_pgsql: user %s denied, no access rules specified (PG-Authoritative)", user); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); ap_note_basic_auth_failure(r); res = HTTP_UNAUTHORIZED; } else { return DECLINED; } } for (x = 0; x < reqs_arr->nelts; x++) { if (!(reqs[x].method_mask & (1 << m))) continue; t = reqs[x].requirement; w = ap_getword(r->pool, &t, ' '); if (!strcmp(w, "valid-user")) return OK; if (!strcmp(w, "user")) { while (t[0]) { w = ap_getword_conf(r->pool, &t); if (!strcmp(user, w)) return OK; } if (sec->auth_pg_authoritative) { /* force error and access denied */ apr_snprintf(pg_errstr, MAX_STRING_LEN, "mod_auth_pgsql: user %s denied, no access rules specified (PG-Authoritative)", user); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; } } else if (!strcmp(w, "group")) { /* look up the membership for each of the groups in the table */ pg_errstr[0] = '\0'; while (t[0]) { if (get_pg_grp(r, ap_getword(r->pool, &t, ' '), user, sec)) { group_result = OK; }; }; if (pg_errstr[0]) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); return HTTP_INTERNAL_SERVER_ERROR; } if (group_result == OK) return OK; if (sec->auth_pg_authoritative) { apr_snprintf(pg_errstr, MAX_STRING_LEN, "[mod_auth_pgsql.c] - user %s not in right groups (PG-Authoritative)", user); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - ERROR - %s", pg_errstr); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; }; } } return DECLINED; }
static triger_bucket_t *where_to_insert_html_fragment_at_tail(ap_filter_t * f) { apr_size_t i = 0; int in_comments = -1; triger_module_ctx_t *ctx = f->ctx; triger_bucket_t *rv = ctx->triger_bucket; apr_size_t j = rv->len; apr_size_t len = rv->len; apr_size_t char_counts = 0; const char *data = rv->data; rv->body_end_tag_pos = rv->html_end_tag_pos = -1; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "Look for </body> and </html>"); for (; j >= 1; j--) { i = j - 1; if (char_counts > rv->limit) return rv; else char_counts++; if (in_comments != -1) { switch (*(data + i)) { case '<': if (in_comments == html_comment) { if (i + 3 < len && *(data + i + 1) == '!' && *(data + i + 2) == '-' && *(data + i + 3) == '-') in_comments = -1; } else if (in_comments == xml_comment) { if (i + 8 < len && *(data + i + 1) == '!' && *(data + i + 2) == '[' && *(data + i + 3) == 'C' && *(data + i + 4) == 'D' && *(data + i + 5) == 'A' && *(data + i + 6) == 'T' && *(data + i + 7) == 'A' && *(data + i + 8) == '[') in_comments = -1; } else if (in_comments == microsoft_comment) if (i + 8 < len && (*(data + i + 1) == 'c' || *(data + i + 1) == 'C') && (*(data + i + 2) == 'o' || *(data + i + 2) == 'O') && (*(data + i + 3) == 'm' || *(data + i + 3) == 'M') && (*(data + i + 4) == 'm' || *(data + i + 4) == 'M') && (*(data + i + 5) == 'e' || *(data + i + 5) == 'E') && (*(data + i + 6) == 'n' || *(data + i + 6) == 'N') && (*(data + i + 7) == 't' || *(data + i + 7) == 'T') && *(data + i + 8) == '>') in_comments = -1; break; default: continue; } } else { switch (*(data + i)) { case '<': if (i + 6 < len && *(data + i + 1) == '/') { if ((*(data + i + 2) == 'h' || *(data + i + 2) == 'H') && (*(data + i + 3) == 't' || *(data + i + 3) == 'T') && (*(data + i + 4) == 'm' || *(data + i + 4) == 'M') && (*(data + i + 5) == 'l' || *(data + i + 5) == 'L') && *(data + i + 6) == '>') { if (!ctx->html_end_tag_find) { ctx->html_end_tag_find = 1; ctx->no_tag_find = 0; } else return rv; rv->html_end_tag_pos = i; } else if ((*(data + i + 2) == 'b' || *(data + i + 2) == 'B') && (*(data + i + 3) == 'o' || *(data + i + 3) == 'O') && (*(data + i + 4) == 'd' || *(data + i + 4) == 'D') && (*(data + i + 5) == 'y' || *(data + i + 5) == 'Y') && *(data + i + 6) == '>') { if (!ctx->body_end_tag_find) { ctx->body_end_tag_find = 1; ctx->no_tag_find = 0; } else return rv; rv->body_end_tag_pos = i; return rv; } else if (i + 9 < len && (*(data + i + 2) == 'c' || *(data + i + 2) == 'C') && (*(data + i + 3) == 'o' || *(data + i + 3) == 'O') && (*(data + i + 4) == 'm' || *(data + i + 4) == 'M') && (*(data + i + 5) == 'm' || *(data + i + 5) == 'M') && (*(data + i + 6) == 'e' || *(data + i + 6) == 'E') && (*(data + i + 7) == 'n' || *(data + i + 7) == 'N') && (*(data + i + 8) == 't' || *(data + i + 8) == 'T') && *(data + i + 9) == '>') in_comments = microsoft_comment; } else { ctx->unknown_end_tag_find = 1; return rv; } break; case '>': if (i >= 2) { if (*(data + i - 1) == '-' && *(data + i - 2) == '-') { in_comments = html_comment; i = i - 2; } else if (*(data + i - 1) == ']' && *(data + i - 2) == ']') { in_comments = xml_comment; i = i - 2; } } break; default: continue; } } } return rv; }
static int mod_vhost_ldap_translate_name(request_rec *r) { mod_vhost_ldap_request_t *reqc = NULL; mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_ng_module); #if (AP_SERVER_MAJORVERSION_NUMBER == 2) && (AP_SERVER_MINORVERSION_NUMBER <= 2) core_server_config *core = (core_server_config *)ap_get_module_config(r->server->module_config, &core_module); #endif LDAP *ld = NULL; char *realfile = NULL; char *myfilter = NULL; alias_t *alias = NULL, *cursor = NULL; int i = 0, ret = 0; apr_table_t *e; LDAPMessage *ldapmsg = NULL, *vhostentry = NULL; if (conf->enabled != MVL_ENABLED || !conf->url || !r->hostname){ ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] Module disabled"); return DECLINED; } //Search in cache reqc = (mod_vhost_ldap_request_t *)get_from_requestscache(r); if(!reqc){ ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] Cannot resolve data from cache"); reqc = apr_pcalloc(vhost_ldap_pool, sizeof(mod_vhost_ldap_request_t)); } if (reqc->expires < apr_time_now()){ //Search ldap //TODO: Create a function while((ret = ldapconnect(&ld, conf)) != 0 && i<2){ i++; ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] ldapconnect: %s", ldap_err2string(ret)); } if(i == 2){ conf->enabled = MVL_DISABLED; return HTTP_GATEWAY_TIME_OUT; } myfilter = apr_psprintf(r->pool,"(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, r->hostname, r->hostname); ret = ldap_search_s (ld, conf->basedn, conf->scope, myfilter, (char **)attributes, 0, &ldapmsg); if(ret != LDAP_SUCCESS){//SIGPIPE? return DECLINED; } if(ldap_count_entries(ld, ldapmsg)!=1){ if(!conf->fallback_name || !conf->fallback_docroot){ reqc->name = apr_pstrdup(vhost_ldap_pool, r->hostname); reqc->decline = 1; reqc->admin = apr_pstrdup(vhost_ldap_pool, r->server->server_admin); add_to_requestscache(reqc, r); if(ldapmsg) ldap_msgfree(ldapmsg); ldapdestroy(&ld); return DECLINED; }else{ reqc->name = conf->fallback_name; reqc->docroot = conf->fallback_docroot; } }else{ reqc->aliases = (apr_array_header_t *)apr_array_make(vhost_ldap_pool, 2, sizeof(alias_t)); reqc->redirects = (apr_array_header_t *)apr_array_make(vhost_ldap_pool, 2, sizeof(alias_t)); reqc->env = apr_table_make(vhost_ldap_pool, 2); vhostentry = ldap_first_entry(ld, ldapmsg); reqc->dn = ldap_get_dn(ld, vhostentry); i=0; while(attributes[i]){ int k = 0, j; char **eValues = ldap_get_values(ld, vhostentry, attributes[i]), *str[3]; if (eValues){ k = ldap_count_values (eValues); if (strcasecmp(attributes[i], "apacheServerName") == 0){ reqc->name = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "apacheServerAdmin") == 0){ reqc->admin = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "apacheDocumentRoot") == 0){ reqc->docroot = apr_pstrdup(vhost_ldap_pool, eValues[0]); /* Make it absolute, relative to ServerRoot */ if(conf->rootdir && (strncmp(reqc->docroot, "/", 1) != 0)) reqc->docroot = apr_pstrcat(vhost_ldap_pool, conf->rootdir, reqc->docroot, NULL); reqc->docroot = ap_server_root_relative(vhost_ldap_pool, reqc->docroot); }else if(strcasecmp(attributes[i], "apacheAlias") == 0){ while(k){ k--; for(j = 0; j < 2; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[k]); if(str[--j] == '\0') ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheAlias parameter: %s", eValues[k]); else{ alias = apr_array_push(reqc->aliases); alias->src = apr_pstrdup(vhost_ldap_pool, str[0]); alias->dst = apr_pstrdup(vhost_ldap_pool, str[1]); } } }else if(strcasecmp(attributes[i], "apacheScriptAlias") == 0){ while(k){ k--; for(j = 0; j < 2; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[k]); if(str[--j] == '\0') ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheScriptAlias parameter: %s", eValues[k]); else{ alias = apr_array_push(reqc->aliases); alias->src = apr_pstrdup(vhost_ldap_pool, str[0]); alias->dst = apr_pstrdup(vhost_ldap_pool, str[1]); } } }else if(strcasecmp (attributes[i], "apacheRedirect") == 0){ while(k){ k--; for(j = 0; j < 3; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[k]); if(str[1] == '\0') ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Missing apacheRedirect parameter: %s", eValues[k]); else{ alias = apr_array_push(reqc->redirects); alias->src = apr_pstrdup(vhost_ldap_pool, str[0]); if(str[2] != '\0'){ if(strcasecmp(str[1], "gone") == 0) alias->flags |= REDIR_GONE; else if (strcasecmp(str[1], "permanent") == 0) alias->flags |= REDIR_PERMANENT; else if (strcasecmp(str[1], "temp") == 0) alias->flags |= REDIR_TEMP; else if (strcasecmp(str[1], "seeother") == 0) alias->flags |= REDIR_SEEOTHER; else{ alias->flags |= REDIR_PERMANENT; ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheRedirect type: %s", str[2]); } alias->dst = apr_pstrdup(vhost_ldap_pool, str[2]); }else alias->dst = apr_pstrdup(vhost_ldap_pool, str[1]); } } }else if(strcasecmp(attributes[i], "apacheSuexecUid") == 0){ reqc->uid = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "apacheSuexecGid") == 0){ reqc->gid = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp (attributes[i], "apacheErrorLog") == 0){ if(conf->rootdir && (strncmp(eValues[0], "/", 1) != 0)) r->server->error_fname = apr_pstrcat(vhost_ldap_pool, conf->rootdir, eValues[0], NULL); else r->server->error_fname = apr_pstrdup(vhost_ldap_pool, eValues[0]);; apr_file_open(&r->server->error_log, r->server->error_fname, APR_APPEND | APR_WRITE | APR_CREATE | APR_LARGEFILE, APR_OS_DEFAULT, r->pool); } #ifdef HAVEPHP else if(strcasecmp(attributes[i], "phpIncludePath") == 0){ if(conf->php_includepath) reqc->php_includepath = apr_pstrcat(vhost_ldap_pool, conf->php_includepath, ":", eValues[0], NULL); else reqc->php_includepath = apr_pstrdup(vhost_ldap_pool, eValues[0]); }else if(strcasecmp(attributes[i], "phpOpenBasedir") == 0){ if(conf->rootdir && (strncmp(eValues[0], "/", 1) != 0)) reqc->php_openbasedir = apr_pstrcat(vhost_ldap_pool, conf->rootdir, eValues[0], NULL); else reqc->php_openbasedir = apr_pstrdup(vhost_ldap_pool, eValues[0]); } else if(strcasecmp(attributes[i], "php_admin_value") == 0){ } #endif else if(strcasecmp(attributes[i], "SetEnv") == 0){ for(j = 0; j < 2; j++) str[j] = ap_getword_conf(r->pool, (const char **)&eValues[0]); if(str[--j] == '\0') ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: Wrong apacheScriptAlias parameter: %s", eValues[0]); else{ apr_table_set(reqc->env, str[0], str[1]); } }else if(strcasecmp(attributes[i], "PassEnv") == 0){ } } i++; } } if(ldapmsg) ldap_msgfree(ldapmsg); ldapdestroy(&ld); add_to_requestscache(reqc, r); } if(reqc->decline) return DECLINED; ap_set_module_config(r->request_config, &vhost_ldap_ng_module, reqc); e = r->subprocess_env; if(apr_table_elts(reqc->env)->nelts) r->subprocess_env = apr_table_overlay(r->pool, e, reqc->env); #ifdef HAVEPHP char *openbasedir, *include; if(!reqc->php_includepath) include = apr_pstrcat(r->pool, conf->php_includepath, ":", reqc->docroot, NULL); else include = apr_pstrcat(r->pool, reqc->php_includepath, ":", conf->php_includepath, ":", reqc->docroot, NULL); zend_alter_ini_entry("include_path", strlen("include_path") + 1, (void *)include, strlen(include), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); if(reqc->php_openbasedir){ openbasedir = apr_pstrcat(r->pool, reqc->php_openbasedir, ":", include, NULL); zend_alter_ini_entry("open_basedir", strlen("open_basedir") + 1, (void *)openbasedir, strlen(openbasedir), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); } #endif if ((reqc->name == NULL)||(reqc->docroot == NULL)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] translate: " "translate failed; ServerName %s or DocumentRoot %s not defined", reqc->name, reqc->docroot); return HTTP_INTERNAL_SERVER_ERROR; } cursor = NULL; //From mod_alias: checking for redirects if(reqc->redirects){ cursor = (alias_t *)reqc->redirects->elts; if (r->uri[0] != '/' && r->uri[0] != '\0') return DECLINED; for(i = 0; i < reqc->redirects->nelts; i++){ alias = (alias_t *) &cursor[i]; if(alias_matches(r->uri, alias->src)){ apr_table_setn(r->headers_out, "Location", alias->dst); /* OLD STUFF if(alias->redir_status){ if (strcasecmp(alias->redir_status, "gone") == 0) return HTTP_GONE; else if (strcasecmp(alias->redir_status, "permanent") == 0) return HTTP_MOVED_PERMANENTLY; else if (strcasecmp(alias->redir_status, "temp") == 0) return HTTP_MOVED_TEMPORARILY; else if (strcasecmp(alias->redir_status, "seeother") == 0) return HTTP_SEE_OTHER; } */ if(alias->flags & REDIR_GONE) return HTTP_GONE; else if(alias->flags & REDIR_TEMP) return HTTP_MOVED_TEMPORARILY; else if(alias->flags & REDIR_SEEOTHER) return HTTP_SEE_OTHER; else return HTTP_MOVED_PERMANENTLY; } } } /* Checking for aliases */ if(reqc->aliases){ cursor = (alias_t *)reqc->aliases->elts; for(i = 0; reqc->aliases && i < reqc->aliases->nelts; i++){ alias = (alias_t *) &cursor[i]; if (alias_matches(r->uri, alias->src)) { /* Set exact filename for CGI script */ realfile = apr_pstrcat(r->pool, alias->dst, r->uri + strlen(alias->src), NULL); /* Add apacheRootDir config param IF realfile is a realative path*/ if(conf->rootdir && (strncmp(realfile, "/", 1) != 0)) realfile = apr_pstrcat(r->pool, conf->rootdir, "/", realfile, NULL); /* Let apache normalize the path */ if((realfile = ap_server_root_relative(r->pool, realfile))) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c]: ap_document_root is: %s", ap_document_root(r)); r->filename = realfile; if(alias->flags & ISCGI){ //r->handler = "cgi-script"; r->handler = "Script"; apr_table_setn(r->notes, "alias-forced-type", r->handler); } return OK; } return OK; } else if (r->uri[0] == '/') { /* we don't set r->filename here, and let other modules do it * this allows other modules (mod_rewrite.c) to work as usual */ /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */ } else { /* We don't handle non-file requests here */ return DECLINED; } } } if ((r->server = apr_pmemdup(r->pool, r->server, sizeof(*r->server))) == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap_ng.c] translate: " "translate failed; Unable to copy r->server structure"); return HTTP_INTERNAL_SERVER_ERROR; } r->server->server_hostname = apr_pstrdup(r->pool,reqc->name); if (reqc->admin) r->server->server_admin = apr_pstrdup(r->pool, reqc->admin); #if (AP_SERVER_MAJORVERSION_NUMBER == 2) && (AP_SERVER_MINORVERSION_NUMBER <= 2) core->ap_document_root = apr_pstrdup(r->pool, reqc->docroot); if (!ap_is_directory(r->pool, reqc->docroot)) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_vhost_ldap_ng.c] set_document_root: Warning: DocumentRoot [%s] does not exist", core->ap_document_root); #else ap_set_document_root(r, reqc->docroot); #endif //ap_set_module_config(r->server->module_config, &core_module, core); /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */ return DECLINED; }
static apr_status_t mod_dechunk_replay_kept_body( ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) { apr_bucket *ec, *e2; replay_ctx_t *ctx = f->ctx; apr_status_t status; /* just get out of the way of things we don't want. */ if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) { return ap_get_brigade(f->next, b, mode, block, readbytes); } /* mod_dechunk is finished, send next filter */ if (ctx->remaining <= 0) { return ap_get_brigade(f->next, b, mode, block, readbytes); } if (readbytes > ctx->remaining) { readbytes = ctx->remaining; } status = apr_brigade_partition(ctx->kept_body, ctx->offset, &ec); if (status != APR_SUCCESS) { ap_log_rerror( APLOG_MARK, APLOG_ERR, status, f->r, "apr_brigade_partition() failed at offset %" APR_OFF_T_FMT, ctx->offset); return status; } status = apr_brigade_partition(ctx->kept_body, ctx->offset + readbytes, &e2); if (status != APR_SUCCESS) { ap_log_rerror( APLOG_MARK, APLOG_ERR, status, f->r, "apr_brigade_partition() failed at offset + readbytes %" APR_OFF_T_FMT, ctx->offset + readbytes); return status; } do { apr_bucket *tmp; apr_bucket_copy(ec, &tmp); APR_BRIGADE_INSERT_TAIL(b, tmp); ec = APR_BUCKET_NEXT(ec); } while (ec != e2); ctx->remaining -= readbytes; ctx->offset += readbytes; return APR_SUCCESS; }
/* obtaining credentials for the secure authentication connection */ static int obtain_credentials(sspi_auth_ctx* ctx) { SECURITY_STATUS ss; TimeStamp throwaway; sspi_header_rec *auth_id; #ifdef UNICODE #define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2 ctx->hdr.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; #else #define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1 ctx->hdr.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; #endif /* setting values based on the basic type authentication and the secured SSPI based authentication */ if (ctx->hdr.authtype == typeBasic) { auth_id = &ctx->hdr; if (auth_id->Domain == NULL && ctx->crec->sspi_domain != NULL) { auth_id->Domain = ctx->crec->sspi_domain; auth_id->DomainLength = (unsigned long)strlen(ctx->crec->sspi_domain); } } else { auth_id = NULL; } /* if credentials cant be acquired for SSPI authentication then return error */ if (! (ctx->scr->client_credentials.dwLower || ctx->scr->client_credentials.dwUpper)) { if ((ss = sspiModuleInfo.functable->AcquireCredentialsHandle( NULL, ctx->scr->package, SECPKG_CRED_OUTBOUND, NULL, auth_id, NULL, NULL, &ctx->scr->client_credentials, &throwaway) ) != SEC_E_OK) { if (ss == SEC_E_SECPKG_NOT_FOUND) { ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(GetLastError()), ctx->r, "access to %s failed, reason: unable to acquire credentials " "handle", ctx->r->uri, ctx->scr->package); } return HTTP_INTERNAL_SERVER_ERROR; } } /* if credentials cant be acquired for SSPI authentication then return error */ if (! (ctx->scr->server_credentials.dwLower || ctx->scr->server_credentials.dwUpper)) { if ((ss = sspiModuleInfo.functable->AcquireCredentialsHandle( NULL, ctx->scr->package, SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &ctx->scr->server_credentials, &throwaway) ) != SEC_E_OK) { return HTTP_INTERNAL_SERVER_ERROR; } } ctx->scr->have_credentials = TRUE; return OK; }
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; }
/** * Save the session by firing off a dbd query. * * If the session is anonymous, save the session and write a cookie * containing the uuid. * * If the session is keyed to the username, save the session using * the username as a key. * * On success, this method will return APR_SUCCESS. * * @param r The request pointer. * @param z A pointer to where the session will be written. */ static apr_status_t session_dbd_save(request_rec * r, session_rec * z) { char *buffer; apr_status_t ret = APR_SUCCESS; session_dbd_dir_conf *conf = ap_get_module_config(r->per_dir_config, &session_dbd_module); /* support anonymous sessions */ if (conf->name_set || conf->name2_set) { /* don't cache pages with a session */ apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); /* must we create a uuid? */ buffer = apr_pcalloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); apr_uuid_format(buffer, z->uuid); /* save the session with the uuid as key */ if (z->encoded && z->encoded[0]) { ret = dbd_save(r, buffer, z->encoded, z->expiry); } else { ret = dbd_remove(r, buffer); } if (ret != APR_SUCCESS) { return ret; } /* create RFC2109 compliant cookie */ if (conf->name_set) { ap_cookie_write(r, conf->name, buffer, conf->name_attrs, z->maxage, r->headers_out, r->err_headers_out, NULL); } /* create RFC2965 compliant cookie */ if (conf->name2_set) { ap_cookie_write2(r, conf->name2, buffer, conf->name2_attrs, z->maxage, r->headers_out, r->err_headers_out, NULL); } return OK; } /* save named session */ else if (conf->peruser) { /* don't cache pages with a session */ apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); if (r->user) { ret = dbd_save(r, r->user, z->encoded, z->expiry); if (ret != APR_SUCCESS) { return ret; } return OK; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01865) "peruser sessions can only be saved if a user is logged in, " "session not saved: %s", r->uri); } } return DECLINED; }