예제 #1
0
void jaxer_add_env_vars(request_rec * r)
{
    /* 
     * Add additonal vars that are needed by jaxer.
     * REMOTE_USER
     * REMOTE_HOST
     * STATUS_CODE
     * HTTPS
     */
	apr_table_t *env = r->subprocess_env;
    jaxer_dir_conf *config =
		ap_get_module_config(r->per_dir_config, &jaxer_module);

    int is_ip;
    int ssl_on;
    const char * ru = ap_get_remote_logname(r);
#ifndef APACHE1_3
    const char * rh = ap_get_remote_host(r->connection, config, REMOTE_NAME, &is_ip);
#else
    const char * rh = ap_get_remote_host(r->connection, config, REMOTE_NAME);
#endif

    if (ru)
        apr_table_setn(env, "REMOTE_USER", ru);
    // else
    //    apr_table_setn(env, "REMOTE_USER", "");

    if (rh && !is_ip)
        ap_table_setn(env, "REMOTE_HOST", rh);

    ap_table_setn(env, "STATUS_CODE", ap_psprintf(r->pool, "%d", r->status));

    ssl_on = jaxer_conn_is_https(r->connection);
    ap_table_setn(env, "HTTPS", ap_psprintf(r->pool, "%s", (ssl_on != 0)? "on" : "off" ));
}
예제 #2
0
파일: scoreboard.c 프로젝트: Ga-vin/apache
static int update_child_status_internal(int child_num,
                                        int thread_num,
                                        int status,
                                        conn_rec *c,
                                        request_rec *r)
{
    int old_status;
    worker_score *ws;
    process_score *ps;
    int mpm_generation;

    ws = &ap_scoreboard_image->servers[child_num][thread_num];
    old_status = ws->status;
    ws->status = status;

    ps = &ap_scoreboard_image->parent[child_num];

    if (status == SERVER_READY
        && old_status == SERVER_STARTING) {
        ws->thread_num = child_num * thread_limit + thread_num;
        ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation);
        ps->generation = mpm_generation;
    }

    if (ap_extended_status) {
        ws->last_used = apr_time_now();
        if (status == SERVER_READY || status == SERVER_DEAD) {
            /*
             * Reset individual counters
             */
            if (status == SERVER_DEAD) {
                ws->my_access_count = 0L;
                ws->my_bytes_served = 0L;
            }
            ws->conn_count = 0;
            ws->conn_bytes = 0;
        }
        if (r) {
            apr_cpystrn(ws->client, ap_get_remote_host(c, r->per_dir_config,
                        REMOTE_NOLOOKUP, NULL), sizeof(ws->client));
            copy_request(ws->request, sizeof(ws->request), r);
            if (r->server) {
                apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d",
                             r->server->server_hostname,
                             r->connection->local_addr->port);
            }
        }
        else if (c) {
            apr_cpystrn(ws->client, ap_get_remote_host(c, NULL,
                        REMOTE_NOLOOKUP, NULL), sizeof(ws->client));
            ws->request[0]='\0';
            ws->vhost[0]='\0';
        }
    }

    return old_status;
}
예제 #3
0
파일: mod_echo.c 프로젝트: Aimbot2/apache2
static int update_echo_child_status(ap_sb_handle_t *sbh,
                                    int status, conn_rec *c,
                                    apr_bucket_brigade *last_echoed)
{
    worker_score *ws = ap_get_scoreboard_worker(sbh);
    int old_status = ws->status;

    ws->status = status;

    if (!ap_extended_status)
        return old_status;

    ws->last_used = apr_time_now();

    /* initial pass only, please - in the name of efficiency */
    if (c) {
        apr_cpystrn(ws->client,
                    ap_get_remote_host(c, c->base_server->lookup_defaults,
                                       REMOTE_NOLOOKUP, NULL),
                    sizeof(ws->client));
        apr_cpystrn(ws->vhost, c->base_server->server_hostname,
                    sizeof(ws->vhost));
        /* Deliberate trailing space - filling in string on WRITE passes */
        apr_cpystrn(ws->request, "ECHO ", sizeof(ws->request));
    }

    /* each subsequent WRITE pass, let's update what we echoed */
    if (last_echoed) {
        brigade_peek(last_echoed, ws->request + sizeof("ECHO ") - 1,
                     sizeof(ws->request) - sizeof("ECHO ") + 1);
    }

    return old_status;
}
예제 #4
0
API_EXPORT(void) ap_log_reason (const char *reason, const char *file, request_rec *r) 
{
    ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
		"access to %s failed for %s, reason: %s",
		file,
		ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
		reason);
}
예제 #5
0
static int req_get_remote_host(lua_State *L)
{
  request_rec *r = CHECK_REQUEST_OBJECT(1);
  int type = (int)luaL_optnumber(L, 2, REMOTE_NOLOOKUP);
  int str_is_ip;

  lua_pushstring (L, ap_get_remote_host (r->connection, r->per_dir_config, type , &str_is_ip));
  lua_pushnumber(L, str_is_ip);
  return 2;
}
예제 #6
0
static int find_allowdeny(request_rec *r, apr_array_header_t *a, int method)
{

    allowdeny *ap = (allowdeny *) a->elts;
    apr_int64_t mmask = (AP_METHOD_BIT << method);
    int i;
    int gothost = 0;
    const char *remotehost = NULL;

    for (i = 0; i < a->nelts; ++i) {
	if (!(mmask & ap[i].limited))
	    continue;

	switch (ap[i].type) {
	case T_ENV:
	    if (apr_table_get(r->subprocess_env, ap[i].x.from)) {
		return 1;
	    }
	    break;

	case T_ALL:
	    return 1;

	case T_IP:
            if (apr_ipsubnet_test(ap[i].x.ip, r->connection->remote_addr)) {
                return 1;
            }
            break;

	case T_HOST:
	    if (!gothost) {
                int remotehost_is_ip;

		remotehost = ap_get_remote_host(r->connection, r->per_dir_config,
                                                REMOTE_DOUBLE_REV, &remotehost_is_ip);

		if ((remotehost == NULL) || remotehost_is_ip)
		    gothost = 1;
		else
		    gothost = 2;
	    }

	    if ((gothost == 2) && in_domain(ap[i].x.from, remotehost))
		return 1;
	    break;

	case T_FAIL:
	    /* do nothing? */
	    break;
	}
    }

    return 0;
}
예제 #7
0
파일: mod_access.c 프로젝트: AzerTyQsdF/osx
static int find_allowdeny(request_rec *r, array_header *a, int method)
{
    allowdeny *ap = (allowdeny *) a->elts;
    int mmask = (1 << method);
    int i;
    int gothost = 0;
    const char *remotehost = NULL;

    for (i = 0; i < a->nelts; ++i) {
	if (!(mmask & ap[i].limited))
	    continue;

	switch (ap[i].type) {
	case T_ENV:
	    if (ap_table_get(r->subprocess_env, ap[i].x.from)) {
		return 1;
	    }
	    break;

	case T_ALL:
	    return 1;

	case T_IP:
	    if (ap[i].x.ip.net.s_addr != INADDR_NONE
		&& (r->connection->remote_addr.sin_addr.s_addr
		    & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) {
		return 1;
	    }
	    break;

	case T_HOST:
	    if (!gothost) {
		remotehost = ap_get_remote_host(r->connection, r->per_dir_config,
					    REMOTE_DOUBLE_REV);

		if ((remotehost == NULL) || is_ip(remotehost))
		    gothost = 1;
		else
		    gothost = 2;
	    }

	    if ((gothost == 2) && in_domain(ap[i].x.from, remotehost))
		return 1;
	    break;

	case T_FAIL:
	    /* do nothing? */
	    break;
	}
    }

    return 0;
}
예제 #8
0
static authn_status pam_authenticate_with_login_password(request_rec * r, const char * pam_service,
	const char * login, const char * password, int steps) {
	pam_handle_t * pamh = NULL;
	struct pam_conv pam_conversation = { &pam_authenticate_conv, (void *) password };
	const char * stage = "PAM transaction failed for service";
	const char * param = pam_service;
	int ret;
	ret = pam_start(pam_service, login, &pam_conversation, &pamh);
	if (ret == PAM_SUCCESS) {
		const char * remote_host_or_ip = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL);
		if (remote_host_or_ip) {
			stage = "PAM pam_set_item PAM_RHOST failed for service";
			ret = pam_set_item(pamh, PAM_RHOST, remote_host_or_ip);
		}
	}
	if (ret == PAM_SUCCESS) {
		if (steps & _PAM_STEP_AUTH) {
			param = login;
			stage = "PAM authentication failed for user";
			ret = pam_authenticate(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
		}
		if ((ret == PAM_SUCCESS) && (steps & _PAM_STEP_ACCOUNT)) {
			param = login;
			stage = "PAM account validation failed for user";
			ret = pam_acct_mgmt(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
			if (ret == PAM_NEW_AUTHTOK_REQD) {
				authnz_pam_config_rec * conf = ap_get_module_config(r->per_dir_config, &authnz_pam_module);
				if (conf && conf->expired_redirect_url) {
					ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
						"mod_authnz_pam: PAM_NEW_AUTHTOK_REQD: redirect to [%s]",
						conf->expired_redirect_url);
					apr_table_addn(r->headers_out, "Location", format_location(r, conf->expired_redirect_url, login));
					return HTTP_TEMPORARY_REDIRECT;
				}
			}
		}
	}
	if (ret != PAM_SUCCESS) {
		const char * strerr = pam_strerror(pamh, ret);
		ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, "mod_authnz_pam: %s %s: %s", stage, param, strerr);
		apr_table_setn(r->subprocess_env, _EXTERNAL_AUTH_ERROR_ENV_NAME, apr_pstrdup(r->pool, strerr));
		pam_end(pamh, ret);
		return AUTH_DENIED;
	}
	apr_table_setn(r->subprocess_env, _REMOTE_USER_ENV_NAME, login);
	r->user = apr_pstrdup(r->pool, login);
	ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, r->server, "mod_authnz_pam: PAM authentication passed for user %s", login);
	pam_end(pamh, ret);
	return AUTH_GRANTED;
}
예제 #9
0
AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num,
                                                    int thread_num,
                                                    int status,
                                                    request_rec *r)
{
    int old_status;
    worker_score *ws;
    process_score *ps;

    if (child_num < 0) {
        return -1;
    }

    ws = &ap_scoreboard_image->servers[child_num][thread_num];
    old_status = ws->status;
    ws->status = status;

    ps = &ap_scoreboard_image->parent[child_num];

    if (status == SERVER_READY
        && old_status == SERVER_STARTING) {
        ws->thread_num = child_num * thread_limit + thread_num;
        ps->generation = ap_my_generation;
    }

    if (ap_extended_status) {
        ws->last_used = apr_time_now();
        if (status == SERVER_READY || status == SERVER_DEAD) {
            /*
             * Reset individual counters
             */
            if (status == SERVER_DEAD) {
                ws->my_access_count = 0L;
                ws->my_bytes_served = 0L;
            }
            ws->conn_count = 0;
            ws->conn_bytes = 0;
        }
        if (r) {
            conn_rec *c = r->connection;
            apr_cpystrn(ws->client, ap_get_remote_host(c, r->per_dir_config,
                        REMOTE_NOLOOKUP, NULL), sizeof(ws->client));
            copy_request(ws->request, sizeof(ws->request), r);
            apr_cpystrn(ws->vhost, r->server->server_hostname,
                        sizeof(ws->vhost));
        }
    }

    return old_status;
}
예제 #10
0
static PyObject * req_get_remote_host(requestobject *self, PyObject *args)
{

    int type = REMOTE_NAME;
    const char *host;

    if (! PyArg_ParseTuple(args, "|i", &type)) 
	return NULL;
    
    host = ap_get_remote_host(self->request_rec->connection, 
			      self->request_rec->per_dir_config, type);

    if (! host) {
	Py_INCREF(Py_None);
	return Py_None;
    }
    else
	return PyString_FromString(host);
}
예제 #11
0
static int find_allowdeny(request_rec *r, apr_array_header_t *a,
                          int method, apr_time_t expire_time)
{

    allowdeny *ap = (allowdeny *) a->elts;
    apr_int64_t mmask = (AP_METHOD_BIT << method);
    int i;
    int gothost = 0;
    const char *remotehost = NULL;
    char errmsg_buf[120];
    apr_status_t rv;
    auth_remote_svr_conf *svr_conf =
        ap_get_module_config(r->server->module_config, &auth_remote_module);

    for (i = 0; i < a->nelts; ++i) {
        if (!(mmask & ap[i].limited)) {
            continue;
        }

        switch (ap[i].type) {
            case T_ENV:
                if (apr_table_get(r->subprocess_env, ap[i].x.from)) {
                    return 1;
                }
                break;

            case T_NENV:
                if (!apr_table_get(r->subprocess_env, ap[i].x.from)) {
                    return 1;
                }
                break;

            case T_ALL:
                return 1;

            case T_IP:
                if (apr_ipsubnet_test(ap[i].x.ip,
                                      r->connection->remote_addr)) {
                    return 1;
                }
                break;
            
            case T_URL:
#if APR_HAS_THREADS
                rv = apr_thread_mutex_lock (svr_conf->mutex);
                if (rv != APR_SUCCESS) {
                    apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                  "fail to obtain mutex: %s", errmsg_buf);
                    break;
                }
                if (init_per_url_directive_data (r, &ap[i].x.remote_info)
                    == -1) {
                    rv = apr_thread_mutex_unlock (svr_conf->mutex);
                    if (rv != APR_SUCCESS) {
                        apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                      "fail to release mutex: %s",
                                      errmsg_buf);
                        break;
                    }
                    break;
                }
                rv = apr_thread_mutex_unlock (svr_conf->mutex);
                if (rv != APR_SUCCESS) {
                    apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                  "fail to release mutex: %s", errmsg_buf);
                    break;
                }
