Exemple #1
0
/**
 * eap_peer_select_phase2_methods - Select phase 2 EAP method
 * @config: Pointer to the network configuration
 * @prefix: 'phase2' configuration prefix, e.g., "auth="
 * @types: Buffer for returning allocated list of allowed EAP methods
 * @num_types: Buffer for returning number of allocated EAP methods
 * Returns: 0 on success, -1 on failure
 *
 * This function is used to parse EAP method list and select allowed methods
 * for Phase2 authentication.
 */
int eap_peer_select_phase2_methods(struct eap_peer_config *config,
				   const char *prefix,
				   struct eap_method_type **types,
				   size_t *num_types)
{
	char *start, *pos, *buf;
	struct eap_method_type *methods = NULL, *_methods;
	u8 method;
	size_t num_methods = 0, prefix_len;

	if (config == NULL || config->phase2 == NULL)
		goto get_defaults;

	start = buf = os_strdup(config->phase2);
	if (buf == NULL)
		return -1;

	prefix_len = os_strlen(prefix);

	while (start && *start != '\0') {
		int vendor;
		pos = os_strstr(start, prefix);
		if (pos == NULL)
			break;
		if (start != pos && *(pos - 1) != ' ') {
			start = pos + prefix_len;
			continue;
		}

		start = pos + prefix_len;
		pos = os_strchr(start, ' ');
		if (pos)
			*pos++ = '\0';
		method = eap_get_phase2_type(start, &vendor);
		if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) {
			wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP "
				   "method '%s'", start);
		} else {
			num_methods++;
			_methods = os_realloc_array(methods, num_methods,
						    sizeof(*methods));
			if (_methods == NULL) {
				os_free(methods);
				os_free(buf);
				return -1;
			}
			methods = _methods;
			methods[num_methods - 1].vendor = vendor;
			methods[num_methods - 1].method = method;
		}

		start = pos;
	}

	os_free(buf);

get_defaults:
	if (methods == NULL)
		methods = eap_get_phase2_types(config, &num_methods);

	if (methods == NULL) {
		wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available");
		return -1;
	}
	wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types",
		    (u8 *) methods,
		    num_methods * sizeof(struct eap_method_type));

	*types = methods;
	*num_types = num_methods;

	return 0;
}
static void * eap_ttls_init(struct eap_sm *sm)
{
	struct eap_ttls_data *data;
	struct wpa_ssid *config = eap_get_config(sm);
	char *selected;

	data = os_zalloc(sizeof(*data));
	if (data == NULL)
		return NULL;
	data->ttls_version = EAP_TTLS_VERSION;
	data->force_ttls_version = -1;
	selected = "EAP";
	data->phase2_type = EAP_TTLS_PHASE2_EAP;

	if (config && config->phase1) {
		char *pos = os_strstr(config->phase1, "ttlsver=");
		if (pos) {
			data->force_ttls_version = atoi(pos + 8);
			data->ttls_version = data->force_ttls_version;
			wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version "
				   "%d", data->force_ttls_version);
		}
	}

	if (config && config->phase2) {
		if (os_strstr(config->phase2, "autheap=")) {
			selected = "EAP";
			data->phase2_type = EAP_TTLS_PHASE2_EAP;
		} else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
			selected = "MSCHAPV2";
			data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
		} else if (os_strstr(config->phase2, "auth=MSCHAP")) {
			selected = "MSCHAP";
			data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
		} else if (os_strstr(config->phase2, "auth=PAP")) {
			selected = "PAP";
			data->phase2_type = EAP_TTLS_PHASE2_PAP;
		} else if (os_strstr(config->phase2, "auth=CHAP")) {
			selected = "CHAP";
			data->phase2_type = EAP_TTLS_PHASE2_CHAP;
		}
	}
	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);

	if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
		if (config && config->phase2) {
			char *start, *pos, *buf;
			struct eap_method_type *methods = NULL, *_methods;
			u8 method;
			size_t num_methods = 0;
			start = buf = os_strdup(config->phase2);
			if (buf == NULL) {
				eap_ttls_deinit(sm, data);
				return NULL;
			}
			while (start && *start != '\0') {
				int vendor;
				pos = os_strstr(start, "autheap=");
				if (pos == NULL)
					break;
				if (start != pos && *(pos - 1) != ' ') {
					start = pos + 8;
					continue;
				}

				start = pos + 8;
				pos = os_strchr(start, ' ');
				if (pos)
					*pos++ = '\0';
				method = eap_get_phase2_type(start, &vendor);
				if (vendor == EAP_VENDOR_IETF &&
				    method == EAP_TYPE_NONE) {
					wpa_printf(MSG_ERROR, "EAP-TTLS: "
						   "Unsupported Phase2 EAP "
						   "method '%s'", start);
				} else {
					num_methods++;
					_methods = os_realloc(
						methods, num_methods *
						sizeof(*methods));
					if (_methods == NULL) {
						os_free(methods);
						os_free(buf);
						eap_ttls_deinit(sm, data);
						return NULL;
					}
					methods = _methods;
					methods[num_methods - 1].vendor =
						vendor;
					methods[num_methods - 1].method =
						method;
				}

				start = pos;
			}
			os_free(buf);
			data->phase2_eap_types = methods;
			data->num_phase2_eap_types = num_methods;
		}
		if (data->phase2_eap_types == NULL) {
			data->phase2_eap_types = eap_get_phase2_types(
				config, &data->num_phase2_eap_types);
		}
		if (data->phase2_eap_types == NULL) {
			wpa_printf(MSG_ERROR, "EAP-TTLS: No Phase2 EAP method "
				   "available");
			eap_ttls_deinit(sm, data);
			return NULL;
		}
		wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase2 EAP types",
			    (u8 *) data->phase2_eap_types,
			    data->num_phase2_eap_types *
			    sizeof(struct eap_method_type));
		data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
		data->phase2_eap_type.method = EAP_TYPE_NONE;
	}

	if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&
	    data->ttls_version > 0) {
		if (data->force_ttls_version > 0) {
			wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "
				   "TLS library does not support TLS/IA.",
				   data->force_ttls_version);
			eap_ttls_deinit(sm, data);
			return NULL;
		}
		data->ttls_version = 0;
	}

	return data;
}