Exemplo n.º 1
0
/*
 *	Check if an incoming request is "ok"
 *
 *	It takes packets, not requests.  It sees if the packet looks
 *	OK.  If so, it does a number of sanity checks on it.
 */
static int vqp_socket_recv(rad_listen_t *listener)
{
	RADIUS_PACKET	*packet;
	RAD_REQUEST_FUNP fun = NULL;
	RADCLIENT	*client;

	packet = vqp_recv(listener->fd);
	if (!packet) {
		ERROR("%s", fr_strerror());
		return 0;
	}

	if ((client = client_listener_find(listener,
					   &packet->src_ipaddr,
					   packet->src_port)) == NULL) {
		rad_free(&packet);
		return 0;
	}

	/*
	 *	Do new stuff.
	 */
	fun = vmps_process;

	if (!request_receive(NULL, listener, packet, client, fun)) {
		rad_free(&packet);
		return 0;
	}

	return 1;
}
Exemplo n.º 2
0
int dual_tls_recv(rad_listen_t *listener)
{
	RADIUS_PACKET *packet;
	REQUEST *request;
	RAD_REQUEST_FUNP fun = NULL;
	listen_socket_t *sock = listener->data;
	RADCLIENT	*client = sock->client;

	if (!tls_socket_recv(listener)) {
		return 0;
	}

	rad_assert(sock->request != NULL);
	rad_assert(sock->request->packet != NULL);
	rad_assert(sock->packet != NULL);
	rad_assert(sock->ssn != NULL);

	request = sock->request;
	packet = sock->packet;

	/*
	 *	Some sanity checks, based on the packet code.
	 */
	switch(packet->code) {
	case PW_AUTHENTICATION_REQUEST:
		if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
		FR_STATS_INC(auth, total_requests);
		fun = rad_authenticate;
		break;

	case PW_ACCOUNTING_REQUEST:
		if (listener->type != RAD_LISTEN_ACCT) goto bad_packet;
		FR_STATS_INC(acct, total_requests);
		fun = rad_accounting;
		break;

	case PW_STATUS_SERVER:
		if (!mainconfig.status_server) {
			FR_STATS_INC(auth, total_unknown_types);
			DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
			rad_free(&sock->packet);
			request->packet = NULL;
			return 0;
		}
		fun = rad_status_server;
		break;

	default:
	bad_packet:
		FR_STATS_INC(auth, total_unknown_types);

		DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
		      packet->code, client->shortname, packet->src_port);
		rad_free(&sock->packet);
		request->packet = NULL;
		return 0;
	} /* switch over packet types */

	if (!request_receive(listener, packet, client, fun)) {
		FR_STATS_INC(auth, total_packets_dropped);
		rad_free(&sock->packet);
		request->packet = NULL;
		return 0;
	}

	sock->packet = NULL;	/* we have no need for more partial reads */
	request->packet = NULL;

	return 1;
}
Exemplo n.º 3
0
static int serviceConnection2(
	http_server srv,
	connection conn,
	http_request request,
	http_response response,
	meta_error e)
{
	dynamic_page dp;
	size_t cbSent;
	int status, error = 0;
	size_t max_posted_content = http_server_get_post_limit(srv);

	while(!http_server_shutting_down(srv)) { 
		if(!data_on_socket(conn)) 
			return set_tcpip_error(e, EAGAIN); 

		/* Were we able to read a valid http request? 
		 * If not, what is the cause of the error? If it is a http 
		 * protocol error, we try to send a response back to the client
		 * and close the connection. If it is anything else(tcp/ip, os)
		 * we stop processing. 
		 */
		error = !request_receive(request, conn, max_posted_content, e);

		/* So far, so good. We have a valid HTTP request.
		 * Now see if we can locate a page handler function for it.
		 * If we do, call it. If not, see if it on disk or if the
		 * http_server has a default page handler. If neither is true,
		 * then the page was not found(404).
		 */
		if(error)
			;
		else if( (dp = http_server_lookup(srv, request)) != NULL) {
			if(!handle_dynamic(srv, dp, request, response, e)) {
				error = 1;
			}
		}
		else if(http_server_can_read_files(srv)) {
			if(!send_disk_file(srv, conn, request, response, e)) {
				error = 1;
			}
		}
		else if(http_server_has_default_page_handler(srv)) {
			if(!http_server_run_default_page_handler(srv, request, response, e)) {
				error = 1;
			}
		}
		else {
			/* We didn't find the page */
			response_set_status(response, HTTP_404_NOT_FOUND);
			response_set_connection(response, "close");
		}

		if(error) {
			if(is_protocol_error(e)) {
				status = get_error_code(e);
				response_set_status(response, status);
				response_set_connection(response, "close");
				cbSent = response_send(response, conn, e);
				http_server_add_logentry(srv, conn, request, status, cbSent);
			}

			return 0;
		}

		/*
		 * Some extra stuff for HTTP 1.0 clients. If client is 1.0
		 * and connection_close() == 1 and connection header field
		 * isn't set, then we set the connection flag to close.
		 * Done so that 1.0 clients (Lynx) can detect closure.
		 */
		if(request_get_version(request) != VERSION_11
		&& !connection_is_persistent(conn)
		&& strlen(response_get_connection(response)) == 0) 
			response_set_connection(response, "close");
		
		cbSent = response_send(response, conn, e);
		http_server_add_logentry(srv, conn, request, response_get_status(response), cbSent);
		if(cbSent == 0)
			return 0;

		/* Did the user set the Connection header field to "close" */
		if(strcmp(response_get_connection(response), "close") == 0)
			return 1;

		if(!connection_is_persistent(conn))
			return 1;

		/**
		 * NOTE: Her må/bør vi legge inn ny funksjonalitet:
		 * Disconnect connections som 
		 * a) Har kjørt lengst i tid
		 * b) Har overført mest bytes (opp eller ned)
		 * eller c) har dårligst transfer rate
		 * Grunnen er at dersom vi har n worker threads og n 
		 * persistent connections, havner alle nye connections i kø.
		 * De får aldri kjøretid. Så disconnect-regelen over gjelder derfor
		 * kun om køen har > 0 entries. 
		 */

		connection_flush(conn);
		request_recycle(request);
		response_recycle(response);
	}

	/* Shutdown detected */
	return 1;
}
Exemplo n.º 4
0
/*
 * thread responsible for receiving data for a client or a server
 * note when we add client, this client is effectively added in the receive queue
 * only few second later due to the select timeout of 3 seconds
 * and there are the same problem for the deleteion of a client
 */