#else
                if (init_per_url_directive_data (&ap[i].x.remote_info) == -1)
                    break;
#endif
                if (ip_in_url_test (r, r->connection->remote_addr,
                                    &ap[i].x.remote_info, expire_time)
                    == 1) {
                    return 1;
                }
                break;

            case T_FILE:
#if APR_HAS_THREADS
                rv = apr_thread_mutex_lock (svr_conf->mutex);
                if (rv != APR_SUCCESS) {
                    apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                  "fail to obtain mutex: %s", errmsg_buf);
                    break;
                }
                if (init_per_local_file_directive_data
                    (r, &ap[i].x.local_file_info)
                    == -1) {
                    rv = apr_thread_mutex_unlock (svr_conf->mutex);
                    if (rv != APR_SUCCESS) {
                        apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                      "fail to release mutex: %s", errmsg_buf);
                        break;
                    }
                    break;
                }
                rv = apr_thread_mutex_unlock (svr_conf->mutex);
                if (rv != APR_SUCCESS) {
                    apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                  "fail to release mutex: %s", errmsg_buf);
                    break;
                }
#else
                if (init_per_local_file_directive_data (&ap[i].x.local_file_info) == -1)
                    break;
#endif
                if (ip_in_local_file_test
                    (r, r->connection->remote_addr, &ap[i].x.local_file_info) == 1) {
                    return 1;
                }
                break;

            case T_HOST:
                if (!gothost) {
                    int remotehost_is_ip;

                    remotehost = ap_get_remote_host(r->connection,
                                                    r->per_dir_config,
                                                    REMOTE_DOUBLE_REV,
                                                    &remotehost_is_ip);

                    if ((remotehost == NULL) || remotehost_is_ip) {
                        gothost = 1;
                    }
                    else {
                        gothost = 2;
                    }
                }

                if ((gothost == 2) && in_domain(ap[i].x.from, remotehost)) {
                    return 1;
                }
                break;

            case T_FAIL:
                    /* do nothing? */
                break;
        }
    }

    return 0;
}
예제 #12
0
static apr_status_t ajp_marshal_into_msgb(ajp_msg_t *msg,
                                          request_rec *r,
                                          apr_uri_t *uri)
{
    int method;
    apr_uint32_t i, num_headers = 0;
    apr_byte_t is_ssl;
    char *remote_host;
    const char *session_route, *envvar;
    const apr_array_header_t *arr = apr_table_elts(r->subprocess_env);
    const apr_table_entry_t *elts = (const apr_table_entry_t *)arr->elts;

    ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, "Into ajp_marshal_into_msgb");

    if ((method = sc_for_req_method_by_id(r)) == UNKNOWN_METHOD) {
        ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, APLOGNO(02437)
               "ajp_marshal_into_msgb - Sending unknown method %s as request attribute",
               r->method);
        method = SC_M_JK_STORED;
    }

    is_ssl = (apr_byte_t) ap_proxy_conn_is_https(r->connection);

    if (r->headers_in && apr_table_elts(r->headers_in)) {
        const apr_array_header_t *t = apr_table_elts(r->headers_in);
        num_headers = t->nelts;
    }

    remote_host = (char *)ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_HOST, NULL);

    ajp_msg_reset(msg);

    if (ajp_msg_append_uint8(msg, CMD_AJP13_FORWARD_REQUEST)     ||
        ajp_msg_append_uint8(msg, (apr_byte_t) method)           ||
        ajp_msg_append_string(msg, r->protocol)                  ||
        ajp_msg_append_string(msg, uri->path)                    ||
        ajp_msg_append_string(msg, r->useragent_ip)              ||
        ajp_msg_append_string(msg, remote_host)                  ||
        ajp_msg_append_string(msg, ap_get_server_name(r))        ||
        ajp_msg_append_uint16(msg, (apr_uint16_t)r->connection->local_addr->port) ||
        ajp_msg_append_uint8(msg, is_ssl)                        ||
        ajp_msg_append_uint16(msg, (apr_uint16_t) num_headers)) {

        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00968)
               "ajp_marshal_into_msgb: "
               "Error appending the message beginning");
        return APR_EGENERAL;
    }

    for (i = 0 ; i < num_headers ; i++) {
        int sc;
        const apr_array_header_t *t = apr_table_elts(r->headers_in);
        const apr_table_entry_t *elts = (apr_table_entry_t *)t->elts;

        if ((sc = sc_for_req_header(elts[i].key)) != UNKNOWN_METHOD) {
            if (ajp_msg_append_uint16(msg, (apr_uint16_t)sc)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00969)
                       "ajp_marshal_into_msgb: "
                       "Error appending the header name");
                return AJP_EOVERFLOW;
            }
        }
        else {
            if (ajp_msg_append_string(msg, elts[i].key)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00970)
                       "ajp_marshal_into_msgb: "
                       "Error appending the header name");
                return AJP_EOVERFLOW;
            }
        }

        if (ajp_msg_append_string(msg, elts[i].val)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00971)
                   "ajp_marshal_into_msgb: "
                   "Error appending the header value");
            return AJP_EOVERFLOW;
        }
        ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r,
                   "ajp_marshal_into_msgb: Header[%d] [%s] = [%s]",
                   i, elts[i].key, elts[i].val);
    }

