Esempio n. 1
0
/** Write the string being parsed, and a marker showing where the parse error occurred
 *
 * @param[in] type	the log category.
 * @param[in] lvl	of debugging this message should be logged at.
 * @param[in] request	The current request.
 * @param[in] msg	string we were parsing.
 * @param[in] idx	The position of the marker relative to the string.
 * @param[in] error	What the parse error was.
 */
void log_request_marker(fr_log_type_t type, fr_log_lvl_t lvl, REQUEST *request,
			char const *msg, size_t idx, char const *error)
{
	char const *prefix = "";
	uint8_t unlang_indent;
	uint8_t module_indent;

	if (idx >= sizeof(spaces)) {
		size_t offset = (idx - (sizeof(spaces) - 1)) + (sizeof(spaces) * 0.75);
		idx -= offset;
		msg += offset;

		prefix = "... ";
	}

	/*
	 *  Don't want format markers being indented
	 */
	unlang_indent = request->log.unlang_indent;
	module_indent = request->log.module_indent;
	request->log.unlang_indent = 0;
	request->log.module_indent = 0;

	log_request(type, lvl, request, "%s%s", prefix, msg);
	log_request(type, lvl, request, "%s%.*s^ %s", prefix, (int) idx, spaces, error);

	request->log.unlang_indent = unlang_indent;
	request->log.module_indent = module_indent;
}
Esempio n. 2
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_rad_missed1(struct sip_msg *rq, char* p1, char* p2)
{
    int code;
    preparse_req(rq);
    if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) {
	code = 0;
    }
    return log_request(rq, GET_RURI(rq), rq->to, code, time(0));
}
Esempio n. 3
0
static void log_ack(struct cell* t , struct sip_msg *ack, time_t req_time)
{
	struct sip_msg *rq;
	struct hdr_field *to;

	rq = t->uas.request;
	if (ack->to) to = ack->to;
	else to = rq->to;
	log_request(ack, GET_RURI(ack), to, t->uas.status, req_time);
}
Esempio n. 4
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_db_request1(struct sip_msg *rq, char* p1, char* p2)
{
    int code;

    if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) {
	code = 0;
    }
    preparse_req(rq);
    return log_request(rq, GET_RURI(rq), rq->to, acc_table.s, code, time(0));
}
Esempio n. 5
0
static void log_missed(struct cell* t, struct sip_msg* reply, unsigned int code, time_t req_time)
{
        str* ouri;

	if (t->relayed_reply_branch >= 0) {
	    ouri = &t->uac[t->relayed_reply_branch].uri;
	} else {
	    ouri = GET_NEXT_HOP(t->uas.request);
	}
	
        log_request(t->uas.request, ouri, valid_to(t, reply), mc_table.s, code, req_time);
}
Esempio n. 6
0
int
main(int argc, char const* argv[])
{
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_in server_address, client_address;

    unlink("server_socket");
    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if(server_sockfd < 0) {
        raise("Can't create socket!!!");
        return -1;
    }

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(DEFAULT_PORT);
    server_len = sizeof(server_address);

    logger_info("Server Ready to Start");
    if(bind(server_sockfd, (struct sockaddr *)&server_address, server_len) < 0) {
        close(server_sockfd);
        raise("Can't bind socket!!!");
        return -1;
    }
    listen(server_sockfd, 5);
    logger_info("Server started");

    while(1) {
        char request_content[BUFFER_SIZE];
        char response_content[BUFFER_SIZE];
        Request req;

        logger_info("Server waiting request...");

        client_len = sizeof(client_address);
        client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);

        read(client_sockfd, request_content, BUFFER_SIZE);
        char verb[64], path[64];
        parse_request(request_content, verb, path);
        req.http_verb = verb;
        req.path = path;
        log_request(&req);
        dispatcher(&req, response_content);
        write(client_sockfd, response_content, strlen(response_content));
        close(client_sockfd);
        logger_info("Process the request successfully\n");
    }
    return 0;
}
Esempio n. 7
0
void log_request_hex(fr_log_type_t type, fr_log_lvl_t lvl, REQUEST *request,
			uint8_t const *data, size_t data_len)
{
	size_t i, j, len;
	char *p;
	char buffer[(0x10 * 3) + 1];

	for (i = 0; i < data_len; i += 0x10) {
		len = 0x10;
		if ((i + len) > data_len) len = data_len - i;

		for (p = buffer, j = 0; j < len; j++, p += 3) sprintf(p, "%02x ", data[i + j]);
		log_request(type, lvl, request, "%04x: %s", (int)i, buffer);
	}
}
void do_request(int clientsd, struct sockaddr_in * client, char* logfile) {
	char* response;
	request_t req;
	int req_len;
	int written;

	req = parse_request(clientsd);
	response = get_response(&req, &req_len);
	req.content_length = req_len;
	send_headers(clientsd, &req);
	written = send_response(clientsd, response);
	free(response);
	req.sockaddr = client;
	if (req.response_code == 200) {
		sprintf(req.resp_string, "200 OK %d/%d", written, req.content_length);
	}
	log_request(&req, logfile);
}
Esempio n. 9
0
void close_connection(struct connection *cn)
{
	if (cn->connection_state == HC_FREE)
		abort();
	if (cn->nread || cn->nwritten || cn->logged == 0) {
		++stats.nrequests;
		log_request(cn->r);
	}
	--stats.nconnections;
	if (debug)
		log_d("close_connection: %d", cn->fd);
	close(cn->fd);
	if (cn->rfd != -1) {
		close(cn->rfd);
		cn->rfd = -1;
	}
	set_connection_state(cn, HC_FREE);
}
Esempio n. 10
0
int reinit_connection(struct connection *cn)
{
	char *s;

	++stats.nrequests;
	log_request(cn->r);
	cn->logged = 1;
	if (cn->rfd != -1) {
		close(cn->rfd);
		cn->rfd = -1;
	}
	init_connection(cn);
	set_connection_state(cn, HC_WAITING);
	s = cn->header_input.middle;
	if (s == cn->header_input.end) {
		cn->header_input.start = cn->header_input.middle = cn->header_input.end = cn->header_input.floor;
		return 0;
	}
	++stats.pipelined_requests;
	cn->header_input.start = s;
	return scan_request(cn);
}
Esempio n. 11
0
/*
 * Figure out what kind of data we've got and do something about it.
 */
