Exemple #1
0
/**
 * Inialialize key_file and cert_file variables
 */
int init_x509_filenames()
{
#if USE_X509
	if (!key_file) {
		key_file =
			(char *) calloc(strlen(CONFIG_DIR) + strlen(KEYFILE) +
					2, sizeof(char));
		if (!key_file) {
			log_area_printf (DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
						"TLS: cannot allocate the key file");
			return 0;
		}
		strcat(key_file, CONFIG_DIR);
		strcat(key_file, "/");
		strcat(key_file, KEYFILE);
	}
	if (!cert_file) {
		cert_file =
			(char *) calloc(strlen(CONFIG_DIR) + strlen(CERTFILE) +
					2, sizeof(char));
		if (!cert_file) {
			log_area_printf (DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
				"TLS: cannot allocate the cert file");
			return 0;
		}
		strcat(cert_file, CONFIG_DIR);
		strcat(cert_file, "/");
		strcat(cert_file, CERTFILE);
	}
#endif
	return 1;
}
Exemple #2
0
/**
 * Process authentication server (NuAuth) packet answer. Different answers
 * can be:
 *   - Decision answer: packet accepted/rejected
 *   - Connection destroy: ask conntrack to destroy a connection
 *   - Connection update: ask conntrack to set connection timeout to given
 *     value
 *
 *  \return -1 in case of error
 */
static int auth_packet_to_decision(char *dgram, int dgram_size)
{
	if (dgram_size < 2) {
		debug_log_printf(DEBUG_AREA_GW, DEBUG_LEVEL_DEBUG,
				 "NuAuth sent too small message");
		return -1;
	}

	if (dgram[0] != PROTO_NUFW_VERSION) {
		debug_log_printf(DEBUG_AREA_GW, DEBUG_LEVEL_DEBUG,
				 "Wrong protocol version from authentication server answer.");
		return -1;
	}

	switch (dgram[1]) {
	case AUTH_ANSWER:
		return auth_process_answer(dgram, dgram_size);
	case AUTH_CONN_DESTROY:
		log_area_printf(DEBUG_AREA_MAIN | DEBUG_AREA_GW,
				DEBUG_LEVEL_WARNING,
				"Connection destroy message not supported");
		break;
	case AUTH_CONN_UPDATE:
		log_area_printf(DEBUG_AREA_MAIN | DEBUG_AREA_GW,
				DEBUG_LEVEL_WARNING,
				"Connection update message not supported");
		break;
	default:
		log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_DEBUG,
				"NuAuth message type %d not for me",
				dgram[1]);
		break;
	}
	return -1;
}
Exemple #3
0
static void packetsrv_activity_cb(struct ev_loop *loop, ev_io *w, int revents)
{
	if (revents & EV_READ) {
		unsigned char buffer[BUFSIZ];
		int rv;
		int fd = nfq_fd(h);
		/* read one packet */
		rv = recv(fd, buffer, sizeof(buffer), 0);
		if (rv < 0) {
			struct nlif_handle *nlif_handle = (struct nlif_handle *) w->data;
			log_area_printf(DEBUG_AREA_MAIN,
					DEBUG_LEVEL_WARNING,
					"[!] Error of read on netfilter queue socket (code %i, errno %d): %s!",
					rv,
					errno,
					strerror(errno));
			log_area_printf(DEBUG_AREA_MAIN,
					DEBUG_LEVEL_SERIOUS_MESSAGE,
					"Reopen netlink connection.");
			packetsrv_close(0);
#ifdef HAVE_NFQ_INDEV_NAME
			fd = packetsrv_open(nlif_handle);
#else
			fd = packetsrv_open(NULL);
#endif
			if (fd < 0) {
				log_area_printf(DEBUG_AREA_MAIN,
						DEBUG_LEVEL_CRITICAL,
						"[!] FATAL ERROR: Fail to reopen netlink connection!");
				exit(EXIT_FAILURE);
			}
			ev_io_stop(loop, w);
			ev_io_set(w, fd, EV_READ);
			ev_io_start(loop, w);
			return;
		}

		ev_io_stop(loop, &tls.ev_io);
		/* process the packet */
		nfq_handle_packet(h, (char *) buffer, rv);
		pckt_rx++;
		ev_io_start(loop, &tls.ev_io);
	}

	if (revents & EV_ERROR) {
		struct nlif_handle *nlif_handle = (struct nlif_handle *) w->data;
		int fd;
		packetsrv_close(0);
		ev_io_stop(loop, w);
#ifdef HAVE_NFQ_INDEV_NAME
		fd = packetsrv_open(nlif_handle);
#else
		fd = packetsrv_open(NULL);
#endif
		ev_io_set(w, fd, EV_READ);
		ev_io_start(loop, w);
	}
}
Exemple #4
0
void tls_connect_unix()
{
	struct sockaddr_un remote;
	socklen_t len;
	int s;
	int ret;
	ufwissl_session* sess;
	int opt;

	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
		"Trying to connect to unix socket: %s", authreq_addr);

	s = socket(AF_UNIX, SOCK_STREAM, 0);
	if (s < 0) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
				"Couldn't create socket");
		return;
	}

	remote.sun_family = AF_UNIX;
	strncpy(remote.sun_path, authreq_addr, UNIX_MAX_PATH-1);
	len = strlen(remote.sun_path) + sizeof(remote.sun_family);
	ret = connect(s, (struct sockaddr *)&remote, len);
	if (ret < 0) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
				"Couldn't connect to unix socket");
		return;
	}

	if (buffer_size != 0) {
		opt = buffer_size;
		ret = setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, &opt, sizeof(opt));
		if (ret < 0) {
			log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
					"Couldn't set send buffer size to unix socket: %s",
					strerror(errno));
			return;
		}
	}

	sess = ufwissl_session_create_with_fd(s, 0 /* verify */);
	/* time *must* be set to 0 (non-blocking calls) to avoid a deadlock
	 * between auth_request_send and authsrv
	 */
	ufwissl_set_read_timeout(sess, 0);

	tls.session = sess;
}
Exemple #5
0
static void tls_activity_cb(struct ev_loop *loop, ev_io *w, int revents) {
	ev_io *nfq_watcher = (ev_io *) w->data;
	int ret;
	int i = 0;

	if (revents & EV_READ) {
		ev_io_stop(loop, w);
		ev_io_stop(loop, nfq_watcher);
		do {
			if (i>0) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
						"remaining data to read");
			}
			/* TODO improve function type here */
			ret = authsrv(NULL);
		} while ((ret != NU_EXIT_ERROR) && (nussl_read_available(tls.session)));
		ev_io_start(loop, nfq_watcher);
		if (tls.session) {
			ev_io_start(loop, w);
		}
		i++;
	}

	if (revents & EV_ERROR) {
		tls.auth_server_running = 0;
	}
}
Exemple #6
0
static void cleaning_timer_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
	int stat_rx, stat_tx;

	ev_io *nfq_watcher = (ev_io *) w->data;
	ev_io_stop(loop, &tls.ev_io);
	ev_io_stop(loop, nfq_watcher);
	clean_old_packets();
	ev_io_start(loop, nfq_watcher);
	ev_io_start(loop, &tls.ev_io);