/* XXXX need to figure out how to do this
    if (s->secret) {
        if (ajp_msg_append_uint8(msg, SC_A_SECRET) ||
            ajp_msg_append_string(msg, s->secret)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                   "Error ajp_marshal_into_msgb - "
                   "Error appending secret");
            return APR_EGENERAL;
        }
    }
 */

    if (r->user) {
        if (ajp_msg_append_uint8(msg, SC_A_REMOTE_USER) ||
            ajp_msg_append_string(msg, r->user)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00972)
                   "ajp_marshal_into_msgb: "
                   "Error appending the remote user");
            return AJP_EOVERFLOW;
        }
    }
    if (r->ap_auth_type) {
        if (ajp_msg_append_uint8(msg, SC_A_AUTH_TYPE) ||
            ajp_msg_append_string(msg, r->ap_auth_type)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00973)
                   "ajp_marshal_into_msgb: "
                   "Error appending the auth type");
            return AJP_EOVERFLOW;
        }
    }
    /* XXXX  ebcdic (args converted?) */
    if (uri->query) {
        if (ajp_msg_append_uint8(msg, SC_A_QUERY_STRING) ||
            ajp_msg_append_string(msg, uri->query)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00974)
                   "ajp_marshal_into_msgb: "
                   "Error appending the query string");
            return AJP_EOVERFLOW;
        }
    }
    if ((session_route = apr_table_get(r->notes, "session-route"))) {
        if (ajp_msg_append_uint8(msg, SC_A_JVM_ROUTE) ||
            ajp_msg_append_string(msg, session_route)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00975)
                   "ajp_marshal_into_msgb: "
                   "Error appending the jvm route");
            return AJP_EOVERFLOW;
        }
    }
