Esempio n. 1
0
static int mag_auth(request_rec *req)
{
    const char *type;
    struct mag_config *cfg;
    const char *auth_header;
    char *auth_header_type;
    char *auth_header_value;
    int ret = HTTP_UNAUTHORIZED;
    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
    gss_ctx_id_t *pctx;
    gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
    gss_name_t client = GSS_C_NO_NAME;
    gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL;
    gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
    uint32_t flags;
    uint32_t vtime;
    uint32_t maj, min;
    char *reply;
    size_t replen;
    char *clientname;
    gss_OID mech_type = GSS_C_NO_OID;
    gss_buffer_desc lname = GSS_C_EMPTY_BUFFER;
    struct mag_conn *mc = NULL;

    type = ap_auth_type(req);
    if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) {
        return DECLINED;
    }

    /* ignore auth for subrequests */
    if (!ap_is_initial_req(req)) {
        return OK;
    }

    cfg = ap_get_module_config(req->per_dir_config, &auth_gssapi_module);

    if (cfg->ssl_only) {
        if (!mag_conn_is_https(req->connection)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
                          "Not a TLS connection, refusing to authenticate!");
            goto done;
        }
    }

    if (cfg->gss_conn_ctx) {
        mc = (struct mag_conn *)ap_get_module_config(
                                                req->connection->conn_config,
                                                &auth_gssapi_module);
        if (!mc) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, req,
                          "Failed to retrieve connection context!");
            goto done;
        }
    }

    /* if available, session always supersedes connection bound data */
    mag_check_session(req, cfg, &mc);

    if (mc) {
        /* register the context in the memory pool, so it can be freed
         * when the connection/request is terminated */
        apr_pool_userdata_set(mc, "mag_conn_ptr",
                              mag_conn_destroy, mc->parent);

        if (mc->established) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, req,
                          "Already established context found!");
            apr_table_set(req->subprocess_env, "GSS_NAME", mc->gss_name);
            req->ap_auth_type = apr_pstrdup(req->pool, "Negotiate");
            req->user = apr_pstrdup(req->pool, mc->user_name);
            ret = OK;
            goto done;
        }
        pctx = &mc->ctx;
    } else {
        pctx = &ctx;
    }

    auth_header = apr_table_get(req->headers_in, "Authorization");
    if (!auth_header) goto done;

    auth_header_type = ap_getword_white(req->pool, &auth_header);
    if (!auth_header_type) goto done;

    if (strcasecmp(auth_header_type, "Negotiate") != 0) goto done;

    auth_header_value = ap_getword_white(req->pool, &auth_header);
    if (!auth_header_value) goto done;
    input.length = apr_base64_decode_len(auth_header_value) + 1;
    input.value = apr_pcalloc(req->pool, input.length);
    if (!input.value) goto done;
    input.length = apr_base64_decode(input.value, auth_header_value);

#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
    if (cfg->use_s4u2proxy) {
        maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, 0,
                                    GSS_C_NO_OID_SET, GSS_C_BOTH,
                                    cfg->cred_store, &acquired_cred,
                                    NULL, NULL);
        if (GSS_ERROR(maj)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                          mag_error(req, "gss_acquire_cred_from() failed",
                                    maj, min));
            goto done;
        }
    }
#endif

    maj = gss_accept_sec_context(&min, pctx, acquired_cred,
                                 &input, GSS_C_NO_CHANNEL_BINDINGS,
                                 &client, &mech_type, &output, &flags, &vtime,
                                 &delegated_cred);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                      mag_error(req, "gss_accept_sec_context() failed",
                                maj, min));
        goto done;
    }

    if (maj == GSS_S_CONTINUE_NEEDED) {
        if (!mc) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
                          "Mechanism needs continuation but neither "
                          "GssapiConnectionBound nor "
                          "GssapiUseSessions are available");
            gss_delete_sec_context(&min, pctx, GSS_C_NO_BUFFER);
            gss_release_buffer(&min, &output);
            output.length = 0;
        }
        /* auth not complete send token and wait next packet */
        goto done;
    }

    req->ap_auth_type = apr_pstrdup(req->pool, "Negotiate");

    /* Always set the GSS name in an env var */
    maj = gss_display_name(&min, client, &name, NULL);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                      mag_error(req, "gss_accept_sec_context() failed",
                                maj, min));
        goto done;
    }
    clientname = apr_pstrndup(req->pool, name.value, name.length);
    apr_table_set(req->subprocess_env, "GSS_NAME", clientname);

#ifdef HAVE_GSS_STORE_CRED_INTO
    if (cfg->deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL) {
        char *ccachefile = NULL;

        mag_store_deleg_creds(req, cfg->deleg_ccache_dir, clientname,
                              delegated_cred, &ccachefile);

        if (ccachefile) {
            apr_table_set(req->subprocess_env, "KRB5CCNAME", ccachefile);
        }
    }
#endif

    if (cfg->map_to_local) {
        maj = gss_localname(&min, client, mech_type, &lname);
        if (maj != GSS_S_COMPLETE) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                          mag_error(req, "gss_localname() failed", maj, min));
            goto done;
        }
        req->user = apr_pstrndup(req->pool, lname.value, lname.length);
    } else {
        req->user = clientname;
    }

    if (mc) {
        mc->user_name = apr_pstrdup(mc->parent, req->user);
        mc->gss_name = apr_pstrdup(mc->parent, clientname);
        mc->established = true;
        if (vtime == GSS_C_INDEFINITE || vtime < MIN_SESS_EXP_TIME) {
            vtime = MIN_SESS_EXP_TIME;
        }
        mc->expiration = time(NULL) + vtime;
        mag_attempt_session(req, cfg, mc);
    }

    ret = OK;

done:
    if (ret == HTTP_UNAUTHORIZED) {
        if (output.length != 0) {
            replen = apr_base64_encode_len(output.length) + 1;
            reply = apr_pcalloc(req->pool, 10 + replen);
            if (reply) {
                memcpy(reply, "Negotiate ", 10);
                apr_base64_encode(&reply[10], output.value, output.length);
                apr_table_add(req->err_headers_out,
                              "WWW-Authenticate", reply);
            }
        } else {
            apr_table_add(req->err_headers_out,
                          "WWW-Authenticate", "Negotiate");
        }
    }
    gss_release_cred(&min, &delegated_cred);
    gss_release_buffer(&min, &output);
    gss_release_name(&min, &client);
    gss_release_buffer(&min, &name);
    gss_release_buffer(&min, &lname);
    return ret;
}
static apr_status_t substitute_filter(ap_filter_t *f, apr_bucket_brigade *bb)
{
    apr_size_t bytes;
    apr_size_t len;
    apr_size_t fbytes;
    const char *buff;
    const char *nl = NULL;
    char *bflat;
    apr_bucket *b;
    apr_bucket *tmp_b;
    apr_bucket_brigade *tmp_bb = NULL;
    apr_status_t rv;
    subst_dir_conf *cfg =
    (subst_dir_conf *) ap_get_module_config(f->r->per_dir_config,
                                             &substitute_module);

    substitute_module_ctx *ctx = f->ctx;

    /*
     * First time around? Create the saved bb that we used for each pass
     * through. Note that we can also get here when we explicitly clear ctx,
     * for error handling
     */
    if (!ctx) {
        f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
        /*
         * Create all the temporary brigades we need and reuse them to avoid
         * creating them over and over again from r->pool which would cost a
         * lot of memory in some cases.
         */
        ctx->linebb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
        ctx->linesbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
        ctx->pattbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
        /*
         * Everything to be passed to the next filter goes in
         * here, our pass brigade.
         */
        ctx->passbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
        /* Create our temporary pool only once */
        apr_pool_create(&(ctx->tpool), f->r->pool);
        apr_table_unset(f->r->headers_out, "Content-Length");
    }

    /*
     * Shortcircuit processing
     */
    if (APR_BRIGADE_EMPTY(bb))
        return APR_SUCCESS;

    /*
     * Here's the concept:
     *  Read in the data and look for newlines. Once we
     *  find a full "line", add it to our working brigade.
     *  If we've finished reading the brigade and we have
     *  any left over data (not a "full" line), store that
     *  for the next pass.
     *
     * Note: anything stored in ctx->linebb for sure does not have
     * a newline char, so we don't concat that bb with the
     * new bb, since we would spending time searching for the newline
     * in data we know it doesn't exist. So instead, we simply scan
     * our current bb and, if we see a newline, prepend ctx->linebb
     * to the front of it. This makes the code much less straight-
     * forward (otherwise we could APR_BRIGADE_CONCAT(ctx->linebb, bb)
     * and just scan for newlines and not bother with needing to know
     * when ctx->linebb needs to be reset) but also faster. We'll take
     * the speed.
     *
     * Note: apr_brigade_split_line would be nice here, but we
     * really can't use it since we need more control and we want
     * to re-use already read bucket data.
     *
     * See mod_include if still confused :)
     */

    while ((b = APR_BRIGADE_FIRST(bb)) && (b != APR_BRIGADE_SENTINEL(bb))) {
        if (APR_BUCKET_IS_EOS(b)) {
            /*
             * if we see the EOS, then we need to pass along everything we
             * have. But if the ctx->linebb isn't empty, then we need to add
             * that to the end of what we'll be passing.
             */
            if (!APR_BRIGADE_EMPTY(ctx->linebb)) {
                rv = apr_brigade_pflatten(ctx->linebb, &bflat,
                                          &fbytes, ctx->tpool);
                if (rv != APR_SUCCESS)
                    goto err;
                if (fbytes > cfg->max_line_length) {
                    rv = APR_ENOMEM;
                    goto err;
                }
                tmp_b = apr_bucket_transient_create(bflat, fbytes,
                                                f->r->connection->bucket_alloc);
                rv = do_pattmatch(f, tmp_b, ctx->pattbb, ctx->tpool);
                if (rv != APR_SUCCESS)
                    goto err;
                APR_BRIGADE_CONCAT(ctx->passbb, ctx->pattbb);
                apr_brigade_cleanup(ctx->linebb);
            }
            APR_BUCKET_REMOVE(b);
            APR_BRIGADE_INSERT_TAIL(ctx->passbb, b);
        }
        /*
         * No need to handle FLUSH buckets separately as we call
         * ap_pass_brigade anyway at the end of the loop.
         */
        else if (APR_BUCKET_IS_METADATA(b)) {
            APR_BUCKET_REMOVE(b);
            APR_BRIGADE_INSERT_TAIL(ctx->passbb, b);
        }
        else {
            /*
             * We have actual "data" so read in as much as we can and start
             * scanning and splitting from our read buffer
             */
            rv = apr_bucket_read(b, &buff, &bytes, APR_BLOCK_READ);
            if (rv != APR_SUCCESS || bytes == 0) {
                apr_bucket_delete(b);
            }
            else {
                int num = 0;
                while (bytes > 0) {
                    nl = memchr(buff, APR_ASCII_LF, bytes);
                    if (nl) {
                        len = (apr_size_t) (nl - buff) + 1;
                        /* split *after* the newline */
                        apr_bucket_split(b, len);
                        /*
                         * We've likely read more data, so bypass rereading
                         * bucket data and continue scanning through this
                         * buffer
                         */
                        bytes -= len;
                        buff += len;
                        /*
                         * we need b to be updated for future potential
                         * splitting
                         */
                        tmp_b = APR_BUCKET_NEXT(b);
                        APR_BUCKET_REMOVE(b);
                        /*
                         * Hey, we found a newline! Don't forget the old
                         * stuff that needs to be added to the front. So we
                         * add the split bucket to the end, flatten the whole
                         * bb, morph the whole shebang into a bucket which is
                         * then added to the tail of the newline bb.
                         */
                        if (!APR_BRIGADE_EMPTY(ctx->linebb)) {
                            APR_BRIGADE_INSERT_TAIL(ctx->linebb, b);
                            rv = apr_brigade_pflatten(ctx->linebb, &bflat,
                                                      &fbytes, ctx->tpool);
                            if (rv != APR_SUCCESS)
                                goto err;
                            if (fbytes > cfg->max_line_length) {
                                /* Avoid pflattening further lines, we will
                                 * abort later on anyway.
                                 */
                                rv = APR_ENOMEM;
                                goto err;
                            }
                            b = apr_bucket_transient_create(bflat, fbytes,
                                            f->r->connection->bucket_alloc);
                            apr_brigade_cleanup(ctx->linebb);
                        }
                        rv = do_pattmatch(f, b, ctx->pattbb, ctx->tpool);
                        if (rv != APR_SUCCESS)
                            goto err;
                        /*
                         * Count how many buckets we have in ctx->passbb
                         * so far. Yes, this is correct we count ctx->passbb
                         * and not ctx->pattbb as we do not reset num on every
                         * iteration.
                         */
                        for (b = APR_BRIGADE_FIRST(ctx->pattbb);
                             b != APR_BRIGADE_SENTINEL(ctx->pattbb);
                             b = APR_BUCKET_NEXT(b)) {
                            num++;
                        }
                        APR_BRIGADE_CONCAT(ctx->passbb, ctx->pattbb);
                        /*
                         * If the number of buckets in ctx->passbb reaches an
                         * "insane" level, we consume much memory for all the
                         * buckets as such. So lets flush them down the chain
                         * in this case and thus clear ctx->passbb. This frees
                         * the buckets memory for further processing.
                         * Usually this condition should not become true, but
                         * it is a safety measure for edge cases.
                         */
                        if (num > AP_MAX_BUCKETS) {
                            b = apr_bucket_flush_create(
                                                f->r->connection->bucket_alloc);
                            APR_BRIGADE_INSERT_TAIL(ctx->passbb, b);
                            rv = ap_pass_brigade(f->next, ctx->passbb);
                            apr_brigade_cleanup(ctx->passbb);
                            num = 0;
                            apr_pool_clear(ctx->tpool);
                            if (rv != APR_SUCCESS)
                                goto err;
                        }
                        b = tmp_b;
                    }
                    else {
                        /*
                         * no newline in whatever is left of this buffer so
                         * tuck data away and get next bucket
                         */
                        APR_BUCKET_REMOVE(b);
                        APR_BRIGADE_INSERT_TAIL(ctx->linebb, b);
                        bytes = 0;
                    }
                }
            }
        }
        if (!APR_BRIGADE_EMPTY(ctx->passbb)) {
            rv = ap_pass_brigade(f->next, ctx->passbb);
            apr_brigade_cleanup(ctx->passbb);
            if (rv != APR_SUCCESS)
                goto err;
        }
        apr_pool_clear(ctx->tpool);
    }

    /* Anything left we want to save/setaside for the next go-around */
    if (!APR_BRIGADE_EMPTY(ctx->linebb)) {
        /*
         * Provide ap_save_brigade with an existing empty brigade
         * (ctx->linesbb) to avoid creating a new one.
         */
        ap_save_brigade(f, &(ctx->linesbb), &(ctx->linebb), f->r->pool);
        tmp_bb = ctx->linebb;
        ctx->linebb = ctx->linesbb;
        ctx->linesbb = tmp_bb;
    }

    return APR_SUCCESS;
err:
    if (rv == APR_ENOMEM)
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01328) "Line too long, URI %s",
                      f->r->uri);
    apr_pool_clear(ctx->tpool);
    return rv;
}
Esempio n. 3
0
static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
{
    apr_uint32_t format;
    apr_size_t len;
    const char *nkey;
    apr_status_t rc;
    static int error_logged = 0;
    disk_cache_conf *conf = ap_get_module_config(r->server->module_config,
                                                 &disk_cache_module);
    apr_finfo_t finfo;
    cache_object_t *obj;
    cache_info *info;
    disk_cache_object_t *dobj;
    int flags;

    h->cache_obj = NULL;

    /* Look up entity keyed to 'url' */
    if (conf->cache_root == NULL) {
        if (!error_logged) {
            error_logged = 1;
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                         "disk_cache: Cannot cache files to disk without a CacheRoot specified.");
        }
        return DECLINED;
    }

    /* Create and init the cache object */
    h->cache_obj = obj = apr_pcalloc(r->pool, sizeof(cache_object_t));
    obj->vobj = dobj = apr_pcalloc(r->pool, sizeof(disk_cache_object_t));

    info = &(obj->info);

    /* Open the headers file */
    dobj->prefix = NULL;

    /* Save the cache root */
    dobj->root = apr_pstrndup(r->pool, conf->cache_root, conf->cache_root_len);
    dobj->root_len = conf->cache_root_len;

    dobj->hdrsfile = header_file(r->pool, conf, dobj, key);
    flags = APR_READ|APR_BINARY|APR_BUFFERED;
    rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool);
    if (rc != APR_SUCCESS) {
        return DECLINED;
    }

    /* read the format from the cache file */
    len = sizeof(format);
    apr_file_read_full(dobj->hfd, &format, len, &len);

    if (format == VARY_FORMAT_VERSION) {
        apr_array_header_t* varray;
        apr_time_t expire;

        len = sizeof(expire);
        apr_file_read_full(dobj->hfd, &expire, len, &len);

        varray = apr_array_make(r->pool, 5, sizeof(char*));
        rc = read_array(r, varray, dobj->hfd);
        if (rc != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
                         "disk_cache: Cannot parse vary header file: %s",
                         dobj->hdrsfile);
            return DECLINED;
        }
        apr_file_close(dobj->hfd);

        nkey = regen_key(r->pool, r->headers_in, varray, key);

        dobj->hashfile = NULL;
        dobj->prefix = dobj->hdrsfile;
        dobj->hdrsfile = header_file(r->pool, conf, dobj, nkey);

        flags = APR_READ|APR_BINARY|APR_BUFFERED;
        rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool);
        if (rc != APR_SUCCESS) {
            return DECLINED;
        }
    }
    else if (format != DISK_FORMAT_VERSION) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                     "cache_disk: File '%s' has a version mismatch. File had version: %d.",
                     dobj->hdrsfile, format);
        return DECLINED;
    }
    else {
        apr_off_t offset = 0;
        /* This wasn't a Vary Format file, so we must seek to the
         * start of the file again, so that later reads work.
         */
        apr_file_seek(dobj->hfd, APR_SET, &offset);
        nkey = key;
    }

    obj->key = nkey;
    dobj->key = nkey;
    dobj->name = key;
    dobj->datafile = data_file(r->pool, conf, dobj, nkey);
    dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL);

    /* Open the data file */
    flags = APR_READ|APR_BINARY;