#ifdef DEBUG_ENABLE
	/* display stats */
	/* FIXME : modify this function */
	/*
	process_poll(0);
	*/
	stat_rx = pckt_rx - p_pckt_rx;
	p_pckt_rx = pckt_rx;

	stat_tx = pckt_rx - p_pckt_rx;
	p_pckt_rx = pckt_rx;

	log_area_printf(DEBUG_AREA_MAIN | DEBUG_AREA_PACKET,
			DEBUG_LEVEL_DEBUG,
			"Average: rx=%.2f, tx=%.2f",
			(1.0 * stat_rx) / CLEANING_DELAY,
			(1.0 * stat_tx) / CLEANING_DELAY);
#endif
}
Exemple #7
0
void tls_crl_update_user_session(GSList *session)
{

    GSList *listrunner = session;
    int ret;

    while ( listrunner ) {
        struct nuauth_thread_t *nuauth_thread = listrunner->data;

        struct tls_user_context_t *context = nuauth_thread->data;

        // Don't update the CRL when nufw is not yet connected
        if (context->nussl == NULL) {
            listrunner = g_slist_next(listrunner);
            continue;
        }

        g_mutex_lock(nuauth_thread->mutex);
        ret = nussl_ssl_set_crl_file(context->nussl, nuauth_tls.crl_file, nuauth_tls.ca);

        if (ret != NUSSL_OK) {
            log_area_printf(DEBUG_AREA_USER, DEBUG_LEVEL_CRITICAL,
                            "User TLS: CRL file reloading failed (%s)",
                            nussl_get_error(context->nussl));
        }
        g_mutex_unlock(nuauth_thread->mutex);

        listrunner = g_slist_next(listrunner);

    }
    g_slist_free(listrunner);

}
Exemple #8
0
void packetsrv_close(int smart)
{
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_SERIOUS_MESSAGE,
			"Destroy netfilter queue socket");
	if (smart)
		nfq_destroy_queue(hndl);

	nfq_close(h);
	/* packet id will be reset after restart, we discard
	   waiting packets */
	clear_packet_list();
}
Exemple #9
0
/**
 * Halt TLS threads and close socket
 */
void shutdown_tls()
{
	if (!tls.auth_server_running)
		return;

	log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_CRITICAL,
			"tls send failure when sending request");

	close_tls_session();

	/* put auth_server_running to 0 because this is this thread which has
	 * just killed auth_server */
	tls.auth_server_running = 0;
}
Exemple #10
0
/**
 * Parse an packet and check if it's TCP in IPv4 packet with TCP flag
 * ACK, FIN or RST set.
 *
 * \param dgram Pointer to data to parse
 * \param datalen Length of the data
 * \return If the TCP if the packet matchs, returns 1. Else, returns 0.
 */
int look_for_tcp_flags(unsigned char *dgram, unsigned int datalen)
{
	struct iphdr *iphdrs = (struct iphdr *) dgram;
	/* check need some data */
	if (datalen < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
				"Incorrect packet data length");
		return 0;
	}
	/* check IP version */
	if (iphdrs->version == 4) {
		if (iphdrs->protocol == IPPROTO_TCP) {
			struct tcphdr *tcphdrs =
			    (struct tcphdr *) (dgram + 4 * iphdrs->ihl);
			if (tcphdrs->fin || tcphdrs->ack || tcphdrs->rst) {
				RETURN_NO_LOG 1;
			}
		}
	}
	return 0;
}
Exemple #11
0
/**
 * Configure NuAuth:
 *   - Init. glib threads: g_thread_init() ;
 *   - Read command line options: parse_options() ;
 *   - Read NuAuth configuration file: init_nuauthconf() ;
 *   - Build configuration options: build_prenuauthconf() ;
 *   - Init SSL library: nussl_init() ;
 *   - Create credentials: create_x509_credentials() ;
 *   - Daemonize the process if asked: daemonize().
 */
