Exemplo n.º 1
0
/*
 *	Do the statistics
 */
static rlm_rcode_t CC_HINT(nonnull) mod_stats(void *instance, void *thread, REQUEST *request)
{
	int i;
	uint32_t stats_type;
	rlm_stats_thread_t *t = thread;
	rlm_stats_t *inst = instance;
	VALUE_PAIR *vp;
	rlm_stats_data_t mydata, *stats;
	fr_cursor_t cursor;
	char buffer[64];
	uint64_t local_stats[sizeof(inst->stats) / sizeof(inst->stats[0])];

	/*
	 *	Increment counters only in "send foo" sections.
	 *
	 *	i.e. only when we have a reply to send.
	 */
	if (request->request_state == REQUEST_SEND) {
		int src_code, dst_code;

		src_code = request->packet->code;
		if (src_code >= FR_MAX_PACKET_CODE) src_code = 0;

		dst_code = request->reply->code;
		if (dst_code >= FR_MAX_PACKET_CODE) dst_code = 0;

		t->stats[src_code]++;
		t->stats[dst_code]++;

		/*
		 *	Update source statistics
		 */
		mydata.ipaddr = request->packet->src_ipaddr;
		stats = rbtree_finddata(t->src, &mydata);
		if (!stats) {
			MEM(stats = talloc_zero(t, rlm_stats_data_t));

			stats->ipaddr = request->packet->src_ipaddr;
			stats->created = request->async->recv_time;

			(void) rbtree_insert(t->src, stats);
		}

		stats->last_packet = request->async->recv_time;
		stats->stats[src_code]++;
		stats->stats[dst_code]++;

		/*
		 *	Update destination statistics
		 */
		mydata.ipaddr = request->packet->dst_ipaddr;
		stats = rbtree_finddata(t->dst, &mydata);
		if (!stats) {
			MEM(stats = talloc_zero(t, rlm_stats_data_t));

			stats->ipaddr = request->packet->dst_ipaddr;
			stats->created = request->async->recv_time;

			(void) rbtree_insert(t->dst, stats);
		}

		stats->last_packet = request->async->recv_time;
		stats->stats[src_code]++;
		stats->stats[dst_code]++;

		/*
		 *	@todo - periodically clean up old entries.
		 */

		if ((t->last_global_update + NANOSEC) > request->async->recv_time) {
			return RLM_MODULE_UPDATED;
		}

		t->last_global_update = request->async->recv_time;

		pthread_mutex_lock(&inst->mutex);
		for (i = 0; i < FR_MAX_PACKET_CODE; i++) {
			inst->stats[i] += t->stats[i];
			t->stats[i] = 0;
		}
		pthread_mutex_unlock(&inst->mutex);

		return RLM_MODULE_UPDATED;
	}

	/*
	 *	Ignore "authenticate" and anything other than Status-Server
	 */
	if ((request->request_state != REQUEST_RECV) ||
	    (request->packet->code != FR_CODE_STATUS_SERVER)) {
		return RLM_MODULE_NOOP;
	}

	vp = fr_pair_find_by_da(request->packet->vps, attr_freeradius_stats4_type, TAG_ANY);
	if (!vp) {
		stats_type = FR_FREERADIUS_STATS4_TYPE_VALUE_GLOBAL;
	} else {
		stats_type = vp->vp_uint32;
	}

	/*
	 *	Create attributes based on the statistics.
	 */
	fr_cursor_init(&cursor, &request->reply->vps);

	MEM(pair_update_reply(&vp, attr_freeradius_stats4_type) >= 0);
	vp->vp_uint32 = stats_type;

	switch (stats_type) {
	case FR_FREERADIUS_STATS4_TYPE_VALUE_GLOBAL:			/* global */
		/*
		 *	Merge our stats with the global stats, and then copy
		 *	the global stats to a thread-local variable.
		 *
		 *	The copy helps minimize mutex contention.
		 */
		pthread_mutex_lock(&inst->mutex);
		for (i = 0; i < FR_MAX_PACKET_CODE; i++) {
			inst->stats[i] += t->stats[i];
			t->stats[i] = 0;
		}
		memcpy(&local_stats, inst->stats, sizeof(inst->stats));
		pthread_mutex_unlock(&inst->mutex);
		vp = NULL;
		break;

	case FR_FREERADIUS_STATS4_TYPE_VALUE_CLIENT:			/* src */
		vp = fr_pair_find_by_da(request->packet->vps, attr_freeradius_stats4_ipv4_address, TAG_ANY);
		if (!vp) vp = fr_pair_find_by_da(request->packet->vps, attr_freeradius_stats4_ipv6_address, TAG_ANY);
		if (!vp) return RLM_MODULE_NOOP;

		mydata.ipaddr = vp->vp_ip;
		coalesce(local_stats, t, offsetof(rlm_stats_thread_t, src), &mydata);
		break;

	case FR_FREERADIUS_STATS4_TYPE_VALUE_LISTENER:			/* dst */
		vp = fr_pair_find_by_da(request->packet->vps, attr_freeradius_stats4_ipv4_address, TAG_ANY);
		if (!vp) vp = fr_pair_find_by_da(request->packet->vps, attr_freeradius_stats4_ipv6_address, TAG_ANY);
		if (!vp) return RLM_MODULE_NOOP;

		mydata.ipaddr = vp->vp_ip;
		coalesce(local_stats, t, offsetof(rlm_stats_thread_t, dst), &mydata);
		break;

	default:
		REDEBUG("Invalid value '%d' for FreeRADIUS-Stats4-type", stats_type);
		return RLM_MODULE_FAIL;
	}

	if (vp ) {
		vp = fr_pair_copy(request->reply, vp);
		if (vp) {
			fr_cursor_append(&cursor, vp);
			(void) fr_cursor_tail(&cursor);
		}
	}

	strcpy(buffer, "FreeRADIUS-Stats4-");

	for (i = 0; i < FR_MAX_PACKET_CODE; i++) {
		fr_dict_attr_t const *da;

		if (!local_stats[i]) continue;

		strlcpy(buffer + 18, fr_packet_codes[i], sizeof(buffer) - 18);
		da = fr_dict_attr_by_name(dict_radius, buffer);
		if (!da) continue;

		vp = fr_pair_afrom_da(request->reply, da);
		if (!vp) return RLM_MODULE_FAIL;

		vp->vp_uint64 = local_stats[i];

		fr_cursor_append(&cursor, vp);
		(void) fr_cursor_tail(&cursor);
	}

	return RLM_MODULE_OK;
}
Exemplo n.º 2
0
/*
 *	Authenticate the user via one of any well-known password.
 */