static void algopr_receive_thread(void *unused)
{
    struct pending_request pending_requests[EXA_MAX_NODES_NUMBER];
    exa_select_handle_t *sh = exa_select_new_handle();
    int i;
    int ret;
    payload_t *payload = NULL;
    struct nbd_root_list root_list_recv;

    /* FIXME: handle the case when we have more than 1024 open file (limit of fd_set) */
    fd_set fds;

    exalog_as(EXAMSG_ISCSI_ID);

    nbd_init_root(EXA_MAX_NODES_NUMBER, sizeof(payload_t), &root_list_recv);

    for (i = 0; i < EXA_MAX_NODES_NUMBER; i++)
        request_reset(&pending_requests[i]);

    while (algopr_run)
    {
	int nfds = 0;
        FD_ZERO(&fds);
        /* if one node is added or deleted, this deletion or addition are
           effective after this */
        os_thread_mutex_lock(&peers_lock);
        for (i = 0; i < EXA_MAX_NODES_NUMBER; i++)
        {
            int fd_act = __get_peer_socket(i);
            if (fd_act < 0)
            {
                payload_t *temp_payload;
                temp_payload = request_reset(&pending_requests[i]);
                if (temp_payload != NULL)
                {
                    if (pending_requests[i].big_buffer)
                        nbd_list_post(&eth.root_list_big_recv.free,
                                      temp_payload->buffer, -1);

                    nbd_list_post(&root_list_recv.free, temp_payload, -1);
                }
                temp_payload = NULL;
                continue;
            }

            FD_SET(fd_act, &fds);
	    nfds = fd_act > nfds ? fd_act : nfds;
        }
        os_thread_mutex_unlock(&peers_lock);

        ret = exa_select_in(sh, nfds + 1, &fds);
        if (ret != 0 && ret != -EFAULT)
            exalog_error("Select upon receive failed: %s (%d)",
                         os_strerror(-ret), ret);

        os_thread_mutex_lock(&peers_lock);
        for (i = 0; i < EXA_MAX_NODES_NUMBER; i++)
        {
            struct pending_request *req;
            int fd_act;

            fd_act = __get_peer_socket(i);
            if (fd_act < 0 || !FD_ISSET(fd_act, &fds))
                continue;

            req = &pending_requests[i];
            /* WARNING payload is kept from an iteration of while loop to
             * another, so the variable MUST be global. */
            /* FIXME Remove the nbdlist which is useless as we already know
             * that we NEED EXA_MAX_NODES_NUMBER payload_t elements to be able
             * to receive simultaneously from EXA_MAX_NODES_NUMBER nodes
             * FIXME the LISTWAIT flag below is WRONG because waiting here
             * would mean deadlock... hopefully there are enough elements, and
             * we never wait.... */
            if (payload == NULL)
            {
                payload = nbd_list_remove(&root_list_recv.free, NULL, LISTWAIT);
                EXA_ASSERT(payload != NULL);
            }
            if (request_init_transfer(payload, req) == 1)
                payload = NULL;

            ret = request_receive(fd_act, req);
            if (ret == DATA_TRANSFER_NEED_BIG_BUFFER)
            {
                req->payload->buffer = nbd_list_remove(&eth.root_list_big_recv.free,
                                                       NULL, LISTWAIT);
                EXA_ASSERT(req->payload->buffer != NULL);

                req->big_buffer = true;

                /* here we just continue because it is forbidden to call
                 * request_receive without passing into select (as sockets are
                 * blocking, we may remain blocked on the recv of nothing) */
                continue;
            }

            if (ret == DATA_TRANSFER_PENDING)
                continue;

            if (ret == DATA_TRANSFER_ERROR)
            {
                payload_t *temp_payload = request_reset(req);

                if (req->big_buffer)
                    nbd_list_post(&eth.root_list_big_recv.free,
                                  temp_payload->buffer, -1);

                nbd_list_post(&root_list_recv.free, temp_payload, -1);

                __disconnect_from_peer(i);

                if (!suspended)
                    exalog_warning("Failed receiving from peer %" PRInodeid
                                  " (socket %d): transfer error.", i, fd_act);
                continue;
            }

            if (ret == DATA_TRANSFER_COMPLETE)
            {
                payload_t *_payload = request_reset(req);

                /* update data network checking data */
                algopr_new_msg(_payload->payload, _payload->size1,
                               _payload->buffer,  _payload->size2);
                nbd_list_post(&root_list_recv.free, _payload, -1);
            }
        }
        os_thread_mutex_unlock(&peers_lock);
    }

    nbd_close_root(&root_list_recv);
    exa_select_delete_handle(sh);
}
Exemplo n.º 5
0
int dual_tls_recv(rad_listen_t *listener)
{
	RADIUS_PACKET *packet;
	RAD_REQUEST_FUNP fun = NULL;
	listen_socket_t *sock = listener->data;
	RADCLIENT	*client = sock->client;

	if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0;

	if (!tls_socket_recv(listener)) {
		return 0;
	}

	rad_assert(sock->packet != NULL);
	rad_assert(sock->tls_session != NULL);
	rad_assert(client != NULL);

	packet = talloc_steal(NULL, sock->packet);
	sock->packet = NULL;

	gettimeofday(&packet->timestamp, NULL);

	/*
	 *	Some sanity checks, based on the packet code.
	 *
	 *	"auth+acct" are marked as "auth", with the "dual" flag
	 *	set.
	 */
	switch (packet->code) {
	case PW_CODE_ACCESS_REQUEST:
		if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
		FR_STATS_INC(auth, total_requests);
		fun = rad_authenticate;
		break;

#ifdef WITH_ACCOUNTING
	case PW_CODE_ACCOUNTING_REQUEST:
		if (listener->type != RAD_LISTEN_ACCT) {
			/*
			 *	Allow auth + dual.  Disallow
			 *	everything else.
			 */
			if (!((listener->type == RAD_LISTEN_AUTH) &&
			      (listener->dual))) {
				    goto bad_packet;
			}
		}
		FR_STATS_INC(acct, total_requests);
		fun = rad_accounting;
		break;
#endif

	case PW_CODE_STATUS_SERVER:
		if (!main_config.status_server) {
			FR_STATS_INC(auth, total_unknown_types);
			WARN("Ignoring Status-Server request due to security configuration");
			fr_radius_free(&packet);
			return 0;
		}
		fun = rad_status_server;
		break;

	default:
	bad_packet:
		FR_STATS_INC(auth, total_unknown_types);

		DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
		      packet->code, client->shortname, packet->src_port);
		fr_radius_free(&packet);
		return 0;
	} /* switch over packet types */

	if (!request_receive(NULL, listener, packet, client, fun)) {
		FR_STATS_INC(auth, total_packets_dropped);
		fr_radius_free(&packet);
		return 0;
	}

	return 1;
}
Exemplo n.º 6
0
int dual_tls_recv(rad_listen_t *listener)
{
	RADIUS_PACKET *packet;
	RAD_REQUEST_FUNP fun = NULL;
	listen_socket_t *sock = listener->data;
	RADCLIENT	*client = sock->client;
	BIO		*rbio;

	if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0;

redo:
	if (!tls_socket_recv(listener)) {
		return 0;
	}

	rad_assert(sock->packet != NULL);
	rad_assert(sock->ssn != NULL);
	rad_assert(client != NULL);

	packet = talloc_steal(NULL, sock->packet);
	sock->packet = NULL;

	/*
	 *	Some sanity checks, based on the packet code.
	 *
	 *	"auth+acct" are marked as "auth", with the "dual" flag
	 *	set.
	 */
	switch (packet->code) {
	case PW_CODE_ACCESS_REQUEST:
		if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
		FR_STATS_INC(auth, total_requests);
		fun = rad_authenticate;
		break;

#ifdef WITH_ACCOUNTING
	case PW_CODE_ACCOUNTING_REQUEST:
		if (listener->type != RAD_LISTEN_ACCT) {
			/*
			 *	Allow auth + dual.  Disallow
			 *	everything else.
			 */
			if (!((listener->type == RAD_LISTEN_AUTH) &&
			      (listener->dual))) {
				    goto bad_packet;
			}
		}
		FR_STATS_INC(acct, total_requests);
		fun = rad_accounting;
		break;
#endif

	case PW_CODE_STATUS_SERVER:
		if (!main_config.status_server) {
			FR_STATS_INC(auth, total_unknown_types);
			WARN("Ignoring Status-Server request due to security configuration");
			rad_free(&packet);
			return 0;
		}
		fun = rad_status_server;
		break;

	default:
	bad_packet:
		FR_STATS_INC(auth, total_unknown_types);

		DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
		      packet->code, client->shortname, packet->src_port);
		rad_free(&packet);
		return 0;
	} /* switch over packet types */

	if (!request_receive(NULL, listener, packet, client, fun)) {
		FR_STATS_INC(auth, total_packets_dropped);
		rad_free(&packet);
		return 0;
	}

	/*
	 *	Check for more application data.
	 *
	 *	If there is pending SSL data, "peek" at the
	 *	application data.  If we get at least one byte of
	 *	application data, go back to tls_socket_recv().
	 *	SSL_peek() will set SSL_pending(), and
	 *	tls_socket_recv() will read another packet.
	 */
	rbio = SSL_get_rbio(sock->ssn->ssl);
	if (BIO_ctrl_pending(rbio)) {
		char buf[1];
		int peek = SSL_peek(sock->ssn->ssl, buf, 1);

		if (peek > 0) {
			DEBUG("more TLS records after dual_tls_recv");
			goto redo;
		}
	}

	return 1;
}
Exemplo n.º 7
0
/*
 *	Check if an incoming request is "ok"
 *
 *	It takes packets, not requests.  It sees if the packet looks
 *	OK.  If so, it does a number of sanity checks on it.
 */