void configure_app(int argc, char **argv)
{
	command_line_params_t params;
	int ret;
	struct rlimit r_limit;
	struct nuauth_params initconf;
	struct nuauth_params *conf;

	/* Avoid creation of core file which may contains username and password */
	if (getrlimit(RLIMIT_CORE, &r_limit) == 0) {
#ifdef DEBUG_ENABLE
		r_limit.rlim_cur = RLIM_INFINITY;
#else
		r_limit.rlim_cur = 0;
#endif
		setrlimit(RLIMIT_CORE, &r_limit);
	}

	if (getrlimit(RLIMIT_NOFILE, &r_limit) == 0) {
		r_limit.rlim_cur = 8096;
		r_limit.rlim_max = 8096;
		setrlimit(RLIMIT_NOFILE, &r_limit);
	}

#ifndef DEBUG_ENABLE
	/* Move to root directory to not block current working directory */
	(void) chdir("/");
#endif

#ifdef DEBUG_MEMORY
	g_mem_set_vtable(glib_mem_profiler_table);
#endif

	/* Initialize glib thread system */
	g_thread_init(NULL);
	g_thread_pool_set_max_unused_threads(5);

	/* init nuauthdatas */
	nuauthdatas = g_new0(struct nuauth_datas, 1);
	nuauthdatas->is_starting = TRUE;
	nuauthdatas->reload_cond = g_cond_new();
	nuauthdatas->reload_cond_mutex = g_mutex_new();
	nuauthdatas->program_fullpath = g_strdup(argv[0]);


	/* set default parameters */
	params.debug_level = 0;
	params.daemonize = 0;
	params.client_srv = NULL;
	params.nufw_srv = NULL;
	params.userpckt_port = NULL;
	params.authreq_port = NULL;
	params.configfile = NULL;

	nuauthconf = &initconf;
	/* check if configuration file is not given on command line */
	parse_options(argc, argv, &params);

	if (params.debug_level) {
		nuauthconf->debug_level = params.debug_level;
	} else {
		nuauthconf->debug_level = DEFAULT_DEBUG_LEVEL;
	}
	nuauthconf->debug_areas = DEFAULT_DEBUG_AREAS;

	if (params.configfile == NULL) {
		nuauthconf->configfile = g_strdup(DEFAULT_CONF_FILE);
	} else {
		nuauthconf->configfile = g_strdup(params.configfile);
	}

	ret = nuauth_parse_configuration(nuauthconf->configfile);
	if (ret < 0) {
		log_message(FATAL, DEBUG_AREA_MAIN,
			    "Cannot load configuration (file '%s')",
			    nuauthconf->configfile);
		exit(EXIT_FAILURE);
	}

	/* load configuration */
	if (!init_nuauthconf(&conf)) {
		log_message(FATAL, DEBUG_AREA_MAIN,
				"Unable to load configuration");
		exit(EXIT_FAILURE);
	}

	conf->configfile = nuauthconf->configfile;
	nuauthconf = conf;
	/* build configuration by overwritting config file option by
	 * command line one */
	nuauthconf_from_cmdline(&params);

	build_prenuauthconf(nuauthconf, NULL, 0);

	ret = nussl_init();
	if ( ret != NUSSL_OK ) {
		log_message(FATAL, DEBUG_AREA_MAIN,
			"FATAL ERROR: NuSSL global initialisation failed.");
		exit(EXIT_FAILURE);

	}

	if (nuauthconf->uses_utf8) {
		setlocale(LC_ALL, "");
	}

	/* debug cannot be above 10 */
	if (nuauthconf->debug_level > MAX_DEBUG_LEVEL)
		nuauthconf->debug_level = MAX_DEBUG_LEVEL;
	if (nuauthconf->debug_level < MIN_DEBUG_LEVEL)
		nuauthconf->debug_level = MIN_DEBUG_LEVEL;
	log_message(INFO, DEBUG_AREA_MAIN,
			"Debug_level is %i", nuauthconf->debug_level);

#if 0
	/* init credential */
	if (! create_x509_credentials()) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
				"Certificate initialization failed");
		exit(EXIT_FAILURE);
	}