void got_packet(struct tcp_stream *ts, void **data)
{
	int todiscard=0;
	struct http_param *param=NULL;

	switch (ts->nids_state) {
		case NIDS_JUST_EST:
			ts->server.collect = 1;
			ts->client.collect = 1;
			param=calloc(sizeof(struct http_param), 1);
			assert(param);
			param->host=strdup(my_ntoa(ts->addr.saddr));
			*data=param;
			break;
		case NIDS_DATA:
			if(ts->server.count_new!=0) {
				todiscard=process(ts, SERVER_STREAM, ts->server, data);
			}
			if(ts->client.count_new!=0) {
				todiscard=process(ts, CLIENT_STREAM, ts->client, data);
			}
			break;
		case NIDS_CLOSE:
		case NIDS_RESET:
		case NIDS_TIMED_OUT:
			param=*data;
			if(param) {
				/* Log automatically frees all the internal state */
				log_request(param);
				free_param(param);
				free(param);
			}
			break;
	}
	nids_discard(ts, todiscard);
}
Esempio n. 12
0
void process_request(char* code_sign_key) {
    PLATFORM* platform;
    int retval;
    double last_rpc_time, x;
    struct tm *rpc_time_tm;
    bool ok_to_send_work = !config.dont_send_jobs;
    bool have_no_work = false;
    char buf[256];
    HOST initial_host;
    unsigned int i;
    time_t t;

    memset(&g_reply->wreq, 0, sizeof(g_reply->wreq));

    // if client has sticky files we don't need any more, tell it
    //
    do_file_delete_regex();

    // if different major version of BOINC, just send a message
    //
    if (wrong_core_client_version()
            || unacceptable_os()
            || unacceptable_cpu()
       ) {
        ok_to_send_work = false;
    }

    // if no jobs reported and none to send, return without accessing DB
    //
    if (!ok_to_send_work && !g_request->results.size()) {
        return;
    }

    warn_user_if_core_client_upgrade_scheduled();

    if (requesting_work()) {
        if (config.locality_scheduling || config.locality_scheduler_fraction || config.enable_assignment) {
            have_no_work = false;
        } else {
            lock_sema();
            have_no_work = ssp->no_work(g_pid);
            if (have_no_work) {
                g_wreq->no_jobs_available = true;
            }
            unlock_sema();
        }
    }

    // If:
    // - there's no work,
    // - a config flag is set,
    // - client isn't returning results,
    // - this isn't an initial RPC,
    // - client is requesting work
    // then return without accessing the DB.
    // This is an efficiency hack for when servers are overloaded
    //
    if (
        have_no_work
        && config.nowork_skip
        && requesting_work()
        && (g_request->results.size() == 0)
        && (g_request->hostid != 0)
    ) {
        g_reply->insert_message("No work available", "low");
        g_reply->set_delay(DELAY_NO_WORK_SKIP);
        if (!config.msg_to_host && !config.enable_vda) {
            log_messages.printf(MSG_NORMAL, "No work - skipping DB access\n");
            return;
        }
    }

    // FROM HERE ON DON'T RETURN; "goto leave" instead
    // (because ssp->no_work() may have tagged an entry in the work array
    // with our process ID)

    retval = open_database();
    if (retval) {
        send_error_message("Server can't open database", 3600);
        g_reply->project_is_down = true;
        goto leave;
    }

    retval = authenticate_user();
    if (retval) goto leave;
    if (g_reply->user.id == 0) {
        log_messages.printf(MSG_CRITICAL, "No user ID!\n");
    }
    initial_host = g_reply->host;
    g_reply->host.rpc_seqno = g_request->rpc_seqno;

    g_reply->nucleus_only = false;

    log_request();

    // is host blacklisted?
    //
    if (g_reply->host._max_results_day == -1) {
        send_error_message("Not accepting requests from this host", 86400);
        goto leave;
    }

    if (strlen(config.sched_lockfile_dir)) {
        int pid_with_lock = lock_sched();
        if (pid_with_lock > 0) {
            log_messages.printf(MSG_CRITICAL,
                                "Another scheduler instance [PID=%d] is running for this host\n",
                                pid_with_lock
                               );
        } else if (pid_with_lock) {
            log_messages.printf(MSG_CRITICAL,
                                "Error acquiring lock for [HOST#%d]\n", g_reply->host.id
                               );
        }
        if (pid_with_lock) {
            send_error_message(
                "Another scheduler instance is running for this host", 60
            );
            goto leave;
        }
    }

    // in deciding whether it's a new day,
    // add a random factor (based on host ID)
    // to smooth out network traffic over the day
    //
    retval = rand();
    srand(g_reply->host.id);
    x = drand()*86400;
    srand(retval);
    last_rpc_time = g_reply->host.rpc_time;
    t = (time_t)(g_reply->host.rpc_time + x);
    rpc_time_tm = localtime(&t);
    g_request->last_rpc_dayofyear = rpc_time_tm->tm_yday;

    t = time(0);
    g_reply->host.rpc_time = t;
    t += (time_t)x;
    rpc_time_tm = localtime(&t);
    g_request->current_rpc_dayofyear = rpc_time_tm->tm_yday;

    retval = modify_host_struct(g_reply->host);

    // write time stats to disk if present
    //
    if (g_request->have_time_stats_log) {
        write_time_stats_log();
    }

    // look up the client's platform(s) in the DB
    //
    platform = ssp->lookup_platform(g_request->platform.name);
    if (platform) g_request->platforms.list.push_back(platform);

    // if primary platform is anonymous, ignore alternate platforms
    //
    if (strcmp(g_request->platform.name, "anonymous")) {
        for (i=0; i<g_request->alt_platforms.size(); i++) {
            platform = ssp->lookup_platform(g_request->alt_platforms[i].name);
            if (platform) g_request->platforms.list.push_back(platform);
        }
    }
    if (g_request->platforms.list.size() == 0) {
        sprintf(buf, "%s %s",
                _("This project doesn't support computers of type"),
                g_request->platform.name
               );
        g_reply->insert_message(buf, "notice");
        log_messages.printf(MSG_CRITICAL,
                            "[HOST#%d] platform '%s' not found\n",
                            g_reply->host.id, g_request->platform.name
                           );
        g_reply->set_delay(DELAY_PLATFORM_UNSUPPORTED);
        goto leave;
    }

    handle_global_prefs();

    read_host_app_versions();
    update_n_jobs_today();

    handle_results();
    handle_file_xfer_results();
    if (config.enable_vda) {
        handle_vda();
    }

    // Do this before resending lost jobs
    //
    if (bad_install_type()) {
        ok_to_send_work = false;
    }
    if (!requesting_work()) {
        ok_to_send_work = false;
    }
    send_work_setup();

    if (g_request->have_other_results_list) {
        if (ok_to_send_work
                && (config.resend_lost_results || g_wreq->resend_lost_results)
                && !g_request->results_truncated
           ) {
            if (resend_lost_work()) {
                ok_to_send_work = false;
            }
        }
        if (config.send_result_abort) {
            send_result_abort();
        }
    }

    if (requesting_work()) {
        if (!send_code_sign_key(code_sign_key)) {
            ok_to_send_work = false;
        }

        if (have_no_work) {
            if (config.debug_send) {
                log_messages.printf(MSG_NORMAL,
                                    "[send] No jobs in shmem cache\n"
                                   );
            }
        }

        // if last RPC was within config.min_sendwork_interval, don't send work
        //
        if (!have_no_work && ok_to_send_work) {
            if (config.min_sendwork_interval) {
                double diff = dtime() - last_rpc_time;
                if (diff < config.min_sendwork_interval) {
                    ok_to_send_work = false;
                    log_messages.printf(MSG_NORMAL,
                                        "Not sending work - last request too recent: %f\n", diff
                                       );
                    sprintf(buf,
                            "Not sending work - last request too recent: %d sec", (int)diff
                           );
                    g_reply->insert_message(buf, "low");

                    // the 1.01 is in case client's clock
                    // is slightly faster than ours
                    //
                    g_reply->set_delay(1.01*config.min_sendwork_interval);
                }
            }
            if (ok_to_send_work) {
                send_work();
            }
        }
        if (g_wreq->no_jobs_available) {
            g_reply->insert_message("Project has no tasks available", "low");
        }
    }


    handle_msgs_from_host();
    if (config.msg_to_host) {
        handle_msgs_to_host();
    }

    update_host_record(initial_host, g_reply->host, g_reply->user);
    write_host_app_versions();

leave:
    if (!have_no_work) {
        ssp->restore_work(g_pid);
    }
}
Esempio n. 13
0
File: http.c Progetto: Dridi/vagent2
static int answer_to_connection (void *cls, struct MHD_Connection *connection,
                      const char *url, const char *method,
                      const char *version, const char *upload_data,
                      size_t *upload_data_size, void **con_cls)
{
	struct agent_core_t *core = (struct agent_core_t *)cls;
	struct http_priv_t *http;
	struct agent_plugin_t *plug;
	struct http_request request;
	struct connection_info_struct *con_info = NULL;
	int ret;

	(void)version;
	plug = plugin_find(core,"http");
	http = (struct http_priv_t *) plug->data;
	assert(plug);
	assert(http);


	if (NULL == *con_cls) {
		con_info = malloc (sizeof (struct connection_info_struct));
		assert(con_info);
		con_info->answerstring[0] = '\0';
		con_info->progress = 0;
		con_info->authed = 0;
		*con_cls = con_info;
		return MHD_YES;
	}
	con_info = *con_cls;
	assert(core->config->userpass);

	log_request(connection, http, method, url);

	if (0 == strcmp (method, "GET") || !strcmp(method, "HEAD") || !strcmp(method,"DELETE")) {
		ret = check_auth(connection, core, con_info);
		if (ret == 1)
			return MHD_YES;
		if (!strcmp(method,"DELETE")) {
			request.method = M_DELETE;
		} else {
			request.method = M_GET;
		}
		request.connection = connection;
		request.url = url;
		request.ndata = 0;
		if (find_listener(&request, http))
			return MHD_YES;
	}


	if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {

		if (*upload_data_size != 0) {
			if (*upload_data_size + con_info->progress >= RCV_BUFFER) {
				warnlog(http->logger, "Client input exceeded buffer size of %u bytes. Dropping client.", RCV_BUFFER);

				 return MHD_NO;
			}
			memcpy(con_info->answerstring + con_info->progress,
				upload_data, *upload_data_size);
			con_info->progress += *upload_data_size;
			*upload_data_size = 0;

			return MHD_YES;
		} else if (NULL != con_info->answerstring){
			ret = check_auth(connection, core, con_info);
			if (ret == 1)
				return MHD_YES;
			if (!strcmp(method,"POST")) {
				request.method = M_POST;
			} else {
				request.method = M_PUT;
			}
			request.connection = connection;
			request.url = url;
			request.ndata = con_info->progress;
			request.data = con_info->answerstring;
			/*
			 * FIXME
			 */
			((char *)request.data)[con_info->progress] = '\0';
			if (find_listener(&request, http))
				return MHD_YES;
		}
	}
	if (request.method == M_GET && !strcmp(url, "/")) {
		if (http->help_page == NULL)
			http->help_page = make_help(http);
		assert (http->help_page);
		return send_response_ok(connection, http->help_page);
	}


	return send_response_fail (connection, "Failed\n");
}
Esempio n. 14
0
void process_request(char* code_sign_key) {
    PLATFORM* platform;
    int retval;
    double last_rpc_time, x;
    struct tm *rpc_time_tm;
    bool ok_to_send_work = !config.dont_send_jobs;
    bool have_no_work = false;
    char buf[256];
    HOST initial_host;
    unsigned int i;
    time_t t;

    memset(&g_reply->wreq, 0, sizeof(g_reply->wreq));

    // if client has sticky files we don't need any more, tell it
    //
    do_file_delete_regex();

    // if different major version of BOINC, just send a message
    //
    if (wrong_core_client_version()
        || unacceptable_os()
        || unacceptable_cpu()
    ) {
        ok_to_send_work = false;
    }

    // if no jobs reported and none to send, return without accessing DB
    //
    if (!ok_to_send_work && !g_request->results.size()) {
        return;
    }

    warn_user_if_core_client_upgrade_scheduled();

    if (requesting_work()) {
        if (config.locality_scheduling || config.locality_scheduler_fraction || config.enable_assignment) {
            have_no_work = false;
        } else {
            lock_sema();
            have_no_work = ssp->no_work(g_pid);
            if (have_no_work) {
                g_wreq->no_jobs_available = true;
            }
            unlock_sema();
        }
    }

    // If:
    // - there's no work,
    // - a config flag is set,
    // - client isn't returning results,
    // - this isn't an initial RPC,
    // - client is requesting work
    // then return without accessing the DB.
    // This is an efficiency hack for when servers are overloaded
    //
    if (
        have_no_work
        && config.nowork_skip
        && requesting_work()
        && (g_request->results.size() == 0)
        && (g_request->hostid != 0)
    ) {
        g_reply->insert_message("No work available", "low");
        g_reply->set_delay(DELAY_NO_WORK_SKIP);
        if (!config.msg_to_host && !config.enable_vda) {
            log_messages.printf(MSG_NORMAL, "No work - skipping DB access\n");
            return;
        }
    }

    // FROM HERE ON DON'T RETURN; "goto leave" instead
    // (because ssp->no_work() may have tagged an entry in the work array
    // with our process ID)

    retval = open_database();
    if (retval) {
        send_error_message("Server can't open database", 3600);
        g_reply->project_is_down = true;
        goto leave;
    }

    retval = authenticate_user();
    if (retval) goto leave;
    if (g_reply->user.id == 0) {
        log_messages.printf(MSG_CRITICAL, "No user ID!\n");
    }
    initial_host = g_reply->host;
    g_reply->host.rpc_seqno = g_request->rpc_seqno;

    g_reply->nucleus_only = false;

    log_request();

#if 0
    // if you need to debug a problem w/ a particular host or user,
    // edit the following
    //
    if (g_reply->user.id == XX || g_reply.host.id == YY) {
        config.sched_debug_level = 3;
        config.debug_send = true;
        ...
    }
Esempio n. 15
0
File: ssi.c Progetto: Algy/uwsgi
static void uwsgi_ssi_log(struct wsgi_request *wsgi_req) {
	log_request(wsgi_req);
}
Esempio n. 16
0
int
tdi_connect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
	PTDI_REQUEST_KERNEL_CONNECT param = (PTDI_REQUEST_KERNEL_CONNECT)(&irps->Parameters);
	TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)(param->RequestConnectionInformation->RemoteAddress))->Address;
	PFILE_OBJECT addrobj;
	NTSTATUS status;
	TA_ADDRESS *local_addr;
	int result = FILTER_DENY, ipproto;
	struct ot_entry *ote_conn = NULL, *ote_addr;
	KIRQL irql;
	struct flt_request request;
	struct flt_rule rule;

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

	KdPrint(("[tdi_fw] tdi_connect: connobj 0x%x, to address %x:%u\n",
		irps->FileObject,
		ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr),
		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port)));

	// check device object: TCP or UDP
	if (irps->DeviceObject != g_tcpfltobj && irps->DeviceObject != g_udpfltobj) {
		KdPrint(("[tdi_fw] tdi_connect: unknown DeviceObject 0x%x!\n", irps->DeviceObject));
		goto done;
	}

	ote_conn = ot_find_fileobj(irps->FileObject, &irql);
	if (ote_conn == NULL) {
		KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)!\n", irps->FileObject));
		goto done;
	}

	if (get_original_devobj(irps->DeviceObject, &ipproto) == NULL ||
		(ipproto != IPPROTO_TCP && ipproto != IPPROTO_UDP)) {
		// invalid device object!
		KdPrint(("[tdi_fw] tdi_connect: invalid device object 0x%x!\n", irps->DeviceObject));
		goto done;
	}

	if (ipproto == IPPROTO_TCP) {
		/*
		 * For TCP: get addrobj by connobj and get local address by it
		 */

		addrobj = ote_conn->associated_fileobj;
		if (addrobj == NULL) {
			KdPrint(("[tdi_fw] tdi_connect: empty addrobj!\n"));
			goto done;
		}

		ote_addr = ot_find_fileobj(addrobj, NULL); // we're already in spinlock
		if (ote_addr == NULL) {
			KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)!\n", addrobj));
			goto done;
		}

	} else {
		/*
		 * For UDP: connobj and addrobj are the same
		 */
		KdPrint(("[tdi_fw] tdi_connect: connected UDP socket detected\n"));

		// for connected UDP sockets connobj and addrobj are the same
		addrobj= irps->FileObject;
		ote_addr = ote_conn;
	}

	local_addr = (TA_ADDRESS *)(ote_addr->local_addr);

	// sanity check
	if (local_addr->AddressLength != remote_addr->AddressLength) {
		KdPrint(("[tdi_fw] tdi_connect: different addr lengths! (%u != %u)\n",
			local_addr->AddressLength, remote_addr->AddressLength));
		goto done;
	}

	// set remote address with connobj
	
	if (remote_addr->AddressLength > sizeof(ote_conn->remote_addr)) {
		KdPrint(("[tdi_fw] tdi_connect: address too long! (%u)\n", remote_addr->AddressLength));
		goto done;
	}
	memcpy(ote_conn->remote_addr, remote_addr, remote_addr->AddressLength);

	// set local address with connobj

	if (local_addr->AddressLength > sizeof(ote_conn->local_addr)) {
		KdPrint(("[tdi_fw] tdi_connect: address to long! (%u)\n", local_addr->AddressLength));
		goto done;
	}
	memcpy(ote_conn->local_addr, local_addr, local_addr->AddressLength);

	KdPrint(("[tdi_fw] tdi_connect(pid:%u/%u): %x:%u -> %x:%u (ipproto = %d)\n",
		ote_conn->pid, PsGetCurrentProcessId(),
		ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr),
		ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port),
		ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr),
		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), ipproto));

	/*
	 * Call quick_filter
	 */

	request.struct_size = sizeof(request);

	request.type = TYPE_CONNECT;
	request.direction = DIRECTION_OUT;
	request.proto = ipproto;

	// don't use ote_conn->pid because one process can create connection object
	// but another one can connect
	request.pid = (ULONG)PsGetCurrentProcessId();
	if (request.pid == 0) {
		// avoid idle process pid (XXX do we need this?)
		request.pid = ote_addr->pid;
	}

	// get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL)
	if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL)
		request.sid_a_size = ote_addr->sid_a_size;
	
	memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr));
	memcpy(&request.addr.to, &remote_addr->AddressType, sizeof(struct sockaddr));
	request.addr.len = sizeof(struct sockaddr_in);

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

	result = quick_filter(&request, &rule);

	memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE);

	if (result == FILTER_ALLOW && ipproto == IPPROTO_TCP) {
		struct flt_request *context_req = NULL;

		// add connection with state "SYN_SENT"
		status = add_tcp_conn(ote_conn, TCP_STATE_SYN_SENT);
		if (status != STATUS_SUCCESS) {
			KdPrint(("[tdi_fw] tdi_connect: add_conn: 0x%x!\n", status));
			
			result = FILTER_DENY;
			goto done;				// don't log this failure
		}

		if (rule.log >= RULE_LOG_LOG) {
			// set ote_conn->log_disconnect
			ote_conn->log_disconnect = (rule.log >= RULE_LOG_COUNT);

			// copy request for completion (LOG success or not)
			context_req = (struct flt_request *)malloc_np(sizeof(*context_req));
			if (context_req != NULL) {
				memcpy(context_req, &request, sizeof(*context_req));

				// don't free SID
				request.sid_a = NULL;

				// don't log request in this time
				rule.log = RULE_LOG_NOLOG;
			}
		}

		// set completion to add connection info to connection table
		completion->routine = tdi_connect_complete;
		completion->context = context_req;
	}

	// if logging is needed log request
	if (rule.log >= RULE_LOG_LOG)
		log_request(&request);