/* XXX: Is the subprocess_env a right place?
 * <Location /examples>
 *   ProxyPass ajp://remote:8009/servlets-examples
 *   SetEnv SSL_SESSION_ID CUSTOM_SSL_SESSION_ID
 * </Location>
 */
    /*
     * Only lookup SSL variables if we are currently running HTTPS.
     * Furthermore ensure that only variables get set in the AJP message
     * that are not NULL and not empty.
     */
    if (is_ssl) {
        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_CLIENT_CERT_INDICATOR))
            && envvar[0]) {
            if (ajp_msg_append_uint8(msg, SC_A_SSL_CERT)
                || ajp_msg_append_string(msg, envvar)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00976)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL certificates");
                return AJP_EOVERFLOW;
            }
        }

        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_CIPHER_INDICATOR))
            && envvar[0]) {
            if (ajp_msg_append_uint8(msg, SC_A_SSL_CIPHER)
                || ajp_msg_append_string(msg, envvar)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00977)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL ciphers");
                return AJP_EOVERFLOW;
            }
        }

        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_SESSION_INDICATOR))
            && envvar[0]) {
            if (ajp_msg_append_uint8(msg, SC_A_SSL_SESSION)
                || ajp_msg_append_string(msg, envvar)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00978)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL session");
                return AJP_EOVERFLOW;
            }
        }

        /* ssl_key_size is required by Servlet 2.3 API */
        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_KEY_SIZE_INDICATOR))
            && envvar[0]) {

            if (ajp_msg_append_uint8(msg, SC_A_SSL_KEY_SIZE)
                || ajp_msg_append_uint16(msg, (unsigned short) atoi(envvar))) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00979)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL key size");
                return APR_EGENERAL;
            }
        }
    }
    /* If the method was unrecognized, encode it as an attribute */
    if (method == SC_M_JK_STORED) {
        if (ajp_msg_append_uint8(msg, SC_A_STORED_METHOD)
            || ajp_msg_append_string(msg, r->method)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02438)
                          "ajp_marshal_into_msgb: "
                          "Error appending the method '%s' as request attribute",
                          r->method);
            return AJP_EOVERFLOW;
        }
    }
    /* Forward the remote port information, which was forgotten
     * from the builtin data of the AJP 13 protocol.
     * Since the servlet spec allows to retrieve it via getRemotePort(),
     * we provide the port to the Tomcat connector as a request
     * attribute. Modern Tomcat versions know how to retrieve
     * the remote port from this attribute.
     */
    {
        const char *key = SC_A_REQ_REMOTE_PORT;
        char *val = apr_itoa(r->pool, r->useragent_addr->port);
        if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
            ajp_msg_append_string(msg, key)   ||
            ajp_msg_append_string(msg, val)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00980)
                    "ajp_marshal_into_msgb: "
                    "Error appending attribute %s=%s",
                    key, val);
            return AJP_EOVERFLOW;
        }
    }
    /* Forward the local ip address information, which was forgotten
     * from the builtin data of the AJP 13 protocol.
     * Since the servlet spec allows to retrieve it via getLocalAddr(),
     * we provide the address to the Tomcat connector as a request
     * attribute. Modern Tomcat versions know how to retrieve
     * the local address from this attribute.
     */
    {
        const char *key = SC_A_REQ_LOCAL_ADDR;
        char *val = r->connection->local_ip;
        if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
            ajp_msg_append_string(msg, key)   ||
            ajp_msg_append_string(msg, val)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02646)
                    "ajp_marshal_into_msgb: "
                    "Error appending attribute %s=%s",
                    key, val);
            return AJP_EOVERFLOW;
        }
    }
    /* Use the environment vars prefixed with AJP_
     * and pass it to the header striping that prefix.
     */
    for (i = 0; i < (apr_uint32_t)arr->nelts; i++) {
        if (!strncmp(elts[i].key, "AJP_", 4)) {
            if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
                ajp_msg_append_string(msg, elts[i].key + 4)   ||
                ajp_msg_append_string(msg, elts[i].val)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00981)
                        "ajp_marshal_into_msgb: "
                        "Error appending attribute %s=%s",
                        elts[i].key, elts[i].val);
                return AJP_EOVERFLOW;
            }
        }
    }

    if (ajp_msg_append_uint8(msg, SC_A_ARE_DONE)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00982)
               "ajp_marshal_into_msgb: "
               "Error appending the message end");
        return AJP_EOVERFLOW;
    }

    ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r,
            "ajp_marshal_into_msgb: Done");
    return APR_SUCCESS;
}
// Find the cookie and figure out what to do
static int spot_cookie(request_rec *r)
{
    cookietrack_settings_rec *dcfg = ap_get_module_config(r->per_dir_config,
                                                &cookietrack_module);

    const char *cookie_header;
    ap_regmatch_t regm[NUM_SUBS];

    /* Do not run in subrequests */
    if (!dcfg->enabled || r->main) {
        return DECLINED;
    }

    /* Is DNT set? */
    const char *dnt_is_set = apr_table_get( r->headers_in, "DNT" );
    _DEBUG && fprintf( stderr, "DNT: %s\n", dnt_is_set );

    /* Do we already have a cookie? */
    char *cur_cookie_value = NULL;
    if( (cookie_header = apr_table_get(r->headers_in, "Cookie")) ){

        // this will match the FIRST occurance of the cookiename, not
        // subsequent ones.
        if( !ap_regexec(dcfg->regexp, cookie_header, NUM_SUBS, regm, 0) ) {
            /* Our regexp,
             * ^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)
             * only allows for $1 or $2 to be available. ($0 is always
             * filled with the entire matched expression, not just
             * the part in parentheses.) So just check for either one
             * and assign to cookieval if present. */
            if( regm[1].rm_so != -1 ) {
                cur_cookie_value = ap_pregsub(r->pool, "$1", cookie_header,
                                       NUM_SUBS, regm);
            }
            if( regm[2].rm_so != -1 ) {
                cur_cookie_value = ap_pregsub(r->pool, "$2", cookie_header,
                                       NUM_SUBS, regm);
            }
        }
    }

    _DEBUG && fprintf( stderr, "Current Cookie: %s\n", cur_cookie_value );

    /* XFF support inspired by this patch:
       http://www.mail-archive.com/[email protected]/msg17378.html

       And this implementation for scanning for remote ip:
       http://apache.wirebrain.de/lxr/source/modules/metadata/mod_remoteip.c?v=2.3-trunk#267
    */

    // Get the IP address of the originating request
    const char *rname = NULL;   // Originating IP address
    char *xff         = NULL;   // X-Forwarded-For, or equivalent header type

    // Should we look at a header?
    if( xff = apr_table_get(r->headers_in, dcfg->cookie_ip_header) ) {

        // There might be multiple addresses in the header
        // Check if there's a comma in there somewhere

        // no comma, this is the address we can use
        if( (rname = strrchr(xff, ',')) == NULL ) {
            rname = xff;

        // whitespace/commas left, remove 'm
        } else {

            // move past the comma
            rname++;

            // and any whitespace we might find
            while( *rname == ' ' ) {
                rname++;
            }
        }

    // otherwise, get it from the remote host
    } else {
        rname = ap_get_remote_host( r->connection, r->per_dir_config,
                                    REMOTE_NAME, NULL );
    }

    _DEBUG && fprintf( stderr, "Remote Address: %s\n", rname );

    /* Determine the value of the cookie we're going to set: */
    /* Make sure we have enough room here... */
    char new_cookie_value[ _MAX_COOKIE_LENGTH ];

    // dnt is set, and we care about that
    if( dnt_is_set && dcfg->comply_with_dnt ) {

        // you don't want us to set a cookie, alright then our work is done.
        if( !dcfg->set_dnt_cookie ) {
            return DECLINED;
        }

        char *dnt_value = dcfg->dnt_value;

        // you already ahve a cookie, but it might be whitelisted
        if( cur_cookie_value ) {

            // you might have whitelisted this value; let's check
            // Following tutorial code here again:
            // http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-19.html
            int i;
            for( i = 0; i < dcfg->dnt_exempt->nelts; i++ ) {
                _DEBUG && fprintf( stderr, "e: %d\n", i );

                char *exempt = ((char **)dcfg->dnt_exempt->elts)[i];

                //it's indeed whiteliested, we should use this value instead
                if( strcasecmp( cur_cookie_value, exempt ) == 0 ) {
                    _DEBUG && fprintf( stderr,
                        "Cookie %s is DNT exempt\n", cur_cookie_value );

                    dnt_value = exempt;
                }
            }
        }

        // dnt_value is a pointer, hence the sprintf
        sprintf( new_cookie_value, "%s", dnt_value );

    // No DNT header, so we need a cookie value to set
    } else {

        // there already is a cookie set
        if( cur_cookie_value ) {

            // but it's set to the DNT cookie
            if( strcasecmp( cur_cookie_value, dcfg->dnt_value ) == 0 ) {

                // if we have some sort of library that's generating the
                // UID, call that with the cookie we would be setting
                if( _EXTERNAL_UID_FUNCTION ) {
                    char ts[ _MAX_COOKIE_LENGTH ];
                    sprintf( ts, "%" APR_TIME_T_FMT, apr_time_now() );
                    gen_uid( new_cookie_value, ts, rname );

                // otherwise, just set it
                } else {
                    sprintf( new_cookie_value,
                             "%s.%" APR_TIME_T_FMT, rname, apr_time_now() );
                }

            // it's set to something reasonable - note we're still setting
            // a new cookie, even when there's no expires requested, because
            // we don't know if there's an expires on the /current/ cookie.
            // this could be added, but this seems to work for now.
            } else {
                // XXX we use a apr_pstrndup instead, so we can't overflow
                // the buffer if we get sent garbage
                // The return value is a
                sprintf( new_cookie_value, "%s",
                    apr_pstrndup( r->pool, cur_cookie_value, _MAX_COOKIE_LENGTH ) );

            }

        // it's either carbage, or not set; either way,
        // we need to generate a new one
        } else {
            // if we have some sort of library that's generating the
            // UID, call that with the cookie we would be setting
            if( _EXTERNAL_UID_FUNCTION ) {
                char ts[ _MAX_COOKIE_LENGTH ];
                sprintf( ts, "%" APR_TIME_T_FMT, apr_time_now() );
                gen_uid( new_cookie_value, ts, rname );

            // otherwise, just set it
            } else {
                sprintf( new_cookie_value,
                         "%s.%" APR_TIME_T_FMT, rname, apr_time_now() );
            }
        }
    }

    _DEBUG && fprintf( stderr, "New cookie: %s\n", new_cookie_value );

    /* Set the cookie in a note, for logging */
    apr_table_setn(r->notes, dcfg->note_name, new_cookie_value);

    make_cookie(r,  new_cookie_value,
                    cur_cookie_value,
                    (dnt_is_set && dcfg->comply_with_dnt)   // should we use dnt expires?
                );

    // We need to flush the stream for messages to appear right away.
    // Performing an fflush() in a production system is not good for
    // performance - don't do this for real.
    _DEBUG && fflush(stderr);

    return OK;                  /* We set our cookie */
}
// Generate the actual cookie
void make_cookie(request_rec *r, char uid[], char cur_uid[], int use_dnt_expires)
{   // configuration
    cookietrack_settings_rec *dcfg;
    dcfg = ap_get_module_config(r->per_dir_config, &cookietrack_module);

    /* 1024 == hardcoded constant */
    char cookiebuf[1024];
    char *new_cookie;
    const char *rname = ap_get_remote_host(r->connection, r->per_dir_config,
                                           REMOTE_NAME, NULL);

    /* XXX: hmm, this should really tie in with mod_unique_id */
    apr_snprintf(cookiebuf, sizeof(cookiebuf), "%s", uid );

    if (dcfg->expires) {

        /* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */
        new_cookie = apr_psprintf(r->pool, "%s=%s; path=/",
                                  dcfg->cookie_name, cookiebuf);

        if ((dcfg->style == CT_UNSET) || (dcfg->style == CT_NETSCAPE)) {
            apr_time_exp_t tms;
            apr_time_exp_gmt(&tms, r->request_time
                                 + apr_time_from_sec(dcfg->expires));

            // this sets a fixed expires in the future
            if( use_dnt_expires ) {
                new_cookie = apr_psprintf( r->pool,
                                "%s; expires=%s", new_cookie, dcfg->dnt_expires );

            // use the dynamic one
            } else {
                new_cookie = apr_psprintf( r->pool,
                                "%s; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT",
                                new_cookie, apr_day_snames[tms.tm_wday],
                                tms.tm_mday,
                                apr_month_snames[tms.tm_mon],
                                tms.tm_year % 100,
                                tms.tm_hour, tms.tm_min, tms.tm_sec
                             );
            }
        } else {
            int expires = 0;

            // use a static expires date in the future
            if( use_dnt_expires ) {
                time_t t;
                time( &t );
                expires = dcfg->dnt_max_age - t;

            // use the dynamic one
            } else {
                expires = dcfg->expires;
            }

            _DEBUG && fprintf( stderr, "Expires = %d\n", expires );

            new_cookie = apr_psprintf( r->pool,
                                       "%s; max-age=%d",
                                       new_cookie,
                                       expires );
        }

    } else {
        new_cookie = apr_psprintf(r->pool, "%s=%s; path=/",
                                  dcfg->cookie_name, cookiebuf);
    }

    if (dcfg->cookie_domain != NULL) {
        new_cookie = apr_pstrcat(r->pool, new_cookie, "; domain=",
                                 dcfg->cookie_domain,
                                 (dcfg->style == CT_COOKIE2
                                  ? "; version=1"
                                  : ""),
                                 NULL);
    }

    // r->err_headers_out also honors non-2xx responses and
    // internal redirects. See the patch here:
    // http://svn.apache.org/viewvc?view=revision&revision=1154620
    apr_table_addn( r->err_headers_out,
                    (dcfg->style == CT_COOKIE2 ? "Set-Cookie2" : "Set-Cookie"),
                    new_cookie );

    // we also set it on the INCOMING cookie header, so the app can
    // Just Use It without worrying. Only do so if we don't already
    // have an incoming cookie value, or it will send 2 cookies with
    // the same name, with both the old and new value :(
    if( !cur_uid ) {
        apr_table_addn( r->headers_in, "Cookie",  new_cookie );
    }

    // Set headers? We set both incoming AND outgoing:
    if( dcfg->send_header ) {
        // incoming
        apr_table_addn( r->headers_in,
                        dcfg->header_name,
                        apr_pstrdup(r->pool, uid) );

        // outgoing
        apr_table_addn( r->err_headers_out,
                        dcfg->header_name,
                        apr_pstrdup(r->pool, uid) );
    }

    // set a note, so we can capture it in the logs
    // this expects chars, and apr_pstrdup will make sure any char stays
    // in scope for the function. If not, it ends up being empty.
    apr_table_setn( r->notes, dcfg->note_name, apr_pstrdup(r->pool, uid) );

}
예제 #15
0
AP_DECLARE(void) ap_add_common_vars(request_rec *r)
{
    apr_table_t *e;
    server_rec *s = r->server;
    conn_rec *c = r->connection;
    core_dir_config *conf =
        (core_dir_config *)ap_get_core_module_config(r->per_dir_config);
    const char *env_temp;
    const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
    const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
    int i;
    apr_port_t rport;
    char *q;

    /* use a temporary apr_table_t which we'll overlap onto
     * r->subprocess_env later
     * (exception: if r->subprocess_env is empty at the start,
     * write directly into it)
     */
    if (apr_is_empty_table(r->subprocess_env)) {
        e = r->subprocess_env;
    }
    else {
        e = apr_table_make(r->pool, 25 + hdrs_arr->nelts);
    }

    /* First, add environment vars from headers... this is as per
     * CGI specs, though other sorts of scripting interfaces see
     * the same vars...
     */

    for (i = 0; i < hdrs_arr->nelts; ++i) {
        if (!hdrs[i].key) {
            continue;
        }

        /* A few headers are special cased --- Authorization to prevent
         * rogue scripts from capturing passwords; content-type and -length
         * for no particular reason.
         */

        if (!strcasecmp(hdrs[i].key, "Content-type")) {
            apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val);
        }
        else if (!strcasecmp(hdrs[i].key, "Content-length")) {
            apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val);
        }
        /*
         * You really don't want to disable this check, since it leaves you
         * wide open to CGIs stealing passwords and people viewing them
         * in the environment with "ps -e".  But, if you must...
         */