#endif
	/* free command line structure */
	g_free(params.client_srv);
	g_free(params.nufw_srv);
	g_free(params.userpckt_port);
	g_free(params.authreq_port);
	g_free(params.configfile);

	debug_areas = DEFAULT_DEBUG_AREAS;
	debug_level = nuauthconf->debug_level;

	/* init gcrypt and gnutls */
	if (params.daemonize == 1) {
		daemonize();
		/* default: use only syslog */
		set_glib_loghandlers(0, nuauthconf->log_to_syslog);

	} else {
		int use_stdout = (quiet_mode == 0);
		/* default: use both stdout and syslog */
		set_glib_loghandlers(use_stdout, nuauthconf->log_to_syslog);
		log_message(FATAL, DEBUG_AREA_MAIN,
				"[+] NuAuth " NUAUTH_FULL_VERSION " with config %s",
				nuauthconf->configfile);
		log_message(FATAL, DEBUG_AREA_MAIN,
		"Nuauth started in foreground (without -D option), "
		"logging on stderr, stdout and syslog");
	}

	/* declare default capabilities */
	register_client_capa("HELLO", &(nuauthdatas->hello_capa));
	register_client_capa("TCP", &(nuauthdatas->tcp_capa));
	register_client_capa("UDP", &(nuauthdatas->udp_capa));
}
Exemple #12
0
/**
 * \brief Callback called by NetFilter when a packet with target QUEUE is matched.
 *
 * For TCP packet with flags different than SYN, just send it to NuAuth and
 * accept it.
 *
 * For other packet: First of all, fill a structure ::packet_idl (identifier,
 * timestamp, ...). Try to add the new packet to ::packets_list (fails if the
 * list is full). Ask an authentication to NuAuth using auth_request_send(),
 * If the packet can't be sended, remove it from the list.
 *
 * \return If an error occurs, returns 0, else returns 1.
 */
static int treat_packet(struct nfq_handle *qh, struct nfgenmsg *nfmsg,
			struct nfq_data *nfa, void *data)
{
	packet_idl *current;
	struct queued_pckt q_pckt;
	struct nfqnl_msg_packet_hdr *ph;
	struct timeval timestamp;
	int ret;
#ifdef HAVE_NFQ_INDEV_NAME
	struct nlif_handle *nlif_handle = (struct nlif_handle *) data;
#endif

	debug_log_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
			 "(*) New packet");

	q_pckt.payload_len = nfq_get_payload(nfa, &(q_pckt.payload));
	if (q_pckt.payload_len == -1) {
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO,
				"Unable to get payload");
		return 0;
	}

	q_pckt.mark = nfq_get_nfmark(nfa);

#ifdef HAVE_NFQ_INDEV_NAME
	if (!get_interface_information(nlif_handle, &q_pckt, nfa)) {
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO,
				"Can not get interfaces information for message");
		return 0;
	}
#else
	snprintf(q_pckt.indev, sizeof(q_pckt.indev), "*");
	snprintf(q_pckt.physindev, sizeof(q_pckt.physindev), "*");
	snprintf(q_pckt.outdev, sizeof(q_pckt.outdev), "*");
	snprintf(q_pckt.physoutdev, sizeof(q_pckt.physoutdev), "*");
#endif

	ret = nfq_get_timestamp(nfa, &timestamp);
	if (ret == 0) {
		q_pckt.timestamp = timestamp.tv_sec;
	} else {
		q_pckt.timestamp = time(NULL);
	}

	if (look_for_tcp_flags
	    ((unsigned char *) q_pckt.payload, q_pckt.payload_len)) {
		ph = nfq_get_msg_packet_hdr(nfa);
		if (ph) {
			q_pckt.packet_id = ntohl(ph->packet_id);
			auth_request_send(AUTH_CONTROL, &q_pckt);
			IPQ_SET_VERDICT(q_pckt.packet_id, NF_ACCEPT);
			RETURN_NO_LOG 1;
		} else {
			log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
					"Can not get the packet headers");
			return 0;
		}
	}
	current = calloc(1, sizeof(packet_idl));
	current->nfmark = q_pckt.mark;
	current->timestamp = q_pckt.timestamp ;
	current->id = 0;
	if (current == NULL) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_MESSAGE,
				"Can not allocate packet_id");
		return 0;
	}
#ifdef PERF_DISPLAY_ENABLE
	gettimeofday(&(current->arrival_time), NULL);
#endif
	/* Get unique identifier of packet in queue */
	ph = nfq_get_msg_packet_hdr(nfa);
	if (ph) {
		current->id = ntohl(ph->packet_id);
	} else {
		free(current);
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO,
				"Can not get id for message");
		return 0;
	}

	/* Try to add the packet to the list */
	ret = padd(current);
	q_pckt.packet_id = current->id;

	if (ret == 0) {
		/* send an auth request packet */
		if (!auth_request_send(AUTH_REQUEST, &q_pckt)) {
			int sandf = 0;
			/* send failure dropping packet */
			IPQ_SET_VERDICT(q_pckt.packet_id, NF_DROP);
			/* we fail to send the packet so we free packet related to current */
			/* search and destroy packet by packet_id */
			sandf = psearch_and_destroy(q_pckt.packet_id,
						&(q_pckt.mark));

			if (!sandf) {
				log_area_printf(DEBUG_AREA_MAIN,
						DEBUG_LEVEL_WARNING,
						"Packet could not be removed: %u",
						q_pckt.packet_id);
			}
		}
	}
	return 1;
}
Exemple #13
0
/**
 * Send an authentication request to NuAuth. May restart TLS session
 * and/or open TLS connection (if closed).
 *
 * Create the thread authsrv() when opening a new session.
 *
 * Packet maximum size is 512 bytes,
 * and it's structure is ::nufw_to_nuauth_auth_message_t.
 *
 * \param type Type of request (::AUTH_REQUEST, ::AUTH_CONTROL, ...)
 * \param pckt_data A pointer to a queued_pckt:: holding packet information
 * \return If an error occurs returns 0, else return 1.
 */