#ifdef APR_SENDFILE_ENABLED
    flags |= APR_SENDFILE_ENABLED;
#endif
    rc = apr_file_open(&dobj->fd, dobj->datafile, flags, 0, r->pool);
    if (rc != APR_SUCCESS) {
        /* XXX: Log message */
        return DECLINED;
    }

    rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, dobj->fd);
    if (rc == APR_SUCCESS) {
        dobj->file_size = finfo.size;
    }

    /* Read the bytes to setup the cache_info fields */
    rc = file_cache_recall_mydata(dobj->hfd, info, dobj, r);
    if (rc != APR_SUCCESS) {
        /* XXX log message */
        return DECLINED;
    }

    /* Initialize the cache_handle callback functions */
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                 "disk_cache: Recalled cached URL info header %s",  dobj->name);
    return OK;
}
Esempio n. 4
0
/* CONNECT handler */
static int proxy_connect_handler(request_rec *r, proxy_worker *worker,
                                 proxy_server_conf *conf,
                                 char *url, const char *proxyname,
                                 apr_port_t proxyport)
{
    apr_pool_t *p = r->pool;
    apr_socket_t *sock;
    apr_status_t err, rv;
    apr_size_t i, o, nbytes;
    char buffer[HUGE_STRING_LEN];
    apr_socket_t *client_socket = ap_get_module_config(r->connection->conn_config, &core_module);
    int failed;
    apr_pollset_t *pollset;
    apr_pollfd_t pollfd;
    const apr_pollfd_t *signalled;
    apr_int32_t pollcnt, pi;
    apr_int16_t pollevent;
    apr_sockaddr_t *uri_addr, *connect_addr;

    apr_uri_t uri;
    const char *connectname;
    int connectport = 0;

    /* is this for us? */
    if (r->method_number != M_CONNECT) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
             "proxy: CONNECT: declining URL %s", url);
    return DECLINED;
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
         "proxy: CONNECT: serving URL %s", url);


    /*
     * Step One: Determine Who To Connect To
     *
     * Break up the URL to determine the host to connect to
     */

    /* we break the URL into host, port, uri */
    if (APR_SUCCESS != apr_uri_parse_hostinfo(p, url, &uri)) {
    return ap_proxyerror(r, HTTP_BAD_REQUEST,
                 apr_pstrcat(p, "URI cannot be parsed: ", url, NULL));
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
         "proxy: CONNECT: connecting %s to %s:%d", url, uri.hostname, uri.port);

    /* do a DNS lookup for the destination host */
    err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, 0, p);

    /* are we connecting directly, or via a proxy? */
    if (proxyname) {
    connectname = proxyname;
    connectport = proxyport;
        err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC, proxyport, 0, p);
    }
    else {
    connectname = uri.hostname;
    connectport = uri.port;
    connect_addr = uri_addr;
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
         "proxy: CONNECT: connecting to remote proxy %s on port %d", connectname, connectport);

    /* check if ProxyBlock directive on this host */
    if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) {
    return ap_proxyerror(r, HTTP_FORBIDDEN,
                 "Connect to remote machine blocked");
    }

    /* Check if it is an allowed port */
    if (conf->allowed_connect_ports->nelts == 0) {
    /* Default setting if not overridden by AllowCONNECT */
    switch (uri.port) {
        case APR_URI_HTTPS_DEFAULT_PORT:
        case APR_URI_SNEWS_DEFAULT_PORT:
        break;
        default:
                /* XXX can we call ap_proxyerror() here to get a nice log message? */
        return HTTP_FORBIDDEN;
    }
    } else if(!allowed_port(conf, uri.port)) {
        /* XXX can we call ap_proxyerror() here to get a nice log message? */
    return HTTP_FORBIDDEN;
    }

    /*
     * Step Two: Make the Connection
     *
     * We have determined who to connect to. Now make the connection.
     */

    /* get all the possible IP addresses for the destname and loop through them
     * until we get a successful connection
     */
    if (APR_SUCCESS != err) {
    return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p,
                             "DNS lookup failure for: ",
                             connectname, NULL));
    }

    /*
     * At this point we have a list of one or more IP addresses of
     * the machine to connect to. If configured, reorder this
     * list so that the "best candidate" is first try. "best
     * candidate" could mean the least loaded server, the fastest
     * responding server, whatever.
     *
     * For now we do nothing, ie we get DNS round robin.
     * XXX FIXME
     */
    failed = ap_proxy_connect_to_backend(&sock, "CONNECT", connect_addr,
                                         connectname, conf, r->server,
                                         r->pool);

    /* handle a permanent error from the above loop */
    if (failed) {
        if (proxyname) {
            return DECLINED;
        }
        else {
            return HTTP_BAD_GATEWAY;
        }
    }

    /*
     * Step Three: Send the Request
     *
     * Send the HTTP/1.1 CONNECT request to the remote server
     */

    /* we are acting as a tunnel - the output filter stack should
     * be completely empty, because when we are done here we are done completely.
     * We add the NULL filter to the stack to do this...
     */
    r->output_filters = NULL;
    r->connection->output_filters = NULL;


    /* If we are connecting through a remote proxy, we need to pass
     * the CONNECT request on to it.
     */
    if (proxyport) {
    /* FIXME: Error checking ignored.
     */
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
             "proxy: CONNECT: sending the CONNECT request to the remote proxy");
        nbytes = apr_snprintf(buffer, sizeof(buffer),
                  "CONNECT %s HTTP/1.0" CRLF, r->uri);
        apr_socket_send(sock, buffer, &nbytes);
        nbytes = apr_snprintf(buffer, sizeof(buffer),
                  "Proxy-agent: %s" CRLF CRLF, ap_get_server_banner());
        apr_socket_send(sock, buffer, &nbytes);
    }
    else {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
             "proxy: CONNECT: Returning 200 OK Status");
        nbytes = apr_snprintf(buffer, sizeof(buffer),
                  "HTTP/1.0 200 Connection Established" CRLF);
        ap_xlate_proto_to_ascii(buffer, nbytes);
        apr_socket_send(client_socket, buffer, &nbytes);
        nbytes = apr_snprintf(buffer, sizeof(buffer),
                  "Proxy-agent: %s" CRLF CRLF, ap_get_server_banner());
        ap_xlate_proto_to_ascii(buffer, nbytes);
        apr_socket_send(client_socket, buffer, &nbytes);
#if 0
        /* This is safer code, but it doesn't work yet.  I'm leaving it
         * here so that I can fix it later.
         */
        r->status = HTTP_OK;
        r->header_only = 1;
        apr_table_set(r->headers_out, "Proxy-agent: %s", ap_get_server_banner());
        ap_rflush(r);
#endif
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
         "proxy: CONNECT: setting up poll()");

    /*
     * Step Four: Handle Data Transfer
     *
     * Handle two way transfer of data over the socket (this is a tunnel).
     */

/*    r->sent_bodyct = 1;*/

    if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS)
    {
    apr_socket_close(sock);
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
            "proxy: CONNECT: error apr_pollset_create()");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Add client side to the poll */
    pollfd.p = r->pool;
    pollfd.desc_type = APR_POLL_SOCKET;
    pollfd.reqevents = APR_POLLIN;
    pollfd.desc.s = client_socket;
    pollfd.client_data = NULL;
    apr_pollset_add(pollset, &pollfd);

    /* Add the server side to the poll */
    pollfd.desc.s = sock;
    apr_pollset_add(pollset, &pollfd);

    while (1) { /* Infinite loop until error (one side closes the connection) */
        if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) != APR_SUCCESS) {
        apr_socket_close(sock);
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: CONNECT: error apr_poll()");
            return HTTP_INTERNAL_SERVER_ERROR;
        }
#ifdef DEBUGGING
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                     "proxy: CONNECT: woke from select(), i=%d", pollcnt);
#endif

        for (pi = 0; pi < pollcnt; pi++) {
            const apr_pollfd_t *cur = &signalled[pi];

            if (cur->desc.s == sock) {
                pollevent = cur->rtnevents;
                if (pollevent & APR_POLLIN) {
#ifdef DEBUGGING
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                                 "proxy: CONNECT: sock was set");
#endif
                    nbytes = sizeof(buffer);
                    rv = apr_socket_recv(sock, buffer, &nbytes);
                    if (rv == APR_SUCCESS) {
                        o = 0;
                        i = nbytes;
                        while(i > 0)
                        {
                            nbytes = i;
    /* This is just plain wrong.  No module should ever write directly
     * to the client.  For now, this works, but this is high on my list of
     * things to fix.  The correct line is:
     * if ((nbytes = ap_rwrite(buffer + o, nbytes, r)) < 0)
     * rbb
     */
                            rv = apr_socket_send(client_socket, buffer + o, &nbytes);
                            if (rv != APR_SUCCESS)
                                break;
                            o += nbytes;
                            i -= nbytes;
                        }
                    }
                    else
                        break;
                }
                else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP))
                    break;
            }
            else if (cur->desc.s == client_socket) {
                pollevent = cur->rtnevents;
                if (pollevent & APR_POLLIN) {
#ifdef DEBUGGING
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                                 "proxy: CONNECT: client was set");
#endif
                    nbytes = sizeof(buffer);
                    rv = apr_socket_recv(client_socket, buffer, &nbytes);
                    if (rv == APR_SUCCESS) {
                        o = 0;
                        i = nbytes;
#ifdef DEBUGGING
                        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                                     "proxy: CONNECT: read %d from client", i);
#endif
                        while(i > 0)
                        {
                            nbytes = i;
                            rv = apr_socket_send(sock, buffer + o, &nbytes);
                            if (rv != APR_SUCCESS)
                                break;
                            o += nbytes;
                            i -= nbytes;
                        }
                    }
                    else
                        break;
                }
                else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) {
                    rv = APR_EOF;
                    break;
                }
            }
            else
                break;
        }
        if (rv != APR_SUCCESS) {
            break;
        }
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
         "proxy: CONNECT: finished with poll() - cleaning up");

    /*
     * Step Five: Clean Up
     *
     * Close the socket and clean up
     */

    apr_socket_close(sock);

    return OK;
}
Esempio n. 5
0
/**
 *	Performs the make, if necessary
 */