#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
        else if (!strcasecmp(hdrs[i].key, "Authorization")
                 || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
            if (conf->cgi_pass_auth == AP_CGI_PASS_AUTH_ON) {
                add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
            }
        }
#endif
        else
            add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
    }

    env_temp = apr_table_get(r->subprocess_env, "PATH");
    if (env_temp == NULL) {
        env_temp = getenv("PATH");
    }
    if (env_temp == NULL) {
        env_temp = DEFAULT_PATH;
    }
    apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp));

#if defined(WIN32)
    env2env(e, "SystemRoot");
    env2env(e, "COMSPEC");
    env2env(e, "PATHEXT");
    env2env(e, "WINDIR");
#elif defined(OS2)
    env2env(e, "COMSPEC");
    env2env(e, "ETC");
    env2env(e, "DPATH");
    env2env(e, "PERLLIB_PREFIX");
#elif defined(BEOS)
    env2env(e, "LIBRARY_PATH");
#elif defined(DARWIN)
    env2env(e, "DYLD_LIBRARY_PATH");
#elif defined(_AIX)
    env2env(e, "LIBPATH");
#elif defined(__HPUX__)
    /* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */
    env2env(e, "SHLIB_PATH");
    env2env(e, "LD_LIBRARY_PATH");
#else /* Some Unix */
    env2env(e, "LD_LIBRARY_PATH");
#endif

    apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
    apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner());
    apr_table_addn(e, "SERVER_NAME",
                   ap_escape_html(r->pool, ap_get_server_name_for_url(r)));
    apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip);  /* Apache */
    apr_table_addn(e, "SERVER_PORT",
                  apr_psprintf(r->pool, "%u", ap_get_server_port(r)));
    add_unless_null(e, "REMOTE_HOST",
                    ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL));
    apr_table_addn(e, "REMOTE_ADDR", r->useragent_ip);
    apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r));    /* Apache */
    apr_table_setn(e, "REQUEST_SCHEME", ap_http_scheme(r));
    apr_table_addn(e, "CONTEXT_PREFIX", ap_context_prefix(r));
    apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r));
    apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
    if (apr_table_get(r->notes, "proxy-noquery") && (q = ap_strchr(r->filename, '?'))) {
        *q = '\0';
        apr_table_addn(e, "SCRIPT_FILENAME", apr_pstrdup(r->pool, r->filename));
        *q = '?';
    }
    else {
        apr_table_addn(e, "SCRIPT_FILENAME", r->filename);  /* Apache */
    }

    rport = c->client_addr->port;
    apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport));

    if (r->user) {
        apr_table_addn(e, "REMOTE_USER", r->user);
    }
    else if (r->prev) {
        request_rec *back = r->prev;

        while (back) {
            if (back->user) {
                apr_table_addn(e, "REDIRECT_REMOTE_USER", back->user);
                break;
            }
            back = back->prev;
        }
    }
    add_unless_null(e, "AUTH_TYPE", r->ap_auth_type);
    env_temp = ap_get_remote_logname(r);
    if (env_temp) {
        apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, env_temp));
    }

    /* Apache custom error responses. If we have redirected set two new vars */

    if (r->prev) {
        /* PR#57785: reconstruct full URL here */
        apr_uri_t *uri = &r->prev->parsed_uri;
        if (!uri->scheme) {
            uri->scheme = (char*)ap_http_scheme(r->prev);
        }
        if (!uri->port) {
            uri->port = ap_get_server_port(r->prev);
            uri->port_str = apr_psprintf(r->pool, "%u", uri->port);
        }
        if (!uri->hostname) {
            uri->hostname = (char*)ap_get_server_name_for_url(r->prev);
        }
        add_unless_null(e, "REDIRECT_QUERY_STRING", r->prev->args);
        add_unless_null(e, "REDIRECT_URL",
                        apr_uri_unparse(r->pool, uri, 0));
    }

    if (e != r->subprocess_env) {
        apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET);
    }
}
/* Run an external authentication program using the given method for passing
 * in the data.  The login name is always passed in.   Dataname is "GROUP" or
 * "PASS" and data is the group list or password being checked.  To launch
 * a detached daemon, run this with extmethod=NULL.
 *
 * If the authenticator was run, we return the numeric code from the
 * authenticator, normally 0 if the login was valid, some small positive
 * number if not.  If we were not able to run the authenticator, we log
 * an error message and return a numeric error code:
 *
 *   -1   Could not execute authenticator, usually a path or permission problem
 *   -2   The external authenticator crashed or was killed.
 *   -3   Could not create process attribute structure
 *   -4   apr_proc_wait() did not return a status code.  Should never happen.
 *   -5   apr_proc_wait() returned before child finished.  Should never happen.
 */