int auth_request_send(uint8_t type, struct queued_pckt *pckt_data)
{
	unsigned char data[512];
	nuv4_nufw_to_nuauth_auth_message_t *msg_header =
	    (nuv4_nufw_to_nuauth_auth_message_t *) & data;
	unsigned char *msg_content =
	    data + sizeof(nuv4_nufw_to_nuauth_auth_message_t);
	int msg_length;

	/* Drop non-IPv(4|6) packet */
	if ((((struct iphdr *) (pckt_data->payload))->version != 4)
	    && (((struct iphdr *) (pckt_data->payload))->version != 6)) {
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_DEBUG,
				 "Dropping non-IPv4/non-IPv6 packet (version %u)",
				 ((struct iphdr *) (pckt_data->payload))->
				 version);
		return 0;
	}

	/* Truncate packet content if needed */
	if (sizeof(data) <
	    sizeof(nuv4_nufw_to_nuauth_auth_message_t) + pckt_data->payload_len) {
		debug_log_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_DEBUG,
				 "Very long packet: truncating!");
		pckt_data->payload_len =
		    sizeof(data) -
		    sizeof(nuv4_nufw_to_nuauth_auth_message_t);
	}
	msg_length = sizeof(nuv4_nufw_to_nuauth_auth_message_t) + pckt_data->payload_len;

	/* Fill message header */
	msg_header->protocol_version = PROTO_NUFW_VERSION;
	msg_header->msg_type = type;
	msg_header->msg_length = htons(msg_length);
	msg_header->packet_id = htonl(pckt_data->packet_id);
	msg_header->timestamp = htonl(pckt_data->timestamp);

	/* Add info about interfaces */
	msg_header->mark = pckt_data->mark;
	memcpy(msg_header->indev, pckt_data->indev,
	       IFNAMSIZ * sizeof(char));
	memcpy(msg_header->outdev, pckt_data->outdev,
	       IFNAMSIZ * sizeof(char));
	memcpy(msg_header->physindev, pckt_data->physindev,
	       IFNAMSIZ * sizeof(char));
	memcpy(msg_header->physoutdev, pckt_data->physoutdev,
	       IFNAMSIZ * sizeof(char));

	/* Copy (maybe truncated) packet content */
	memcpy(msg_content, pckt_data->payload, pckt_data->payload_len);

	/* Display message */
	log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_DEBUG,
			"Sending request for %lu", (long)pckt_data->packet_id);

	/* negotiate TLS connection if needed */
	if (!tls.session) {
		log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_INFO,
				"Not connected, trying TLS connection");
		tls_connect();

		if (tls.session) {
			int fd;
			char buf[256];
			buf[0] = '\0';
			nussl_session_get_cipher(tls.session, buf, sizeof(buf));
			log_area_printf(DEBUG_AREA_GW,
					DEBUG_LEVEL_WARNING,
					"[+] TLS connection to nuauth restored (%s:%d), cipher is %s",
					authreq_addr, authreq_port,
					(buf[0] != '\0') ? buf : "none" );

			fd = nussl_session_get_fd(tls.session);
			if (fd >= 0) {
				ev_io_init(&tls.ev_io, tls_activity_cb,
						nussl_session_get_fd(tls.session), EV_READ);
				tls.ev_io.data = &nufw_nfq_watcher;
				ev_io_start(nufw_loop, &tls.ev_io);
			}
		} else {
			log_area_printf(DEBUG_AREA_GW,
					DEBUG_LEVEL_WARNING,
					"[!] TLS connection to nuauth can NOT be restored (%s:%d)",
					authreq_addr, authreq_port);
			return 0;
		}
	}

	if (nussl_write(tls.session, (char*)data, msg_length) < 0) {
		debug_log_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
				 "Error during nussl_write (auth_request_send).");
		shutdown_tls();
		log_area_printf(DEBUG_AREA_GW,
				DEBUG_LEVEL_WARNING,
				"[!] TLS send failure");
		return 0;
	}
	return 1;
}
Exemple #14
0
/**
 * \brief Packet server thread function.
 *
 * Connect to netfilter to ask a netlink. Read packet
 * on this link. Check if packet useful for NuFW. If yes, add it to packet
 * list and/or send it to NuAuth.
 *
 * When using NetFilter queue, it uses treat_packet() as callback.
 * In ipq mode it uses an internal packet parser and process mechanism.
 *
 * \return NULL
 */