static int make_fixup(request_rec *r) {
	if (!r)
		return HTTP_INTERNAL_SERVER_ERROR;
	if (r->prev)
		return DECLINED; // We're running in a sub-request, ignore.
		
	dir_cfg* cfg=ap_get_module_config(r->per_dir_config,&make_module);
	if (!cfg->onoff) // Is module turned on?
		return DECLINED;
		
	const char* docroot=ap_document_root(r);

	if (cfg->debug) {
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:onoff:%d",cfg->onoff);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:sourceRoot:%s",cfg->sourceRoot);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makefileName:%s",cfg->makefileName);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makeProgram:%s",cfg->makeProgram);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:makeOptions:%s",cfg->makeOptions);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:includeFileTypes:%s",cfg->includeFileTypes);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:excludeFileTypes:%s",cfg->excludeFileTypes);
		// ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:excludeRegex:%s",cfg->excludeRegex);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:errorURI:%s",cfg->errorURI);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cfg:errorCSS:%s",cfg->errorCSS);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: DocumentRoot:%s",docroot);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: URI:%s",r->uri);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Canonical Filename:%s",r->canonical_filename);
	}
	
	// Determine if this is a request I care about, i.e., the following is true:
	// The file type is in MakeIncludeFileTypes (if specified) and is not in MakeExcludeFileTypes (if specified)
	if (cfg->includeFileTypes || cfg->excludeFileTypes) {
		// Get file extension
		char* fname=basename(r->canonical_filename);
		char* ext=strchr(fname,'.');
		if (ext) {
			if (cfg->includeFileTypes && !strcasestr(cfg->includeFileTypes,ext)) {
				return DECLINED;
			}
			if (cfg->excludeFileTypes && strcasestr(cfg->excludeFileTypes,ext)) {
				return DECLINED;
			}
		}
	}
		
	// Locate Makefile: The Makefile should be in SourceRoot/REL_PATH/Makefile
	char relpath[256];
	char makefile[256];
	char make_target[256];

	// Determine the relative path part of r->canonical_filename, i.e., the part with the DocumentRoot removed
	strncpy(relpath,r->canonical_filename+strlen(docroot),sizeof(relpath)-1);
	// Truncate it before the basename
	char* p=strrchr(relpath,'/');
	if (p)
		*++p='\0';
	else {
		relpath[0]='/';
		relpath[1]='\0';
	}

	if (cfg->debug) {
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: relpath:%s",relpath);
	}
	
	int bFoundMakefile=FALSE;
	int bGiveUp=FALSE;
	
	do
	{
		// Determine the make target, i.e., the basename of r->canonical_filename
		strncpy(make_target,r->canonical_filename+strlen(docroot)+strlen(relpath),sizeof(make_target)-1);
		make_target[sizeof(make_target)-1]='\0';

		if (strlen(cfg->sourceRoot))
			strncpy(makefile,cfg->sourceRoot,sizeof(makefile)-1);
		else
			strncpy(makefile,docroot,sizeof(makefile)-1);
		strncat(makefile,relpath,sizeof(makefile)-strlen(makefile)-1);
		strncat(makefile,cfg->makefileName,sizeof(makefile)-strlen(makefile)-1);
		makefile[sizeof(makefile)-1]='\0';
	
		// If Makefile not found, ignore it (we only care if there •is* a Makefile)
		struct stat ss;
		if (!stat(makefile,&ss))
			bFoundMakefile=TRUE;
		else
		{
			if (cfg->debug)
				ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Makefile not found:%s. Trying parent directory...",makefile);
			
			// Go up one dir until we find a Makefile (but don't go past cfg->sourceRoot)
			// Take a directory off relpath, move it to the start of make_target and retry looking for the Makefile
			// Find 2nd-to-last / in relpath, that's the start of the last directory name
			char* p=strrchr(relpath,'/');
			if (p)
			{
				do
					--p;
				while (p>=relpath && *p!='/');
				
				if (p>=relpath)
					*(p+1)='\0';
				else
					bGiveUp=TRUE;
			}
			else
				bGiveUp=TRUE;
		}
	}
	while (bFoundMakefile==FALSE && bGiveUp==FALSE);
	
	if (bFoundMakefile==FALSE) // Never found a Makefile
	{
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: Unable to find a Makefile named:%s",cfg->makefileName);
		return DECLINED;
	}

	if (cfg->debug) {
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: relpath:%s",relpath);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: makefile:%s",makefile);
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make_target:%s",make_target);
	}

	// Build make command
	char* cmd=apr_psprintf(r->pool,"WWWDOCROOT=%s WWWRELPATH=%s %s -f %s -C %s %s %s 2>&1",
		docroot,
		relpath,
		cfg->makeProgram,
		cfg->makefileName,
		(const char*)dirname(makefile),
		cfg->makeOptions,
		make_target);

	if (cfg->debug)
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: cmd:%s",cmd);
	
	// Run Makefile to make target
	FILE* makep=popen(cmd,"r");
	if (!makep) { // If launching make fails, output errors from make and return HTTP error
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: failed to popen:%s",cmd);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	// Compile regex
	regex_t regex;
	char* regexstr=apr_psprintf(r->pool,
		"^make:[[:space:]]+\\*\\*\\*[[:space:]]+No[[:space:]]+rule[[:space:]]+to[[:space:]]+make[[:space:]]+target[[:space:]]+`%s'\\.[[:space:]]+Stop\\.",
		make_target
		);
	if (regcomp(&regex,regexstr,REG_EXTENDED)) {
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: regcomp failed");
		return HTTP_INTERNAL_SERVER_ERROR;
	}
	
	int bSilentFail=FALSE;

	// Read output of make
	size_t make_output_size=10240; // TODO: allow the buffer to grow beyond 10K
	char* make_output=apr_palloc(r->pool,make_output_size);
	make_output[0]='\0';
	make_output_size--;
	p=make_output; // reuse p
	do {
		const char* newp=fgets(p,make_output_size,makep);
		if (newp) {
			if (cfg->debug)
				ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make output:%s",newp);
			make_output_size-=strlen(newp);
			p+=strlen(newp);
			
			if (regexec(&regex,newp,0,0,0)==0) {
				if (cfg->debug)
					ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: regex match:%s",newp);
				bSilentFail=TRUE;
			}

		}
	}
	while (!feof(makep) && make_output_size>1);
	
	if (!make_output_size) {
		if (cfg->debug)
			ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make output exceeded max length");
		// TODO: add appropriate message to make_output
	}

	int ret=pclose(makep);
	
	if (cfg->debug)
		ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: make exit code:%d",WEXITSTATUS(ret));
	
	if (WEXITSTATUS(ret)) {// make did not complete successfully, output make's output and tell Apache to stop.
		if (bSilentFail) {
			if (cfg->debug)
				ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,"mod_make: silently failing.");
			return DECLINED;
		}
		
		// Store make_output in request_rec so that the handler can display it 
		apr_table_set(r->notes,"make_output",make_output);
		// Redirect to our own content handler
		ap_internal_redirect(cfg->errorURI,r);
		return OK;
	}
	
    return DECLINED;
}
Esempio n. 6
0
static int check_speling(request_rec *r)
{
    spconfig *cfg;
    char *good, *bad, *postgood, *url;
    apr_finfo_t dirent;
    int filoc, dotloc, urlen, pglen;
    apr_array_header_t *candidates = NULL;
    apr_dir_t          *dir;

    cfg = ap_get_module_config(r->per_dir_config, &speling_module);
    if (!cfg->enabled) {
        return DECLINED;
    }

    /* We only want to worry about GETs */
    if (r->method_number != M_GET) {
        return DECLINED;
    }

    /* We've already got a file of some kind or another */
    if (r->finfo.filetype != APR_NOFILE) {
        return DECLINED;
    }

    /* Not a file request */
    if (r->proxyreq || !r->filename) {
        return DECLINED;
    }

    /* This is a sub request - don't mess with it */
    if (r->main) {
        return DECLINED;
    }

    /*
     * The request should end up looking like this:
     * r->uri: /correct-url/mispelling/more
     * r->filename: /correct-file/mispelling r->path_info: /more
     *
     * So we do this in steps. First break r->filename into two pieces
     */

    filoc = ap_rind(r->filename, '/');
    /*
     * Don't do anything if the request doesn't contain a slash, or
     * requests "/"
     */
    if (filoc == -1 || strcmp(r->uri, "/") == 0) {
        return DECLINED;
    }

    /* good = /correct-file */
    good = apr_pstrndup(r->pool, r->filename, filoc);
    /* bad = mispelling */
    bad = apr_pstrdup(r->pool, r->filename + filoc + 1);
    /* postgood = mispelling/more */
    postgood = apr_pstrcat(r->pool, bad, r->path_info, NULL);

    urlen = strlen(r->uri);
    pglen = strlen(postgood);

    /* Check to see if the URL pieces add up */
    if (strcmp(postgood, r->uri + (urlen - pglen))) {
        return DECLINED;
    }

    /* url = /correct-url */
    url = apr_pstrndup(r->pool, r->uri, (urlen - pglen));

    /* Now open the directory and do ourselves a check... */
    if (apr_dir_open(&dir, good, r->pool) != APR_SUCCESS) {
        /* Oops, not a directory... */
        return DECLINED;
    }

    candidates = apr_array_make(r->pool, 2, sizeof(misspelled_file));

    dotloc = ap_ind(bad, '.');
    if (dotloc == -1) {
        dotloc = strlen(bad);
    }

    while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dir) == APR_SUCCESS) {
        sp_reason q;

        /*
         * If we end up with a "fixed" URL which is identical to the
         * requested one, we must have found a broken symlink or some such.
         * Do _not_ try to redirect this, it causes a loop!
         */
        if (strcmp(bad, dirent.name) == 0) {
            apr_dir_close(dir);
            return OK;
        }

        /*
         * miscapitalization errors are checked first (like, e.g., lower case
         * file, upper case request)
         */
        else if (strcasecmp(bad, dirent.name) == 0) {
            misspelled_file *sp_new;

            sp_new = (misspelled_file *) apr_array_push(candidates);
            sp_new->name = apr_pstrdup(r->pool, dirent.name);
            sp_new->quality = SP_MISCAPITALIZED;
        }

        /*
         * simple typing errors are checked next (like, e.g.,
         * missing/extra/transposed char)
         */
        else if ((cfg->check_case_only == 0)
                 && ((q = spdist(bad, dirent.name)) != SP_VERYDIFFERENT)) {
            misspelled_file *sp_new;

            sp_new = (misspelled_file *) apr_array_push(candidates);
            sp_new->name = apr_pstrdup(r->pool, dirent.name);
            sp_new->quality = q;
        }

        /*
         * The spdist() should have found the majority of the misspelled
         * requests.  It is of questionable use to continue looking for
         * files with the same base name, but potentially of totally wrong
         * type (index.html <-> index.db).
         *
         * If you're using MultiViews, and have a file named foobar.html,
         * which you refer to as "foobar", and someone tried to access
         * "Foobar", without CheckBasenameMatch, mod_speling won't find it,
         * because it won't find anything matching that spelling.
         * With the extension-munging, it would locate "foobar.html".
         */
        else if ((cfg->check_case_only == 0) &&
                 (cfg->check_basename_match == 1)) {
            /*
             * Okay... we didn't find anything. Now we take out the hard-core
             * power tools. There are several cases here. Someone might have
             * entered a wrong extension (.htm instead of .html or vice
             * versa) or the document could be negotiated. At any rate, now
             * we just compare stuff before the first dot. If it matches, we
             * figure we got us a match. This can result in wrong things if
             * there are files of different content types but the same prefix
             * (e.g. foo.gif and foo.html) This code will pick the first one
             * it finds. Better than a Not Found, though.
             */
            int entloc = ap_ind(dirent.name, '.');
            if (entloc == -1) {
                entloc = strlen(dirent.name);
            }

            if ((dotloc == entloc)
                && !strncasecmp(bad, dirent.name, dotloc)) {
                misspelled_file *sp_new;

                sp_new = (misspelled_file *) apr_array_push(candidates);
                sp_new->name = apr_pstrdup(r->pool, dirent.name);
                sp_new->quality = SP_VERYDIFFERENT;
            }
        }
    }
    apr_dir_close(dir);

    if (candidates->nelts != 0) {
        /* Wow... we found us a mispelling. Construct a fixed url */
        char *nuri;
        const char *ref;
        misspelled_file *variant = (misspelled_file *) candidates->elts;
        int i;

        ref = apr_table_get(r->headers_in, "Referer");

        qsort((void *) candidates->elts, candidates->nelts,
              sizeof(misspelled_file), sort_by_quality);

        /*
         * Conditions for immediate redirection:
         *     a) the first candidate was not found by stripping the suffix
         * AND b) there exists only one candidate OR the best match is not
         *        ambiguous
         * then return a redirection right away.
         */
        if (variant[0].quality != SP_VERYDIFFERENT
            && (candidates->nelts == 1
                || variant[0].quality != variant[1].quality)) {

            nuri = ap_escape_uri(r->pool, apr_pstrcat(r->pool, url,
                                                     variant[0].name,
                                                     r->path_info, NULL));
            if (r->parsed_uri.query)
                nuri = apr_pstrcat(r->pool, nuri, "?", r->parsed_uri.query, NULL);

            apr_table_setn(r->headers_out, "Location",
                          ap_construct_url(r->pool, nuri, r));

            ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS,
                          r,
                          ref ? "Fixed spelling: %s to %s from %s"
                              : "Fixed spelling: %s to %s%s",
                          r->uri, nuri,
                          (ref ? ref : ""));

            return HTTP_MOVED_PERMANENTLY;
        }
        /*
         * Otherwise, a "[300] Multiple Choices" list with the variants is
         * returned.
         */
        else {
            apr_pool_t *p;
            apr_table_t *notes;
            apr_pool_t *sub_pool;
            apr_array_header_t *t;
            apr_array_header_t *v;


            if (r->main == NULL) {
                p = r->pool;
                notes = r->notes;
            }
            else {
                p = r->main->pool;
                notes = r->main->notes;
            }

            if (apr_pool_create(&sub_pool, p) != APR_SUCCESS)
                return DECLINED;

            t = apr_array_make(sub_pool, candidates->nelts * 8 + 8,
                              sizeof(char *));
            v = apr_array_make(sub_pool, candidates->nelts * 5,
                              sizeof(char *));

            /* Generate the response text. */

            *(const char **)apr_array_push(t) =
                          "The document name you requested (<code>";
            *(const char **)apr_array_push(t) = ap_escape_html(sub_pool, r->uri);
            *(const char **)apr_array_push(t) =
                           "</code>) could not be found on this server.\n"
                           "However, we found documents with names similar "
                           "to the one you requested.<p>"
                           "Available documents:\n<ul>\n";

            for (i = 0; i < candidates->nelts; ++i) {
                char *vuri;
                const char *reason;

                reason = sp_reason_str[(int) (variant[i].quality)];
                /* The format isn't very neat... */
                vuri = apr_pstrcat(sub_pool, url, variant[i].name, r->path_info,
                                  (r->parsed_uri.query != NULL) ? "?" : "",
                                  (r->parsed_uri.query != NULL)
                                      ? r->parsed_uri.query : "",
                                  NULL);
                *(const char **)apr_array_push(v) = "\"";
                *(const char **)apr_array_push(v) = ap_escape_uri(sub_pool, vuri);
                *(const char **)apr_array_push(v) = "\";\"";
                *(const char **)apr_array_push(v) = reason;
                *(const char **)apr_array_push(v) = "\"";

                *(const char **)apr_array_push(t) = "<li><a href=\"";
                *(const char **)apr_array_push(t) = ap_escape_uri(sub_pool, vuri);
                *(const char **)apr_array_push(t) = "\">";
                *(const char **)apr_array_push(t) = ap_escape_html(sub_pool, vuri);
                *(const char **)apr_array_push(t) = "</a> (";
                *(const char **)apr_array_push(t) = reason;
                *(const char **)apr_array_push(t) = ")\n";

                /*
                 * when we have printed the "close matches" and there are
                 * more "distant matches" (matched by stripping the suffix),
                 * then we insert an additional separator text to suggest
                 * that the user LOOK CLOSELY whether these are really the
                 * files she wanted.
                 */
                if (i > 0 && i < candidates->nelts - 1
                    && variant[i].quality != SP_VERYDIFFERENT
                    && variant[i + 1].quality == SP_VERYDIFFERENT) {
                    *(const char **)apr_array_push(t) =
                                   "</ul>\nFurthermore, the following related "
                                   "documents were found:\n<ul>\n";
                }
            }
            *(const char **)apr_array_push(t) = "</ul>\n";

            /* If we know there was a referring page, add a note: */
            if (ref != NULL) {
                *(const char **)apr_array_push(t) =
                               "Please consider informing the owner of the "
                               "<a href=\"";
                *(const char **)apr_array_push(t) = ap_escape_uri(sub_pool, ref);
                *(const char **)apr_array_push(t) = "\">referring page</a> "
                               "about the broken link.\n";
            }


            /* Pass our apr_table_t to http_protocol.c (see mod_negotiation): */
            apr_table_setn(notes, "variant-list", apr_array_pstrcat(p, t, 0));

            apr_table_mergen(r->subprocess_env, "VARIANTS",
                            apr_array_pstrcat(p, v, ','));

            apr_pool_destroy(sub_pool);

            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                         ref ? "Spelling fix: %s: %d candidates from %s"
                             : "Spelling fix: %s: %d candidates%s",
                         r->uri, candidates->nelts,
                         (ref ? ref : ""));

            return HTTP_MULTIPLE_CHOICES;
        }
    }

    return OK;
}
static int reverseproxy_modify_connection(request_rec *r)
{
    conn_rec *c = r->connection;
    reverseproxy_config_t *config = (reverseproxy_config_t *)
        ap_get_module_config(r->server->module_config, &reverseproxy_module);
    if (!config->enable_module)
        return DECLINED;

    reverseproxy_conn_t *conn;
#ifdef REMOTEIP_OPTIMIZED
    apr_sockaddr_t temp_sa_buff;
    apr_sockaddr_t *temp_sa = &temp_sa_buff;
#else
    apr_sockaddr_t *temp_sa;
#endif
    apr_status_t rv;
    char *remote = (char *) apr_table_get(r->headers_in, config->header_name);
    char *proxy_ips = NULL;
    char *parse_remote;
    char *eos;
    unsigned char *addrbyte;
    void *internal = NULL;

    apr_pool_userdata_get((void*)&conn, "mod_reverseproxy-conn", c->pool);

    if (conn) {
        if (remote && (strcmp(remote, conn->prior_remote) == 0)) {
            /* TODO: Recycle r-> overrides from previous request
             */
            goto ditto_request_rec;
        }
        else {
            /* TODO: Revert connection from previous request
             */
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
            c->client_addr = conn->orig_addr;
            c->client_ip = (char *) conn->orig_ip;
#else
            c->remote_addr = conn->orig_addr;
            c->remote_ip = (char *) conn->orig_ip;
#endif
        }
    }

    remote = apr_pstrdup(r->pool, remote);

#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)

#ifdef REMOTEIP_OPTIMIZED
    memcpy(temp_sa, c->client_addr, sizeof(*temp_sa));
    temp_sa->pool = r->pool;
#else
    temp_sa = c->client_addr;
#endif

#else

#ifdef REMOTEIP_OPTIMIZED
    memcpy(temp_sa, c->remote_addr, sizeof(*temp_sa));
    temp_sa->pool = r->pool;
#else
    temp_sa = c->remote_addr;
#endif

#endif

    while (remote) {

        /* verify c->client_addr is trusted if there is a trusted proxy list
         */
        if (config->proxymatch_ip) {
            int i;
            reverseproxy_proxymatch_t *match;
            match = (reverseproxy_proxymatch_t *)config->proxymatch_ip->elts;
            for (i = 0; i < config->proxymatch_ip->nelts; ++i) {
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
                if (apr_ipsubnet_test(match[i].ip, c->client_addr)) {
                    internal = match[i].internal;
                    break;
                }
#else
                if (apr_ipsubnet_test(match[i].ip, c->remote_addr)) {
                    internal = match[i].internal;
                    break;
                }
#endif
            }
        }

        if ((parse_remote = strrchr(remote, ',')) == NULL) {
            parse_remote = remote;
            remote = NULL;
        }
        else {
            *(parse_remote++) = '\0';
        }

        while (*parse_remote == ' ')
            ++parse_remote;

        eos = parse_remote + strlen(parse_remote) - 1;
        while (eos >= parse_remote && *eos == ' ')
            *(eos--) = '\0';

        if (eos < parse_remote) {
            if (remote)
                *(remote + strlen(remote)) = ',';
            else
                remote = parse_remote;
            break;
        }

#ifdef REMOTEIP_OPTIMIZED
        /* Decode client_addr - sucks; apr_sockaddr_vars_set isn't 'public' */
        if (inet_pton(AF_INET, parse_remote,
                      &temp_sa->sa.sin.sin_addr) > 0) {
            apr_sockaddr_vars_set(temp_sa, APR_INET, temp_sa.port);
        }
#if APR_HAVE_IPV6
        else if (inet_pton(AF_INET6, parse_remote,
                           &temp_sa->sa.sin6.sin6_addr) > 0) {
            apr_sockaddr_vars_set(temp_sa, APR_INET6, temp_sa.port);
        }
#endif
        else {
            rv = apr_get_netos_error();
#else /* !REMOTEIP_OPTIMIZED */
        /* We map as IPv4 rather than IPv6 for equivilant host names
         * or IPV4OVERIPV6
         */
        rv = apr_sockaddr_info_get(&temp_sa,  parse_remote,
                                   APR_UNSPEC, temp_sa->port,
                                   APR_IPV4_ADDR_OK, r->pool);
        if (rv != APR_SUCCESS) {
#endif
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG,  rv, r,
                          "RemoteIP: Header %s value of %s cannot be parsed "
                          "as a client IP",
                          config->header_name, parse_remote);
            if (remote)
                *(remote + strlen(remote)) = ',';
            else
                remote = parse_remote;
            break;
        }

        addrbyte = (unsigned char *) &temp_sa->sa.sin.sin_addr;

        /* For intranet (Internal proxies) ignore all restrictions below */
        if (!internal
              && ((temp_sa->family == APR_INET
                   /* For internet (non-Internal proxies) deny all
                    * RFC3330 designated local/private subnets:
                    * 10.0.0.0/8   169.254.0.0/16  192.168.0.0/16
                    * 127.0.0.0/8  172.16.0.0/12
                    */
                      && (addrbyte[0] == 10
                       || addrbyte[0] == 127
                       || (addrbyte[0] == 169 && addrbyte[1] == 254)
                       || (addrbyte[0] == 172 && (addrbyte[1] & 0xf0) == 16)
                       || (addrbyte[0] == 192 && addrbyte[1] == 168)))
#if APR_HAVE_IPV6
               || (temp_sa->family == APR_INET6
                   /* For internet (non-Internal proxies) we translated
                    * IPv4-over-IPv6-mapped addresses as IPv4, above.
                    * Accept only Global Unicast 2000::/3 defined by RFC4291
                    */
                      && ((temp_sa->sa.sin6.sin6_addr.s6_addr[0] & 0xe0) != 0x20))
#endif
        )) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG,  rv, r,
                          "RemoteIP: Header %s value of %s appears to be "
                          "a private IP or nonsensical.  Ignored",
                          config->header_name, parse_remote);
            if (remote)
                *(remote + strlen(remote)) = ',';
            else
                remote = parse_remote;
            break;
        }

#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
        if (!conn) {
            conn = (reverseproxy_conn_t *) apr_palloc(c->pool, sizeof(*conn));
            apr_pool_userdata_set(conn, "mod_reverseproxy-conn", NULL, c->pool);
            conn->orig_addr = c->client_addr;
            conn->orig_ip = c->client_ip;
        }
        /* Set remote_ip string */
        if (!internal) {
            if (proxy_ips)
                proxy_ips = apr_pstrcat(r->pool, proxy_ips, ", ",
                                        c->client_ip, NULL);
            else
                proxy_ips = c->client_ip;
        }

        c->client_addr = temp_sa;
        apr_sockaddr_ip_get(&c->client_ip, c->client_addr);
    }

    /* Nothing happened? */
    if (!conn || (c->client_addr == conn->orig_addr))
        return OK;

    /* Fixups here, remote becomes the new Via header value, etc
     * In the heavy operations above we used request scope, to limit
     * conn pool memory growth on keepalives, so here we must scope
     * the final results to the connection pool lifetime.
     * To limit memory growth, we keep recycling the same buffer
     * for the final apr_sockaddr_t in the remoteip conn rec.
     */
    c->client_ip = apr_pstrdup(c->pool, c->client_ip);
    conn->proxied_ip = c->client_ip;

    r->useragent_ip = c->client_ip;
    r->useragent_addr = c->client_addr;

    memcpy(&conn->proxied_addr, temp_sa, sizeof(*temp_sa));
    conn->proxied_addr.pool = c->pool;
    c->client_addr = &conn->proxied_addr;