static int exec_external(const char *extpath, const char *extmethod,
		const request_rec *r, const char *dataname, const char *data)
{
    conn_rec *c= r->connection;
    apr_pool_t *p= r->pool;
    int isdaemon, usecheck= 0, usepipeout= 0, usepipein= 0;
    apr_procattr_t *procattr;
    apr_proc_t proc;
    apr_status_t rc= APR_SUCCESS;
    char *child_env[12];
    char *child_arg[MAX_ARG+2];
    const char *t;
    int i, status= -4;
    apr_exit_why_e why= APR_PROC_EXIT;
    apr_sigfunc_t *sigchld;

    /* Set various flags based on the execution method */

    isdaemon= (extmethod == NULL);
    if (!isdaemon)
    {
	usecheck= extmethod && !strcasecmp(extmethod, "checkpassword");
	usepipeout= usecheck || (extmethod && !strcasecmp(extmethod, "pipes"));
	usepipein= usepipeout || (extmethod && !strcasecmp(extmethod, "pipe"));
    }

    /* Create the environment for the child.  Daemons don't get these, they
     * just inherit apache's environment variables.
     */

    if (!isdaemon)
    {
	const char *cookie, *host, *remote_host;
	authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
	    ap_get_module_config(r->per_dir_config, &authnz_external_module);
	i= 0;

	if (!usepipein)
	{
	    /* Put user name and password/group into environment */
	    child_env[i++]= apr_pstrcat(p, ENV_USER"=", r->user, NULL);
	    child_env[i++]= apr_pstrcat(p, dataname, "=", data, NULL);
	}

	child_env[i++]= apr_pstrcat(p, "PATH=", getenv("PATH"), NULL);

	child_env[i++]= apr_pstrcat(p, "AUTHTYPE=", dataname, NULL);

	remote_host= ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST,NULL);
	if (remote_host != NULL)
	    child_env[i++]= apr_pstrcat(p, ENV_HOST"=", remote_host,NULL);

	if (r->useragent_ip)
	    child_env[i++]= apr_pstrcat(p, ENV_IP"=", r->useragent_ip, NULL);

	if (r->uri)
	    child_env[i++]= apr_pstrcat(p, ENV_URI"=", r->uri, NULL);

	if ((host= apr_table_get(r->headers_in, "Host")) != NULL)
	    child_env[i++]= apr_pstrcat(p, ENV_HTTP_HOST"=", host, NULL);

	if (dir->context)
	    child_env[i++]= apr_pstrcat(r->pool, ENV_CONTEXT"=",
	    	dir->context, NULL);

#ifdef ENV_COOKIE
	if ((cookie= apr_table_get(r->headers_in, "Cookie")) != NULL)
	    child_env[i++]= apr_pstrcat(p, ENV_COOKIE"=", cookie, NULL);
#endif
	/* NOTE:  If you add environment variables,
	 *   remember to increase the size of the child_env[] array */

	/* End of environment */
	child_env[i]= NULL;
    }

    /* Construct argument array */
    for (t= extpath, i=0; *t != '\0' && (i <= MAX_ARG + 1);
	 child_arg[i++]= ap_getword_white(p, &t)) {}
    child_arg[i]= NULL;

    /* Create the process attribute structure describing the script we
     * want to run using the Thread/Process functions from the Apache
     * portable runtime library. */

    if (((rc= apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||

	/* should we create pipes to stdin, stdout and stderr? */
        ((rc= apr_procattr_io_set(procattr,
	    (usepipein && !usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE,
	    usepipeout ? APR_FULL_BLOCK : APR_NO_PIPE,
	    (usepipein && usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE))
	       != APR_SUCCESS ) ||

	/* will give full path of program and make a new environment */
	((rc= apr_procattr_cmdtype_set(procattr,
	    isdaemon ? APR_PROGRAM_ENV : APR_PROGRAM)) != APR_SUCCESS) ||

	/* detach the child only if it is a daemon */
	((rc= apr_procattr_detach_set(procattr, isdaemon)) != APR_SUCCESS) ||

	/* function to call if child has error after fork, before exec */
	((rc= apr_procattr_child_errfn_set(procattr, extchilderr)
	      != APR_SUCCESS)))
    {
	/* Failed.  Probably never happens. */
    	ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
	    "could not set child process attributes");
	return -3;
    }

    /* Sometimes other modules wil mess up sigchild.  Need to fix it for
     * the wait call to work correctly.  */
    sigchld= apr_signal(SIGCHLD,SIG_DFL);

    /* Start the child process */
    rc= apr_proc_create(&proc, child_arg[0],
    	(const char * const *)child_arg,
	(const char * const *)child_env, procattr, p);
    if (rc != APR_SUCCESS)
    {
	ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
		"Could not run external authenticator: %d: %s", rc,
		child_arg[0]);
	return -1;
    }

    if (isdaemon) return 0;

    apr_pool_note_subprocess(p, &proc, APR_KILL_AFTER_TIMEOUT);

    if (usepipein)
    {
	/* Select appropriate pipe to write to */
	apr_file_t *pipe= (usecheck ? proc.err : proc.in);

	/* Send the user */
	apr_file_write_full(pipe, r->user, strlen(r->user), NULL);
	apr_file_putc(usecheck ? '\0' : '\n', pipe);

	/* Send the password */
	apr_file_write_full(pipe, data, strlen(data), NULL);
	apr_file_putc(usecheck ? '\0' : '\n', pipe);

	/* Send the uri/path */
	apr_file_write_full(pipe, r->uri, strlen(r->uri), NULL);
	apr_file_putc(usecheck ? '\0' : '\n', pipe);

	/* Send dummy timestamp for checkpassword */
	if (usecheck) apr_file_write_full(pipe, "0", 2, NULL);

	/* Close the file */
	apr_file_close(pipe);
    }

    /* Wait for the child process to terminate, and get status */
    rc= apr_proc_wait(&proc,&status,&why,APR_WAIT);

    /* Restore sigchild to whatever it was before we reset it */
    apr_signal(SIGCHLD,sigchld);

    if (!APR_STATUS_IS_CHILD_DONE(rc))
    {
    	ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
		"Could not get status from child process");
	return -5;
    }
    if (!APR_PROC_CHECK_EXIT(why))
    {
	ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
		"External authenticator died on signal %d",status);
	return -2;
    }

    return status;
}
예제 #17
0
/**
 * Writes request parameters to srun.
 */
static void
write_env(stream_t *s, request_rec *r, char *session_id)
{
  char buf[4096];
  int ch;
  int i;
  
  conn_rec *c = r->connection;
  const char *host;
  int port;
  int is_sub_request = 1;
  char *uri;

  /*
   * is_sub_request is always true, since we can't detect mod_rewrite
   * and mod_rewrite doesn't change the unparsed_uri.
   */
  if (is_sub_request)
    uri = r->uri; /* for mod_rewrite */
  else
    uri = r->unparsed_uri; /* #937 */
  
  for (i = 0; (ch = uri[i]) && ch != '?' && i + 1 < sizeof(buf); i++) 
    buf[i] = ch;
  if (session_id) {
    buf[i++] = *s->config->session_url_prefix;
    for (session_id++; *session_id && i + 1 < sizeof(buf); i++)
      buf[i] = *session_id++;
  }
  buf[i] = 0;
  cse_write_string(s, HMUX_URL, buf);

  cse_write_string(s, HMUX_METHOD, r->method);
  if (*s->config->alt_session_url_prefix && r->request_config) {
    char *suburi = ap_get_module_config(r->request_config, &caucho_module);

    if (suburi)
      uri = suburi;
  }
  cse_write_string(s, CSE_PROTOCOL, r->protocol);

  if (r->args)
    cse_write_string(s, CSE_QUERY_STRING, r->args);

  /* Gets the server name */
  host = ap_get_server_name(r);
  port = ap_get_server_port(r);

  cse_write_string(s, HMUX_SERVER_NAME, host);
  cse_write_string(s, CSE_SERVER_PORT, ap_psprintf(r->pool, "%u", port));

  host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST);
  if (host)
    cse_write_string(s, CSE_REMOTE_HOST, host);
  else
    cse_write_string(s, CSE_REMOTE_HOST, c->remote_ip);

  cse_write_string(s, CSE_REMOTE_ADDR, c->remote_ip);
  cse_write_string(s, CSE_REMOTE_PORT,
		   ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port)));
  
  if (c->user)
    cse_write_string(s, CSE_REMOTE_USER, c->user);
  if (c->ap_auth_type)
    cse_write_string(s, CSE_AUTH_TYPE, c->ap_auth_type);
}
예제 #18
0
AP_DECLARE(void) ap_add_common_vars(request_rec *r)
{
    apr_table_t *e;
    server_rec *s = r->server;
    conn_rec *c = r->connection;
    const char *rem_logname;
    char *env_path;
#if defined(WIN32) || defined(OS2) || defined(BEOS)
    char *env_temp;
#endif
    const char *host;
    const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
    const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
    int i;
    apr_port_t rport;

    /* use a temporary apr_table_t which we'll overlap onto
     * r->subprocess_env later
     * (exception: if r->subprocess_env is empty at the start,
     * write directly into it)
     */
    if (apr_is_empty_table(r->subprocess_env)) {
        e = r->subprocess_env;
    }
    else {
        e = apr_table_make(r->pool, 25 + hdrs_arr->nelts);
    }

    /* First, add environment vars from headers... this is as per
     * CGI specs, though other sorts of scripting interfaces see
     * the same vars...
     */

    for (i = 0; i < hdrs_arr->nelts; ++i) {
        if (!hdrs[i].key) {
            continue;
        }

        /* A few headers are special cased --- Authorization to prevent
         * rogue scripts from capturing passwords; content-type and -length
         * for no particular reason.
         */

        if (!strcasecmp(hdrs[i].key, "Content-type")) {
            apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val);
        }
        else if (!strcasecmp(hdrs[i].key, "Content-length")) {
            apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val);
        }
        /*
         * You really don't want to disable this check, since it leaves you
         * wide open to CGIs stealing passwords and people viewing them
         * in the environment with "ps -e".  But, if you must...
         */
#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
        else if (!strcasecmp(hdrs[i].key, "Authorization")
                 || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
            continue;
        }
#endif
        else {
            apr_table_addn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val);
        }
    }

    if (!(env_path = getenv("PATH"))) {
        env_path = DEFAULT_PATH;
    }
    apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_path));

#ifdef WIN32
    if ((env_temp = getenv("SystemRoot")) != NULL) {
        apr_table_addn(e, "SystemRoot", env_temp);
    }
    if ((env_temp = getenv("COMSPEC")) != NULL) {
        apr_table_addn(e, "COMSPEC", env_temp);
    }
    if ((env_temp = getenv("PATHEXT")) != NULL) {
        apr_table_addn(e, "PATHEXT", env_temp);
    }
    if ((env_temp = getenv("WINDIR")) != NULL) {
        apr_table_addn(e, "WINDIR", env_temp);
    }
#endif