void *packetsrv(void *void_arg)
{
	int fatal_error = 0;
	ev_io iface_watcher;
	ev_timer timer;
	int fd;
#ifdef HAVE_NFQ_INDEV_NAME
	struct nlif_handle *nlif_handle;
	int if_fd;
#endif

#ifdef HAVE_NFQ_INDEV_NAME
	nlif_handle = iface_table_open();

	if (!nlif_handle)
		exit(EXIT_FAILURE);

	if_fd = nlif_fd(nlif_handle);
	if (if_fd < 0) {
		exit(EXIT_FAILURE);
	}

	fd = packetsrv_open((void *) nlif_handle);
#else
	fd = packetsrv_open(NULL);
#endif

	if (fd < 0) {
		exit(EXIT_FAILURE);
	}

	log_area_printf(DEBUG_AREA_MAIN | DEBUG_AREA_PACKET, DEBUG_LEVEL_DEBUG,
			"[+] Packet server started");

	nufw_loop = ev_loop_new(0);
	/* add io for nfq */
	ev_io_init(&nufw_nfq_watcher , packetsrv_activity_cb, fd, EV_READ);
	nufw_nfq_watcher.data = nlif_handle;
	ev_io_start(nufw_loop, &nufw_nfq_watcher);
#ifdef HAVE_NFQ_INDEV_NAME
	/* add io for iface */
	ev_io_init(&iface_watcher , iface_activity_cb, if_fd, EV_READ);
	iface_watcher.data = nlif_handle;
	ev_io_start(nufw_loop, &iface_watcher);
#endif
	fd = nussl_session_get_fd(tls.session);
	if (fd >= 0) {
		ev_io_init(&tls.ev_io, tls_activity_cb,
				nussl_session_get_fd(tls.session), EV_READ);
		tls.ev_io.data = &nufw_nfq_watcher;
		ev_io_start(nufw_loop, &tls.ev_io);
	}

	p_pckt_rx = 0;
	p_pckt_tx = 0;
	ev_timer_init(&timer, cleaning_timer_cb, 0, 1.0 * CLEANING_DELAY);
	timer.data = &nufw_nfq_watcher;
	ev_timer_start(nufw_loop, &timer);

	/* start loop */
	ev_loop(nufw_loop, 0);

	ev_loop_destroy(nufw_loop);


#ifdef HAVE_NFQ_INDEV_NAME
	iface_table_close(nlif_handle);
#endif

	packetsrv_close(!fatal_error);

	log_area_printf(DEBUG_AREA_MAIN | DEBUG_AREA_PACKET,
			DEBUG_LEVEL_WARNING,
			"[+] Leave packet server thread");
	return NULL;
}
Exemple #15
0
/**
 * Process NuAuth message of type #AUTH_ANSWER
 */
int auth_process_answer(char *dgram, int dgram_size)
{
	nuv5_nuauth_decision_response_t *answer;
	uint32_t nfmark;
	int sandf;
	u_int32_t packet_id;
	int payload_len;
	int msg_len;

	/* check packet size */
	if (dgram_size < (int) sizeof(nuv4_nuauth_decision_response_t)) {
		return -1;
	}
	answer = (nuv5_nuauth_decision_response_t *) dgram;

	/* check payload length */
	payload_len = ntohs(answer->payload_len);
	msg_len = payload_len + sizeof(nuv5_nuauth_decision_response_t);
	if (dgram_size < msg_len) {
		log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
				"[!] Packet with improper size: payload of %d, received %d (vs %d)",
				payload_len,
				dgram_size,
				(int) (sizeof(nuv5_nuauth_decision_response_t) + payload_len));
		return -1;
	}

	/* get packet id and user id */
	packet_id = ntohl(answer->packet_id);

	/* search and destroy packet by packet_id */
	sandf = psearch_and_destroy(packet_id, &nfmark);
	if (!sandf) {
		log_area_printf(DEBUG_AREA_GW | DEBUG_AREA_GW,
				DEBUG_LEVEL_WARNING,
				"[!] Packet without a known ID: %u",
				packet_id);
		return -1;
	}

	switch (answer->decision) {
	case DECISION_ACCEPT:
		/* accept packet */
		debug_log_printf(DEBUG_AREA_PACKET,
				 DEBUG_LEVEL_VERBOSE_DEBUG,
				 "(*) Accepting packet with id=%u",
				 packet_id);
		if (nufw_set_mark) {
			debug_log_printf(DEBUG_AREA_PACKET,
					 DEBUG_LEVEL_VERBOSE_DEBUG,
					 "(*) Marking packet with %d",
					 ntohl(answer->tcmark));
#if HAVE_NFQ_MARK_EXPTIME
			if (ntohl(answer->expiration) != -1) {
				IPQ_SET_VWMARK_EXPTIME(packet_id, NF_ACCEPT,
					       answer->tcmark,
					       ntohl(answer->expiration));
			} else {
				IPQ_SET_VWMARK(packet_id, NF_ACCEPT,
					       answer->tcmark);
			}
#else
			IPQ_SET_VWMARK(packet_id, NF_ACCEPT,
				       answer->tcmark);
#endif
		} else {
			IPQ_SET_VERDICT(packet_id, NF_ACCEPT);
		}
		pckt_tx++;
		break;

	case DECISION_REJECT:
		/* Packet is rejected, ie. dropped and ICMP signalized */
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
				"(*) Rejecting %" PRIu32, packet_id);
		IPQ_SET_VERDICT(packet_id, NF_DROP);
		if (send_icmp_unreach(dgram +
				  sizeof(nuv5_nuauth_decision_response_t),
				  payload_len) == -1) {
			log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_WARNING,
					"(*) Could not sent ICMP reject for %" PRIu32, packet_id);
		}
		break;

	default:
		/* drop packet */
		debug_log_printf(DEBUG_AREA_PACKET,
				 DEBUG_LEVEL_VERBOSE_DEBUG,
				 "(*) Drop packet %u", packet_id);
		IPQ_SET_VERDICT(packet_id, NF_DROP);
	}
	return msg_len;
}
Exemple #16
0
/**
 * Create a TLS connection to NuAuth: create a TCP socket and connect
 * to NuAuth using ::adr_srv.
 *
 * If x509 is enable (USE_X509 equals to 1), create credentials and check
 * NuAuth's one. This function modify the tls variable and in particular
 * set tls.session.
 *
 */