done:
	// cleanup
	if (ote_conn != NULL)
		KeReleaseSpinLock(&g_ot_hash_guard, irql);
	if (request.sid_a != NULL)
		free(request.sid_a);

	if (result != FILTER_ALLOW) {
		irp->IoStatus.Status = STATUS_REMOTE_NOT_LISTENING;	// set fake status
	}

	return result;
}
Esempio n. 17
0
NTSTATUS tdi_event_receive_datagram(
    IN PVOID TdiEventContext,
    IN LONG SourceAddressLength,
    IN PVOID SourceAddress,
    IN LONG OptionsLength,
    IN PVOID Options,
    IN ULONG ReceiveDatagramFlags,
    IN ULONG BytesIndicated,
    IN ULONG BytesAvailable,
    OUT ULONG *BytesTaken,
    IN PVOID Tsdu,
    OUT PIRP *IoRequestPacket)
{
	TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext;
	struct ot_entry *ote_addr = NULL;
	KIRQL irql;
	TA_ADDRESS *remote_addr, *local_addr;
	NTSTATUS status;
	int ipproto, result = FILTER_DENY;
	struct flt_request request;
	struct flt_rule rule;

	// get local address of address object

	memset(&request, 0, sizeof(request));
	ote_addr = ot_find_fileobj(ctx->fileobj, &irql);
	if (ote_addr == NULL) {
		KdPrint(("[tdi_fw] tdi_receive_datagram: ot_find_fileobj(0x%x)!\n", ctx->fileobj));
		goto done;
	}

	KdPrint(("[tdi_fw] tdi_event_receive_datagram: addrobj 0x%x\n", ctx->fileobj));

	// check device object: UDP or RawIP
	if (get_original_devobj(ote_addr->devobj, &ipproto) == NULL ||
		(ipproto != IPPROTO_UDP && ipproto != IPPROTO_IP)) {
		// unknown device object!
		KdPrint(("[tdi_fw] tdi_event_receive_datagram: unknown DeviceObject 0x%x!\n",
			ote_addr));
		goto done;
	}

	local_addr = (TA_ADDRESS *)(ote_addr->local_addr);
	remote_addr = ((TRANSPORT_ADDRESS *)SourceAddress)->Address;

	KdPrint(("[tdi_fw] tdi_event_receive_datagram(pid:%u): %x:%u -> %x:%u\n",
		ote_addr->pid,
		ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr),
		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port),
		ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr),
		ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port)));

	// call quick filter for datagram
	request.struct_size = sizeof(request);

	request.type = TYPE_DATAGRAM;
	request.direction = DIRECTION_IN;
	request.proto = ipproto;
	request.pid = ote_addr->pid;

	// get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL)
	if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL)
		request.sid_a_size = ote_addr->sid_a_size;
	
	memcpy(&request.addr.from, &remote_addr->AddressType, sizeof(struct sockaddr));
	memcpy(&request.addr.to, &local_addr->AddressType, sizeof(struct sockaddr));
	request.addr.len = sizeof(struct sockaddr_in);

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

	result = quick_filter(&request, &rule);

	memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE);

	if (rule.log >= RULE_LOG_LOG) {
		ULONG bytes = BytesAvailable;

		// traffic stats
		KeAcquireSpinLockAtDpcLevel(&g_traffic_guard);
		
		g_traffic[TRAFFIC_TOTAL_IN] += bytes;
		
		if (rule.log >= RULE_LOG_COUNT) {
			request.log_bytes_in = bytes;

			g_traffic[TRAFFIC_COUNTED_IN] += bytes;

		} else
			request.log_bytes_in = (ULONG)-1;

		KeReleaseSpinLockFromDpcLevel(&g_traffic_guard);

		log_request(&request);
	}