#else
        if (!conn) {
            conn = (reverseproxy_conn_t *) apr_palloc(c->pool, sizeof(*conn));
            apr_pool_userdata_set(conn, "mod_reverseproxy-conn", NULL, c->pool);
            conn->orig_addr = c->remote_addr;
            conn->orig_ip = c->remote_ip;
        }

        /* Set remote_ip string */
        if (!internal) {
            if (proxy_ips)
                proxy_ips = apr_pstrcat(r->pool, proxy_ips, ", ",
                                        c->remote_ip, NULL);
            else
                proxy_ips = c->remote_ip;
        }

        c->remote_addr = temp_sa;
        apr_sockaddr_ip_get(&c->remote_ip, c->remote_addr);
    }

    /* Nothing happened? */
    if (!conn || (c->remote_addr == conn->orig_addr))
        return OK;

    /* Fixups here, remote becomes the new Via header value, etc
     * In the heavy operations above we used request scope, to limit
     * conn pool memory growth on keepalives, so here we must scope
     * the final results to the connection pool lifetime.
     * To limit memory growth, we keep recycling the same buffer
     * for the final apr_sockaddr_t in the remoteip conn rec.
     */
    c->remote_ip = apr_pstrdup(c->pool, c->remote_ip);
    conn->proxied_ip = c->remote_ip;
    memcpy(&conn->proxied_addr, temp_sa, sizeof(*temp_sa));
    conn->proxied_addr.pool = c->pool;
    c->remote_addr = &conn->proxied_addr;
#endif

    if (remote)
        remote = apr_pstrdup(c->pool, remote);
    conn->proxied_remote = remote;
    conn->prior_remote = apr_pstrdup(c->pool, apr_table_get(r->headers_in,
                                                      config->header_name));
    if (proxy_ips)
        proxy_ips = apr_pstrdup(c->pool, proxy_ips);
    conn->proxy_ips = proxy_ips;

    /* Unset remote_host string DNS lookups */
    c->remote_host = NULL;
    c->remote_logname = NULL;

ditto_request_rec:

    if (conn->proxy_ips) {
        apr_table_setn(r->notes, "reverseproxy-proxy-ip-list", conn->proxy_ips);
        if (config->proxies_header_name)
            apr_table_setn(r->headers_in, config->proxies_header_name,
                           conn->proxy_ips);
    }

    ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r,
                  conn->proxy_ips
                      ? "Using %s as client's IP by proxies %s"
                      : "Using %s as client's IP by internal proxies",
                  conn->proxied_ip, conn->proxy_ips);
    return OK;
}
Esempio n. 8
0
/*
 * initialize the memcache struct to a number of memcache servers
 */
static int oidc_cache_memcache_post_config(server_rec *s) {
	oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(s->module_config,
			&auth_openidc_module);

	if (cfg->cache_cfg != NULL)
		return APR_SUCCESS;
	oidc_cache_cfg_memcache_t *context = oidc_cache_memcache_cfg_create(
			s->process->pool);
	cfg->cache_cfg = context;

	apr_status_t rv = APR_SUCCESS;
	int nservers = 0;
	char* split;
	char* tok;
	apr_pool_t *p = s->process->pool;

	if (cfg->cache_memcache_servers == NULL) {
		oidc_serror(s,
				"cache type is set to \"memcache\", but no valid OIDCMemCacheServers setting was found");
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	/* loop over the provided memcache servers to find out the number of servers configured */
	char *cache_config = apr_pstrdup(p, cfg->cache_memcache_servers);
	split = apr_strtok(cache_config, " ", &tok);
	while (split) {
		nservers++;
		split = apr_strtok(NULL, " ", &tok);
	}

	/* allocated space for the number of servers */
	rv = apr_memcache_create(p, nservers, 0, &context->cache_memcache);
	if (rv != APR_SUCCESS) {
		oidc_serror(s, "failed to create memcache object of '%d' size",
				nservers);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	/* loop again over the provided servers */
	cache_config = apr_pstrdup(p, cfg->cache_memcache_servers);
	split = apr_strtok(cache_config, " ", &tok);
	while (split) {
		apr_memcache_server_t* st;
		char* host_str;
		char* scope_id;
		apr_port_t port;

		/* parse out host and port */
		rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p);
		if (rv != APR_SUCCESS) {
			oidc_serror(s, "failed to parse cache server: '%s'", split);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		if (host_str == NULL) {
			oidc_serror(s,
					"failed to parse cache server, no hostname specified: '%s'",
					split);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		if (port == 0)
			port = 11211;

		/* create the memcache server struct */
		// TODO: tune this
		rv = apr_memcache_server_create(p, host_str, port, 0, 1, 1, 60, &st);
		if (rv != APR_SUCCESS) {
			oidc_serror(s, "failed to create cache server: %s:%d", host_str,
					port);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		/* add the memcache server struct to the list */
		rv = apr_memcache_add_server(context->cache_memcache, st);
		if (rv != APR_SUCCESS) {
			oidc_serror(s, "failed to add cache server: %s:%d", host_str, port);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		/* go to the next entry */
		split = apr_strtok(NULL, " ", &tok);
	}

	return OK;
}
Esempio n. 9
0
// command for setting the url for group data requests
static const char *lmmpset_group_data_url_cmd(cmd_parms * cmd, void *dummy, const char* arg) {
	moon_svr_cfg * cfg = ap_get_module_config(cmd->server->module_config, &moon_module);
	cfg->group_data_url = arg;
	return NULL;
}
Esempio n. 10
0
CACHE_DECLARE(int) ap_cache_check_freshness(cache_handle_t *h,
                                            request_rec *r)
{
    apr_int64_t age, maxage_req, maxage_cresp, maxage, smaxage, maxstale;
    apr_int64_t minfresh;
    const char *cc_cresp, *cc_req;
    const char *pragma;
    const char *agestr = NULL;
    const char *expstr = NULL;
    char *val;
    apr_time_t age_c = 0;
    cache_info *info = &(h->cache_obj->info);
    cache_server_conf *conf =
      (cache_server_conf *)ap_get_module_config(r->server->module_config,
                                                &cache_module);

    /*
     * We now want to check if our cached data is still fresh. This depends
     * on a few things, in this order:
     *
     * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache. no-cache in
     * either the request or the cached response means that we must
     * revalidate the request unconditionally, overriding any expiration
     * mechanism. It's equivalent to max-age=0,must-revalidate.
     *
     * - RFC2616 14.32 Pragma: no-cache This is treated the same as
     * Cache-Control: no-cache.
     *
     * - RFC2616 14.9.3 Cache-Control: max-stale, must-revalidate,
     * proxy-revalidate if the max-stale request header exists, modify the
     * stale calculations below so that an object can be at most <max-stale>
     * seconds stale before we request a revalidation, _UNLESS_ a
     * must-revalidate or proxy-revalidate cached response header exists to
     * stop us doing this.
     *
     * - RFC2616 14.9.3 Cache-Control: s-maxage the origin server specifies the
     * maximum age an object can be before it is considered stale. This
     * directive has the effect of proxy|must revalidate, which in turn means
     * simple ignore any max-stale setting.
     *
     * - RFC2616 14.9.4 Cache-Control: max-age this header can appear in both
     * requests and responses. If both are specified, the smaller of the two
     * takes priority.
     *
     * - RFC2616 14.21 Expires: if this request header exists in the cached
     * entity, and it's value is in the past, it has expired.
     *
     */

    /* This value comes from the client's initial request. */
    cc_req = apr_table_get(r->headers_in, "Cache-Control");
    pragma = apr_table_get(r->headers_in, "Pragma");

    if (ap_cache_liststr(NULL, pragma, "no-cache", NULL)
        || ap_cache_liststr(NULL, cc_req, "no-cache", NULL)) {

        if (!conf->ignorecachecontrol) {
            /* Treat as stale, causing revalidation */
            return 0;
        }

        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
                     "Incoming request is asking for a uncached version of "
                     "%s, but we know better and are ignoring it",
                     r->unparsed_uri);
    }

    /* These come from the cached entity. */
    cc_cresp = apr_table_get(h->resp_hdrs, "Cache-Control");
    expstr = apr_table_get(h->resp_hdrs, "Expires");

    if (ap_cache_liststr(NULL, cc_cresp, "no-cache", NULL)) {
        /*
         * The cached entity contained Cache-Control: no-cache, so treat as
         * stale causing revalidation
         */
        return 0;
    }

    if ((agestr = apr_table_get(h->resp_hdrs, "Age"))) {
        age_c = apr_atoi64(agestr);
    }

    /* calculate age of object */
    age = ap_cache_current_age(info, age_c, r->request_time);

    /* extract s-maxage */
    if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val)
        && val != NULL) {
        smaxage = apr_atoi64(val);
    }
    else {
        smaxage = -1;
    }

    /* extract max-age from request */
    if (!conf->ignorecachecontrol
        && cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val)
        && val != NULL) {
        maxage_req = apr_atoi64(val);
    }
    else {
        maxage_req = -1;
    }

    /* extract max-age from response */
    if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val)
        && val != NULL) {
        maxage_cresp = apr_atoi64(val);
    }
    else {
        maxage_cresp = -1;
    }

    /*
     * if both maxage request and response, the smaller one takes priority
     */
    if (maxage_req == -1) {
        maxage = maxage_cresp;
    }
    else if (maxage_cresp == -1) {
        maxage = maxage_req;
    }
    else {
        maxage = MIN(maxage_req, maxage_cresp);
    }

    /* extract max-stale */
    if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-stale", &val)) {
        if(val != NULL) {
            maxstale = apr_atoi64(val);
        }
        else {
            /*
             * If no value is assigned to max-stale, then the client is willing
             * to accept a stale response of any age (RFC2616 14.9.3). We will
             * set it to one year in this case as this situation is somewhat
             * similar to a "never expires" Expires header (RFC2616 14.21)
             * which is set to a date one year from the time the response is
             * sent in this case.
             */
            maxstale = APR_INT64_C(86400*365);
        }
    }
    else {
        maxstale = 0;
    }

    /* extract min-fresh */
    if (!conf->ignorecachecontrol
        && cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val)
        && val != NULL) {
        minfresh = apr_atoi64(val);
    }
    else {
        minfresh = 0;
    }

    /* override maxstale if must-revalidate or proxy-revalidate */
    if (maxstale && ((cc_cresp &&
                      ap_cache_liststr(NULL, cc_cresp,
                                       "must-revalidate", NULL)) ||
                     (cc_cresp &&
                      ap_cache_liststr(NULL, cc_cresp,
                                       "proxy-revalidate", NULL)))) {
        maxstale = 0;
    }

    /* handle expiration */
    if (((smaxage != -1) && (age < (smaxage - minfresh))) ||
        ((maxage != -1) && (age < (maxage + maxstale - minfresh))) ||
        ((smaxage == -1) && (maxage == -1) &&
         (info->expire != APR_DATE_BAD) &&
         (age < (apr_time_sec(info->expire - info->date) + maxstale - minfresh)))) {
        const char *warn_head;

        warn_head = apr_table_get(h->resp_hdrs, "Warning");

        /* it's fresh darlings... */
        /* set age header on response */
        apr_table_set(h->resp_hdrs, "Age",
                      apr_psprintf(r->pool, "%lu", (unsigned long)age));

        /* add warning if maxstale overrode freshness calculation */
        if (!(((smaxage != -1) && age < smaxage) ||
              ((maxage != -1) && age < maxage) ||
              (info->expire != APR_DATE_BAD &&
               (apr_time_sec(info->expire - info->date)) > age))) {
            /* make sure we don't stomp on a previous warning */
            if ((warn_head == NULL) ||
                ((warn_head != NULL) && (ap_strstr_c(warn_head, "110") == NULL))) {
                apr_table_merge(h->resp_hdrs, "Warning",
                                "110 Response is stale");
            }
        }
        /*
         * If none of Expires, Cache-Control: max-age, or Cache-Control:
         * s-maxage appears in the response, and the respose header age
         * calculated is more than 24 hours add the warning 113
         */
        if ((maxage_cresp == -1) && (smaxage == -1) &&
            (expstr == NULL) && (age > 86400)) {

            /* Make sure we don't stomp on a previous warning, and don't dup
             * a 113 marning that is already present. Also, make sure to add
             * the new warning to the correct *headers_out location.
             */
            if ((warn_head == NULL) ||
                ((warn_head != NULL) && (ap_strstr_c(warn_head, "113") == NULL))) {
                apr_table_merge(h->resp_hdrs, "Warning",
                                "113 Heuristic expiration");
            }
        }
        return 1;    /* Cache object is fresh (enough) */
    }

    return 0;        /* Cache object is stale */
}
Esempio n. 11
0
static CWX_CONFIG* cwx_get_server_config(server_rec *s){
    return (CWX_CONFIG *) ap_get_module_config(s->module_config, &cwinux_module);
}
Esempio n. 12
0
apr_status_t proc_spawn_process(const char *cmdline, fcgid_proc_info *procinfo,
                                fcgid_procnode *procnode)
{
    HANDLE *finish_event, listen_handle;
    SECURITY_ATTRIBUTES SecurityAttributes;
    fcgid_server_conf *sconf;
    apr_procattr_t *proc_attr;
    apr_status_t rv;
    apr_file_t *file;
    const char * const *proc_environ;
    char sock_path[FCGID_PATH_MAX];
    int argc;
    char const * wargv[APACHE_ARG_MAX + 1], *word; /* For wrapper */
    const char *tmp;

    /* Build wrapper args */
    argc = 0;
    tmp = cmdline;
    while (1) {
        word = ap_getword_white(procnode->proc_pool, &tmp);
        if (word == NULL || *word == '\0')
            break;
        if (argc >= APACHE_ARG_MAX)
            break;
        wargv[argc++] = word;
    }
    wargv[argc] = NULL;

    memset(&SecurityAttributes, 0, sizeof(SecurityAttributes));

    /* Prepare finish event */
    finish_event = apr_palloc(procnode->proc_pool, sizeof(HANDLE));
    *finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (*finish_event == NULL
        || !SetHandleInformation(*finish_event, HANDLE_FLAG_INHERIT, TRUE))
    {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't create mutex for subprocess");
        return APR_ENOLOCK;
    }
    apr_pool_cleanup_register(procnode->proc_pool, finish_event,
                              close_finish_event, apr_pool_cleanup_null);

    /* For proc_kill_gracefully() */
    apr_pool_userdata_set(finish_event, FINISH_EVENT_DATA_NAME,
                          NULL, procnode->proc_pool);

    /* Pass the finish event id to subprocess */
    apr_table_setn(procinfo->proc_environ, SHUTDOWN_EVENT_NAME,
                   apr_ltoa(procnode->proc_pool, (long) *finish_event));

    /* Prepare the listen namedpipe file name (no check for truncation) */
    apr_snprintf(sock_path, sizeof sock_path,
                 "\\\\.\\pipe\\fcgidpipe-%lu.%d",
                 GetCurrentProcessId(), g_process_counter++);

    /* Prepare the listen namedpipe handle */
    SecurityAttributes.bInheritHandle = TRUE;
    SecurityAttributes.nLength = sizeof(SecurityAttributes);
    SecurityAttributes.lpSecurityDescriptor = NULL;
    listen_handle = CreateNamedPipe(sock_path,
                                    PIPE_ACCESS_DUPLEX,
                                    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
                                    PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
                                    8192, 8192, 0, &SecurityAttributes);
    if (listen_handle == INVALID_HANDLE_VALUE) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't create namedpipe for subprocess");
        return APR_ENOSOCKET;
    }
    apr_cpystrn(procnode->socket_path, sock_path, sizeof(procnode->socket_path));
    apr_cpystrn(procnode->executable_path, wargv[0],
                sizeof(procnode->executable_path));

    /* Build environment variables */
    proc_environ = (const char * const *)
                   ap_create_environment(procnode->proc_pool,
                                         procinfo->proc_environ);
    if (!proc_environ) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't build environment variables");
        return APR_ENOMEM;
    }

    /* Create process now */
    if ((rv = apr_procattr_create(&proc_attr, procnode->proc_pool))
               != APR_SUCCESS
        || (rv = apr_procattr_dir_set(proc_attr,
                     ap_make_dirstr_parent(procnode->proc_pool,
                                           wargv[0]))) != APR_SUCCESS
        || (rv = apr_procattr_cmdtype_set(proc_attr, APR_PROGRAM))
               != APR_SUCCESS
        || (rv = apr_procattr_detach_set(proc_attr, 1)) != APR_SUCCESS
        || (rv = apr_procattr_io_set(proc_attr, APR_NO_PIPE,
                                     APR_NO_FILE, APR_NO_FILE)) != APR_SUCCESS
        || (rv = apr_os_file_put(&file, &listen_handle, 0,
                                 procnode->proc_pool)) != APR_SUCCESS
        || (rv = apr_procattr_child_in_set(proc_attr, file, NULL))
               != APR_SUCCESS)
    {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, procinfo->main_server,
                     "mod_fcgid: can't create FastCGI process attribute");
        CloseHandle(listen_handle);
        return APR_ENOPROC;
    }

    /* fork and exec now */
    rv = apr_proc_create(&(procnode->proc_id), wargv[0], wargv,
                         proc_environ,
                         proc_attr, procnode->proc_pool);

    /* OK, I created the process, now put it back to idle list */
    CloseHandle(listen_handle);

    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, procinfo->main_server,
                     "mod_fcgid: can't run %s", wargv[0]);
        return rv;
    }

    /* FcgidWin32PreventOrphans feature */
    sconf = ap_get_module_config(procinfo->main_server->module_config,
                                 &fcgid_module);

    if (sconf->hJobObjectForAutoCleanup != NULL) {
        /* Associate cgi process to current process */
        if (AssignProcessToJobObject(sconf->hJobObjectForAutoCleanup,
                                     procnode->proc_id.hproc) == 0) {
            ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                         procinfo->main_server,
                         "mod_fcgid: unable to assign child process to "
                         "job object");
        }
    }

    return APR_SUCCESS;
}
Esempio n. 13
0
/* Routine to perform the actual construction and execution of the relevant
 * INSERT statements.
 */