void tls_connect()
{
	int ret;
	ufwissl_session* sess;

	tls.session = NULL;

	if (authreq_addr[0] == '/')
		return tls_connect_unix();

	if (!init_x509_filenames()) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
				"Couldn't malloc for key or cert filename!");
		return;
	}

	sess = ufwissl_session_create(UFWISSL_SSL_CTX_CLIENT);
	if (!sess) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
				"Unable to create NuSSL session: %s", ufwissl_get_error(sess));
		return;
	}

	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL, "Loading certificate:%s", cert_file);
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL, "Loading key:%s", key_file);

	ret = ufwissl_ssl_set_keypair(sess, cert_file, key_file);
	if (ret != UFWISSL_OK) {
		log_area_printf(DEBUG_AREA_MAIN,
				DEBUG_LEVEL_FATAL,
				"TLS: can not set ufwissl certificate or keyfile: %s",
				ufwissl_get_error(sess));
		ufwissl_session_destroy(sess);
		return;
	}

	/* sets the trusted CA file */
	if (ca_file) {
		ret = ufwissl_ssl_trust_cert_file(sess, ca_file);
		if (ret != UFWISSL_OK) {
			log_area_printf(DEBUG_AREA_MAIN,
					DEBUG_LEVEL_FATAL,
					"TLS: can not set ufwissl CA file: %s",
					ufwissl_get_error(sess));
			ufwissl_session_destroy(sess);
			return;
		}
	}

	/* sets the CRL */
	if (crl_file) {
		ret = ufwissl_ssl_set_crl_file(sess, crl_file, ca_file);
		if (ret != UFWISSL_OK) {
			log_area_printf(DEBUG_AREA_MAIN,
					DEBUG_LEVEL_FATAL,
					"TLS: can not set ufwissl CRL file: %s",
					ufwissl_get_error(sess));
			ufwissl_session_destroy(sess);
			return;
		}
	}

	ufwissl_set_hostinfo(sess, authreq_addr, authreq_port);
	ufwissl_set_read_timeout(sess, 0);
	if (!nufw_strict_tls) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
				"TLS: disabling certificate verification, as asked.");
		ufwissl_ssl_disable_certificate_check(sess, 1);
	}
	if (!nufw_fqdn_check) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
				"TLS: disabling FQDN verification, as asked.");
		ufwissl_set_session_flag(sess, UFWISSL_SESSFLAG_IGNORE_ID_MISMATCH, 1);
	}

	if (ufwissl_open_connection(sess) != UFWISSL_OK) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
				"TLS: cannot connect to tls_socket (%s)",
				ufwissl_get_error(sess));
		ufwissl_session_destroy(sess);
		return;
	}

#ifdef XXX
	if (ca_file) {
		if (nuauth_cert_dn) {
			if (!check_nuauth_cert_dn(tls_session)) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
					"TLS: Cannot check the certificate DN");
				return;
			}
		}
	}
#endif

	tls.session = sess;
}
Exemple #17
0
unsigned int check_nuauth_cert_dn(gnutls_session *tls_session)
{
	/* we check that dn provided in nuauth certificate is valid */
	char dn[128];
	size_t size;
	int ret;

#if 0
	unsigned int algo, bits;
	time_t expiration_time,
	       activation_time;
#endif
	const gnutls_datum *cert_list;
	unsigned int cert_list_size = 0;
	gnutls_x509_crt cert;

	/* This function only works for X.509 certificates.
	*/
	if (gnutls_certificate_type_get(*tls_session) != GNUTLS_CRT_X509)
		return 0;

	cert_list = gnutls_certificate_get_peers(*tls_session, &cert_list_size);
	if (cert_list_size == 0) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
				"TLS: cannot get the peer certificate");
		return 1;
	}

	/* we only print information about the first certificate */
	ret = gnutls_x509_crt_init(&cert);
	if (ret != 0) {
		log_area_printf	(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
				"TLS: cannot init x509 cert: %s",
				gnutls_strerror(ret));
		return 0;
	}

	ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
	if (ret != 0) {
		log_area_printf
			(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
			 "TLS: cannot import x509 cert: %s",
			 gnutls_strerror(ret));
		return 0;
	}

	/* TODO: verify date */
#if 0
	expiration_time = gnutls_x509_crt_get_expiration_time(cert);
	activation_time = gnutls_x509_crt_get_activation_time(cert);

	/* Extract some of the public key algorithm's parameters */
	algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
#endif
	size = sizeof(dn);
	ret = gnutls_x509_crt_get_dn(cert, dn, &size);
	if (ret != 0) {
		log_area_printf (DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
			 "TLS: cannot copy x509 cert name into buffer: %s",
			 gnutls_strerror(ret));
		return 0;
	}
	dn[sizeof(dn)-1] = 0;
	if (strcmp(dn, nuauth_cert_dn)) {
		log_area_printf (DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
			 "TLS: bad certificate DN received from nuauth server: %s",
			 dn);
		return 0;
	}
	return 1;
}
Exemple #18
0
/**
 * Thread waiting to authentication server (NuAuth) answer.
 * Call auth_packet_to_decision() on new packet.
 */