static int arp_socket_recv(rad_listen_t *listener)
{
	int ret;
	arp_socket_t *sock = listener->data;
	pcap_t *handle = sock->lsock.pcap->handle;

	const uint8_t *data;
	struct pcap_pkthdr *header;
	ssize_t link_len;

	arp_over_ether_t const *arp;
	RADIUS_PACKET *packet;

	ret = pcap_next_ex(handle, &header, &data);
	if (ret == 0) {
		DEBUG("No packet retrieved from pcap.");
		return 0; /* no packet */
	}

	if (ret < 0) {
		ERROR("Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
		return 0;
	}

	link_len = fr_pcap_link_layer_offset(data, header->caplen, sock->lsock.pcap->link_layer);
	if (link_len < 0) {
		PERROR("Failed determining link layer header offset");
		return 0;
	}

	/*
	 *	Silently ignore it if it's too small to be ARP.
	 *
	 *	This can happen when pcap gets overloaded and starts truncating packets.
	 */
	if (header->caplen < (link_len + sizeof(*arp))) {
		ERROR("Packet too small, we require at least %zu bytes, got %i bytes",
		      link_len + sizeof(*arp), header->caplen);
		return 0;
	}

	data += link_len;
	arp = (arp_over_ether_t const *) data;

	if (ntohs(arp->htype) != ARPHRD_ETHER) return 0;

	if (ntohs(arp->ptype) != 0x0800) return 0;

	if (arp->hlen != ETHER_ADDR_LEN) return 0; /* FIXME: malformed error */

	if (arp->plen != 4) return 0; /* FIXME: malformed packet error */

	packet = talloc_zero(NULL, RADIUS_PACKET);
	if (!packet) return 0;

	packet->dst_port = 1;	/* so it's not a "fake" request */
	packet->data_len = header->caplen - link_len;
	packet->data = talloc_memdup(packet, arp, packet->data_len);
	talloc_set_type(packet->data, uint8_t);

	DEBUG("ARP received on interface %s", sock->lsock.interface);

	if (!request_receive(NULL, listener, packet, &sock->client, arp_process)) {
		fr_radius_packet_free(&packet);
		return 0;
	}

	return 1;
}