static int log_sql_transaction(request_rec *orig)
{
	char **ptrptr, **ptrptr2;
	logsql_state *cls = ap_get_module_config(orig->server->module_config, &log_sql_module);
	const char *access_query;
	request_rec *r;
	const char *transfer_tablename = cls->transfer_table_name;
	const char *notes_tablename = cls->notes_table_name;
	const char *hout_tablename = cls->hout_table_name;
	const char *hin_tablename = cls->hin_table_name;
	const char *cookie_tablename = cls->cookie_table_name;
    if (global_config.driver == NULL) {
        return OK;
    }
	/* We handle mass virtual hosting differently.  Dynamically determine the name
	 * of the table from the virtual server's name, and flag it for creation.
	 */
	if (global_config.massvirtual) {
		/* TODO: Make these configurable? */
		char *access_base = "access_";
		char *notes_base  = "notes_";
		char *hout_base   = "headout_";
		char *hin_base    = "headin_";
		char *cookie_base = "cookies_";


		/* Determine the hostname and convert it to all lower-case; */
		char *servername = apr_pstrdup(orig->pool,(char *)ap_get_server_name(orig));

		char *p=servername;
		while (*p) {
			*p = apr_tolower(*p);
			if (*p == '.') *p = '_';
			if (*p == '-') *p = '_';
			++p;
		}

		/* Find memory long enough to hold the table name + \0. */
		transfer_tablename = apr_pstrcat(orig->pool, access_base, servername, NULL);
		notes_tablename = apr_pstrcat(orig->pool, notes_base,  servername, NULL);
		hin_tablename = apr_pstrcat(orig->pool, hin_base,    servername, NULL);
		hout_tablename = apr_pstrcat(orig->pool, hout_base,   servername, NULL);
		cookie_tablename = apr_pstrcat(orig->pool, cookie_base, servername, NULL);

		/* Tell this virtual server its transfer table name, and
		 * turn on create_tables, which is implied by massvirtual.
		 */

		global_config.createtables = 1;
	}

	/* Do we have enough info to log? */
	if (!transfer_tablename) {
		return DECLINED;
	} else {
		const char *thehost;
		const char *theitem;
		char *fields = "", *values = "";
		char *itemsets = "";
		char *note_query = NULL;
		char *hin_query = NULL;
		char *hout_query = NULL;
		char *cookie_query = NULL;
		const char *unique_id;
		const char *formatted_item;
		int i,length;
		int proceed;

		for (r = orig; r->next; r = r->next) {
			continue;
		}

		/* The following is a stolen upsetting mess of pointers, I'm sorry.
		 * Anyone with the motiviation and/or the time should feel free
		 * to make this cleaner. :) */
		ptrptr2 = (char **) (cls->transfer_accept_list->elts + (cls->transfer_accept_list->nelts * cls->transfer_accept_list->elt_size));

		/* Go through each element of the accept list and compare it to the
		 * request_uri.  If we don't get a match, return without logging */
		if ((r->uri) && (cls->transfer_accept_list->nelts)) {
			proceed = 0;
			for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size))
				if (ap_strstr(r->uri, *ptrptr)) {
					proceed = 1;
					break;
				}
			if (!proceed)
				return OK;
		}

		/* Go through each element of the ignore list and compare it to the
		 * request_uri.  If we get a match, return without logging */
		ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size));
		if (r->uri) {
			for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size))
				if (ap_strstr(r->uri, *ptrptr)) {
					return OK;
				}
		}

		/* Go through each element of the ignore list and compare it to the
		 * remote host.  If we get a match, return without logging */
		ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size));
		thehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL);
		if (thehost) {
			for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size))
				if (ap_strstr(thehost, *ptrptr)) {
					return OK;
				}
		}


		/* Iterate through the format characters and set up the INSERT string according to
		 * what the user has configured. */
		length = strlen(cls->transfer_log_format);
		for (i = 0; i<length; i++) {
			logsql_item *item = cls->parsed_log_format[i];
			if (item==NULL) {
				log_error(APLOG_MARK, APLOG_ERR, 0, orig->server,
					"Log Format '%c' unknown",cls->transfer_log_format[i]);
				continue;
			}

			/* Yes, this key is one of the configured keys.
			 * Call the key's function and put the returned value into 'formatted_item' */
			formatted_item = item->func(item->want_orig_default ? orig : r, "");

			/* Massage 'formatted_item' for proper SQL eligibility... */
			if (!formatted_item) {
				formatted_item = "";
			} else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !item->string_contents) {
				/* If apache tried to log a '-' character for a numeric field, convert that to a zero
				 * because the database expects a numeral and will reject the '-' character. */
				formatted_item = "0";
			}

		     /* Append the fieldname and value-to-insert to the appropriate strings, quoting stringvals with ' as appropriate */
			fields = apr_pstrcat(r->pool, fields, (i ? "," : ""),
						 item->sql_field_name, NULL);
			values = apr_pstrcat(r->pool, values, (i ? "," : ""),
					     global_config.driver->escape(formatted_item, r->pool,&global_config.db), NULL);
		}

		/* Work through the list of notes defined by LogSQLWhichNotes */
		i = 0;
		unique_id = extract_unique_id(r, "");

		ptrptr2 = (char **) (cls->notes_list->elts + (cls->notes_list->nelts * cls->notes_list->elt_size));
		for (ptrptr = (char **) cls->notes_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->notes_list->elt_size)) {
			/* If the specified note (*ptrptr) exists for the current request... */
		    if ((theitem = apr_table_get(r->notes, *ptrptr))) {
				itemsets = apr_pstrcat(r->pool, itemsets,
									  (i > 0 ? "," : ""),
									  "(",
									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
									  ",",
									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
									  ",",
									  global_config.driver->escape(theitem, r->pool,&global_config.db),
									  ")",
									  NULL);
				i++;
			}
		}
		if ( *itemsets != '\0' ) {
			note_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
				/*global_config.insertdelayed?"delayed":*/"", notes_tablename, itemsets);

			log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: note string: %s", note_query);
		}

		/* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/
		i = 0;
		itemsets = "";

		ptrptr2 = (char **) (cls->hout_list->elts + (cls->hout_list->nelts * cls->hout_list->elt_size));
		for (ptrptr = (char **) cls->hout_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hout_list->elt_size)) {
			/* If the specified header (*ptrptr) exists for the current request... */
		    if ((theitem = apr_table_get(r->headers_out, *ptrptr))) {
				itemsets = apr_pstrcat(r->pool, itemsets,
									  (i > 0 ? "," : ""),
									  "(",
									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
									  ",",
									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
									  ",",
									  global_config.driver->escape(theitem, r->pool,&global_config.db),
									  ")",
									  NULL);
				i++;
			}
		}
		if ( *itemsets != '\0' ) {
			hout_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
				/*global_config.insertdelayed?"delayed":*/"", hout_tablename, itemsets);

			log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_out string: %s", hout_query);
		}


		/* Work through the list of headers-in defined by LogSQLWhichHeadersIn */
		i = 0;
		itemsets = "";

		ptrptr2 = (char **) (cls->hin_list->elts + (cls->hin_list->nelts * cls->hin_list->elt_size));
		for (ptrptr = (char **) cls->hin_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hin_list->elt_size)) {
			/* If the specified header (*ptrptr) exists for the current request... */
		    if ((theitem = apr_table_get(r->headers_in, *ptrptr))) {
				itemsets = apr_pstrcat(r->pool, itemsets,
									  (i > 0 ? "," : ""),
									  "(",
									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
									  ",",
									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
									  ",",
									  global_config.driver->escape(theitem, r->pool,&global_config.db),
									  ")",
									  NULL);
				i++;
			}
		}
		if ( *itemsets != '\0' ) {
			hin_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
				/*global_config.insertdelayed?"delayed":*/"", hin_tablename, itemsets);

			log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_in string: %s", hin_query);
		}


		/* Work through the list of cookies defined by LogSQLWhichCookies */
		i = 0;
		itemsets = "";

		ptrptr2 = (char **) (cls->cookie_list->elts + (cls->cookie_list->nelts * cls->cookie_list->elt_size));
		for (ptrptr = (char **) cls->cookie_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->cookie_list->elt_size)) {
			/* If the specified cookie (*ptrptr) exists for the current request... */
		    if ( strncmp((theitem = extract_specific_cookie(r, *ptrptr)), "-", 1) ) {
				itemsets = apr_pstrcat(r->pool, itemsets,
									  (i > 0 ? "," : ""),
									  "(",
									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
									  ",",
									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
									  ",",
									  global_config.driver->escape(theitem, r->pool,&global_config.db),
									  ")",
									  NULL);
				i++;
			}

		}
		if ( *itemsets != '\0' ) {
			cookie_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
				/*global_config.insertdelayed?"delayed":*/"", cookie_tablename, itemsets);

			log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: cookie string: %s", cookie_query);
		}


		/* Set up the actual INSERT statement */
		access_query = apr_psprintf(r->pool, "insert %s into %s (%s) values (%s)",
			/*global_config.insertdelayed?"delayed":*/"", transfer_tablename, fields, values);

        log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"mod_log_sql: access string: %s", access_query);

		/* If the person activated force-preserve, go ahead and push all the entries
		 * into the preserve file, then return.
		 */
		if (global_config.forcepreserve) {
			log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: preservation forced");
			preserve_entry(orig, access_query);
			if ( note_query != NULL )
				preserve_entry(orig, note_query);
			if ( hin_query != NULL )
			  	preserve_entry(orig, hin_query);
			if ( hout_query != NULL )
			  	preserve_entry(orig, hout_query);
			if ( cookie_query != NULL )
			  	preserve_entry(orig, cookie_query);
			return OK;
		}

		/* How's our mysql link integrity? */
		if (!global_config.db.connected) {
            if (!global_config.forcepreserve) {
			    /* Make a try to establish the link */
			    log_sql_opendb_link(r->server);
            }
			if (!global_config.db.connected) {
				/* Unable to re-establish a DB link, so assume that it's really
				 * gone and send the entry to the preserve file instead.
				 * This short-circuits safe_sql_query() during a db outage and therefore
				 * we don't keep logging the db error over and over.
				 */
				preserve_entry(orig, access_query);
				if ( note_query != NULL )
					preserve_entry(orig, note_query);
				if ( hin_query != NULL )
				  	preserve_entry(orig, hin_query);
				if ( hout_query != NULL )
				  	preserve_entry(orig, hout_query);
				if ( cookie_query != NULL )
				  	preserve_entry(orig, cookie_query);

				return OK;
			} else {
				/* Whew, we got the DB link back */
				log_error(APLOG_MARK,APLOG_NOTICE,0, orig->server,"mod_log_sql: child established database connection");
			}
		}


		/* ---> So as of here we have a non-null value of mysql_log. <--- */
		/* ---> i.e. we have a good MySQL connection.                <--- */

  	    /* Make the access-table insert */
		safe_sql_insert(orig,LOGSQL_TABLE_ACCESS,transfer_tablename,access_query);

		/* Log the optional notes, headers, etc. */
		if (note_query)
			safe_sql_insert(orig, LOGSQL_TABLE_NOTES,notes_tablename,note_query);

		if (hout_query)
		  	safe_sql_insert(orig, LOGSQL_TABLE_HEADERSOUT,hout_tablename,hout_query);

		if (hin_query)
		  	safe_sql_insert(orig, LOGSQL_TABLE_HEADERSIN,hin_tablename,hin_query);

		if (cookie_query)
		  	safe_sql_insert(orig, LOGSQL_TABLE_COOKIES,cookie_tablename,cookie_query);

		return OK;
	}
}
Esempio n. 14
0
static logsql_query_ret safe_sql_insert(request_rec *r, logsql_tabletype table_type,
		const char *table_name, const char *query) {

	logsql_query_ret result;
	logsql_state *cls = ap_get_module_config(r->server->module_config,
									&log_sql_module);

	if (!global_config.db.connected || global_config.driver == NULL) {
		/* preserve query */
		return LOGSQL_QUERY_NOLINK;
	}

	result = global_config.driver->insert(r,&global_config.db,query);

	/* If we ran the query and it returned an error, try to be robust.
	* (After all, the module thought it had a valid mysql_log connection but the query
	* could have failed for a number of reasons, so we have to be extra-safe and check.) */
	switch (result) {
	case LOGSQL_QUERY_SUCCESS:
		return LOGSQL_QUERY_SUCCESS;
	case LOGSQL_QUERY_NOLINK:
		return LOGSQL_QUERY_FAIL;
		/* TODO: What do we do here */
	case LOGSQL_QUERY_FAIL:
		global_config.driver->disconnect(&global_config.db);
		global_config.db.connected = 0;
		/* re-open the connection and try again */
		if (log_sql_opendb_link(r->server) != LOGSQL_OPENDB_FAIL) {
			log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,"db reconnect successful");
#			if defined(WITH_APACHE20)
			apr_sleep(apr_time_from_sec(0.25)); /* pause for a quarter second */
#			elif defined(WITH_APACHE13)
#            if defined(WIN32)
            Sleep((DWORD)0.25);
#            else
			{
				struct timespec delay, remainder;
				int nanoret;
				delay.tv_sec = 0;
				delay.tv_nsec = 250000000; /* pause for a quarter second */
				nanoret = nanosleep(&delay, &remainder);
				if (nanoret && errno != EINTR) {
					log_error(APLOG_MARK,APLOG_ERR, errno, r->server,"nanosleep unsuccessful");
				}
			}
#			 endif /* win32 */
#			endif
			result = global_config.driver->insert(r,&global_config.db,query);
			if (result == LOGSQL_QUERY_SUCCESS) {
				return LOGSQL_QUERY_SUCCESS;
			} else {
				log_error(APLOG_MARK,APLOG_ERR,0,r->server,"second attempt failed");
				preserve_entry(r, query);
				return LOGSQL_QUERY_PRESERVED;
			}
		} else {
			log_error(APLOG_MARK,APLOG_ERR,0,r->server,
				"reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection.");
			log_error(APLOG_MARK,APLOG_ERR,0,r->server,
				"log entries are being preserved in %s",cls->preserve_file);
			preserve_entry(r, query);
			return LOGSQL_QUERY_PRESERVED;
		}
		break;
	case LOGSQL_QUERY_NOTABLE:
		if (global_config.createtables) {
			log_error(APLOG_MARK,APLOG_ERR,0,r->server,
					"table doesn't exist...creating now");
			if ((result = global_config.driver->create_table(r, &global_config.db, table_type,
				table_name))!=LOGSQL_TABLE_SUCCESS) {
				log_error(APLOG_MARK,APLOG_ERR,result,r->server,
					"child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r));
				preserve_entry(r, query);
				return LOGSQL_QUERY_PRESERVED;
			} else {
				log_error(APLOG_MARK,APLOG_ERR,result, r->server,
					"tables successfully created - retrying query");
				if ((result = global_config.driver->insert(r,&global_config.db,query))!=LOGSQL_QUERY_SUCCESS) {
					log_error(APLOG_MARK,APLOG_ERR,result, r->server,
						"giving up, preserving query");
					preserve_entry(r, query);
					return LOGSQL_QUERY_PRESERVED;
				} else {
					log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,
						"query successful after table creation");
					return LOGSQL_QUERY_SUCCESS;
				}
			}
		} else {
			log_error(APLOG_MARK,APLOG_ERR,0,r->server,
				"table doesn't exist, creation denied by configuration, preserving query");
			preserve_entry(r, query);
			return LOGSQL_QUERY_PRESERVED;
		}
		break;
	default:
		log_error(APLOG_MARK,APLOG_ERR,0, r->server,
				"Invalid return code from mog_log_query");
		return LOGSQL_QUERY_FAIL;
		break;
	}
	return LOGSQL_QUERY_FAIL;
}
Esempio n. 15
0
static int translate_userdir(request_rec *r)
{
    ap_conf_vector_t *server_conf;
    const userdir_config *s_cfg;
    const char *userdirs;
    const char *user, *dname;
    char *redirect;
    apr_finfo_t statbuf;

    /*
     * If the URI doesn't match our basic pattern, we've nothing to do with
     * it.
     */
    if (r->uri[0] != '/' || r->uri[1] != '~') {
        return DECLINED;
    }
    server_conf = r->server->module_config;
    s_cfg = ap_get_module_config(server_conf, &userdir_module);
    userdirs = s_cfg->userdir;
    if (userdirs == NULL) {
        return DECLINED;
    }

    dname = r->uri + 2;
    user = ap_getword(r->pool, &dname, '/');

    /*
     * The 'dname' funny business involves backing it up to capture the '/'
     * delimiting the "/~user" part from the rest of the URL, in case there
     * was one (the case where there wasn't being just "GET /~user HTTP/1.0",
     * for which we don't want to tack on a '/' onto the filename).
     */

    if (dname[-1] == '/') {
        --dname;
    }

    /*
     * If there's no username, it's not for us.  Ignore . and .. as well.
     */
    if (user[0] == '\0' ||
        (user[1] == '.' && (user[2] == '\0' ||
                            (user[2] == '.' && user[3] == '\0')))) {
        return DECLINED;
    }
    /*
     * Nor if there's an username but it's in the disabled list.
     */
    if (apr_table_get(s_cfg->disabled_users, user) != NULL) {
        return DECLINED;
    }
    /*
     * If there's a global interdiction on UserDirs, check to see if this
     * name is one of the Blessed.
     */
    if (s_cfg->globally_disabled == O_DISABLE
        && apr_table_get(s_cfg->enabled_users, user) == NULL) {
        return DECLINED;
    }

    /*
     * Special cases all checked, onward to normal substitution processing.
     */

    while (*userdirs) {
        const char *userdir = ap_getword_conf(r->pool, &userdirs);
        char *filename = NULL, *prefix = NULL;
        apr_status_t rv;
        int is_absolute = ap_os_is_path_absolute(r->pool, userdir);

        if (ap_strchr_c(userdir, '*'))
            prefix = ap_getword(r->pool, &userdir, '*');

        if (userdir[0] == '\0' || is_absolute) {
            if (prefix) {
#ifdef HAVE_DRIVE_LETTERS
                /*
                 * Crummy hack. Need to figure out whether we have been
                 * redirected to a URL or to a file on some drive. Since I
                 * know of no protocols that are a single letter, ignore
                 * a : as the first or second character, and assume a file
                 * was specified
                 */
                if (strchr(prefix + 2, ':'))
#else
                if (strchr(prefix, ':') && !is_absolute)
#endif /* HAVE_DRIVE_LETTERS */
                {
                    redirect = apr_pstrcat(r->pool, prefix, user, userdir,
                                           dname, NULL);
                    apr_table_setn(r->headers_out, "Location", redirect);
                    return HTTP_MOVED_TEMPORARILY;
                }
                else
                    filename = apr_pstrcat(r->pool, prefix, user, userdir,
                                           NULL);
            }
            else
                filename = apr_pstrcat(r->pool, userdir, "/", user, NULL);
        }
        else if (prefix && ap_strchr_c(prefix, ':')) {
            redirect = apr_pstrcat(r->pool, prefix, user, dname, NULL);
            apr_table_setn(r->headers_out, "Location", redirect);
            return HTTP_MOVED_TEMPORARILY;
        }
        else {
#if APR_HAS_USER
            char *homedir;

            if (apr_uid_homepath_get(&homedir, user, r->pool) == APR_SUCCESS) {
                filename = apr_pstrcat(r->pool, homedir, "/", userdir, NULL);
            }
#else
            return DECLINED;
#endif
        }

        /*
         * Now see if it exists, or we're at the last entry. If we are at the
         * last entry, then use the filename generated (if there is one)
         * anyway, in the hope that some handler might handle it. This can be
         * used, for example, to run a CGI script for the user.
         */
        if (filename && (!*userdirs
                      || ((rv = apr_stat(&statbuf, filename, APR_FINFO_MIN,
                                         r->pool)) == APR_SUCCESS
                                             || rv == APR_INCOMPLETE))) {
            r->filename = apr_pstrcat(r->pool, filename, dname, NULL);
            ap_set_context_info(r, apr_pstrmemdup(r->pool, r->uri,
                                                  dname - r->uri),
                                filename);
            /* XXX: Does this walk us around FollowSymLink rules?
             * When statbuf contains info on r->filename we can save a syscall
             * by copying it to r->finfo
             */
            if (*userdirs && dname[0] == 0)
                r->finfo = statbuf;

            /* For use in the get_suexec_identity phase */
            apr_table_setn(r->notes, "mod_userdir_user", user);

            return OK;
        }
    }

    return DECLINED;
}
Esempio n. 16
0
// generate content takes the request rec and a file_t pointing to the
// already opened file from the request
// it adds the html information surrounding the body then loops
// over the names in the file and prints their coordinates
static int generate_content(request_rec *r, apr_file_t *fd) {
	// initialization
	char buf[MAX_BUF_LENGTH];
	apr_status_t rv;
	apr_file_t *name_data;
	const char * cookies;
	char * user = NULL;
	char * groups = NULL;
	moon_svr_cfg* cfg = ap_get_module_config(r->server->module_config, &moon_module);

	// get the cookies string from the request, retrieve the data
	// about a user and set the user and groups strings
	cookies = get_cookies_from_request(r);
	if(cookies != NULL) {
		rv = get_user_info(r, cookies, &user, &groups);
		if(rv != OK) {
			return rv;
		}
	}
	
	// set the reponse content type
	ap_set_content_type(r, "text/html;charset=ascii");

	// send initial html data
	ap_rputs(DOCTYPE, r);
	ap_rputs(OPEN_HTML_AND_HEAD, r);
	ap_rputs(TITLE, r);
	
	add_user_css(r, cfg, user);
	add_group_css(r, cfg, groups);

	ap_rputs(CLOSE_HEAD_OPEN_BODY, r);
	// check headers and return cookie, if NULL then no cookie set
	if(cookies != NULL && user != NULL) {
		add_user_info(r, user, groups);
	}
	else {
		add_anonymous_info(r);
	}

	// loop over file, get the next place
	// and print information about that place
	while(1) {
		rv = get_next_place(r, fd, buf);
		if(rv != OK) {
			if(rv==DONE) {
				break;
			} else {
				return rv;
			}
		}
		rv = get_place_coordinates(r, buf);
		ap_rprintf(r, "\n\t\t<p>\n\t\tCoordinates: %s\t\t</p>", buf);
		if(rv != OK) {
			return rv;
		}
	}	

	// cleanup and return 
	ap_rputs(CLOSE_HTML, r);
	return OK;
}
Esempio n. 17
0
static int dbm_check_auth(request_rec *r)
{
    dbm_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
                                                     &auth_dbm_module);
    char *user = r->user;
    int m = r->method_number;

    const apr_array_header_t *reqs_arr = ap_requires(r);
    require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;

    register int x;
    const char *t;
    char *w;

    if (!conf->auth_dbmgrpfile)
        return DECLINED;
    if (!reqs_arr)
        return DECLINED;

    for (x = 0; x < reqs_arr->nelts; x++) {

        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m)))
            continue;

        t = reqs[x].requirement;
        w = ap_getword_white(r->pool, &t);

        if (!strcmp(w, "group") && conf->auth_dbmgrpfile) {
            const char *orig_groups, *groups;
            char *v;

            if (!(groups = get_dbm_grp(r, user, conf->auth_dbmgrpfile,
                                       conf->auth_dbmtype))) {
                if (!(conf->auth_dbmauthoritative))
                    return DECLINED;
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                            "user %s not in DBM group file %s: %s",
                            user, conf->auth_dbmgrpfile, r->filename);
                ap_note_basic_auth_failure(r);
                return HTTP_UNAUTHORIZED;
            }
            orig_groups = groups;
            while (t[0]) {
                w = ap_getword_white(r->pool, &t);
                groups = orig_groups;
                while (groups[0]) {
                    v = ap_getword(r->pool, &groups, ',');
                    if (!strcmp(v, w))
                        return OK;
                }
            }
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "user %s not in right group: %s",
                          user, r->filename);
            ap_note_basic_auth_failure(r);
            return HTTP_UNAUTHORIZED;
        }
    }

    return DECLINED;
}
Esempio n. 18
0
// get_user_info uses CURL calls to get the data for a user name and groups associated
// with a given opensso cookie
static int get_user_info(request_rec *r, const char *cookies, char ** user, char **groups) {
	CURL *curl_handle;
	CURLcode ec;
	curl_global_init(CURL_GLOBAL_ALL);
	curl_handle = curl_easy_init();
	long no_cert_flag = 0L;
	moon_svr_cfg* cfg = ap_get_module_config(r->server->module_config, &moon_module);

	if(curl_handle==NULL) {
		return HTTP_INTERNAL_SERVER_ERROR;
	}
	apr_file_t *groups_data;
	apr_file_t *user_data;
	apr_status_t rv;

	// opens the file/stream for writing data about user
	if(rv = open_file(r, &user_data, USER_TEMP_FILE_LOC) != OK) {
		curl_easy_cleanup(curl_handle);
		return rv;
	}
	// opens the file/stream for writing data about user groups
	if(rv = open_file(r, &groups_data, GROUPS_TEMP_FILE_LOC) != OK) {
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		return rv;
	}
	
	// set all options for curl call requesting user data
	rv = set_curl_options(curl_handle, (char*)cfg->user_data_url, &no_cert_flag, user_data,
									write_data, cookies);
	if(rv != OK) {
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return rv;
	}

	// execute request
	ec = curl_easy_perform(curl_handle);
	if(ec != CURLE_WRITE_ERROR && ec != CURLE_OK ) {	
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	double x = 0.0;
	curl_easy_getinfo(curl_handle,CURLINFO_TOTAL_TIME,&x);
	ap_rprintf(r,"\n\n<!--\nTime for user data request: %f\n-->\n\n",x);

	// set all options for curl call requesting groups data
	rv = set_curl_options(curl_handle, (char*)cfg->group_data_url, &no_cert_flag, groups_data, 					 				write_data, cookies);
	if(rv != OK) {
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return rv;
	}

	// execute request
	ec = curl_easy_perform(curl_handle);
	if(ec != CURLE_WRITE_ERROR && ec != CURLE_OK ) {	
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	curl_easy_getinfo(curl_handle,CURLINFO_TOTAL_TIME,&x);
	ap_rprintf(r,"\n\n<!--\nTime for group data request: %f\n-->\n\n",x);

	// parse information from responses
	get_user(r, user_data, user);
	get_groups(r, groups_data, groups);

	// cleanup and return
	curl_easy_cleanup(curl_handle);
	apr_file_close(user_data);
	apr_file_close(groups_data);
	return OK;
}
static const char *reveseproxy_enable(cmd_parms *cmd, void *dummy, int flag) {
    reverseproxy_config_t *config = ap_get_module_config(cmd->server->module_config,
                                                      &reverseproxy_module);
    config->enable_module = flag;
    return NULL;
}
Esempio n. 20
0
static int process_echo_connection(conn_rec *c)
{
    apr_bucket_brigade *bb;
    apr_bucket *b;
    apr_socket_t *csd = NULL;
    EchoConfig *pConfig = ap_get_module_config(c->base_server->module_config,
                                               &echo_module);

    if (!pConfig->bEnabled) {
        return DECLINED;
    }

    ap_time_process_request(c->sbh, START_PREQUEST);
    update_echo_child_status(c->sbh, SERVER_BUSY_READ, c, NULL);

    bb = apr_brigade_create(c->pool, c->bucket_alloc);

    for ( ; ; ) {
        apr_status_t rv;

        /* Get a single line of input from the client */
        if (((rv = ap_get_brigade(c->input_filters, bb, AP_MODE_GETLINE,
                                  APR_BLOCK_READ, 0)) != APR_SUCCESS)) {
            apr_brigade_cleanup(bb);
            if (!APR_STATUS_IS_EOF(rv) && ! APR_STATUS_IS_TIMEUP(rv))
                ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01611)
                             "ProtocolEcho: Failure reading from %s",
                             c->client_ip);
            break;
        }

        /* Something horribly wrong happened.  Someone didn't block! */
        if (APR_BRIGADE_EMPTY(bb)) {
            apr_brigade_cleanup(bb);
            ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01612)
                         "ProtocolEcho: Error - read empty brigade from %s!",
                         c->client_ip);
            break;
        }

        if (!csd) {
            csd = ap_get_conn_socket(c);
            apr_socket_timeout_set(csd, c->base_server->keep_alive_timeout);
        }

        update_echo_child_status(c->sbh, SERVER_BUSY_WRITE, NULL, bb);

        /* Make sure the data is flushed to the client */
        b = apr_bucket_flush_create(c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(bb, b);
        rv = ap_pass_brigade(c->output_filters, bb);
        if (rv != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01613)
                         "ProtocolEcho: Failure writing to %s",
                         c->client_ip);
            break;
        }
        apr_brigade_cleanup(bb);

        /* Announce our intent to loop */
        update_echo_child_status(c->sbh, SERVER_BUSY_KEEPALIVE, NULL, NULL);
    }
    apr_brigade_destroy(bb);
    ap_time_process_request(c->sbh, STOP_PREQUEST);
    update_echo_child_status(c->sbh, SERVER_CLOSING, c, NULL);
    return OK;
}
Esempio n. 21
0
static const char *load_module(cmd_parms *cmd, void *dummy,
                               const char *modname, const char *filename)
{
    apr_dso_handle_t *modhandle;
    apr_dso_handle_sym_t modsym;
    module *modp;
    const char *szModuleFile = ap_server_root_relative(cmd->pool, filename);
    so_server_conf *sconf;
    ap_module_symbol_t *modi;
    ap_module_symbol_t *modie;
    int i;
    const char *error;

    /* we need to setup this value for dummy to make sure that we don't try
     * to add a non-existant tree into the build when we return to
     * execute_now.
     */
    *(ap_directive_t **)dummy = NULL;

    if (!szModuleFile) {
        return apr_pstrcat(cmd->pool, "Invalid LoadModule path ",
                           filename, NULL);
    }

    /*
     * check for already existing module
     * If it already exists, we have nothing to do
     * Check both dynamically-loaded modules and statically-linked modules.
     */
    sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config,
                                                &so_module);
    modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
    for (i = 0; i < sconf->loaded_modules->nelts; i++) {
        modi = &modie[i];
        if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
            ap_log_perror(APLOG_MARK, APLOG_WARNING, 0,
                          cmd->pool, "module %s is already loaded, skipping",
                          modname);
            return NULL;
        }
    }

    for (i = 0; ap_preloaded_modules[i]; i++) {
        const char *preload_name;
        apr_size_t preload_len;
        apr_size_t thismod_len;

        modp = ap_preloaded_modules[i];

        /* make sure we're comparing apples with apples
         * make sure name of preloaded module is mod_FOO.c
         * make sure name of structure being loaded is FOO_module
         */

        if (memcmp(modp->name, "mod_", 4)) {
            continue;
        }

        preload_name = modp->name + strlen("mod_");
        preload_len = strlen(preload_name) - 2;

        if (strlen(modname) <= strlen("_module")) {
            continue;
        }
        thismod_len = strlen(modname) - strlen("_module");
        if (strcmp(modname + thismod_len, "_module")) {
            continue;
        }

        if (thismod_len != preload_len) {
            continue;
        }

        if (!memcmp(modname, preload_name, preload_len)) {
            return apr_pstrcat(cmd->pool, "module ", modname,
                               " is built-in and can't be loaded",
                               NULL);
        }
    }

    modi = apr_array_push(sconf->loaded_modules);
    modi->name = modname;

    /*
     * Load the file into the Apache address space
     */
    if (apr_dso_load(&modhandle, szModuleFile, cmd->pool) != APR_SUCCESS) {
        char my_error[256];

        return apr_pstrcat(cmd->pool, "Cannot load ", szModuleFile,
                          " into server: ",
                          apr_dso_error(modhandle, my_error, sizeof(my_error)),
                          NULL);
    }
    ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool,
                 "loaded module %s", modname);

    /*
     * Retrieve the pointer to the module structure through the module name:
     * First with the hidden variant (prefix `AP_') and then with the plain
     * symbol name.
     */
    if (apr_dso_sym(&modsym, modhandle, modname) != APR_SUCCESS) {
        char my_error[256];

        return apr_pstrcat(cmd->pool, "Can't locate API module structure `",
                          modname, "' in file ", szModuleFile, ": ",
                          apr_dso_error(modhandle, my_error, sizeof(my_error)),
                          NULL);
    }
    modp = (module*) modsym;
    modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle;
    modi->modp = modp;

    /*
     * Make sure the found module structure is really a module structure
     *
     */
    if (modp->magic != MODULE_MAGIC_COOKIE) {
        return apr_pstrcat(cmd->pool, "API module structure `", modname,
                          "' in file ", szModuleFile, " is garbled -"
                          " perhaps this is not an Apache module DSO?", NULL);
    }

    /*
     * Add this module to the Apache core structures
     */
    error = ap_add_loaded_module(modp, cmd->pool);
    if (error) {
        return error;
    }

    /*
     * Register a cleanup in the config apr_pool_t (normally pconf). When
     * we do a restart (or shutdown) this cleanup will cause the
     * shared object to be unloaded.
     */
    apr_pool_cleanup_register(cmd->pool, modi, unload_module, apr_pool_cleanup_null);

    /*
     * Finally we need to run the configuration process for the module
     */
    ap_single_module_configure(cmd->pool, cmd->server, modp);

    return NULL;
}
static void ap_logio_add_bytes_in(conn_rec *c, apr_off_t bytes){
    logio_config_t *cf = ap_get_module_config(c->conn_config, &logio_module);

    cf->bytes_in += bytes;
}
Esempio n. 23
0
static int amagent_auth_handler(request_rec *r) {
    const char *thisfunc = "amagent_auth_handler():";
    int rv;
    am_request_t d;
    am_config_t *boot = NULL;

    amagent_config_t *c = ap_get_module_config(r->server->module_config, &amagent_module);

    if (c == NULL || !c->enabled || c->error != AM_SUCCESS) {
        /* amagent module is not enabled for this 
         * server/virtualhost - we are not handling this request
         **/
        return DECLINED;
    }

    if (c->error != AM_SUCCESS) {
        LOG_R(APLOG_ERR, r, "%s is not configured to handle the request "
                "to %s (unable to load bootstrap configuration from %s, error: %s)",
                DESCRIPTION, r->uri, c->config, am_strerror(c->error));
        return HTTP_FORBIDDEN;
    }

    LOG_R(APLOG_DEBUG, r, "amagent_auth_handler(): [%s] [%ld]", c->config, c->config_id);

    /* register and update instance logger configuration (for already registered
     * instances - update logging level only 
     */
    am_log_register_instance(c->config_id, c->debug_file, c->debug_level,
            c->audit_file, c->audit_level);

    am_log_debug(c->config_id, "%s begin", thisfunc);

    /* fetch agent configuration instance (from cache if available) */
    rv = am_get_agent_config(c->config_id, c->config, &boot);
    if (boot == NULL || rv != AM_SUCCESS) {
        LOG_R(APLOG_ERR, r, "%s is not configured to handle the request "
                "to %s (unable to get agent configuration instance, configuration: %s, error: %s)",
                DESCRIPTION, r->uri, c->config, am_strerror(rv));
        am_log_error(c->config_id, "amagent_auth_handler(): failed to get agent configuration instance, error: %s",
                am_strerror(rv));
        return HTTP_FORBIDDEN;
    }

    /* set up request processor data structure */
    memset(&d, 0, sizeof (am_request_t));
    d.conf = boot;
    d.status = AM_ERROR;
    d.instance_id = c->config_id;
    d.ctx = r;
    d.method = get_method_num(r, c->config_id);
    d.content_type = apr_table_get(r->headers_in, "Content-Type");
    d.cookies = apr_table_get(r->headers_in, "Cookie");

    if (ISVALID(d.conf->client_ip_header)) {
        d.client_ip = (char *) apr_table_get(r->headers_in, d.conf->client_ip_header);
    }
    if (!ISVALID(d.client_ip)) {
#ifdef APACHE24
        d.client_ip = (char *) r->connection->client_ip;
#else
        d.client_ip = (char *) r->connection->remote_ip;
#endif
    }

    if (ISVALID(d.conf->client_hostname_header)) {
        d.client_host = (char *) apr_table_get(r->headers_in, d.conf->client_hostname_header);
    }

    d.am_get_request_url_f = get_request_url;
    d.am_get_post_data_f = get_request_body;
    d.am_set_post_data_f = set_request_body;
    d.am_set_user_f = set_user;
    d.am_set_header_in_request_f = set_header_in_request;
    d.am_add_header_in_response_f = add_header_in_response;
    d.am_set_cookie_f = set_cookie;
    d.am_set_custom_response_f = set_custom_response;
    d.am_set_method_f = set_method;

    am_process_request(&d);

    rv = am_status_value(d.status);

    am_log_debug(c->config_id, "amagent_auth_handler(): exit status: %s (%d)",
            am_strerror(d.status), d.status);

    am_config_free(&d.conf);
    am_request_free(&d);

    LOG_R(APLOG_DEBUG, r, "amagent_auth_handler(): return status: %d", rv);
    return rv;
}
static apr_off_t ap_logio_get_last_bytes(conn_rec *c)
{
    logio_config_t *cf = ap_get_module_config(c->conn_config, &logio_module);

    return cf->bytes_last_request;
}
static apr_status_t do_pattmatch(ap_filter_t *f, apr_bucket *inb,
                                 apr_bucket_brigade *mybb,
                                 apr_pool_t *pool)
{
    int i;
    int force_quick = 0;
    ap_regmatch_t regm[AP_MAX_REG_MATCH];
    apr_size_t bytes;
    apr_size_t len;
    const char *buff;
    struct ap_varbuf vb;
    apr_bucket *b;
    apr_bucket *tmp_b;

    subst_dir_conf *cfg =
    (subst_dir_conf *) ap_get_module_config(f->r->per_dir_config,
                                             &substitute_module);
    subst_pattern_t *script;

    APR_BRIGADE_INSERT_TAIL(mybb, inb);
    ap_varbuf_init(pool, &vb, 0);

    script = (subst_pattern_t *) cfg->patterns->elts;
    /*
     * Simple optimization. If we only have one pattern, then
     * we can safely avoid the overhead of flattening
     */
    if (cfg->patterns->nelts == 1) {
       force_quick = 1;
    }
    for (i = 0; i < cfg->patterns->nelts; i++) {
        for (b = APR_BRIGADE_FIRST(mybb);
             b != APR_BRIGADE_SENTINEL(mybb);
             b = APR_BUCKET_NEXT(b)) {
            if (APR_BUCKET_IS_METADATA(b)) {
                /*
                 * we should NEVER see this, because we should never
                 * be passed any, but "handle" it just in case.
                 */
                continue;
            }
            if (apr_bucket_read(b, &buff, &bytes, APR_BLOCK_READ)
                    == APR_SUCCESS) {
                int have_match = 0;
                vb.strlen = 0;
                if (script->pattern) {
                    const char *repl;
                    /*
                     * space_left counts how many bytes we have left until the
                     * line length reaches max_line_length.
                     */
                    apr_size_t space_left = cfg->max_line_length;
                    apr_size_t repl_len = strlen(script->replacement);
                    while ((repl = apr_strmatch(script->pattern, buff, bytes)))
                    {
                        have_match = 1;
                        /* get offset into buff for pattern */
                        len = (apr_size_t) (repl - buff);
                        if (script->flatten && !force_quick) {
                            /*
                             * We are flattening the buckets here, meaning
                             * that we don't do the fast bucket splits.
                             * Instead we copy over what the buckets would
                             * contain and use them. This is slow, since we
                             * are constanting allocing space and copying
                             * strings.
                             */
                            if (vb.strlen + len + repl_len > cfg->max_line_length)
                                return APR_ENOMEM;
                            ap_varbuf_strmemcat(&vb, buff, len);
                            ap_varbuf_strmemcat(&vb, script->replacement, repl_len);
                        }
                        else {
                            /*
                             * The string before the match but after the
                             * previous match (if any) has length 'len'.
                             * Check if we still have space for this string and
                             * the replacement string.
                             */
                            if (space_left < len + repl_len)
                                return APR_ENOMEM;
                            space_left -= len + repl_len;
                            /*
                             * We now split off the string before the match
                             * as its own bucket, then isolate the matched
                             * string and delete it.
                             */
                            SEDRMPATBCKT(b, len, tmp_b, script->patlen);
                            /*
                             * Finally, we create a bucket that contains the
                             * replacement...
                             */
                            tmp_b = apr_bucket_transient_create(script->replacement,
                                      script->replen,
                                      f->r->connection->bucket_alloc);
                            /* ... and insert it */
                            APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                        }
                        /* now we need to adjust buff for all these changes */
                        len += script->patlen;
                        bytes -= len;
                        buff += len;
                    }
                    if (have_match) {
                        if (script->flatten && !force_quick) {
                            /* XXX: we should check for AP_MAX_BUCKETS here and
                             * XXX: call ap_pass_brigade accordingly
                             */
                            char *copy = ap_varbuf_pdup(pool, &vb, NULL, 0,
                                                        buff, bytes, &len);
                            tmp_b = apr_bucket_pool_create(copy, len, pool,
                                                           f->r->connection->bucket_alloc);
                            APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                            apr_bucket_delete(b);
                            b = tmp_b;
                        }
                        else {
                            /*
                             * We want the behaviour to be predictable.
                             * Therefore we try to always error out if the
                             * line length is larger than the limit,
                             * regardless of the content of the line. So,
                             * let's check if the remaining non-matching
                             * string does not exceed the limit.
                             */
                            if (space_left < b->length)
                                return APR_ENOMEM;
                        }
                    }
                }
                else if (script->regexp) {
                    int left = bytes;
                    const char *pos = buff;
                    char *repl;
                    apr_size_t space_left = cfg->max_line_length;
                    while (!ap_regexec_len(script->regexp, pos, left,
                                       AP_MAX_REG_MATCH, regm, 0)) {
                        apr_status_t rv;
                        have_match = 1;
                        if (script->flatten && !force_quick) {
                            /* check remaining buffer size */
                            /* Note that the last param in ap_varbuf_regsub below
                             * must stay positive. If it gets 0, it would mean
                             * unlimited space available. */
                            if (vb.strlen + regm[0].rm_so >= cfg->max_line_length)
                                return APR_ENOMEM;
                            /* copy bytes before the match */
                            if (regm[0].rm_so > 0)
                                ap_varbuf_strmemcat(&vb, pos, regm[0].rm_so);
                            /* add replacement string, last argument is unsigned! */
                            rv = ap_varbuf_regsub(&vb, script->replacement, pos,
                                                  AP_MAX_REG_MATCH, regm,
                                                  cfg->max_line_length - vb.strlen);
                            if (rv != APR_SUCCESS)
                                return rv;
                        }
                        else {
                            apr_size_t repl_len;
                            /* acount for string before the match */
                            if (space_left <= regm[0].rm_so)
                                return APR_ENOMEM;
                            space_left -= regm[0].rm_so;
                            rv = ap_pregsub_ex(pool, &repl,
                                               script->replacement, pos,
                                               AP_MAX_REG_MATCH, regm,
                                               space_left);
                            if (rv != APR_SUCCESS)
                                return rv;
                            repl_len = strlen(repl);
                            space_left -= repl_len;
                            len = (apr_size_t) (regm[0].rm_eo - regm[0].rm_so);
                            SEDRMPATBCKT(b, regm[0].rm_so, tmp_b, len);
                            tmp_b = apr_bucket_transient_create(repl, repl_len,
                                                f->r->connection->bucket_alloc);
                            APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                        }
                        /*
                         * reset to past what we just did. pos now maps to b
                         * again
                         */
                        pos += regm[0].rm_eo;
                        left -= regm[0].rm_eo;
                    }
                    if (have_match && script->flatten && !force_quick) {
                        char *copy;
                        /* Copy result plus the part after the last match into
                         * a bucket.
                         */
                        copy = ap_varbuf_pdup(pool, &vb, NULL, 0, pos, left,
                                              &len);
                        tmp_b = apr_bucket_pool_create(copy, len, pool,
                                           f->r->connection->bucket_alloc);
                        APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                        apr_bucket_delete(b);
                        b = tmp_b;
                    }
                }
                else {
                    ap_assert(0);
                    continue;
                }
            }
        }
        script++;
    }
    ap_varbuf_free(&vb);
    return APR_SUCCESS;
}
Esempio n. 26
0
static const char *set_cookie_exp(cmd_parms *parms, void *dummy,
                                  const char *arg)
{
    cookie_log_state *cls;
    time_t factor, modifier = 0;
    time_t num = 0;
    char *word;

    cls  = ap_get_module_config(parms->server->module_config,
                                &usertrack_module);
    /* The simple case first - all numbers (we assume) */
    if (apr_isdigit(arg[0]) && apr_isdigit(arg[strlen(arg) - 1])) {
        cls->expires = atol(arg);
        return NULL;
    }

    /*
     * The harder case - stolen from mod_expires
     *
     * CookieExpires "[plus] {<num> <type>}*"
     */

    word = ap_getword_conf(parms->temp_pool, &arg);
    if (!strncasecmp(word, "plus", 1)) {
        word = ap_getword_conf(parms->temp_pool, &arg);
    };

    /* {<num> <type>}* */
    while (word[0]) {
        /* <num> */
        if (apr_isdigit(word[0]))
            num = atoi(word);
        else
            return "bad expires code, numeric value expected.";

        /* <type> */
        word = ap_getword_conf(parms->temp_pool, &arg);
        if (!word[0])
            return "bad expires code, missing <type>";

        if (!strncasecmp(word, "years", 1))
            factor = 60 * 60 * 24 * 365;
        else if (!strncasecmp(word, "months", 2))
            factor = 60 * 60 * 24 * 30;
        else if (!strncasecmp(word, "weeks", 1))
            factor = 60 * 60 * 24 * 7;
        else if (!strncasecmp(word, "days", 1))
            factor = 60 * 60 * 24;
        else if (!strncasecmp(word, "hours", 1))
            factor = 60 * 60;
        else if (!strncasecmp(word, "minutes", 2))
            factor = 60;
        else if (!strncasecmp(word, "seconds", 1))
            factor = 1;
        else
            return "bad expires code, unrecognized type";

        modifier = modifier + factor * num;

        /* next <num> */
        word = ap_getword_conf(parms->temp_pool, &arg);
    }

    cls->expires = modifier;

    return NULL;
}
Esempio n. 27
0
static int geoip_header_parser(request_rec * r)
{
    char *orgorisp;
    char *ipaddr;
    char *free_me = NULL;
    short int country_id;
    const char *continent_code;
    const char *country_code;
    const char *country_name;
    const char *region_name;

    geoip_server_config_rec *cfg;

    unsigned char databaseType;
    GeoIPRecord *gir;
    GeoIPRegion *giregion;
    int i;
    int netspeed;
    /* For splitting proxy headers */
    char *ipaddr_ptr = NULL;
    char *comma_ptr;
    cfg = ap_get_module_config(r->server->module_config, &geoip_module);

    if (!cfg)
        return DECLINED;

    if (!cfg->scanProxyHeaders) {
        ipaddr = _get_client_ip(r);
    } else {
        ap_add_common_vars(r);
        if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP");
        } else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->subprocess_env,
                                      "HTTP_X_FORWARDED_FOR");
        } else if (apr_table_get(r->headers_in, "X-Forwarded-For")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->headers_in, "X-Forwarded-For");
        } else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR");
        }
        if (!ipaddr_ptr) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
                         r->server,
                         "[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR.");
            ipaddr = _get_client_ip(r);
        } else {
            /* Found XFF like header */
            ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
                         r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr);

            if (cfg->proxyHeaderMode ==
                GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP) {
                ipaddr = free_me = _get_ip_from_xff(ipaddr_ptr);
                if (!ipaddr)
                    ipaddr = _get_client_ip(r);
            } else {
                ipaddr = free_me = (char *)calloc(8 * 4 + 7 + 1, sizeof(char));
                /* proxyHeaderMode is
                 * GEOIP_PROXY_HEADER_MODE_LAST_IP or GEOIP_PROXY_HEADER_MODE_FIRST_IP
                 */

                /*
                 * Check to ensure that the HTTP_CLIENT_IP or
                 * X-Forwarded-For header is not a comma separated
                 * list of addresses, which would cause mod_geoip to
                 * return no country code. If the header is a comma
                 * separated list, return the first IP address in the
                 * list, which is (hopefully!) the real client IP.
                 */

                if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_LAST_IP) {
                    comma_ptr = strrchr(ipaddr_ptr, ',');
                    if (comma_ptr) {
                        /* skip over whitespace */
                        ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t");
                    }
                }

                strncpy(ipaddr, ipaddr_ptr, 8 * 4 + 7);
                comma_ptr = strchr(ipaddr, ',');
                if (comma_ptr != 0)
                    *comma_ptr = '\0';
            }
        }
    }

