diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20 index a167186bc..8d2bdbc85 100644 --- a/wpa_supplicant/README-HS20 +++ b/wpa_supplicant/README-HS20 @@ -202,6 +202,15 @@ Credentials can be pre-configured for automatic network selection: # Roaming Consortium OI that is required to be advertised by the AP for # the credential to be considered matching. # +# roaming_consortiums: Roaming Consortium OI(s) memberships +# This string field contains one or more comma delimited OIs (hexdump) +# identifying the roaming consortiums of which the provider is a member. +# The list is sorted from the most preferred one to the least preferred +# one. A match between the Roaming Consortium OIs advertised by an AP and +# the OIs in this list indicates that successful authentication is +# possible. +# (Hotspot 2.0 PerProviderSubscription//HomeSP/RoamingConsortiumOI) +# # eap: Pre-configured EAP method # This optional field can be used to specify which EAP method will be # used with this credential. If not set, the EAP method is selected @@ -300,6 +309,7 @@ Credentials can be pre-configured for automatic network selection: # ca_cert="/etc/wpa_supplicant/ca.pem" # domain="example.com" # roaming_consortium=223344 +# roaming_consortiums="112233,4455667788,aabbcc" # eap=TTLS # phase2="auth=MSCHAPV2" #} diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index a0b8cd007..5247e9086 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -3104,11 +3104,62 @@ static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred, } +static int wpa_config_set_cred_roaming_consortiums(struct wpa_cred *cred, + const char *value) +{ + u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN]; + size_t roaming_consortiums_len[MAX_ROAMING_CONS]; + unsigned int num_roaming_consortiums = 0; + const char *pos, *end; + size_t len; + + os_memset(roaming_consortiums, 0, sizeof(roaming_consortiums)); + os_memset(roaming_consortiums_len, 0, sizeof(roaming_consortiums_len)); + + for (pos = value;;) { + end = os_strchr(pos, ','); + len = end ? (size_t) (end - pos) : os_strlen(pos); + if (!end && len == 0) + break; + if (len == 0 || (len & 1) != 0 || + len / 2 > MAX_ROAMING_CONS_OI_LEN || + hexstr2bin(pos, + roaming_consortiums[num_roaming_consortiums], + len / 2) < 0) { + wpa_printf(MSG_INFO, + "Invalid roaming_consortiums entry: %s", + pos); + return -1; + } + roaming_consortiums_len[num_roaming_consortiums] = len / 2; + num_roaming_consortiums++; + if (num_roaming_consortiums > MAX_ROAMING_CONS) { + wpa_printf(MSG_INFO, + "Too many roaming_consortiums OIs"); + return -1; + } + + if (!end) + break; + pos = end + 1; + } + + os_memcpy(cred->roaming_consortiums, roaming_consortiums, + sizeof(roaming_consortiums)); + os_memcpy(cred->roaming_consortiums_len, roaming_consortiums_len, + sizeof(roaming_consortiums_len)); + cred->num_roaming_consortiums = num_roaming_consortiums; + + return 0; +} + + int wpa_config_set_cred(struct wpa_cred *cred, const char *var, const char *value, int line) { char *val; size_t len; + int res; if (os_strcmp(var, "temporary") == 0) { cred->temporary = atoi(value); @@ -3331,6 +3382,16 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, return 0; } + if (os_strcmp(var, "roaming_consortiums") == 0) { + res = wpa_config_set_cred_roaming_consortiums(cred, val); + if (res < 0) + wpa_printf(MSG_ERROR, + "Line %d: invalid roaming_consortiums", + line); + os_free(val); + return res; + } + if (os_strcmp(var, "excluded_ssid") == 0) { struct excluded_ssid *e; @@ -3642,6 +3703,31 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) return buf; } + if (os_strcmp(var, "roaming_consortiums") == 0) { + size_t buflen; + char *buf, *pos; + size_t i; + + if (!cred->num_roaming_consortiums) + return NULL; + buflen = cred->num_roaming_consortiums * + MAX_ROAMING_CONS_OI_LEN * 2 + 1; + buf = os_malloc(buflen); + if (!buf) + return NULL; + pos = buf; + for (i = 0; i < cred->num_roaming_consortiums; i++) { + if (i > 0) + *pos++ = ','; + pos += wpa_snprintf_hex( + pos, buf + buflen - pos, + cred->roaming_consortiums[i], + cred->roaming_consortiums_len[i]); + } + *pos = '\0'; + return buf; + } + if (os_strcmp(var, "excluded_ssid") == 0) { unsigned int i; char *buf, *end, *pos; diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 4dae36963..ad4dd886f 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -51,6 +51,9 @@ #include "common/ieee802_11_common.h" +#define MAX_ROAMING_CONS 36 +#define MAX_ROAMING_CONS_OI_LEN 15 + struct wpa_cred { /** * next - Next credential in the list @@ -239,6 +242,28 @@ struct wpa_cred { */ size_t required_roaming_consortium_len; + /** + * roaming_consortiums - Roaming Consortium OI(s) memberships + * + * This field contains one or more OIs identifying the roaming + * consortiums of which the provider is a member. The list is sorted + * from the most preferred one to the least preferred one. A match + * between the Roaming Consortium OIs advertised by an AP and the OIs + * in this list indicates that successful authentication is possible. + * (Hotspot 2.0 PerProviderSubscription//HomeSP/RoamingConsortiumOI) + */ + u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN]; + + /** + * roaming_consortiums_len - Length on roaming_consortiums[i] + */ + size_t roaming_consortiums_len[MAX_ROAMING_CONS]; + + /** + * num_roaming_consortiums - Number of entries in roaming_consortiums + */ + unsigned int num_roaming_consortiums; + /** * eap_method - EAP method to use * diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 5a7186961..e94a26f32 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1039,6 +1039,20 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) fprintf(f, "\n"); } + if (cred->num_roaming_consortiums) { + size_t j; + + fprintf(f, "\troaming_consortiums=\""); + for (i = 0; i < cred->num_roaming_consortiums; i++) { + if (i > 0) + fprintf(f, ","); + for (j = 0; j < cred->roaming_consortiums_len[i]; j++) + fprintf(f, "%02x", + cred->roaming_consortiums[i][j]); + } + fprintf(f, "\"\n"); + } + if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) fprintf(f, "\tsim_num=%d\n", cred->sim_num); } diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 38e6403f4..159537e7a 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -602,6 +602,15 @@ fast_reauth=1 # Roaming Consortium OI that is required to be advertised by the AP for # the credential to be considered matching. # +# roaming_consortiums: Roaming Consortium OI(s) memberships +# This string field contains one or more comma delimited OIs (hexdump) +# identifying the roaming consortiums of which the provider is a member. +# The list is sorted from the most preferred one to the least preferred +# one. A match between the Roaming Consortium OIs advertised by an AP and +# the OIs in this list indicates that successful authentication is +# possible. +# (Hotspot 2.0 PerProviderSubscription//HomeSP/RoamingConsortiumOI) +# # eap: Pre-configured EAP method # This optional field can be used to specify which EAP method will be # used with this credential. If not set, the EAP method is selected