From 463c8ffbd5bf15dc5158d68fc32347cfb5746a83 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 2 Aug 2013 18:42:54 +0300 Subject: [PATCH] Interworking: Add support for multiple home FQDNs Credentials can now be configured with more than one FQDN ('domain' field in the cred block) to perform Domain Name List matching against multiple home domains. Signed-hostap: Jouni Malinen --- wpa_supplicant/README-HS20 | 6 ++++-- wpa_supplicant/config.c | 16 ++++++++++++++-- wpa_supplicant/config.h | 13 ++++++++++--- wpa_supplicant/config_file.c | 9 +++++---- wpa_supplicant/ctrl_iface.c | 30 +++++++++++++++++++++--------- wpa_supplicant/interworking.c | 11 +++++++---- wpa_supplicant/wpa_supplicant.conf | 6 ++++-- 7 files changed, 65 insertions(+), 26 deletions(-) diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20 index 5669c55c3..7a570bdd7 100644 --- a/wpa_supplicant/README-HS20 +++ b/wpa_supplicant/README-HS20 @@ -166,9 +166,11 @@ Credentials can be pre-configured for automatic network selection: # milenage: Milenage parameters for SIM/USIM simulator in :: # format # -# domain: Home service provider FQDN +# domain: Home service provider FQDN(s) # This is used to compare against the Domain Name List to figure out -# whether the AP is operated by the Home SP. +# whether the AP is operated by the Home SP. Multiple domain entries can +# be used to configure alternative FQDNs that will be considered home +# networks. # # roaming_consortium: Roaming Consortium OI # If roaming_consortium_len is non-zero, this field contains the diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index c4fc7b670..2b47e8e69 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1855,6 +1855,8 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) void wpa_config_free_cred(struct wpa_cred *cred) { + size_t i; + os_free(cred->realm); os_free(cred->username); os_free(cred->password); @@ -1864,6 +1866,8 @@ void wpa_config_free_cred(struct wpa_cred *cred) os_free(cred->private_key_passwd); os_free(cred->imsi); os_free(cred->milenage); + for (i = 0; i < cred->num_domain; i++) + os_free(cred->domain[i]); os_free(cred->domain); os_free(cred->eap_method); os_free(cred->phase1); @@ -2437,8 +2441,16 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, } if (os_strcmp(var, "domain") == 0) { - os_free(cred->domain); - cred->domain = val; + char **new_domain; + new_domain = os_realloc_array(cred->domain, + cred->num_domain + 1, + sizeof(char *)); + if (new_domain == NULL) { + os_free(val); + return -1; + } + new_domain[cred->num_domain++] = val; + cred->domain = new_domain; return 0; } diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 1748cf3b8..27301b803 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -150,12 +150,19 @@ struct wpa_cred { char *milenage; /** - * domain - Home service provider FQDN + * domain - Home service provider FQDN(s) * * This is used to compare against the Domain Name List to figure out - * whether the AP is operated by the Home SP. + * whether the AP is operated by the Home SP. Multiple domain entries + * can be used to configure alternative FQDNs that will be considered + * home networks. */ - char *domain; + char **domain; + + /** + * num_domain - Number of FQDNs in the domain array + */ + size_t num_domain; /** * roaming_consortium - Roaming Consortium OI diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 6512a8270..2c14a2c91 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -728,6 +728,8 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 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) @@ -753,10 +755,9 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) fprintf(f, "\timsi=\"%s\"\n", cred->imsi); if (cred->milenage) fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); - if (cred->domain) - fprintf(f, "\tdomain=\"%s\"\n", cred->domain); + for (i = 0; i < cred->num_domain; i++) + fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); if (cred->roaming_consortium_len) { - size_t i; fprintf(f, "\troaming_consortium="); for (i = 0; i < cred->roaming_consortium_len; i++) fprintf(f, "%02x", cred->roaming_consortium[i]); @@ -773,7 +774,7 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) if (cred->phase2) fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); if (cred->excluded_ssid) { - size_t i, j; + size_t j; for (i = 0; i < cred->num_excluded_ssid; i++) { struct excluded_ssid *e = &cred->excluded_ssid[i]; fprintf(f, "\texcluded_ssid="); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 0f893f7e6..7b3af28d0 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1565,16 +1565,21 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, char *type; for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + size_t i; + if (wpa_s->current_ssid->parent_cred != cred) continue; if (!cred->domain) continue; - ret = os_snprintf(pos, end - pos, "home_sp=%s\n", - cred->domain); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; + for (i = 0; i < cred->num_domain; i++) { + ret = os_snprintf(pos, end - pos, + "home_sp=%s\n", + cred->domain[i]); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } if (wpa_s->current_bss == NULL || wpa_s->current_bss->anqp == NULL) @@ -2448,7 +2453,7 @@ static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", cred->id, cred->realm ? cred->realm : "", cred->username ? cred->username : "", - cred->domain ? cred->domain : "", + cred->domain ? cred->domain[0] : "", cred->imsi ? cred->imsi : ""); if (ret < 0 || ret >= end - pos) return pos - buf; @@ -2533,9 +2538,16 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, while (cred) { prev = cred; cred = cred->next; - if (prev->domain && - os_strcmp(prev->domain, cmd + 8) == 0) - wpas_ctrl_remove_cred(wpa_s, prev); + if (prev->domain) { + size_t i; + for (i = 0; i < prev->num_domain; i++) { + if (os_strcmp(prev->domain[i], cmd + 8) + != 0) + continue; + wpas_ctrl_remove_cred(wpa_s, prev); + break; + } + } } return 0; } diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 36f75a166..01acae1c6 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -1514,6 +1514,7 @@ int interworking_home_sp_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred, struct wpabuf *domain_names) { + size_t i; #ifdef INTERWORKING_3GPP char nai[100], *realm; @@ -1544,10 +1545,12 @@ int interworking_home_sp_cred(struct wpa_supplicant *wpa_s, if (domain_names == NULL || cred->domain == NULL) return 0; - wpa_printf(MSG_DEBUG, "Interworking: Search for match with " - "home SP FQDN %s", cred->domain); - if (domain_name_list_contains(domain_names, cred->domain)) - return 1; + for (i = 0; i < cred->num_domain; i++) { + wpa_printf(MSG_DEBUG, "Interworking: Search for match with " + "home SP FQDN %s", cred->domain[i]); + if (domain_name_list_contains(domain_names, cred->domain[i])) + return 1; + } return 0; } diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index d73d3715a..6414f447d 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -399,9 +399,11 @@ fast_reauth=1 # milenage: Milenage parameters for SIM/USIM simulator in :: # format # -# domain: Home service provider FQDN +# domain: Home service provider FQDN(s) # This is used to compare against the Domain Name List to figure out -# whether the AP is operated by the Home SP. +# whether the AP is operated by the Home SP. Multiple domain entries can +# be used to configure alternative FQDNs that will be considered home +# networks. # # roaming_consortium: Roaming Consortium OI # If roaming_consortium_len is non-zero, this field contains the