/* this block should be removed! */
#if 1
    if (!cfg->gips) {
        if (cfg->GeoIPFilenames != NULL) {
            cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles);
            for (i = 0; i < cfg->numGeoIPFiles; i++) {
                cfg->gips[i] =
                    GeoIP_open(cfg->GeoIPFilenames[i],
                               (cfg->GeoIPFlags2[i] ==
                                GEOIP_UNKNOWN) ? cfg->GeoIPFlags
                               : cfg->GeoIPFlags2[i]);

                if (cfg->gips[i]) {
                    if (cfg->GeoIPEnableUTF8) {
                        GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
                    }
                } else {
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0,
                                 r->server,
                                 "[mod_geoip]: Error while opening data file %s",
                                 cfg->GeoIPFilenames[i]);
                    return DECLINED;
                }
            }
        } else {
            cfg->gips = malloc(sizeof(GeoIP *));
            cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
            if (!cfg->gips[0]) {
                ap_log_error(APLOG_MARK, APLOG_ERR, 0,
                             r->server,
                             "[mod_geoip]: Error while opening data file");
                return DECLINED;
            }
            cfg->numGeoIPFiles = 1;
        }
    }
#endif

    set_geoip_output(cfg, r, "GEOIP_ADDR", ipaddr);

    for (i = 0; i < cfg->numGeoIPFiles; i++) {

        /*
         * skip database handles that can not be opned for some
         * reason
         */
        if (cfg->gips[i] == NULL)
            continue;

        databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1;        /* -1 is "magic value"
                                                                                         * in case file not
                                                                                         * found */
        switch (databaseType) {
        case GEOIP_NETSPEED_EDITION_REV1:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_NETSPEED", orgorisp);
            break;

        case GEOIP_NETSPEED_EDITION:
            netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr);
            if (netspeed == GEOIP_UNKNOWN_SPEED) {
                netspeedstring = "unknown";
            } else if (netspeed == GEOIP_DIALUP_SPEED) {
                netspeedstring = "dialup";
            } else if (netspeed == GEOIP_CABLEDSL_SPEED) {
                netspeedstring = "cabledsl";
            } else if (netspeed == GEOIP_CORPORATE_SPEED) {
                netspeedstring = "corporate";
            }
            setn_geoip_output(cfg, r, "GEOIP_NETSPEED", netspeedstring);
            break;
        case GEOIP_COUNTRY_EDITION_V6:
            /* Get the Country ID */
            country_id = GeoIP_id_by_addr_v6(cfg->gips[i], ipaddr);

            if (country_id > 0) {
                /* Lookup the Code and the Name with the ID */
                continent_code = GeoIP_country_continent[country_id];
                country_code = GeoIP_country_code[country_id];
                country_name = GeoIP_country_name[country_id];

                if (cfg->numGeoIPFiles == 0) {
                    cfg->numGeoIPFiles = 0;
                }
                if (cfg->GeoIPFilenames == 0) {
                    cfg->GeoIPFilenames = 0;
                }
                /* Set it for our user */
                setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6",
                                  continent_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6",
                                  country_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6",
                                  country_name);
            }
            break;
        case GEOIP_COUNTRY_EDITION:
            /* Get the Country ID */
            country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr);

            if (country_id > 0) {
                /* Lookup the Code and the Name with the ID */
                continent_code = GeoIP_country_continent[country_id];
                country_code = GeoIP_country_code[country_id];
                country_name = GeoIP_country_name[country_id];

                if (cfg->numGeoIPFiles == 0) {
                    cfg->numGeoIPFiles = 0;
                }
                if (cfg->GeoIPFilenames == 0) {
                    cfg->GeoIPFilenames = 0;
                }
                /* Set it for our user */
                setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE",
                                  continent_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", country_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", country_name);
            }

            break;
        case GEOIP_REGION_EDITION_REV0:
        case GEOIP_REGION_EDITION_REV1:
            giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr);
            if (giregion != NULL) {
                region_name = NULL;
                if (giregion->country_code[0]) {
                    region_name =
                        GeoIP_region_name_by_code
                        (giregion->country_code, giregion->region);
                    set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE",
                                      giregion->country_code);
                    country_id = GeoIP_id_by_code(giregion->country_code);
                    setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME",
                                      GeoIP_country_name[country_id]);
                    setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE",
                                      GeoIP_country_continent[country_id]);
                }
                if (giregion->region[0]) {
                    set_geoip_output(cfg, r, "GEOIP_REGION", giregion->region);
                }
                if (region_name != NULL) {
                    set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name);
                }
                GeoIPRegion_delete(giregion);
            }
            break;
        case GEOIP_CITY_EDITION_REV0_V6:
        case GEOIP_CITY_EDITION_REV1_V6:
            gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr);
            if (gir != NULL) {
                if (gir->country_code != NULL) {
                    region_name =
                        GeoIP_region_name_by_code(gir->country_code,
                                                  gir->region);
                }
                sprintf(metrocodestr, "%d", gir->dma_code);
                sprintf(areacodestr, "%d", gir->area_code);
                set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6",
                                  gir->continent_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6",
                                  gir->country_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6",
                                  gir->country_name);
                set_geoip_output(cfg, r, "GEOIP_REGION_V6", gir->region);
                set_geoip_output(cfg, r, "GEOIP_REGION_NAME_V6", region_name);
                set_geoip_output(cfg, r, "GEOIP_CITY_V6", gir->city);
                set_geoip_output(cfg, r, "GEOIP_DMA_CODE_V6", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_METRO_CODE_V6", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_AREA_CODE_V6", areacodestr);
                sprintf(latstr, "%f", gir->latitude);
                sprintf(lonstr, "%f", gir->longitude);
                set_geoip_output(cfg, r, "GEOIP_LATITUDE_V6", latstr);
                set_geoip_output(cfg, r, "GEOIP_LONGITUDE_V6", lonstr);

                set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE_V6",
                                  gir->postal_code);
                GeoIPRecord_delete(gir);
            }

            break;
        case GEOIP_CITY_EDITION_REV0:
        case GEOIP_CITY_EDITION_REV1:
            gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr);
            if (gir != NULL) {
                if (gir->country_code != NULL) {
                    region_name =
                        GeoIP_region_name_by_code(gir->country_code,
                                                  gir->region);
                }
                sprintf(metrocodestr, "%d", gir->dma_code);
                sprintf(areacodestr, "%d", gir->area_code);
                set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE",
                                  gir->continent_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE",
                                  gir->country_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME",
                                  gir->country_name);
                set_geoip_output(cfg, r, "GEOIP_REGION", gir->region);
                set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name);
                set_geoip_output(cfg, r, "GEOIP_CITY", gir->city);
                set_geoip_output(cfg, r, "GEOIP_DMA_CODE", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_METRO_CODE", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_AREA_CODE", areacodestr);
                sprintf(latstr, "%f", gir->latitude);
                sprintf(lonstr, "%f", gir->longitude);
                set_geoip_output(cfg, r, "GEOIP_LATITUDE", latstr);
                set_geoip_output(cfg, r, "GEOIP_LONGITUDE", lonstr);
                set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE",
                                  gir->postal_code);
                GeoIPRecord_delete(gir);
            }

            break;
        case GEOIP_ORG_EDITION:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_ORGANIZATION", orgorisp);
            break;
        case GEOIP_ISP_EDITION:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_ISP", orgorisp);
            break;
        case GEOIP_DOMAIN_EDITION:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_DOMAIN", orgorisp);
            break;
        }
    }

    if (free_me)
        free(free_me);
    return OK;
}
Esempio n. 28
0
/* The wiki handler */
static int wiki_handler(request_rec *r)
{
    wiki_conf *conf;
    git_repository *repo;
    const git_oid *tree_oid;
    char *path;

    const git_oid *oid;
    char hash[41];
    hash[40] = '\0';
    int ret;
    int type;

    MMIOT *doc;

    if (strcmp(r->handler, "wiki")) {
        return DECLINED;
    }

    if (r->header_only) {
        return OK;
    }

    conf =
        (wiki_conf *) ap_get_module_config(r->per_dir_config,
                                           &wiki_module);

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "filename=%s",
                  r->filename);
    if (conf->basepath) {
        path = ltrim(conf->basepath, r->parsed_uri.path);
    } else {
        path = r->parsed_uri.path + 1;
    }

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "path=%s", path);
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                  "r->content_type=%s", r->content_type);

    if (conf->repo == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "WikiRepository is not set.");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    ret = git_repository_open(&repo, conf->repo);
    if (ret) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "Cannot open git repository.(%s)", conf->repo);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    tree_oid = lookup_master_tree(repo);
    if (tree_oid == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "Not found master tree.");
        git_repository_free(repo);
    }

    type = lookup_object_oid(r, repo, tree_oid, path, &oid);
    if (type == WIKI_NOTFOUND) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "Object is not found.");
        git_repository_free(repo);
        return HTTP_NOT_FOUND;
    } else if(type == WIKI_DIR) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "Directory listing is not implement yet.");
        git_repository_free(repo);
        return HTTP_FORBIDDEN;
    } else if(type == WIKI_ERROR) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "Error at lookup.");
        git_repository_free(repo);
        return HTTP_NOT_FOUND;
    }

    git_oid_fmt(hash, oid);
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "object hash=%s", hash);

    const char *data;
    size_t size;

    git_odb *odb;
    ret = git_repository_odb(&odb, repo);
    git_odb_object *odb_object;
    ret = git_odb_read(&odb_object, odb, oid);
    data = git_odb_object_data(odb_object);
    size = git_odb_object_size(odb_object);

    git_odb_object_free(odb_object);	// is this safe?

    if (type == WIKI_FOUND) {
        ap_rwrite(data, size, r);
    } else if(type == WIKI_MARKDOWN) {
        r->content_type = "text/html";
        doc = mkd_string(data, size, 0);
        if (doc == NULL) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "mkd_string() returned NULL\n");
            git_repository_free(repo);
            return HTTP_INTERNAL_SERVER_ERROR;
        }
        wiki_output(doc, r);
        mkd_cleanup(doc);
    } else {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "Unknown Error.\n");
        git_repository_free(repo);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    git_repository_free(repo);
    return OK;
}
Esempio n. 29
0
static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info *info)
{
    disk_cache_conf *conf = ap_get_module_config(r->server->module_config,
                                                 &disk_cache_module);
    apr_status_t rv;
    apr_size_t amt;
    disk_cache_object_t *dobj = (disk_cache_object_t*) h->cache_obj->vobj;

    disk_cache_info_t disk_info;
    struct iovec iov[2];

    /* This is flaky... we need to manage the cache_info differently */
    h->cache_obj->info = *info;

    if (r->headers_out) {
        const char *tmp;

        tmp = apr_table_get(r->headers_out, "Vary");

        if (tmp) {
            apr_array_header_t* varray;
            apr_uint32_t format = VARY_FORMAT_VERSION;

            /* If we were initially opened as a vary format, rollback
             * that internal state for the moment so we can recreate the
             * vary format hints in the appropriate directory.
             */
            if (dobj->prefix) {
                dobj->hdrsfile = dobj->prefix;
                dobj->prefix = NULL;
            }

            mkdir_structure(conf, dobj->hdrsfile, r->pool);

            rv = apr_file_mktemp(&dobj->tfd, dobj->tempfile,
                                 APR_CREATE | APR_WRITE | APR_BINARY | APR_EXCL,
                                 r->pool);

            if (rv != APR_SUCCESS) {
                return rv;
            }

            amt = sizeof(format);
            apr_file_write(dobj->tfd, &format, &amt);

            amt = sizeof(info->expire);
            apr_file_write(dobj->tfd, &info->expire, &amt);

            varray = apr_array_make(r->pool, 6, sizeof(char*));
            tokens_to_array(r->pool, tmp, varray);

            store_array(dobj->tfd, varray);

            apr_file_close(dobj->tfd);

            dobj->tfd = NULL;

            rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile,
                                  r->pool);
            if (rv != APR_SUCCESS) {
                ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server,
                    "disk_cache: rename tempfile to varyfile failed: %s -> %s",
                    dobj->tempfile, dobj->hdrsfile);
                apr_file_remove(dobj->tempfile, r->pool);
                return rv;
            }

            dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL);
            tmp = regen_key(r->pool, r->headers_in, varray, dobj->name);
            dobj->prefix = dobj->hdrsfile;
            dobj->hashfile = NULL;
            dobj->datafile = data_file(r->pool, conf, dobj, tmp);
            dobj->hdrsfile = header_file(r->pool, conf, dobj, tmp);
        }
    }


    rv = apr_file_mktemp(&dobj->hfd, dobj->tempfile,
                         APR_CREATE | APR_WRITE | APR_BINARY |
                         APR_BUFFERED | APR_EXCL, r->pool);

    if (rv != APR_SUCCESS) {
        return rv;
    }

    disk_info.format = DISK_FORMAT_VERSION;
    disk_info.date = info->date;
    disk_info.expire = info->expire;
    disk_info.entity_version = dobj->disk_info.entity_version++;
    disk_info.request_time = info->request_time;
    disk_info.response_time = info->response_time;
    disk_info.status = info->status;

    disk_info.name_len = strlen(dobj->name);

    iov[0].iov_base = (void*)&disk_info;
    iov[0].iov_len = sizeof(disk_cache_info_t);
    iov[1].iov_base = (void*)dobj->name;
    iov[1].iov_len = disk_info.name_len;

    rv = apr_file_writev(dobj->hfd, (const struct iovec *) &iov, 2, &amt);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    if (r->headers_out) {
        apr_table_t *headers_out;

        headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out,
                                                  r->server);

        if (!apr_table_get(headers_out, "Content-Type")
            && r->content_type) {
            apr_table_setn(headers_out, "Content-Type",
                           ap_make_content_type(r, r->content_type));
        }

        headers_out = apr_table_overlay(r->pool, headers_out,
                                        r->err_headers_out);
        rv = store_table(dobj->hfd, headers_out);
        if (rv != APR_SUCCESS) {
            return rv;
        }
    }

    /* Parse the vary header and dump those fields from the headers_in. */
    /* FIXME: Make call to the same thing cache_select calls to crack Vary. */
    if (r->headers_in) {
        apr_table_t *headers_in;

        headers_in = ap_cache_cacheable_hdrs_out(r->pool, r->headers_in,
                                                 r->server);
        rv = store_table(dobj->hfd, headers_in);
        if (rv != APR_SUCCESS) {
            return rv;
        }
    }

    apr_file_close(dobj->hfd); /* flush and close */

    /* Remove old file with the same name. If remove fails, then
     * perhaps we need to create the directory tree where we are
     * about to write the new headers file.
     */
    rv = apr_file_remove(dobj->hdrsfile, r->pool);
    if (rv != APR_SUCCESS) {
        mkdir_structure(conf, dobj->hdrsfile, r->pool);
    }

    rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile, r->pool);
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server,
                     "disk_cache: rename tempfile to hdrsfile failed: %s -> %s",
                     dobj->tempfile, dobj->hdrsfile);
        apr_file_remove(dobj->tempfile, r->pool);
        return rv;
    }

    dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL);

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                 "disk_cache: Stored headers for URL %s",  dobj->name);
    return APR_SUCCESS;
}
static int check_auth_cookie(request_rec *r)
{

	const char *cookies = NULL, *auth_line = NULL;
	char *cookie = NULL;

    /* Debug. */
	/*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
	    "check_auth_cookie called");*/

	/* Get config for this directory. */
    cookie_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
		&auth_cookie_module);

    /* Check we have been configured. */
    if (!conf->cookie_auth_cookie) {
        return DECLINED;
    }

	/* Do not override real auth header, unless config instructs us to. */
	if (!conf->cookie_auth_override &&
		apr_table_get(r->headers_in, "Authorization")) {
		if (conf->cookie_auth_env) {
			unsetenv(conf->cookie_auth_env);
		}
		return DECLINED;
	}

	/* todo: protect against xxxCookieNamexxx, regex? */
	/* todo: make case insensitive? */
	/* Get the cookie (code from mod_log_config). */
	if ((cookies = apr_table_get(r->headers_in, "Cookie"))) {
		char *start_cookie, *end_cookie;
		if ((start_cookie = ap_strstr_c(cookies, conf->cookie_auth_cookie))) {
		    start_cookie += strlen(conf->cookie_auth_cookie) + 1;
		    cookie = apr_pstrdup(r->pool, start_cookie);
			/* kill everything in cookie after ';' */
			end_cookie = strchr(cookie, ';');
			if (end_cookie) {
				*end_cookie = '\0';
      }
      ap_unescape_url(cookie);
		}
	}

	/* No cookie? Nothing for us to do. */
	if (!cookie) {
                if (conf->cookie_auth_unauth_redirect) {
        	        const char* redirect = conf->cookie_auth_unauth_redirect;
        		compose_and_set_redirect(r, redirect);
                        return HTTP_MOVED_TEMPORARILY;
                }
                else {
			return DECLINED;
                }
	}

	/* Debug. */
	/*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
	    "%s=%s", conf->cookie_auth_cookie, cookie);*/

	char* aux_auth_info = "";

	/* Construct the fake auth_line. */
	if (conf->cookie_auth_base64) {
		char* decoded_cookie = apr_palloc(r->pool, apr_base64_decode_len(cookie));
    int decoded_cookie_length = apr_base64_decode(decoded_cookie, cookie);

		int valid = 1;

		/* if the cookie is encrypted, decrypt it in place */
		if (conf->cookie_auth_encrypt) {
      MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
      int keysize = strlen(conf->cookie_auth_encrypt);
      int blocksize = mcrypt_enc_get_block_size(td);

			// We will copy the iv from the beginning of the cookie.
			// The iv does not need to be null-terminated, but we will
			// null-terminate it for convenience.
			int iv_length = mcrypt_enc_get_iv_size(td);
			char* iv = (char*) apr_palloc(r->pool, iv_length + 1);
			memcpy(iv, decoded_cookie, iv_length);
			iv[iv_length] = '\0';

			// Take the iv off the beginning of the cookie
			decoded_cookie += iv_length;
      decoded_cookie_length -= iv_length;

      mcrypt_generic_init( td, conf->cookie_auth_encrypt, keysize, iv);
      // Encryption in CBC is performed in blocks, so our
      // decryption string will always be an integral number
      // of full blocks.
      char* decrypt_ptr = decoded_cookie;
      while (decoded_cookie_length >= blocksize) {
        mdecrypt_generic(td, decrypt_ptr, blocksize);
        decrypt_ptr += blocksize;
        decoded_cookie_length -= blocksize;
      }
      if (decoded_cookie_length != 0) {
        valid = 0;
      }
      mcrypt_generic_deinit (td);
      mcrypt_module_close(td);
      /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
        "mdecrypt(%s)=%s", conf->cookie_auth_cookie, decoded_cookie);*/
		}

		/* if the cookie did not decrypt, then do nothing */
		if (valid) {
			char* end_auth_info = strchr(decoded_cookie, '\t');

			if (end_auth_info) {
				aux_auth_info = decoded_cookie;
				char* unencoded_cookie = end_auth_info + 1;
				*end_auth_info = 0;

				auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, unencoded_cookie), NULL);
			}
			else {
				auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, decoded_cookie), NULL);
			}
		}
	} else {
		// Aux auth info and cookie encrypt features only available in base64 mode
		ap_unescape_url(cookie);
		auth_line = apr_pstrcat(r->pool, "Basic ",
			ap_pbase64encode(r->pool, cookie), NULL);
	}

	/* If there is aux auth info, then set the env variable */
	if (conf->cookie_auth_env) {
	  apr_table_set(r->subprocess_env, conf->cookie_auth_env, aux_auth_info);
	}

	/* Debug. */
	/*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
		"Authorization: %s", auth_line);*/

	/* If there is no aux auth info, then force a redirect if our conf directives say that we should */
        if (conf->cookie_auth_env_redirect && !strlen(aux_auth_info)) {
        	const char* redirect = conf->cookie_auth_env_redirect;
        	compose_and_set_redirect(r, redirect);
                return HTTP_MOVED_TEMPORARILY;
        }
        else {
	        /* Set fake auth_line. */
		if (auth_line) {
                	apr_table_set(r->headers_in, "Authorization", auth_line);
                }
	}

	/* Always return DECLINED because we don't authorize, */
	/* we just set things up for the next auth module to. */
    return DECLINED;
}