done:
	// cleanup
	if (ote_addr != NULL)
		KeReleaseSpinLock(&g_ot_hash_guard, irql);
	if (request.sid_a != NULL)
		free(request.sid_a);

	if (result == FILTER_ALLOW) {

		return ((PTDI_IND_RECEIVE_DATAGRAM)(ctx->old_handler))
			(ctx->old_context, SourceAddressLength, SourceAddress, OptionsLength,
			Options, ReceiveDatagramFlags, BytesIndicated, BytesAvailable, BytesTaken,
			Tsdu, IoRequestPacket);
	
	} else
		return STATUS_DATA_NOT_ACCEPTED;
}
Esempio n. 18
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_rad_missed0(struct sip_msg *rq, char* p1, char* p2)
{
	preparse_req(rq);
	return log_request(rq, GET_RURI(rq), rq->to, 0, time(0));
}
Esempio n. 19
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_db_request0(struct sip_msg *rq, char* s1, char* s2)
{
	preparse_req(rq);
	return log_request(rq, GET_RURI(rq), rq->to, write_acc, 0, time(0));
}
Esempio n. 20
0
int
tdi_set_event_handler(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
	PTDI_REQUEST_KERNEL_SET_EVENT r = (PTDI_REQUEST_KERNEL_SET_EVENT)&irps->Parameters;
	NTSTATUS status;
	struct ot_entry *ote_addr = NULL;
	KIRQL irql;
	int result = FILTER_DENY;
	TDI_EVENT_CONTEXT *ctx;

	KdPrint(("[tdi_fw] tdi_set_event_handler: [%s] devobj 0x%x; addrobj 0x%x; EventType: %d\n",
		r->EventHandler ? "(+)ADD" : "(-)REMOVE",
		irps->DeviceObject,
		irps->FileObject,
		r->EventType));

	ote_addr = ot_find_fileobj(irps->FileObject, &irql);
	if (ote_addr == NULL) {
		KdPrint(("[tdi_fw] tdi_set_event_handler: ot_find_fileobj(0x%x)\n", irps->FileObject));
		if (r->EventHandler == NULL) {
			 // for fileobjects loaded earlier than our driver allow removing
			result = FILTER_ALLOW;
		}
		goto done;
	}

	if (r->EventType < 0 || r->EventType >= MAX_EVENT) {
		KdPrint(("[tdi_fw] tdi_set_event_handler: unknown EventType %d!\n", r->EventType));
		result = FILTER_ALLOW;
		goto done;
	}

	ctx = &ote_addr->ctx[r->EventType];

	if (r->EventHandler != NULL) {
		/* add EventHandler */
		int i;

		for (i = 0; g_tdi_event_handlers[i].event != (ULONG)-1; i++)
			if (g_tdi_event_handlers[i].event == r->EventType)
				break;

		if (g_tdi_event_handlers[i].event == (ULONG)-1) {
			KdPrint(("[tdi_fw] tdi_set_event_handler: unknown EventType %d!\n", r->EventType));
			result = FILTER_ALLOW;
			goto done;
		}

		ctx->old_handler = r->EventHandler;
		ctx->old_context = r->EventContext;

		if (g_tdi_event_handlers[i].handler != NULL) {
			r->EventHandler = g_tdi_event_handlers[i].handler;
			r->EventContext = ctx;
		} else {
			r->EventHandler = NULL;
			r->EventContext = NULL;
		}

		KdPrint(("[tdi_fw] tdi_set_event_handler: old_handler 0x%x; old_context 0x%x\n",
			r->EventHandler, r->EventContext));

	} else {
		/* remove EventHandler */
		ctx->old_handler = NULL;
		ctx->old_context = NULL;
	}

	// change LISTEN state
	if (r->EventType == TDI_EVENT_CONNECT) {
		TA_ADDRESS *local_addr;

		if (r->EventHandler != NULL) {
			// add "LISTEN" info
			status = add_listen(ote_addr);
			if (status != STATUS_SUCCESS) {
				KdPrint(("[tdi_fw] tdi_set_event_handler: add_listen: 0x%x!\n", status));
				goto done;
			}
		} else if (ote_addr->listen_entry != NULL) {
			// remove "LISTEN" info
			del_listen_obj(ote_addr->listen_entry, FALSE);

			ote_addr->listen_entry = NULL;
		}
	
		// log it if address is not 127.0.0.1
		local_addr = (TA_ADDRESS *)(ote_addr->local_addr);
		if (ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr) != 0x7f000001) {
			struct flt_request request;
		
			memset(&request, 0, sizeof(request));

			request.struct_size = sizeof(request);

			request.type = (r->EventHandler != NULL) ? TYPE_LISTEN : TYPE_NOT_LISTEN;
			request.proto = IPPROTO_TCP;	// correct?

			if (r->EventHandler != NULL) {
				// for removing event handler ProcessNotifyProc can be already called
				request.pid = (ULONG)PsGetCurrentProcessId();
				if (request.pid == 0) {
					// avoid idle process pid (XXX do we need this?)
					request.pid = ote_addr->pid;
				}
			} else
				request.pid = (ULONG)-1;

			// get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL)
			if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL)
				request.sid_a_size = ote_addr->sid_a_size;
			
			memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr));
			request.addr.len = sizeof(struct sockaddr_in);

			log_request(&request);

			if (request.sid_a != NULL)
				free(request.sid_a);
		}
	}

	result = FILTER_ALLOW;
done:
	// cleanup
	if (ote_addr != NULL)
		KeReleaseSpinLock(&g_ot_hash_guard, irql);

	return result;
}
Esempio n. 21
0
NTSTATUS
tdi_connect_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
	NTSTATUS status;
	struct flt_request *request = (struct flt_request *)Context;
	PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp);

	KdPrint(("[tdi_fw] tdi_connect_complete: status 0x%x\n", Irp->IoStatus.Status));

	if (Irp->IoStatus.Status == STATUS_SUCCESS) {

		if (request != NULL)
			log_request(request);		// log successful connection
		
		// very good! set connection state to "ESTABLISHED"
		status = set_tcp_conn_state(irps->FileObject, TCP_STATE_ESTABLISHED_OUT);
		if (status != STATUS_SUCCESS) {
			KdPrint(("[tdi_fw] tdi_connect_complete: set_tcp_conn_state: 0x%x!\n", status));

			// set fake status
			Irp->IoStatus.Status = STATUS_REMOTE_NOT_LISTENING;
			// TDI client will close connection object and connection will not "hang" (maybe)
			goto done;
		}

		// and update local address for this connection in state table
		update_conn_info(DeviceObject, irps->FileObject);

	} else {

		if (request != NULL) {

			switch (Irp->IoStatus.Status) {		// are status codes correct?
			case STATUS_CONNECTION_REFUSED:
			case STATUS_CONNECTION_RESET:
				request->type = TYPE_CONNECT_RESET;
				break;
			case STATUS_CONNECTION_ABORTED:
			case STATUS_CANCELLED:
				request->type = TYPE_CONNECT_CANCELED;
				break;
			case STATUS_IO_TIMEOUT:
				request->type = TYPE_CONNECT_TIMEOUT;
				break;
			case STATUS_NETWORK_UNREACHABLE:
			case STATUS_HOST_UNREACHABLE:
			case STATUS_PROTOCOL_UNREACHABLE:
			case STATUS_PORT_UNREACHABLE:
				request->type = TYPE_CONNECT_UNREACH;
				break;
			default:
				request->type = TYPE_CONNECT_ERROR;
			}

			// anyway save status
			request->status = Irp->IoStatus.Status;

			log_request(request);
		}

		del_tcp_conn(irps->FileObject, FALSE);
	}

done:
	if (request != NULL) {
		if (request->sid_a != NULL)
			free(request->sid_a);
		free(request);
	}
	return tdi_generic_complete(DeviceObject, Irp, Context);
}
Esempio n. 22
0
File: webdav.c Progetto: JuanS/uwsgi
static void uwsgi_webdav_after_request(struct wsgi_request *wsgi_req) {
	if (!udav.mountpoints) return;
	log_request(wsgi_req);
}
Esempio n. 23
0
/* Serve the client that connected to the webserver
 */
