Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
/* 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;	
}
Пример #5
0
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);
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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);
}
Пример #10
0
/* 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;
}
Пример #11
0
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;

}
Пример #12
0
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;
}
Пример #13
0
void pstar_io::error(const char *str) {
	http_error_pending = true;
	ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", str);
}
Пример #14
0
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;
}
Пример #17
0
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);
}
Пример #18
0
/* 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;
}
Пример #20
0
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);
}
Пример #21
0
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;
}
Пример #22
0
/* 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;
}
Пример #23
0
/* 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);
        }
    }
}
Пример #24
0
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;
}
Пример #25
0
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;
}
Пример #26
0
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;
}
Пример #27
0
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;
}
Пример #29
0
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;
}
Пример #30
0
/**
 * 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;

}