int authsrv(void *data)
{
	int ret;
	int read_size;
	char cdgram[512];
	char *dgram = cdgram;
	int offset = 0;
	int i = 0;

	log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
			"[+] In auth server thread");

	if (tls.session) {
		read_size = sizeof(nuv5_nuauth_decision_response_t);
		/* read size of data */
		do {
			if (i>0) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
						"Reading header (pass %d)", i);
			}
			ret = ufwissl_read(tls.session, dgram + offset, read_size - offset);
			if (ret < 0) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
						"Unable to read header");
				if (!strcmp("Resource temporarily unavailable",
							ufwissl_get_error(tls.session))) {
					log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
							"Resource temporarily unavailable");
					i++;
					continue;
				} else {
					close_tls_session();
					return NU_EXIT_ERROR;
				}
			} else if (ret == 0) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
						"Disconnect during read");
				close_tls_session();
				return NU_EXIT_ERROR;
			} else if (ret != (read_size - offset)) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
						"Under read: %d for %d",
						ret,
						read_size);
				offset += ret;
				i++;
				continue;
			} else {
				offset += ret;
				break;
			}
		} while ((offset != read_size) && i < 3);

		if (i == 3) {
			log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
					"Unable to ufwissl_read %d from session", read_size);
			return NU_EXIT_ERROR;
		}

		read_size = ntohs(((nuv5_nuauth_decision_response_t *) dgram)->payload_len);
		if (read_size != 0) {
			log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
					"going to ufwissl_read: %d", read_size);
			if (read_size + offset > (int) sizeof(cdgram)) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
						"too big to read ufwissl_read: %d", read_size);
				close_tls_session();
				return NU_EXIT_ERROR;
			}
			ret = ufwissl_read(tls.session, dgram + offset, read_size);
			if (ret != read_size) {
				log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
						"Unable to read data");
				return NU_EXIT_ERROR;
			}
		}
	} else
		ret = 0;
	if (ret == UFWISSL_SOCK_TIMEOUT) {
		return NU_EXIT_ERROR;
	}
	if (ret <= 0) {
		log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
				"Error during ufwissl_read: %s", ufwissl_get_error(tls.session));
		close_tls_session();
		return NU_EXIT_ERROR;
	} else {
		ret = read_size + offset;
		do {
			read_size = auth_packet_to_decision(dgram, ret);
			ret -= read_size;
			dgram = dgram + read_size;
		} while (ret > 0 && (read_size != -1));
	}

	dgram = cdgram;
	return NU_EXIT_OK;
}
Exemple #19
0
/**
 * Open a netlink connection and returns file descriptor
 */
int packetsrv_open(void *data)
{
	int ret;

	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
			"Opening netfilter queue socket");
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
			"[!] Don't forget to load kernel modules nfnetlink and nfnetlink_queue (using modprobe command)");

	/* opening library handle */
	h = nfq_open();
	if (!h) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Error during nfq_open()");
		return -1;
	}

	/* unbinding existing nf_queue handler for AF_INET (if any) */
	/* ignoring return, see http://www.spinics.net/lists/netfilter/msg42063.html */
	nfq_unbind_pf(h, AF_INET);

	/* binding nfnetlink_queue as nf_queue handler for AF_INET */
	if (nfq_bind_pf(h, AF_INET) < 0) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Error during nfq_bind_pf()");
		return -1;
	}

	if (!nufw_no_ipv6) {
		/* unbinding existing nf_queue handler for AF_INET6 (if any) */
		nfq_unbind_pf(h, AF_INET6);

		/* binding nfnetlink_queue as nf_queue handler for AF_INET6 */
		if (nfq_bind_pf(h, AF_INET6) < 0) {
			log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
					"[!] Error during nfq_bind_pf()");
			log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
					"Maybe you need to compile NF_NETLINK* kernel options as modules (not built in the kernel!)");
			return -1;
		}
	}

	ret = nfnl_rcvbufsiz(nfq_nfnlh(h), 10 * 65536);
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
			"rcv buf size set to %d (%d asked)",
			ret, 10 * 65536);

	/* binding this socket to queue number ::nfqueue_num
	 * and install our packet handler */
	log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_DEBUG,
			"[+] Binding to netfilter queue %d", nfqueue_num);
	hndl = nfq_create_queue(h, nfqueue_num,
			     (nfq_callback *) & treat_packet, data);
	if (!hndl) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Error during nfq_create_queue() (queue %d busy ?)",
				nfqueue_num);
		return -1;
	}

	/* setting copy_packet mode */
	if (nfq_set_mode(hndl, NFQNL_COPY_PACKET, 0xffff) < 0) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
				"[!] Can't set packet_copy mode");
		return -1;
	}
#ifdef HAVE_NFQ_SET_QUEUE_MAXLEN
	/* setting queue length */
	if (queue_maxlen) {
		if (nfq_set_queue_maxlen(hndl, queue_maxlen) < 0) {
			if (nufw_set_mark) {
				log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
						"[!] Can't set queue length, and mark will be set, leaving !");
				exit(EXIT_FAILURE);
			} else {
				log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
						"[!] Can't set queue length, continuing anyway");
			}
		}
	}
#endif

	return nfq_fd(h);
}