static int serve_client(t_session *session) {
	int result, length, auth_result;
	char *qmark, chr, *header;
	t_host *host_record;
	t_access access;
	t_deny_body *deny_body;
	t_req_method request_method;
	t_ip_addr ip_addr;
#ifdef ENABLE_XSLT
	char *xslt_file;
#endif
#ifdef ENABLE_TOOLKIT
	int i;
	t_toolkit_options toolkit_options;
#endif
#ifdef ENABLE_RPROXY
	t_rproxy *rproxy;
#endif

#ifdef ENABLE_DEBUG
	session->current_task = "fetch & parse request";
#endif

	if ((result = fetch_request(session)) != 200) {
		session->request_method = GET;
		return result;
	} else if ((result = parse_request(session, session->header_length + session->content_length)) != 200) {
		session->request_method = GET;
		return result;
	}

#ifdef ENABLE_DEBUG
	session->current_task = "serve client";
#endif

	session->time = time(NULL);

	/* Hide reverse proxies
	 */
	if (in_iplist(session->config->hide_proxy, &(session->ip_address))) {
		if (last_forwarded_ip(session->http_headers, &ip_addr) == 0) {
			if (reposition_client(session, &ip_addr) != -1) {
				copy_ip(&(session->ip_address), &ip_addr);
			}
		}
	}

	/* SSH tunneling
	 */
#ifdef ENABLE_RPROXY
	if (session->request_method == CONNECT) {
		if (in_iplist(session->config->tunnel_ssh, &(session->ip_address)) == false) {
			return 405;
		}

#ifdef ENABLE_SSL
		if (session->binding->use_ssl) {
			return 405;
		}
#endif

		if (strcmp(session->request_uri, "localhost:22") != 0) {
			if (strcmp(session->request_uri, "127.0.0.1:22") != 0) {
				if (strcmp(session->request_uri, "::1.22") != 0) {
					return 403;
				}
			}
		}

		log_system(session, "SSH tunnel requested");
		if (tunnel_ssh_connection(session->client_socket) != 0) {
			log_system(session, "SSH tunnel failed");
		} else {
			log_system(session, "SSH tunnel terminated");
		}

		session->keep_alive = false;

		return 200;
	}
#endif

	/* Find host record
	 */
	if (session->hostname != NULL) {
		if (remove_port_from_hostname(session) == -1) {
			log_error(session, "error removing port from hostname");
			return 500;
		}

		if ((host_record = get_hostrecord(session->config->first_host, session->hostname, session->binding)) != NULL) {
			session->host = host_record;
#ifdef ENABLE_TOMAHAWK
			session->last_host = host_record;
#endif
		}
	}
	session->host->access_time = session->time;

#ifdef ENABLE_SSL
	/* SSL client authentication
	 */
	if (session->binding->use_ssl) {
		if ((session->host->ca_certificate != NULL) && (ssl_has_peer_cert(&(session->ssl_context)) == false)) {
			log_error(session, "Missing client SSL certificate");
			return 440;
		}
	}
#endif

	/* Enforce usage of first hostname
	 */
	if (session->host->enforce_first_hostname && (session->hostname != NULL)) {
		if (**(session->host->hostname.item) != '*') {
			if (strcmp(session->hostname, *(session->host->hostname.item)) != 0) {
				session->cause_of_301 = enforce_first_hostname;
				return 301;
			}
		}
	}

	/* Enforce usage of SSL
	 */
#ifdef ENABLE_SSL
	if (session->host->require_ssl && (session->binding->use_ssl == false)) {
		if ((qmark = strchr(session->uri, '?')) != NULL) {
			*qmark = '\0';
			session->vars = qmark + 1;
			session->uri_len = strlen(session->uri);
		}
		session->cause_of_301 = require_ssl;
		return 301;
	}
#endif

	/* Deny matching bodies
	 */
	if (session->body != NULL) {
		chr = *(session->body + session->content_length);
		*(session->body + session->content_length) = '\0';

		deny_body = session->host->deny_body;
		while (deny_body != NULL) {
			if (strpcmp(session->body, &(deny_body->pattern)) == 0) {
				if ((session->config->ban_on_denied_body > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
					ban_ip(&(session->ip_address), session->config->ban_on_denied_body, session->config->kick_on_ban);
					log_system(session, "Client banned because of denied body");
#ifdef ENABLE_MONITOR
					if (session->config->monitor_enabled) {
						monitor_count_ban(session);
					}
#endif
				}

				log_exploit_attempt(session, "denied body", session->body);
#ifdef ENABLE_TOMAHAWK
				increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_exploit(session);
					monitor_event("Request body denied for %s", session->host->hostname.item[0]);
				}
#endif

				*(session->body + session->content_length) = chr;

				return 403;
			}
			deny_body = deny_body->next;
		}

		*(session->body + session->content_length) = chr;
	}

	/* Websocket
	 */
	if (session->request_method == GET) {
		if ((header = get_http_header("Connection:", session->http_headers)) != NULL) {
			if (strcasestr(header, "upgrade") != NULL) {
				if ((header = get_http_header("Upgrade:", session->http_headers)) != NULL) {
					if (strcasecmp(header, "websocket") == 0) {
						switch (access = allow_client(session)) {
							case deny:
								log_error(session, fb_accesslist);
								return 403;
							case allow:
								break;
							case pwd:
							case unspecified:
								if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
									return auth_result;
								}
						}

						session->keep_alive = false;
						if (forward_to_websocket(session) == -1) {
							return 500;
						}

						return 200;
					}
				}
			}
		}
	}

#ifdef ENABLE_RPROXY
	/* Reverse proxy
	 */
	rproxy = session->host->rproxy;
	while (rproxy != NULL) {
		if (rproxy_match(rproxy, session->request_uri)) {
			if (rproxy_loop_detected(session->http_headers)) {
				return 508;
			}

			if ((qmark = strchr(session->uri, '?')) != NULL) {
				*qmark = '\0';
				session->vars = qmark + 1;
			}

			if (validate_url(session) == false) {
				return -1;
			}

			if ((session->vars != NULL) && (session->host->secure_url)) {
				if (forbidden_chars_present(session->vars)) {
					log_error(session, "URL contains forbidden characters");
					return 403;
				}
			}

			if (duplicate_host(session) == false) {
				log_error(session, "duplicate_host() error");
				return 500;
			}

			if ((result = uri_to_path(session)) != 200) {
				return result;
			}

			if (session->host->ignore_dot_hiawatha == false) {
				if (load_user_config(session) == -1) {
					return 500;
				}
			}

			if ((result = copy_directory_settings(session)) != 200) {
				return result;
			}

			switch (access = allow_client(session)) {
				case deny:
					log_error(session, fb_accesslist);
					return 403;
				case allow:
					break;
				case pwd:
				case unspecified:
					if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
						return auth_result;
					}
			}

			/* Prevent SQL injection
			 */
			if (session->host->prevent_sqli) {
				result = prevent_sqli(session);
				if (result == 1) {
					session->error_cause = ec_SQL_INJECTION;
				}
				if (result != 0) {
					return -1;
				}
			}

			/* Prevent Cross-site Scripting
			 */
			if (session->host->prevent_xss != p_no) {
				if (prevent_xss(session) > 0) {
					if (session->host->prevent_xss == p_block) {
						session->error_cause = ec_XSS;
						return -1;
					}
				}
			}

			/* Prevent Cross-site Request Forgery
			 */
			if (session->host->prevent_csrf != p_no) {
				if (prevent_csrf(session) > 0) {
					if (session->host->prevent_csrf == p_block) {
						session->error_cause = ec_CSRF;
						return -1;
					}
				}
			}

			return proxy_request(session, rproxy);
		}

		rproxy = rproxy->next;
	}
#endif

	/* Actions based on request method
	 */
	switch (session->request_method) {
		case TRACE:
			if (session->binding->enable_trace == false) {
				return 501;
			}
			return handle_trace_request(session);
		case PUT:
		case DELETE:
			if ((session->binding->enable_alter == false) && (session->host->webdav_app == false)) {
				return 501;
			}
			break;
		case unknown:
			return 400;
		case unsupported:
			if (session->host->webdav_app == false) {
				return 501;
			}
			break;
		default:
			break;
	}

	if (duplicate_host(session) == false) {
		log_error(session, "duplicate_host() error");
		return 500;
	}

#ifdef ENABLE_TOOLKIT
	if (session->host->ignore_dot_hiawatha == false) {
		if (load_user_root_config(session) == -1) {
			return 500;
		}
	}

	/* URL toolkit
	 */
	init_toolkit_options(&toolkit_options);
	toolkit_options.method = session->method;
	toolkit_options.website_root = session->host->website_root;
	toolkit_options.url_toolkit = session->config->url_toolkit;
	toolkit_options.allow_dot_files = session->host->allow_dot_files;
	toolkit_options.http_headers = session->http_headers;
#ifdef ENABLE_SSL
	toolkit_options.use_ssl = session->binding->use_ssl;
#endif

	if (((session->request_method != PUT) && (session->request_method != DELETE)) || session->host->webdav_app) {
		for (i = 0; i < session->host->toolkit_rules.size; i++) {
			if ((result = use_toolkit(session->uri, session->host->toolkit_rules.item[i], &toolkit_options)) == UT_ERROR) {
				return 500;
			}

			if ((toolkit_options.ban > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), toolkit_options.ban, session->config->kick_on_ban);
				log_system(session, "Client banned because of URL match in UrlToolkit rule");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
				return 403;
			}

			session->toolkit_fastcgi = toolkit_options.fastcgi_server;
			if (toolkit_options.new_url != NULL) {
				if (register_tempdata(&(session->tempdata), toolkit_options.new_url, tc_data) == -1) {
					free(toolkit_options.new_url);
					log_error(session, "error registering temporary data");
					return 500;
				}
				session->uri = toolkit_options.new_url;
			}

			if (result == UT_REDIRECT) {
				if ((session->location = strdup(toolkit_options.new_url)) == NULL) {
					return -1;
				}
				session->cause_of_301 = location;
				return 301;
			}

			if (result == UT_DENY_ACCESS) {
				log_error(session, "access denied via URL toolkit rule");
				return 403;
			}

			if (toolkit_options.expire > -1) {
				session->expires = toolkit_options.expire;
				session->caco_private = toolkit_options.caco_private;
			}
		}
	}