#ifdef OS2
    if ((env_temp = getenv("COMSPEC")) != NULL) {
        apr_table_addn(e, "COMSPEC", env_temp);
    }
    if ((env_temp = getenv("ETC")) != NULL) {
        apr_table_addn(e, "ETC", env_temp);
    }
    if ((env_temp = getenv("DPATH")) != NULL) {
        apr_table_addn(e, "DPATH", env_temp);
    }
    if ((env_temp = getenv("PERLLIB_PREFIX")) != NULL) {
        apr_table_addn(e, "PERLLIB_PREFIX", env_temp);
    }
#endif

#ifdef BEOS
    if ((env_temp = getenv("LIBRARY_PATH")) != NULL) {
        apr_table_addn(e, "LIBRARY_PATH", env_temp);
    }
#endif

    apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
    apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner());
    apr_table_addn(e, "SERVER_NAME",
                   ap_escape_html(r->pool, ap_get_server_name(r)));
    apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip);  /* Apache */
    apr_table_addn(e, "SERVER_PORT",
                  apr_psprintf(r->pool, "%u", ap_get_server_port(r)));
    host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL);
    if (host) {
        apr_table_addn(e, "REMOTE_HOST", host);
    }
    apr_table_addn(e, "REMOTE_ADDR", c->remote_ip);
    apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r));    /* Apache */
    apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
    apr_table_addn(e, "SCRIPT_FILENAME", r->filename);  /* Apache */

    rport = c->remote_addr->port;
    apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport));

    if (r->user) {
        apr_table_addn(e, "REMOTE_USER", r->user);
    }
    else if (r->prev) {
        request_rec *back = r->prev;

        while (back) {
            if (back->user) {
                apr_table_addn(e, "REDIRECT_REMOTE_USER", back->user);
                break;
            }
            back = back->prev;
        }
    }
    if (r->ap_auth_type) {
        apr_table_addn(e, "AUTH_TYPE", r->ap_auth_type);
    }
    rem_logname = ap_get_remote_logname(r);
    if (rem_logname) {
        apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, rem_logname));
    }

    /* Apache custom error responses. If we have redirected set two new vars */

    if (r->prev) {
        if (r->prev->args) {
            apr_table_addn(e, "REDIRECT_QUERY_STRING", r->prev->args);
        }
        if (r->prev->uri) {
            apr_table_addn(e, "REDIRECT_URL", r->prev->uri);
        }
    }

    if (e != r->subprocess_env) {
      apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET);
    }
}
예제 #19
0
static const char *log_remote_host(request_rec *r, char *a)
{
    return ap_escape_logitem(r->pool, ap_get_remote_host(r->connection, r->per_dir_config,
                                    REMOTE_NAME));
}
예제 #20
0
static int
ipp_handler(request_rec *r)
{
	papi_attribute_t **request = NULL, **response = NULL;
	IPPListenerConfig *config;
	papi_status_t status;
	int ret;

	/* Really, IPP is all POST requests */
	if (r->method_number != M_POST)
		return (DECLINED);

#ifndef APACHE2
	/*
	 * An IPP request must have a MIME type of "application/ipp"
	 * (RFC-2910, Section 4, page 19).  If it doesn't match this
	 * MIME type, we should decline the request and let someone else
	 * try and handle it.
	 */
	if (r->headers_in != NULL) {
		char *mime_type = (char *)ap_table_get(r->headers_in,
							"Content-Type");

		if ((mime_type == NULL) ||
		    (strcasecmp(mime_type, "application/ipp") != 0))
			return (DECLINED);
	}
#endif
	/* CHUNKED_DECHUNK might not work right for IPP? */
	if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK)
		return (ret);

	if (!ap_should_client_block(r))
		return (HTTP_INTERNAL_SERVER_ERROR);

#ifndef APACHE2
	ap_soft_timeout("ipp_module: read/reply request ", r);
#endif
	/* read the IPP request off the network */
	status = ipp_read_message(read_data, r, &request, IPP_TYPE_REQUEST);

	if (status != PAPI_OK)
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"read failed: %s\n", papiStatusString(status));
#ifdef DEBUG
	papiAttributeListPrint(stderr, request, "request (%d)  ", getpid());
#endif

	(void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
		"originating-host", (char *)
#ifdef APACHE2
		ap_get_remote_host
			(r->connection, r->per_dir_config, REMOTE_NAME, NULL));
#else
		ap_get_remote_host
			(r->connection, r->per_dir_config, REMOTE_NAME));
#endif

	(void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
				"uri-port", ap_get_server_port(r));
	if (r->headers_in != NULL) {
		char *host = (char *)ap_table_get(r->headers_in, "Host");

		if ((host == NULL) || (host[0] == '\0'))
			host = (char *)ap_get_server_name(r);

		(void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
				"uri-host", host);
	}
	(void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
				"uri-path", r->uri);

	config = ap_get_module_config(r->per_dir_config, &ipp_module);
	if (config != NULL) {
		(void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
				"conformance", config->conformance);
		(void) papiAttributeListAddCollection(&request, PAPI_ATTR_EXCL,
				"operations", config->operations);
		if (config->default_user != NULL)
			(void) papiAttributeListAddString(&request,
						PAPI_ATTR_EXCL, "default-user",
						config->default_user);
		if (config->default_svc != NULL)
			(void) papiAttributeListAddString(&request,
					PAPI_ATTR_EXCL, "default-service",
					config->default_svc);
	}

	/*
	 * For Trusted Solaris, pass the fd number of the socket connection
	 * to the backend so the it can be forwarded to the backend print
	 * service to retrieve the sensativity label off of a multi-level
	 * port.
	 */
	(void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
			"peer-socket", ap_bfileno(r->connection->client, B_RD));

	/* process the request */
	status = ipp_process_request(request, &response, read_data, r);
	if (status != PAPI_OK) {
		errno = 0;
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"request failed: %s\n", papiStatusString(status));
		discard_data(r);
	}
#ifdef DEBUG
	fprintf(stderr, "processing result: %s\n", papiStatusString(status));
	papiAttributeListPrint(stderr, response, "response (%d)  ", getpid());
#endif

	/*
	 * If the client is using chunking and we have not yet received the
	 * final "0" sized chunk, we need to discard any data that may
	 * remain in the post request.
	 */
	if ((r->read_chunked != 0) &&
	    (ap_table_get(r->headers_in, "Content-Length") == NULL))
		discard_data(r);

	/* write an IPP response back to the network */
	r->content_type = "application/ipp";

#ifndef	APACHE2
	ap_send_http_header(r);
#endif

	status = ipp_write_message(write_data, r, response);
	if (status != PAPI_OK)
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"write failed: %s\n", papiStatusString(status));
#ifdef DEBUG
	fprintf(stderr, "write result: %s\n", papiStatusString(status));
	fflush(stderr);
#endif

	papiAttributeListFree(request);
	papiAttributeListFree(response);

#ifndef APACHE2
	ap_kill_timeout(r);
	if (ap_rflush(r) < 0)
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"flush failed, response may not have been sent");
#endif

	return (OK);
}
예제 #21
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;
	}
}
예제 #22
0
API_EXPORT(void) ap_add_common_vars(request_rec *r)
{
    table *e;
    server_rec *s = r->server;
    conn_rec *c = r->connection;
    const char *rem_logname;
    char *env_path;
#if defined(WIN32) || defined(OS2)
    char *env_temp;
#endif
    const char *host;
    array_header *hdrs_arr = ap_table_elts(r->headers_in);
    table_entry *hdrs = (table_entry *) hdrs_arr->elts;
    int i;
    char servbuf[NI_MAXSERV];

    /* use a temporary table which we'll overlap onto
     * r->subprocess_env later
     */
    e = ap_make_table(r->pool, 25 + hdrs_arr->nelts);

    /* First, add environment vars from headers... this is as per
     * CGI specs, though other sorts of scripting interfaces see
     * the same vars...
     */

    for (i = 0; i < hdrs_arr->nelts; ++i) {
        if (!hdrs[i].key) {
	    continue;
	}

	/* A few headers are special cased --- Authorization to prevent
	 * rogue scripts from capturing passwords; content-type and -length
	 * for no particular reason.
	 */

	if (!strcasecmp(hdrs[i].key, "Content-type")) {
	    ap_table_addn(e, "CONTENT_TYPE", hdrs[i].val);
	}
	else if (!strcasecmp(hdrs[i].key, "Content-length")) {
	    ap_table_addn(e, "CONTENT_LENGTH", hdrs[i].val);
	}
	/*
	 * You really don't want to disable this check, since it leaves you
	 * wide open to CGIs stealing passwords and people viewing them
	 * in the environment with "ps -e".  But, if you must...
	 */
#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
	else if (!strcasecmp(hdrs[i].key, "Authorization") 
		 || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
	    continue;
	}
#endif
	else {
	    ap_table_addn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val);
	}
    }

    if (!(env_path = ap_pstrdup(r->pool, getenv("PATH")))) {
	env_path = DEFAULT_PATH;
    }

