/** * 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; }