#endif

	/* Find GET data
	 */
	if ((qmark = strchr(session->uri, '?')) != NULL) {
		*qmark = '\0';
		session->vars = qmark + 1;
	}

	url_decode(session->uri);
	session->uri_len = strlen(session->uri);

	if ((session->vars != NULL) && (session->host->secure_url)) {
		if (forbidden_chars_present(session->vars)) {
			log_error(session, "URL contains forbidden characters");
			return 403;
		}
	}

	if (validate_url(session) == false) {
		return -1;
	}

	if ((result = uri_to_path(session)) != 200) {
		return result;
	}

	/* Load configfile from directories
	 */
	if (session->host->ignore_dot_hiawatha == false) {
		if (load_user_config(session) == -1) {
			return 500;
		}
	}

	if ((result = copy_directory_settings(session)) != 200) {
		return result;
	}

	switch (access = allow_client(session)) {
		case deny:
			log_error(session, fb_accesslist);
			return 403;
		case allow:
			break;
		case pwd:
		case unspecified:
			if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
				return auth_result;
			}
	}

	switch (is_directory(session->file_on_disk)) {
		case error:
			return 500;
		case yes:
			session->uri_is_dir = true;
			break;
		case no:
			if (((session->request_method != PUT) || session->host->webdav_app) && (session->host->enable_path_info)) {
				if ((result = get_path_info(session)) != 200) {
					return result;
				}
			}
			break;
		case no_access:
			log_error(session, fb_filesystem);
			return 403;
		case not_found:
			if (session->request_method == DELETE) {
				return 404;
			}
	}

#ifdef ENABLE_TOOLKIT
	if ((session->toolkit_fastcgi == NULL) && session->uri_is_dir) {
#else
	if (session->uri_is_dir) {
#endif
		length = strlen(session->file_on_disk);
		if (*(session->file_on_disk + length - 1) == '/') {
			strcpy(session->file_on_disk + length, session->host->start_file);
		} else {
			return 301;
		}
	}

	if (get_target_extension(session) == -1) {
		log_error(session, "error getting extension");
		return 500;
	}

	if (((session->request_method != PUT) && (session->request_method != DELETE)) || session->host->webdav_app) {
		check_target_is_cgi(session);
	}

	/* Handle request based on request method
	 */
	request_method = session->request_method;
	if (session->host->webdav_app) {
		if ((request_method == PUT) || (request_method == DELETE)) {
			request_method = POST;
		}
	}

	switch (request_method) {
		case GET:
		case HEAD:
			if (session->cgi_type != no_cgi) {
				session->body = NULL;
				result = execute_cgi(session);
#ifdef ENABLE_XSLT
			} else if ((xslt_file = find_xslt_file(session)) != NULL) {
				result = handle_xml_file(session, xslt_file);
				free(xslt_file);
#endif
			} else {
				result = send_file(session);
			}
			if (result == 404) {
#ifdef ENABLE_XSLT
				if ((session->host->show_index != NULL) && (session->uri[session->uri_len - 1] == '/')) {
					result = show_index(session);
				}
#endif
#ifdef ENABLE_MONITOR
			} else if (session->config->monitor_enabled) {
				if ((result == 200) && (session->host->monitor_host)) {
					unlink(session->file_on_disk);
				}
#endif
			}

			if ((session->request_method == GET) && (session->cgi_type == no_cgi) && (session->directory != NULL)) {
				if (session->directory->run_on_download != NULL) {
					run_program(session, session->directory->run_on_download, result);
				}
			}
			break;
		case POST:
		case unsupported:
			if (session->cgi_type != no_cgi) {
				result = execute_cgi(session);
#ifdef ENABLE_XSLT
			} else if ((xslt_file = find_xslt_file(session)) != NULL) {
				result = handle_xml_file(session, xslt_file);
				free(xslt_file);
#endif
			} else {
				result = 405;
			}
			break;
		case PUT:
			result = handle_put_request(session);
			if (((result == 201) || (result == 204)) && (session->host->run_on_alter != NULL)) {
				run_program(session, session->host->run_on_alter, result);
			}
			break;
		case DELETE:
			result = handle_delete_request(session);
			if ((result == 204) && (session->host->run_on_alter != NULL)) {
				run_program(session, session->host->run_on_alter, result);
			}
			break;
		case WHEN:
			send_code(session);
			break;
		default:
			result = 400;
	}

	return result;
}

/* Handle timeout upon sending request
 */
