Exemple #1
0
static int eap_post_auth(void *instance, REQUEST *request)
{
	rlm_eap_t	*inst = instance;
	VALUE_PAIR	*vp;
	EAP_HANDLER	*handler;
	eap_packet_t	*eap_packet;
	
	/*
	 * Only build a failure message if something previously rejected the request
	 */
	vp = pairfind(request->config_items, PW_POSTAUTHTYPE, 0, TAG_ANY);

	if (!vp || (vp->vp_integer != PW_POSTAUTHTYPE_REJECT)) return RLM_MODULE_NOOP;
	
	if (!pairfind(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
		RDEBUG2("Request didn't contain an EAP-Message, not inserting EAP-Failure");
		return RLM_MODULE_NOOP;
	}
	
	if (pairfind(request->reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
		RDEBUG2("Reply already contained an EAP-Message, not inserting EAP-Failure");
		return RLM_MODULE_NOOP;
	}
	
	eap_packet = eap_vp2packet(request->packet->vps);
	if (eap_packet == NULL) {
		radlog_request(L_ERR, 0, request, "Malformed EAP Message");
		return RLM_MODULE_FAIL;
	}

	handler = eap_handler(inst, &eap_packet, request);
	if (handler == NULL) {
		RDEBUG2("Failed to get handler, probably already removed, not inserting EAP-Failure");
		return RLM_MODULE_NOOP;
	}

	RDEBUG2("Request was previously rejected, inserting EAP-Failure");
	eap_fail(handler);
	eap_handler_free(inst, handler);
	
	/*
	 * Make sure there's a message authenticator attribute in the response
	 * RADIUS protocol code will calculate the correct value later...
	 */
	vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
	if (!vp) {
		vp = pairmake("Message-Authenticator",
				  "0x00", T_OP_EQ);
		rad_assert(vp != NULL);
		pairadd(&(request->reply->vps), vp);
	}

	return RLM_MODULE_UPDATED;
}
/*
 *	For backwards compatibility.
 */
static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request)
{
	rlm_eap_t		*inst;
	eap_handler_t		*handler;
	eap_packet_raw_t	*eap_packet;
	eap_rcode_t		status;
	rlm_rcode_t		rcode;

	inst = (rlm_eap_t *) instance;

	if (!pairfind(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
		RDEBUGE("You set 'Auth-Type = EAP' for a request that does "
			"not contain an EAP-Message attribute!");
		return RLM_MODULE_INVALID;
	}

	/*
	 *	Get the eap packet  to start with
	 */
	eap_packet = eap_vp2packet(request, request->packet->vps);
	if (!eap_packet) {
		radlog_request(L_ERR, 0, request, "Malformed EAP Message");
		return RLM_MODULE_FAIL;
	}

	/*
	 *	Create the eap handler.  The eap_packet will end up being
	 *	"swallowed" into the handler, so we can't access it after
	 *	this call.
	 */
	handler = eap_handler(inst, &eap_packet, request);
	if (!handler) {
		RDEBUG2("Failed in handler");
		return RLM_MODULE_INVALID;
	}

	/*
	 *	Select the appropriate method or default to the
	 *	configured one
	 */
	status = eap_method_select(inst, handler);

	/*
	 *	If it failed, die.
	 */
	if (status == EAP_INVALID) {
		eap_fail(handler);
		eap_handler_free(inst, handler);
		RDEBUG2("Failed in EAP select");
		return RLM_MODULE_INVALID;
	}

#ifdef WITH_PROXY
	/*
	 *	If we're doing horrible tunneling work, remember it.
	 */
	if ((request->options & RAD_REQUEST_OPTION_PROXY_EAP) != 0) {
		RDEBUG2("  Not-EAP proxy set.  Not composing EAP");
		/*
		 *	Add the handle to the proxied list, so that we
		 *	can retrieve it in the post-proxy stage, and
		 *	send a response.
		 */
		handler->inst_holder = inst;
		status = request_data_add(request,
					  inst, REQUEST_DATA_eap_handler_t,
					  handler, (void *) eap_opaque_free);
		rad_assert(status == 0);
		return RLM_MODULE_HANDLED;
	}
#endif

#ifdef WITH_PROXY
	/*
	 *	Maybe the request was marked to be proxied.  If so,
	 *	proxy it.
	 */
	if (request->proxy != NULL) {
		VALUE_PAIR *vp = NULL;

		rad_assert(!request->proxy_reply);

		/*
		 *	Add the handle to the proxied list, so that we
		 *	can retrieve it in the post-proxy stage, and
		 *	send a response.
		 */
		handler->inst_holder = inst;
		status = request_data_add(request,
					  inst, REQUEST_DATA_eap_handler_t,
					  handler,
					  (void *) eap_opaque_free);
		rad_assert(status == 0);

		/*
		 *	Some simple sanity checks.  These should really
		 *	be handled by the radius library...
		 */
		vp = pairfind(request->proxy->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
		if (vp) {
			vp = pairfind(request->proxy->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
			if (!vp) {
				pairmake(request->proxy,
					 &request->proxy->vps,
					 "Message-Authenticator",
					 "0x00", T_OP_EQ);
			}
		}

		/*
		 *	Delete the "proxied to" attribute, as it's
		 *	set to 127.0.0.1 for tunneled requests, and
		 *	we don't want to tell the world that...
		 */
		pairdelete(&request->proxy->vps, PW_FREERADIUS_PROXIED_TO, VENDORPEC_FREERADIUS, TAG_ANY);

		RDEBUG2("  Tunneled session will be proxied.  Not doing EAP.");
		return RLM_MODULE_HANDLED;
	}
#endif

	/*
	 *	We are done, wrap the EAP-request in RADIUS to send
	 *	with all other required radius attributes
	 */
	rcode = eap_compose(handler);

	/*
	 *	Add to the list only if it is EAP-Request, OR if
	 *	it's LEAP, and a response.
	 */
	if (((handler->eap_ds->request->code == PW_EAP_REQUEST) &&
	    (handler->eap_ds->request->type.num >= PW_EAP_MD5)) ||

		/*
		 *	LEAP is a little different.  At Stage 4,
		 *	it sends an EAP-Success message, but we still
		 *	need to keep the State attribute & session
		 *	data structure around for the AP Challenge.
		 *
		 *	At stage 6, LEAP sends an EAP-Response, which
		 *	isn't put into the list.
		 */
	    ((handler->eap_ds->response->code == PW_EAP_RESPONSE) &&
	     (handler->eap_ds->response->type.num == PW_EAP_LEAP) &&
	     (handler->eap_ds->request->code == PW_EAP_SUCCESS) &&
	     (handler->eap_ds->request->type.num == 0))) {

		/*
		 *	Return FAIL if we can't remember the handler.
		 *	This is actually disallowed by the
		 *	specification, as unexpected FAILs could have
		 *	been forged.  However, we want to signal to
		 *	everyone else involved that we are
		 *	intentionally failing the session, as opposed
		 *	to accidentally failing it.
		 */
		if (!eaplist_add(inst, handler)) {
			RDEBUG("Failed adding handler to the list");
			eap_fail(handler);
			eap_handler_free(inst, handler);
			return RLM_MODULE_FAIL;
		}

	} else {
		RDEBUG2("Freeing handler");
		/* handler is not required any more, free it now */
		eap_handler_free(inst, handler);
	}

	/*
	 *	If it's an Access-Accept, RFC 2869, Section 2.3.1
	 *	says that we MUST include a User-Name attribute in the
	 *	Access-Accept.
	 */
	if ((request->reply->code == PW_AUTHENTICATION_ACK) &&
	    request->username) {
		VALUE_PAIR *vp;

		/*
		 *	Doesn't exist, add it in.
		 */
		vp = pairfind(request->reply->vps, PW_USER_NAME, 0, TAG_ANY);
		if (!vp) {
			vp = pairmake_reply("User-Name", "",
				      T_OP_EQ);
			strlcpy(vp->vp_strvalue, request->username->vp_strvalue,
				sizeof(vp->vp_strvalue));
			vp->length = request->username->length;
		}

		/*
		 *	Cisco AP1230 has a bug and needs a zero
		 *	terminated string in Access-Accept.
		 */
		if ((inst->mod_accounting_username_bug) &&
		    (vp->length < (int) sizeof(vp->vp_strvalue))) {
			vp->vp_strvalue[vp->length] = '\0';
			vp->length++;
		}
	}

	return rcode;
}