예제 #1
0
파일: events.c 프로젝트: AxelLin/Drv
/**
 * wpa_supplicant_scard_init - Initialize SIM/USIM access with PC/SC
 * @wpa_s: pointer to wpa_supplicant data
 * @ssid: Configuration data for the network
 * Returns: 0 on success, -1 on failure
 *
 * This function is called when starting authentication with a network that is
 * configured to use PC/SC for SIM/USIM access (EAP-SIM or EAP-AKA).
 */
int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
			      struct wpa_ssid *ssid)
{
#ifdef IEEE8021X_EAPOL
	int aka = 0, sim = 0, type;

	if (ssid->pcsc == NULL || wpa_s->scard != NULL)
		return 0;

	if (ssid->eap_methods == NULL) {
		sim = 1;
		aka = 1;
	} else {
		struct eap_method_type *eap = ssid->eap_methods;
		while (eap->vendor != EAP_VENDOR_IETF ||
		       eap->method != EAP_TYPE_NONE) {
			if (eap->vendor == EAP_VENDOR_IETF) {
				if (eap->method == EAP_TYPE_SIM)
					sim = 1;
				else if (eap->method == EAP_TYPE_AKA)
					aka = 1;
			}
			eap++;
		}
	}

	if (eap_sm_get_eap_methods(EAP_VENDOR_IETF, EAP_TYPE_SIM) == NULL)
		sim = 0;
	if (eap_sm_get_eap_methods(EAP_VENDOR_IETF, EAP_TYPE_AKA) == NULL)
		aka = 0;

	if (!sim && !aka) {
		wpa_printf(MSG_DEBUG, "Selected network is configured to use "
			   "SIM, but neither EAP-SIM nor EAP-AKA are enabled");
		return 0;
	}

	wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM "
		   "(sim=%d aka=%d) - initialize PCSC", sim, aka);
	if (sim && aka)
		type = SCARD_TRY_BOTH;
	else if (aka)
		type = SCARD_USIM_ONLY;
	else
		type = SCARD_GSM_SIM_ONLY;

	wpa_s->scard = scard_init(type);
	if (wpa_s->scard == NULL) {
		wpa_printf(MSG_WARNING, "Failed to initialize SIM "
			   "(pcsc-lite)");
		return -1;
	}
	wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
