static int nai_realm_cred_username(struct nai_realm_eap *eap) { if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) return 0; /* method not supported */ if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP) { /* Only tunneled methods with username/password supported */ return 0; } if (eap->method == EAP_TYPE_PEAP && eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) return 0; if (eap->method == EAP_TYPE_TTLS) { if (eap->inner_method == 0 && eap->inner_non_eap == 0) return 0; if (eap->inner_method && eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) return 0; if (eap->inner_non_eap && eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP && eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP && eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP && eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2) return 0; } if (eap->inner_method && eap->inner_method != EAP_TYPE_GTC && eap->inner_method != EAP_TYPE_MSCHAPV2) return 0; return 1; }
static char * wpa_config_write_eap(const struct parse_data *data, struct wpa_ssid *ssid) { int i, ret; char *buf, *pos, *end; const struct eap_method_type *eap_methods = ssid->eap.eap_methods; const char *name; if (eap_methods == NULL) return NULL; pos = buf = os_zalloc(100); if (buf == NULL) return NULL; end = buf + 100; for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF || eap_methods[i].method != EAP_TYPE_NONE; i++) { name = eap_get_name(eap_methods[i].vendor, eap_methods[i].method); if (name) { ret = os_snprintf(pos, end - pos, "%s%s", pos == buf ? "" : " ", name); if (ret < 0 || ret >= end - pos) break; pos += ret; } } end[-1] = '\0'; return buf; }
static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) { size_t i; if (cred->priority) fprintf(f, "\tpriority=%d\n", cred->priority); if (cred->pcsc) fprintf(f, "\tpcsc=%d\n", cred->pcsc); if (cred->realm) fprintf(f, "\trealm=\"%s\"\n", cred->realm); if (cred->username) fprintf(f, "\tusername=\"%s\"\n", cred->username); if (cred->password && cred->ext_password) fprintf(f, "\tpassword=ext:%s\n", cred->password); else if (cred->password) fprintf(f, "\tpassword=\"%s\"\n", cred->password); if (cred->ca_cert) fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert); if (cred->client_cert) fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert); if (cred->private_key) fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key); if (cred->private_key_passwd) fprintf(f, "\tprivate_key_passwd=\"%s\"\n", cred->private_key_passwd); if (cred->imsi) fprintf(f, "\timsi=\"%s\"\n", cred->imsi); if (cred->milenage) fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); for (i = 0; i < cred->num_domain; i++) fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); if (cred->roaming_consortium_len) { fprintf(f, "\troaming_consortium="); for (i = 0; i < cred->roaming_consortium_len; i++) fprintf(f, "%02x", cred->roaming_consortium[i]); fprintf(f, "\n"); } if (cred->eap_method) { const char *name; name = eap_get_name(cred->eap_method[0].vendor, cred->eap_method[0].method); fprintf(f, "\teap=%s\n", name); } if (cred->phase1) fprintf(f, "\tphase1=\"%s\"\n", cred->phase1); if (cred->phase2) fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); if (cred->excluded_ssid) { size_t j; for (i = 0; i < cred->num_excluded_ssid; i++) { struct excluded_ssid *e = &cred->excluded_ssid[i]; fprintf(f, "\texcluded_ssid="); for (j = 0; j < e->ssid_len; j++) fprintf(f, "%02x", e->ssid[j]); fprintf(f, "\n"); } } }
static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) { size_t i; if (cred->priority) fprintf(f, "\tpriority=%d\n", cred->priority); if (cred->pcsc) fprintf(f, "\tpcsc=%d\n", cred->pcsc); if (cred->realm) fprintf(f, "\trealm=\"%s\"\n", cred->realm); if (cred->username) fprintf(f, "\tusername=\"%s\"\n", cred->username); if (cred->password && cred->ext_password) fprintf(f, "\tpassword=ext:%s\n", cred->password); else if (cred->password) fprintf(f, "\tpassword=\"%s\"\n", cred->password); if (cred->ca_cert) fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert); if (cred->client_cert) fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert); if (cred->private_key) fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key); if (cred->private_key_passwd) fprintf(f, "\tprivate_key_passwd=\"%s\"\n", cred->private_key_passwd); if (cred->imsi) fprintf(f, "\timsi=\"%s\"\n", cred->imsi); if (cred->milenage) fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); for (i = 0; i < cred->num_domain; i++) fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); if (cred->domain_suffix_match) fprintf(f, "\tdomain_suffix_match=\"%s\"\n", cred->domain_suffix_match); if (cred->roaming_consortium_len) { fprintf(f, "\troaming_consortium="); for (i = 0; i < cred->roaming_consortium_len; i++) fprintf(f, "%02x", cred->roaming_consortium[i]); fprintf(f, "\n"); } if (cred->eap_method) { const char *name; name = eap_get_name(cred->eap_method[0].vendor, cred->eap_method[0].method); if (name) fprintf(f, "\teap=%s\n", name); } if (cred->phase1) fprintf(f, "\tphase1=\"%s\"\n", cred->phase1); if (cred->phase2) fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); if (cred->excluded_ssid) { size_t j; for (i = 0; i < cred->num_excluded_ssid; i++) { struct excluded_ssid *e = &cred->excluded_ssid[i]; fprintf(f, "\texcluded_ssid="); for (j = 0; j < e->ssid_len; j++) fprintf(f, "%02x", e->ssid[j]); fprintf(f, "\n"); } } if (cred->roaming_partner) { for (i = 0; i < cred->num_roaming_partner; i++) { struct roaming_partner *p = &cred->roaming_partner[i]; fprintf(f, "\troaming_partner=\"%s,%d,%u,%s\"\n", p->fqdn, p->exact_match, p->priority, p->country); } } if (cred->update_identifier) fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier); if (cred->provisioning_sp) fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp); if (cred->sp_priority) fprintf(f, "\tsp_priority=%d\n", cred->sp_priority); if (cred->min_dl_bandwidth_home) fprintf(f, "\tmin_dl_bandwidth_home=%u\n", cred->min_dl_bandwidth_home); if (cred->min_ul_bandwidth_home) fprintf(f, "\tmin_ul_bandwidth_home=%u\n", cred->min_ul_bandwidth_home); if (cred->min_dl_bandwidth_roaming) fprintf(f, "\tmin_dl_bandwidth_roaming=%u\n", cred->min_dl_bandwidth_roaming); if (cred->min_ul_bandwidth_roaming) fprintf(f, "\tmin_ul_bandwidth_roaming=%u\n", cred->min_ul_bandwidth_roaming); if (cred->max_bss_load) fprintf(f, "\tmax_bss_load=%u\n", cred->max_bss_load); if (cred->ocsp) fprintf(f, "\tocsp=%d\n", cred->ocsp); if (cred->num_req_conn_capab) { for (i = 0; i < cred->num_req_conn_capab; i++) { int *ports; fprintf(f, "\treq_conn_capab=%u", cred->req_conn_capab_proto[i]); ports = cred->req_conn_capab_port[i]; if (ports) { int j; for (j = 0; ports[j] != -1; j++) { fprintf(f, "%s%d", j > 0 ? "," : ":", ports[j]); } } fprintf(f, "\n"); } } if (cred->required_roaming_consortium_len) { fprintf(f, "\trequired_roaming_consortium="); for (i = 0; i < cred->required_roaming_consortium_len; i++) fprintf(f, "%02x", cred->required_roaming_consortium[i]); fprintf(f, "\n"); } if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) fprintf(f, "\tsim_num=%d\n", cred->sim_num); }
int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { struct wpa_ssid *ssid; struct nai_realm *realm; struct nai_realm_eap *eap = NULL; u16 count, i; char buf[100]; const u8 *ie; if (bss == NULL) return -1; ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); if (ie == NULL || ie[1] == 0) { wpa_printf(MSG_DEBUG, "Interworking: No SSID known for " MACSTR, MAC2STR(bss->bssid)); return -1; } realm = nai_realm_parse(bss->anqp_nai_realm, &count); if (realm == NULL) { wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " "Realm list from " MACSTR, MAC2STR(bss->bssid)); count = 0; } for (i = 0; i < count; i++) { if (!nai_realm_match(&realm[i], wpa_s->conf->home_realm)) continue; eap = nai_realm_find_eap(wpa_s, &realm[i]); if (eap) break; } if (!eap) { if (interworking_connect_3gpp(wpa_s, bss) == 0) { if (realm) nai_realm_free(realm, count); return 0; } wpa_printf(MSG_DEBUG, "Interworking: No matching credentials " "and EAP method found for " MACSTR, MAC2STR(bss->bssid)); nai_realm_free(realm, count); return -1; } wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR, MAC2STR(bss->bssid)); ssid = wpa_config_add_network(wpa_s->conf); if (ssid == NULL) { nai_realm_free(realm, count); return -1; } wpas_notify_network_added(wpa_s, ssid); wpa_config_set_network_defaults(ssid); ssid->temporary = 1; ssid->ssid = os_zalloc(ie[1] + 1); if (ssid->ssid == NULL) goto fail; os_memcpy(ssid->ssid, ie + 2, ie[1]); ssid->ssid_len = ie[1]; if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF, eap->method), 0) < 0) goto fail; if (wpa_s->conf->home_username && wpa_s->conf->home_username[0] && wpa_config_set_quoted(ssid, "identity", wpa_s->conf->home_username) < 0) goto fail; if (wpa_s->conf->home_password && wpa_s->conf->home_password[0] && wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_password) < 0) goto fail; switch (eap->method) { case EAP_TYPE_TTLS: if (eap->inner_method) { os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", eap_get_name(EAP_VENDOR_IETF, eap->inner_method)); if (wpa_config_set(ssid, "phase2", buf, 0) < 0) goto fail; break; } switch (eap->inner_non_eap) { case NAI_REALM_INNER_NON_EAP_PAP: if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) < 0) goto fail; break; case NAI_REALM_INNER_NON_EAP_CHAP: if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0) < 0) goto fail; break; case NAI_REALM_INNER_NON_EAP_MSCHAP: if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"", 0) < 0) goto fail; break; case NAI_REALM_INNER_NON_EAP_MSCHAPV2: if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 0) < 0) goto fail; break; } break; case EAP_TYPE_PEAP: os_snprintf(buf, sizeof(buf), "\"auth=%s\"", eap_get_name(EAP_VENDOR_IETF, eap->inner_method)); if (wpa_config_set(ssid, "phase2", buf, 0) < 0) goto fail; break; } if (wpa_s->conf->home_ca_cert && wpa_s->conf->home_ca_cert[0] && wpa_config_set_quoted(ssid, "ca_cert", wpa_s->conf->home_ca_cert) < 0) goto fail; nai_realm_free(realm, count); wpa_supplicant_select_network(wpa_s, ssid); return 0; fail: wpas_notify_network_removed(wpa_s, ssid); wpa_config_remove_network(wpa_s->conf, ssid->id); nai_realm_free(realm, count); return -1; }