#ifdef WIN32
    if (env_temp = getenv("SystemRoot")) {
        ap_table_addn(e, "SystemRoot", env_temp);         
    }
    if (env_temp = getenv("COMSPEC")) {
        ap_table_addn(e, "COMSPEC", env_temp);            
    }
    if (env_temp = getenv("WINDIR")) {
        ap_table_addn(e, "WINDIR", env_temp);
    }
#endif

#ifdef OS2
    if ((env_temp = getenv("COMSPEC")) != NULL) {
        ap_table_addn(e, "COMSPEC", env_temp);            
    }
    if ((env_temp = getenv("ETC")) != NULL) {
        ap_table_addn(e, "ETC", env_temp);            
    }
    if ((env_temp = getenv("DPATH")) != NULL) {
        ap_table_addn(e, "DPATH", env_temp);            
    }
    if ((env_temp = getenv("PERLLIB_PREFIX")) != NULL) {
        ap_table_addn(e, "PERLLIB_PREFIX", env_temp);            
    }
#endif

    ap_table_addn(e, "PATH", env_path);
    ap_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
    ap_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version());
    ap_table_addn(e, "SERVER_NAME", 
		  ap_escape_html(r->pool,ap_get_server_name(r)));
    ap_table_addn(e, "SERVER_ADDR", r->connection->local_ip);	/* Apache */
    ap_table_addn(e, "SERVER_PORT",
		  ap_psprintf(r->pool, "%u", ap_get_server_port(r)));
    host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST);
    if (host) {
	ap_table_addn(e, "REMOTE_HOST", host);
    }
    ap_table_addn(e, "REMOTE_ADDR", c->remote_ip);
    ap_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r));	/* Apache */
    ap_table_addn(e, "SERVER_ADMIN", s->server_admin);	/* Apache */
    ap_table_addn(e, "SCRIPT_FILENAME", r->filename);	/* Apache */

    servbuf[0] = '\0';
    if (!getnameinfo((struct sockaddr *)&c->remote_addr,
#ifndef HAVE_SOCKADDR_LEN
		     SA_LEN((struct sockaddr *)&c->remote_addr),
#else
		     c->remote_addr.ss_len,
#endif
		     NULL, 0, servbuf, sizeof(servbuf), NI_NUMERICSERV)){
	ap_table_addn(e, "REMOTE_PORT", ap_pstrdup(r->pool, servbuf));
    }

    if (c->user) {
	ap_table_addn(e, "REMOTE_USER", c->user);
    }
    if (c->ap_auth_type) {
	ap_table_addn(e, "AUTH_TYPE", c->ap_auth_type);
    }
    rem_logname = ap_get_remote_logname(r);
    if (rem_logname) {
	ap_table_addn(e, "REMOTE_IDENT", ap_pstrdup(r->pool, rem_logname));
    }

    /* Apache custom error responses. If we have redirected set two new vars */

    if (r->prev) {
        if (r->prev->args) {
	    ap_table_addn(e, "REDIRECT_QUERY_STRING", r->prev->args);
	}
	if (r->prev->uri) {
	    ap_table_addn(e, "REDIRECT_URL", r->prev->uri);
	}
    }

    ap_overlap_tables(r->subprocess_env, e, AP_OVERLAP_TABLES_SET);
}
예제 #23
0
static int hostprotect_handler(request_rec *r)
{
  char *client_ip;
  int is_ip = 0;
  int rbl_status = 0;
  if(hp.enabled == 1) {
    client_ip = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, &is_ip);
    if(is_ip) {

      /* purging */
      if(!strcmp(client_ip, hp.purger) && !strcmp(r->method, "DELETE")) {

        char *ip_to_purge = apr_table_get(r->headers_in, "X-Purge-From-BL");
        if(ip_to_purge == NULL)
          return DECLINED;

        int purge_status = purge_shm(ip_to_purge);
        if(purge_status == PURGE_OK) {

          int cache_to_clear = clear_shm(hp.expire);
          if(cache_to_clear != CLEAR_ERR) {
          if(hp.debug)
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%s: PURGED %d ITEMS FROM CACHE, EXPIRE TIME %d", MODULE_NAME, cache_to_clear, hp.expire);
          }

          if(hp.debug)
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%s: PURGED FROM CACHE %s", MODULE_NAME, ip_to_purge);
        }
        return DECLINED;

      }

      /* cache search */
      int cache_hit = search_shm(client_ip);

      /* cache hit */
      if(cache_hit > 1) {
  
        /* clear expired cache on random HIT request */
        if(!(r->request_time % 256)) {
          int cache_to_clear = clear_shm(hp.expire);
          if(cache_to_clear != CLEAR_ERR) {
          if(hp.debug)
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%s: PURGED %d ITEMS FROM CACHE, EXPIRE TIME %d", MODULE_NAME, cache_to_clear, hp.expire);
          }
        }

        if(hp.debug)
          ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%s: CACHE HIT FOR %s (counter %d)", MODULE_NAME, client_ip, cache_hit);
        update_shm(client_ip);
        rbl_status = 1;
        goto err_redirect;
      } else {

        /* cache miss */
        check_rbl(client_ip, hp.resolver, &rbl_status, r);
        if(hp.debug)
          ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%s: Checking for blacklist %s | status %d", MODULE_NAME, client_ip, rbl_status);

err_redirect:
        /* blacklisted */
        if(rbl_status) {
          update_shm(client_ip);
          ap_set_content_type(r, "text/html");
          ap_rprintf(r, "<html><head><title>Your IP is blacklisted in bl.hostprotect.net - redirecting..</title><META http-equiv='refresh' content='1;URL=http://www.hostprotect.net/'></head><body bgcolor='#ffffff'><center>Your IP is blacklisted in bl.hostprotect.net. You will be redirected automatically in 3 seconds.</center></body></html>");
          return OK;
        }

      }

    }
  }
  return DECLINED;
}
예제 #24
0
static int authenticate_token(request_rec *r)
{
	const char *usertoken, *timestamp, *path, *remoteip;
	unsigned char digest[APR_MD5_DIGESTSIZE];
	char token[APR_MD5_DIGESTSIZE * 2];
	auth_token_config_rec *conf;
	apr_md5_ctx_t context;

	conf = ap_get_module_config(r->per_dir_config, &auth_token_module);
	
	/* Get the remote IP , forcing to get an IP instead DNS record*/
	if (conf->checkip) {
		remoteip = ap_get_remote_host(r->connection, NULL, REMOTE_NAME, NULL);
    	if(NULL == remoteip)
		{	
			ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "mod_auth_token: request from ip FAILED." );
			return DECLINED;
		}		
		ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "mod_auth_token: request from ip %s", remoteip );
	}


	/* check if the request uri is to be protected */
	if (conf->prefix == NULL || strncmp(r->uri, conf->prefix, conf->prefix_len)) {
		return DECLINED;
	}

	/* <prefix> <32-byte-token> "/" <8-byte-timestamp> "/" */
	if (strlen(r->uri) < conf->prefix_len + 32 + 1 + 8 + 1) {
		ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "mod_auth_token: malformed or nonexistent token");
		return HTTP_UNAUTHORIZED;
	}

	/* mark token, timestamp and relative path components */
	usertoken = r->uri + conf->prefix_len;
	timestamp = r->uri + conf->prefix_len + 32 + 1;
	path = r->uri + conf->prefix_len + 32 + 1 + 8;

	/* check if token has expired */
	if ((unsigned int)apr_time_sec(apr_time_now()) > auth_token_hex2sec(timestamp) + conf->timeout) {
		ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "mod_auth_token: token expired at %u, now is %u",
			auth_token_hex2sec(timestamp) + conf->timeout, (unsigned int)apr_time_sec(apr_time_now()));
		return HTTP_GONE;
	}

	/* create md5 token of secret + path + timestamp */
	apr_md5_init(&context);

	apr_md5_update(&context, (unsigned char *) conf->secret, strlen(conf->secret));
	apr_md5_update(&context, (unsigned char *) path, strlen(path));
	apr_md5_update(&context, (unsigned char *) timestamp, 8);
	if (conf->checkip)
		apr_md5_update(&context, (unsigned char *) remoteip, strlen(remoteip));
	apr_md5_final(digest, &context);

	/* compare hex encoded token and user provided token */
	auth_token_bin2hex(token, (const char *)digest, APR_MD5_DIGESTSIZE);

	if (strncasecmp(token, usertoken, APR_MD5_DIGESTSIZE * 2) == 0) {
		/* remove token and timestamp from uri */
		memmove(r->uri + conf->prefix_len - 1, path, strlen(path) + 1);
		r->filename = apr_pstrdup(r->pool, r->uri);

		/* allow other modules to run their hooks */
		return DECLINED;
	}

	ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "mod_auth_token: failed token auth (got '%s', expected '%s', uri '%s')",
		apr_pstrndup(r->pool, usertoken, 32), apr_pstrndup(r->pool, token, 32), r->uri);
	return HTTP_FORBIDDEN;
}