static void handle_timeout(t_session *session) {
	if ((session->config->ban_on_timeout > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
		ban_ip(&(session->ip_address), session->config->ban_on_timeout, session->config->kick_on_ban);
		log_system(session, "Client banned because of connection timeout");
#ifdef ENABLE_MONITOR
		if (session->config->monitor_enabled) {
			monitor_count_ban(session);
		}
#endif
	} else {
		log_system(session, "Timeout while waiting for first request");
	}
}

/* Request has been handled, handle the return code.
 */
static void handle_request_result(t_session *session, int result) {
	char *hostname;

#ifdef ENABLE_DEBUG
	session->current_task = "handle request result";
#endif

	if (result == -1) switch (session->error_cause) {
		case ec_MAX_REQUESTSIZE:
			log_system(session, "Maximum request size reached");
			session->return_code = 413;
			send_code(session);
			if ((session->config->ban_on_max_request_size > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_max_request_size, session->config->kick_on_ban);
				log_system(session, "Client banned because of sending a too large request");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			break;
		case ec_TIMEOUT:
			if (session->kept_alive == 0) {
				session->return_code = 408;
				send_code(session);
				handle_timeout(session);
			}
			break;
		case ec_CLIENT_DISCONNECTED:
			if (session->kept_alive == 0) {
				log_system(session, "Silent client disconnected");
			}
			break;
		case ec_SOCKET_READ_ERROR:
			if (errno != ECONNRESET) {
				log_system(session, "Error while reading request");
			}
			break;
		case ec_SOCKET_WRITE_ERROR:
			log_request(session);
			break;
		case ec_FORCE_QUIT:
			log_system(session, "Client kicked");
			break;
		case ec_SQL_INJECTION:
			if ((session->config->ban_on_sqli > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_sqli, session->config->kick_on_ban);
				hostname = (session->hostname != NULL) ? session->hostname : unknown_host;
				log_system(session, "Client banned because of SQL injection on %s", hostname);
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			session->return_code = 441;
			send_code(session);
			log_request(session);
			break;
		case ec_XSS:
			session->return_code = 442;
			send_code(session);
			log_request(session);
			break;
		case ec_CSRF:
			session->return_code = 443;
			send_code(session);
			log_request(session);
			break;
		case ec_INVALID_URL:
			if ((session->config->ban_on_invalid_url > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_invalid_url, session->config->kick_on_ban);
				hostname = (session->hostname != NULL) ? session->hostname : unknown_host;
				log_system(session, "Client banned because of invalid URL on %s", hostname);
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			send_code(session);
			break;
		default:
			if (session->data_sent == false) {
				session->return_code = 500;
				if (send_code(session) == -1) {
					session->keep_alive = false;
				}
			}
	} else switch (result) {
		case 200:
			break;
		case 201:
		case 204:
		case 304:
		case 412:
			if (session->data_sent == false) {
				session->return_code = result;
				if (send_header(session) == -1) {
					session->keep_alive = false;
				} else if (send_buffer(session, "Content-Length: 0\r\n\r\n", 21) == -1) {
					session->keep_alive = false;
				}
			}
			break;
		case 411:
		case 413:
			session->keep_alive = false;
			if (session->data_sent == false) {
				session->return_code = result;
				if (send_header(session) == -1) {
					session->keep_alive = false;
				} else if (send_buffer(session, "Content-Length: 0\r\n\r\n", 21) == -1) {
					session->keep_alive = false;
				}
			}
			break;
		case 400:
			log_garbage(session);
			if (session->data_sent == false) {
				session->return_code = 400;
				if (send_code(session) == -1) {
					session->keep_alive = false;
				}
			}
			if ((session->config->ban_on_garbage > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_garbage, session->config->kick_on_ban);
				log_system(session, "Client banned because of sending garbage");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
#ifdef ENABLE_MONITOR
			if (session->config->monitor_enabled) {
				monitor_count_bad_request(session);
			}
#endif
			break;
		case 401:
		case 403:
		case 404:
		case 501:
		case 503:
			if (session->data_sent == false) {
				switch (handle_error(session, result)) {
					case -1:
						session->keep_alive = false;
						break;
					case 200:
						break;
					default:
						if (session->data_sent == false) {
							session->return_code = result;
							if (send_code(session) == -1) {
								session->keep_alive = false;
							}
						}
				}
			}
			break;
		case 500:
			session->keep_alive = false;
		default:
			if (session->data_sent == false) {
				session->return_code = result;
				send_code(session);
			}
	}

	if ((result > 0) && (result != 400)) {
		log_request(session);
	} else {
		session->keep_alive = false;
	}
}
Esempio n. 24
0
int
tdi_create(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
	NTSTATUS status;
	FILE_FULL_EA_INFORMATION *ea = (FILE_FULL_EA_INFORMATION *)irp->AssociatedIrp.SystemBuffer;

	/* pid resolving stuff: a good place for it (PASSIVE level, begin of working with TDI-objects) */
	ULONG pid = (ULONG)PsGetCurrentProcessId();

	// if process name is unknown try to resolve it
	if (!pid_pname_resolve(pid, NULL, 0)) {
		KEVENT event;
		struct flt_request request;
	
		KeInitializeEvent(&event, NotificationEvent, FALSE);
		pid_pname_set_event(pid, &event);

		memset(&request, 0, sizeof(request));
		request.struct_size = sizeof(request);

		request.type = TYPE_RESOLVE_PID;
		request.pid = pid;

		// get user SID & attributes!
		request.sid_a = get_current_sid_a(&request.sid_a_size);
		
		if (log_request(&request)) {
			// wait a little for reply from user-mode application
			LARGE_INTEGER li;
			li.QuadPart = 5000 * -10000;	// 5 sec

			status = KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, &li);

		} else {
			// check all rulesets: we've got the only _default_ ruleset active
			status = default_chain_only() ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
		}

		if (request.sid_a != NULL)
			free(request.sid_a);

		// reset wait event
		pid_pname_set_event(pid, NULL);

		if (status != STATUS_SUCCESS)
			return FILTER_DENY;			// deny it!
	}

	/* TDI_CREATE related stuff */

	if (ea != NULL) {
		/*
		 * We have FILE_FULL_EA_INFORMATION
		 */

		PDEVICE_OBJECT devobj;
		int ipproto;
		
		devobj = get_original_devobj(irps->DeviceObject, &ipproto);
		if (devobj == NULL) {
			KdPrint(("[tdi_fw] tdi_create: unknown device object 0x%x!\n", irps->DeviceObject));
			return FILTER_DENY;
		}
		// NOTE: for RawIp you can extract protocol number from irps->FileObject->FileName

		if (ea->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH &&
			memcmp(ea->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) == 0) {

			PIRP query_irp;

			/*
			 * This is creation of address object
			 */

			KdPrint(("[tdi_fw] tdi_create: devobj 0x%x; addrobj 0x%x\n",
				irps->DeviceObject,
				irps->FileObject));

			status = ot_add_fileobj(irps->DeviceObject, irps->FileObject, FILEOBJ_ADDROBJ, ipproto, NULL);
			if (status != STATUS_SUCCESS) {
				KdPrint(("[tdi_fw] tdi_create: ot_add_fileobj: 0x%x\n", status));
				return FILTER_DENY;
			}

			// while we're on PASSIVE_LEVEL build control IRP for completion
			query_irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION,
				devobj, irps->FileObject, NULL, NULL);
			if (query_irp == NULL) {
				KdPrint(("[tdi_fw] tdi_create: TdiBuildInternalDeviceControlIrp\n"));
				return FILTER_DENY;
			}

			/* set IRP completion & context for completion */

			completion->routine = tdi_create_addrobj_complete;
			completion->context = query_irp;

		} else if (ea->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH &&
			memcmp(ea->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) == 0) {
			
			/*
			 * This is creation of connection object
			 */

			CONNECTION_CONTEXT conn_ctx = *(CONNECTION_CONTEXT *)
				(ea->EaName + ea->EaNameLength + 1);

			KdPrint(("[tdi_fw] tdi_create: devobj 0x%x; connobj 0x%x; conn_ctx 0x%x\n",
				irps->DeviceObject,
				irps->FileObject,
				conn_ctx));

			status = ot_add_fileobj(irps->DeviceObject, irps->FileObject,
				FILEOBJ_CONNOBJ, ipproto, conn_ctx);

			if (status != STATUS_SUCCESS) {
				KdPrint(("[tdi_fw] tdi_create: ot_add_fileobj: 0x%x\n", status));
				return FILTER_DENY;
			}
		}
	
	} else {
		/*
		 * This is creation of control object
		 */
		
		KdPrint(("[tdi_fw] tdi_create(pid:%u): devobj 0x%x; Control Object: 0x%x\n",
			pid, irps->DeviceObject, irps->FileObject));
	}

	return FILTER_ALLOW;
}
Esempio n. 25
0
static void uwsgi_jvm_after_request(struct wsgi_request *wsgi_req) {
	log_request(wsgi_req);
}
Esempio n. 26
0
/*
 * Process the response data.
 */
int processResponse(char *data, int length, struct http_param *param)
{
	int processed=0;
	char *p=NULL;

	processed=length;

	/* Find out how far it is to the end of the headers */
	if(param->response.header_len==0) {
		/* Just go ahead and keep adding here */
		param->response.length+=length;
		p=strstr(data, "\r\n\r\n");

		if(p==NULL) {
			/* We don't have the end of the headers, ask for more data */
			processed=0;
		} else {
			/* Figure out how far in the headers stop */
			param->response.header_len=(p-data)+4;
			param->response.length-=param->response.header_len;

			/* Actually process the headers, see what we're dealing with. */
			p=strtok(data, "\r\n");
			param->response.status_str=strdup(p);
			/* Find the status */
			p=strchr(p, ' ');
			if(p!=NULL) {
				param->response.status=atoi(p);
			}

			/* Look through the headers and see what kind of stuff we've got */
			while( (p=strtok(NULL, "\r\n"))!=NULL) {
				if(strncasecmp(p, "Connection: ", 16) == 0) {
					if(strncasecmp(p+16, "close", 5)) {
						param->response.connection=CONNECTION_CLOSE;
					} else if(strncasecmp(p+16, "keepalive", 9)) {
						param->response.connection=CONNECTION_KEEPALIVE;
					}
				} else if(strncasecmp(p, "Transfer-Encoding: ", 19) == 0) {
					if(strncasecmp(p+19, "chunked", 7) == 0) {
						param->response.trans_enc=ENCODING_CHUNKED;
					}
				} else if(strncasecmp(p, "Content-Length: ", 16) == 0) {
					param->response.body_len=atoi(p+16);
				}
			}
		}

		/* If we're doing chunked encoding, let's get set up for that */
		if(param->response.trans_enc==ENCODING_CHUNKED) {
			char *start=data+param->response.header_len;
			char *end=data+param->response.header_len;
			int old_remaining=0;
			/* Find the last hex digit */
			while(*end && isxdigit(*end)) { end++; }
			/* Figure out what the value of that hex string is */
			param->response.remaining=strtoul(start, &end, 16);
			fprintf(stderr, "*** Chunk size is %d\n",
				param->response.remaining);
			/* Skip to the newline */
			while(*end!='\r' && *end!='\n') { end++; }
			/* and then past it */
			while(*end=='\r' || *end=='\n') { end++; }
			/* Adjust the length */
			param->response.length-=(end-start);
			/* Adjust the remaining length */
			old_remaining=param->response.remaining;
			/* The length minus the length of the length */
			param->response.remaining-=(length-(end-data));
			assert(param->response.remaining>=0);
			assert(param->response.remaining < old_remaining);
			fprintf(stderr, "*** Remaining size is %d, current length is %d\n",
				param->response.remaining, param->response.length);
		}
	} else { /* This is not the first packet */
		/* Special processing for chunked encoding */
		if(param->response.trans_enc==ENCODING_CHUNKED) {
			/* Find out how much of the current chunk we've got */
			if(length>param->response.remaining) {
				/* We've got the entire chunk here */
				char *start=NULL, *end=NULL;

				param->response.length+=param->response.remaining;

				start=data+param->response.remaining;
				end=start;
				while(*end && isxdigit(*end)) { end++; }
				param->response.remaining=strtoul(start, &end, 16);
				/* Skip past the newline */
				while(*end!='\r' && *end!='\n') { end++; }
				while(*end=='\r' || *end=='\n') { end++; }

				fprintf(stderr, "*** New remaining is %d\n",
					param->response.remaining);
				if(param->response.remaining>0) {
					param->response.length-=(end-start);
					param->response.remaining-=(length-(end-data));
					assert(param->response.remaining>=0);
				} else {
					/* Log here, we're done for a while */
					log_request(param);

					/* OK, let's drop off some of the ``processed'' data.  */
					processed=(end-data);

					/* If this was a keepalive connection, see if we have
					 * another request in there. */
					if(param->response.connection!=CONNECTION_CLOSE) {
						next_request(param);
					}
				}

			} else {
				/* This is part of our current chunk */
				param->response.remaining-=length;
				param->response.length+=length;
				fprintf(stderr, "%d bytes of the same chunk.\n", length);
			}
		} else {
			param->response.length+=length;
		}
	}

	return(processed);
}
Esempio n. 27
0
static int
answer_to_connection(void *cls, struct MHD_Connection *connection,
    const char *url, const char *method,
    const char *version, const char *upload_data,
    size_t * upload_data_size, void **con_cls)
{
	struct agent_core_t *core = (struct agent_core_t *)cls;
	struct http_priv_t *http;
	struct http_request request;
	struct connection_info_struct *con_info;

	(void)version;

	GET_PRIV(core, http);

	if (*con_cls == NULL) {
		ALLOC_OBJ(con_info);
		*con_cls = con_info;
		return (MHD_YES);
	}
	con_info = *con_cls;
	assert(core->config->userpass);

	log_request(connection, http, method, url);

	if (!strcmp(method, "OPTIONS")) {
		/* We need this for preflight requests (CORS). */
		return (http_reply(connection, 200, NULL));
	} else if (!strcmp(method, "GET") || !strcmp(method, "HEAD") ||
	    !strcmp(method, "DELETE")) {
		if (check_auth(connection, core, con_info))
			return (MHD_YES);
		if (!strcmp(method, "DELETE"))
			request.method = M_DELETE;
		else
			request.method = M_GET;
		request.connection = connection;
		request.url = url;
		request.ndata = 0;
		if (find_listener(&request, http))
			return (MHD_YES);
	} else if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
		if (*upload_data_size != 0) {
			if (*upload_data_size + con_info->progress >=
			    RCV_BUFFER) {
				warnlog(http->logger,
				    "Client input exceeded buffer size "
				    "of %u bytes. Dropping client.",
				    RCV_BUFFER);
				return (MHD_NO);
			}
			memcpy(con_info->answerstring + con_info->progress,
			    upload_data, *upload_data_size);
			con_info->progress += *upload_data_size;
			*upload_data_size = 0;
			return (MHD_YES);
		} else if ((char *)con_info->answerstring != NULL) {
			if (check_auth(connection, core, con_info))
				return (MHD_YES);
			if (!strcmp(method, "POST"))
				request.method = M_POST;
			else
				request.method = M_PUT;
			request.connection = connection;
			request.url = url;
			request.ndata = con_info->progress;
			request.data = con_info->answerstring;
			/*
			 * FIXME
			 */
			((char *)request.data)[con_info->progress] = '\0';
			if (find_listener(&request, http))
				return (MHD_YES);
		}
	}
	if (request.method == M_GET && !strcmp(url, "/")) {
		if (http->help_page == NULL)
			http->help_page = make_help(http);
		assert(http->help_page);
		return (http_reply(connection, 200, http->help_page));
	}

	return (http_reply(connection, 500, "Failed"));
}
Esempio n. 28
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int acc_db_missed0(struct sip_msg *rq, char* s1, char* s2)
{
	preparse_req(rq);
	return log_request(rq, GET_RURI(rq), rq->to, mc_table.s, 0, time(0));
}
Esempio n. 29
0
NTSTATUS
tdi_event_connect(
    IN PVOID TdiEventContext,
    IN LONG RemoteAddressLength,
    IN PVOID RemoteAddress,
    IN LONG UserDataLength,
    IN PVOID UserData,
    IN LONG OptionsLength,
    IN PVOID Options,
    OUT CONNECTION_CONTEXT *ConnectionContext,
    OUT PIRP *AcceptIrp)
{
	TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext;
	TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)RemoteAddress)->Address, *local_addr;
	struct ot_entry *ote_addr = NULL, *ote_conn = NULL;
	KIRQL irql;
	struct flt_request request;
	struct flt_rule rule;
	int result = FILTER_DENY;
	NTSTATUS status;
	PIO_STACK_LOCATION irps = NULL;
	struct accept_param *param = NULL;

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

	KdPrint(("[tdi_fw] tdi_event_connect: addrobj 0x%x\n", ctx->fileobj));
	
	ote_addr = ot_find_fileobj(ctx->fileobj, &irql);
	if (ote_addr == NULL) {
		KdPrint(("[tdi_fw] tdi_event_connect: ot_find_fileobj(0x%x)\n", ctx->fileobj));
		goto done;
	}

	local_addr = (TA_ADDRESS *)(ote_addr->local_addr);

	KdPrint(("[tdi_fw] tdi_event_connect(pid:%u): %x:%u -> %x:%u\n",
		ote_addr->pid,
		ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr),
		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port),
		ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr),
		ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port)));

	/*
	 * request quick filter
	 */

	request.struct_size = sizeof(request);

	request.type = TYPE_CONNECT;
	request.direction = DIRECTION_IN;
	request.proto = IPPROTO_TCP;
	request.pid = ote_addr->pid;

	// get user SID & attributes!
	if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL)
		request.sid_a_size = ote_addr->sid_a_size;
	
	memcpy(&request.addr.from, &remote_addr->AddressType, sizeof(struct sockaddr));
	memcpy(&request.addr.to, &local_addr->AddressType, sizeof(struct sockaddr));
	request.addr.len = sizeof(struct sockaddr_in);

	result = quick_filter(&request, &rule);

	memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE);

	// log request later

	if (result == FILTER_DENY)
		goto done;

	result = FILTER_DENY;

	// leave spinlock before calling original handler
	KeReleaseSpinLock(&g_ot_hash_guard, irql);
	ote_addr = NULL;

	/*
	 * run original handler
	 */

	status = ((PTDI_IND_CONNECT)(ctx->old_handler))
		(ctx->old_context, RemoteAddressLength, RemoteAddress,
		UserDataLength, UserData, OptionsLength, Options, ConnectionContext,
		AcceptIrp);

    if (status != STATUS_MORE_PROCESSING_REQUIRED || *AcceptIrp == NULL) {
        KdPrint(("[tdi_fw] tdi_event_connect: status from original handler: 0x%x\n", status));
		goto done;
    }

	/*
	 * reinitialize connobj
	 */

	irps = IoGetCurrentIrpStackLocation(*AcceptIrp);
	KdPrint(("[tdi_fw] tdi_event_connect: connobj 0x%x\n", irps->FileObject));

	// patch *AcceptIrp to change completion routine

	param = (struct accept_param *)malloc_np(sizeof(*param));
	if (param == NULL) {
		KdPrint(("[tdi_fw] tdi_event_connect: malloc_np!\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
		goto done;
	}

	param->old_cr = irps->CompletionRoutine;
	param->old_context = irps->Context;
	param->fileobj = irps->FileObject;

	param->old_control = irps->Control;

	// can't use IoSetCompletionRoutine because it uses next not current stack location
	irps->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL;
	irps->CompletionRoutine = tdi_evconn_accept_complete;
	irps->Context = param;

	param = NULL;

	// find connobj for changing

	ote_conn = ot_find_fileobj(irps->FileObject, &irql);
	if (ote_conn == NULL) {
		KdPrint(("[tdi_fw] tdi_event_connect: ot_find_fileobj(0x%x)\n", irps->FileObject));
        status = STATUS_OBJECT_NAME_NOT_FOUND;
		goto done;
	}

    ASSERT(ote_conn->type == FILEOBJ_CONNOBJ);

    // connobj must be associated with addrobj!
    if (ote_conn->associated_fileobj != ctx->fileobj) {
        KdPrint(("[tdi_fw] tdi_event_connect: 0x%x != 0x%x\n", ote_conn->associated_fileobj, ctx->fileobj));
        status = STATUS_INVALID_PARAMETER;
        goto done;
    }

    // change conn_ctx (if needed)
    if (ote_conn->conn_ctx != *ConnectionContext) {
        // update (conn_ctx, addrobj)->connobj

	    status = ot_del_conn_ctx(ote_conn->associated_fileobj, ote_conn->conn_ctx);
	    if (status != STATUS_SUCCESS) {
		    KdPrint(("[tdi_fw] tdi_event_connect: ot_del_conn_ctx: 0x%x\n", status));
            goto done;
        }

        ote_conn->conn_ctx = *ConnectionContext;

	    status = ot_add_conn_ctx(ote_conn->associated_fileobj, ote_conn->conn_ctx, irps->FileObject);
	    if (status != STATUS_SUCCESS) {
		    KdPrint(("[tdi_fw] tdi_event_connect: ot_add_conn_ctx: 0x%x\n", status));
		    goto done;
	    }
    
    }

    // clear listen & conn entries in connobj (fileobject can be reused)

    ASSERT(ote_conn->listen_entry == NULL);
    if (ote_conn->listen_entry != NULL)
		del_listen_obj(ote_conn->listen_entry, FALSE);       // free build case
    
    if (ote_conn->conn_entry != NULL) {

		if (ote_conn->ipproto == IPPROTO_TCP && ote_conn->log_disconnect)
			log_disconnect(ote_conn);
    	
		del_tcp_conn_obj(ote_conn->conn_entry, FALSE);
	}

    // clear bytes count
    ote_conn->bytes_in = ote_conn->bytes_out = 0;

    // setup log_disconnect flag from rule
    ote_conn->log_disconnect = (rule.log >= RULE_LOG_COUNT);

	// sanity check
	if (local_addr->AddressLength != remote_addr->AddressLength) {
		KdPrint(("[tdi_fw] tdi_event_connect: different addr lengths! (%u != %u)\n",
			local_addr->AddressLength,
			remote_addr->AddressLength));
        status = STATUS_INFO_LENGTH_MISMATCH;
		goto done;
	}

	// associate remote address with connobj
	
	if (remote_addr->AddressLength > sizeof(ote_conn->remote_addr)) {
		KdPrint(("[tdi_fw] tdi_event_connect: address too long! (%u)\n",
			remote_addr->AddressLength));
        status = STATUS_BUFFER_TOO_SMALL;
		goto done;
	}
	memcpy(ote_conn->remote_addr, remote_addr, remote_addr->AddressLength);

	// associate local address with connobj

	if (local_addr->AddressLength > sizeof(ote_conn->local_addr)) {
		KdPrint(("[tdi_fw] tdi_event_connect: address too long! (%u)\n",
			local_addr->AddressLength));
        status = STATUS_BUFFER_TOO_SMALL;
		goto done;
	}
	memcpy(ote_conn->local_addr, local_addr, local_addr->AddressLength);

	// create connection with "SYN_RCVD" state
	status = add_tcp_conn(ote_conn, TCP_STATE_SYN_RCVD);
	if (status != STATUS_SUCCESS) {
		KdPrint(("[tdi_fw] tdi_event_connect: add_tcp_conn: 0x%x\n", status));
		goto done;
	}

	result = FILTER_ALLOW;

done:
	// if logging is needed log request
	if (rule.log >= RULE_LOG_LOG) {
        if (result != FILTER_ALLOW && rule.result == FILTER_ALLOW) {
			request.type = TYPE_CONNECT_ERROR;		// error has been occured
            request.status = status;
        }

		log_request(&request);
	}

	if (result != FILTER_ALLOW) {
		// deny incoming connection

        KdPrint(("[tdi_fw] tdi_event_connect: deny on reason 0x%x\n", status));

		if (irps != NULL) {
			// delete connection
			if (ote_conn != NULL && ote_conn->conn_entry != NULL) {
				del_tcp_conn_obj(ote_conn->conn_entry, FALSE);
				ote_conn->conn_entry = NULL;
			}

	        // release spinlock before IoCompleteRequest to avoid completion call inside spinlock
            if (ote_addr != NULL || ote_conn != NULL) {
		        KeReleaseSpinLock(&g_ot_hash_guard, irql);
                
                ote_addr = NULL;
                ote_conn = NULL;
            }

			// destroy accepted IRP
			(*AcceptIrp)->IoStatus.Status = STATUS_UNSUCCESSFUL;
			IoCompleteRequest(*AcceptIrp, IO_NO_INCREMENT);
		}

		*AcceptIrp = NULL;
		status = STATUS_CONNECTION_REFUSED;
	} else
		status = STATUS_MORE_PROCESSING_REQUIRED;

	// cleanup
	if (ote_addr != NULL || ote_conn != NULL)
		KeReleaseSpinLock(&g_ot_hash_guard, irql);
	if (param != NULL)
		free(param);
	if (request.sid_a != NULL)
		free(request.sid_a);

	return status;
}
Esempio n. 30
0
void uwsgi_go_after_request(struct wsgi_request *wsgi_req) {

        log_request(wsgi_req);

}