#endif /* IEEE8021X_EAPOL */

	return 0;
}
예제 #2
0
SM_STATE(EAP, PROPOSE_METHOD)
{
	SM_ENTRY(EAP, PROPOSE_METHOD);

	sm->currentMethod = eap_sm_Policy_getNextMethod(sm);
	if (sm->m && sm->eap_method_priv) {
		sm->m->reset(sm, sm->eap_method_priv);
		sm->eap_method_priv = NULL;
	}
	sm->m = eap_sm_get_eap_methods(sm->currentMethod);
	if (sm->m) {
		sm->eap_method_priv = sm->m->init(sm);
		if (sm->eap_method_priv == NULL) {
			wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
				   "method %d", sm->currentMethod);
			sm->m = NULL;
			sm->currentMethod = EAP_TYPE_NONE;
		}
	}
	if (sm->currentMethod == EAP_TYPE_IDENTITY ||
	    sm->currentMethod == EAP_TYPE_NOTIFICATION)
		sm->methodState = METHOD_CONTINUE;
	else
		sm->methodState = METHOD_PROPOSED;
}
예제 #3
0
SM_STATE(EAP, PICK_UP_METHOD)
{
	SM_ENTRY(EAP, PICK_UP_METHOD);

	if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
		sm->currentMethod = sm->respMethod;
		if (sm->m && sm->eap_method_priv) {
			sm->m->reset(sm, sm->eap_method_priv);
			sm->eap_method_priv = NULL;
		}
		sm->m = eap_sm_get_eap_methods(sm->currentMethod);
		if (sm->m && sm->m->initPickUp) {
			sm->eap_method_priv = sm->m->initPickUp(sm);
			if (sm->eap_method_priv == NULL) {
				wpa_printf(MSG_DEBUG, "EAP: Failed to "
					   "initialize EAP method %d",
					   sm->currentMethod);
				sm->m = NULL;
				sm->currentMethod = EAP_TYPE_NONE;
			}
		} else {
			sm->m = NULL;
			sm->currentMethod = EAP_TYPE_NONE;
		}
	}
}
SM_STATE(EAP, PROPOSE_METHOD)
{
	int vendor;
	EapType type;

	SM_ENTRY(EAP, PROPOSE_METHOD);

	type = eap_sm_Policy_getNextMethod(sm, &vendor);
	if (vendor == EAP_VENDOR_IETF)
		sm->currentMethod = type;
	else
		sm->currentMethod = EAP_TYPE_EXPANDED;
	if (sm->m && sm->eap_method_priv) {
		sm->m->reset(sm, sm->eap_method_priv);
		sm->eap_method_priv = NULL;
	}
	sm->m = eap_sm_get_eap_methods(vendor, type);
	if (sm->m) {
		sm->eap_method_priv = sm->m->init(sm);
		if (sm->eap_method_priv == NULL) {
			wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
				   "method %d", sm->currentMethod);
			sm->m = NULL;
			sm->currentMethod = EAP_TYPE_NONE;
		}
	}
	if (sm->currentMethod == EAP_TYPE_IDENTITY ||
	    sm->currentMethod == EAP_TYPE_NOTIFICATION)
		sm->methodState = METHOD_CONTINUE;
	else
		sm->methodState = METHOD_PROPOSED;
}
예제 #5
0
SM_STATE(EAP, GET_METHOD)
{
	SM_ENTRY(EAP, GET_METHOD);
	if (eap_sm_allowMethod(sm, sm->reqMethod)) {
		int reinit = 0;
		if (sm->fast_reauth &&
		    sm->m && sm->m->method == sm->reqMethod &&
		    sm->m->has_reauth_data &&
		    sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
			wpa_printf(MSG_DEBUG, "EAP: using previous method data"
				   " for fast re-authentication");
			reinit = 1;
		} else
			eap_deinit_prev_method(sm, "GET_METHOD");
		sm->selectedMethod = sm->reqMethod;
		if (sm->m == NULL)
			sm->m = eap_sm_get_eap_methods(sm->selectedMethod);
		if (sm->m) {
			wpa_printf(MSG_DEBUG, "EAP: initialize selected EAP "
				   "method (%d, %s)",
				   sm->selectedMethod, sm->m->name);
			if (reinit)
				sm->eap_method_priv = sm->m->init_for_reauth(
					sm, sm->eap_method_priv);
			else
				sm->eap_method_priv = sm->m->init(sm);
			if (sm->eap_method_priv == NULL) {
				struct wpa_ssid *config = eap_get_config(sm);
				wpa_printf(MSG_DEBUG, "EAP: Failed to "
					   "initialize EAP method %d",
					   sm->selectedMethod);
				sm->m = NULL;
				sm->methodState = METHOD_NONE;
				sm->selectedMethod = EAP_TYPE_NONE;
				if (sm->reqMethod == EAP_TYPE_TLS &&
				    config && config->pending_req_pin) {
					/*
					 * Return without generating Nak in
					 * order to allow entering of PIN code
					 * to retry the current EAP packet.
					 */
					wpa_printf(MSG_DEBUG, "EAP: Pending "
						   "PIN request - skip Nak");
					return;
				}
			} else {
				sm->methodState = METHOD_INIT;
				return;
			}
		}
	}

	free(sm->eapRespData);
	sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen);
}
예제 #6
0
int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
{
	int len;

	if (sm == NULL)
		return 0;

	len = snprintf(buf, buflen,
		       "EAP state=%s\n",
		       eap_sm_state_txt(sm->EAP_state));

	if (sm->selectedMethod != EAP_TYPE_NONE) {
		const char *name;
		if (sm->m) {
			name = sm->m->name;
		} else {
			const struct eap_method *m =
				eap_sm_get_eap_methods(sm->selectedMethod);
			if (m)
				name = m->name;
			else
				name = "?";
		}
		len += snprintf(buf + len, buflen - len,
				"selectedMethod=%d (EAP-%s)\n",
				sm->selectedMethod, name);

		if (sm->m && sm->m->get_status) {
			len += sm->m->get_status(sm, sm->eap_method_priv,
						 buf + len, buflen - len,
						 verbose);
		}
	}

	if (verbose) {
		len += snprintf(buf + len, buflen - len,
				"reqMethod=%d\n"
				"methodState=%s\n"
				"decision=%s\n"
				"ClientTimeout=%d\n",
				sm->reqMethod,
				eap_sm_method_state_txt(sm->methodState),
				eap_sm_decision_txt(sm->decision),
				sm->ClientTimeout);
	}

	return len;
}
예제 #7
0
static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
				u8 eap_type)
{
	if (data->phase2_priv && data->phase2_method) {
		data->phase2_method->reset(sm, data->phase2_priv);
		data->phase2_method = NULL;
		data->phase2_priv = NULL;
	}
	data->phase2_method = eap_sm_get_eap_methods(eap_type);
	if (!data->phase2_method)
		return -1;

	sm->init_phase2 = 1;
	data->phase2_priv = data->phase2_method->init(sm);
	sm->init_phase2 = 0;
	return 0;
}
static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
				       struct eap_ttls_data *data,
				       struct eap_method_ret *ret,
				       struct eap_hdr *hdr,
				       u8 **resp, size_t *resp_len)
{
	size_t len = be_to_host16(hdr->length);
	u8 *pos;
	struct eap_method_ret iret;
	struct wpa_ssid *config = eap_get_config(sm);

	if (len <= sizeof(struct eap_hdr)) {
		wpa_printf(MSG_INFO, "EAP-TTLS: too short "
			   "Phase 2 request (len=%lu)", (unsigned long) len);
		return -1;
	}
	pos = (u8 *) (hdr + 1);
	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);
	switch (*pos) {
	case EAP_TYPE_IDENTITY:
		*resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1);
		break;
	default:
		if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
		    data->phase2_eap_type.method == EAP_TYPE_NONE) {
			size_t i;
			for (i = 0; i < data->num_phase2_eap_types; i++) {
				if (data->phase2_eap_types[i].vendor !=
				    EAP_VENDOR_IETF ||
				    data->phase2_eap_types[i].method != *pos)
					continue;

				data->phase2_eap_type.vendor =
					data->phase2_eap_types[i].vendor;
				data->phase2_eap_type.method =
					data->phase2_eap_types[i].method;
				wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
					   "Phase 2 EAP vendor %d method %d",
					   data->phase2_eap_type.vendor,
					   data->phase2_eap_type.method);
				break;
			}
		}
		if (*pos != data->phase2_eap_type.method ||
		    *pos == EAP_TYPE_NONE) {
			if (eap_ttls_phase2_nak(data, hdr, resp, resp_len))
				return -1;
			break;
		}

		if (data->phase2_priv == NULL) {
			data->phase2_method = eap_sm_get_eap_methods(
				EAP_VENDOR_IETF, *pos);
			if (data->phase2_method) {
				sm->init_phase2 = 1;
				sm->mschapv2_full_key = 1;
				data->phase2_priv =
					data->phase2_method->init(sm);
				sm->init_phase2 = 0;
				sm->mschapv2_full_key = 0;
			}
		}
		if (data->phase2_priv == NULL || data->phase2_method == NULL) {
			wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
				   "Phase 2 EAP method %d", *pos);
			return -1;
		}
		os_memset(&iret, 0, sizeof(iret));
		*resp = data->phase2_method->process(sm, data->phase2_priv,
						     &iret, (u8 *) hdr, len,
						     resp_len);
		if ((iret.methodState == METHOD_DONE ||
		     iret.methodState == METHOD_MAY_CONT) &&
		    (iret.decision == DECISION_UNCOND_SUCC ||
		     iret.decision == DECISION_COND_SUCC ||
		     iret.decision == DECISION_FAIL)) {
			ret->methodState = iret.methodState;
			ret->decision = iret.decision;
		}
		if (data->ttls_version > 0) {
			const struct eap_method *m = data->phase2_method;
			void *priv = data->phase2_priv;

			/* TTLSv1 requires TLS/IA FinalPhaseFinished */
			if (ret->decision == DECISION_UNCOND_SUCC)
				ret->decision = DECISION_COND_SUCC;
			ret->methodState = METHOD_CONT;

			if (ret->decision == DECISION_COND_SUCC &&
			    m->isKeyAvailable && m->getKey &&
			    m->isKeyAvailable(sm, priv)) {
				u8 *key;
				size_t key_len;
				key = m->getKey(sm, priv, &key_len);
				if (key) {
					eap_ttls_ia_permute_inner_secret(
						sm, data, key, key_len);
					os_free(key);
				}
			}
		}
		break;
	}

	if (*resp == NULL &&
	    (config->pending_req_identity || config->pending_req_password ||
	     config->pending_req_otp)) {
		return 0;
	}

	if (*resp == NULL)
		return -1;

	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response",
		    *resp, *resp_len);
	return eap_ttls_avp_encapsulate(resp, resp_len,
					RADIUS_ATTR_EAP_MESSAGE, 1);
}