static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, UNUSED void *thread, REQUEST *request)
{
	int		rcode;
	rlm_securid_t	const *inst = instance;
	char		 buffer[FR_MAX_STRING_LEN]="";
	char const	*username=NULL, *password=NULL;
	VALUE_PAIR	*vp;

	/*
	 *	We can only authenticate user requests which HAVE
	 *	a User-Name attribute.
	 */
	if (!request->username) {
		REDEBUG("Attribute \"User-Name\" is required for authentication");
		return RLM_MODULE_INVALID;
	}

	if (!request->password) {
		REDEBUG("Attribute \"Password\" is required for authentication");
		return RLM_MODULE_INVALID;
	}

	/*
	 *	Clear-text passwords are the only ones we support.
	 */
	if (request->password->da != attr_user_password) {
		REDEBUG("Attribute \"User-Password\" is required for authentication. Cannot use \"%s\"",
			request->password->da->name);
		return RLM_MODULE_INVALID;
	}

	/*
	 *	The user MUST supply a non-zero-length password.
	 */
	if (request->password->vp_length == 0) {
		REDEBUG("Password should not be empty");
		return RLM_MODULE_INVALID;
	}

	/*
	 *	shortcuts
	 */
	username = request->username->vp_strvalue;
	password = request->password->vp_strvalue;

	if (RDEBUG_ENABLED3) {
		RDEBUG3("Login attempt with password \"%s\"", password);
	} else {
		RDEBUG2("Login attempt with password");
	}

	rcode = securidAuth(inst, request, username, password,
			    buffer, sizeof(buffer));

	switch (rcode) {
	case RC_SECURID_AUTH_SUCCESS:
		rcode = RLM_MODULE_OK;
		break;

	case RC_SECURID_AUTH_CHALLENGE:
		/* reply with Access-challenge message code (11) */

		/* Generate Prompt attribute */
		MEM(pair_update_reply(&vp, attr_prompt) >= 0);
		vp->vp_uint32 = 0; /* no echo */

		/* Mark the packet as a Acceess-Challenge Packet */
		request->reply->code = FR_CODE_ACCESS_CHALLENGE;
		RDEBUG2("Sending Access-Challenge");
		rcode = RLM_MODULE_HANDLED;
		break;

	case RC_SECURID_AUTH_FAILURE:
	case RC_SECURID_AUTH_ACCESS_DENIED_FAILURE:
	case RC_SECURID_AUTH_INVALID_SERVER_FAILURE:
	default:
		rcode = RLM_MODULE_REJECT;
		break;
	}

	if (*buffer) {
		MEM(pair_update_reply(&vp, attr_reply_message) >= 0);
		fr_pair_value_strcpy(vp, buffer);
	}
	return rcode;
}