]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
HS20: Support credentials with multiple home OIs
authorDamien Dejean <damiendejean@chromium.org>
Thu, 15 Sep 2022 08:02:13 +0000 (08:02 +0000)
committerJouni Malinen <j@w1.fi>
Sat, 26 Nov 2022 15:58:54 +0000 (17:58 +0200)
Until now Hotspot 2.0 credentials were only supporting one home OI (with
roaming_consortium option) and one required home OI (with
required_roaming_consortium option). To improve the compliance with
Passpoint specification, add the support for multiple home and required
OIs.

The lists of OIs are provided using two new configuration options
home_ois and required_home_ois that expect a list of OIs formatted as
the roaming_consortiums list. It allows to keep the old options to avoid
breaking currently running configurations and better fits the vocabulary
used in the spec.

The OI match algorithm is updated to implement the behavior described in
Passpoint specification v3.2 section 9.1.2 (Home OIs nodes description
PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>).

Signed-off-by: Damien Dejean <damiendejean@chromium.org>
wpa_supplicant/README-HS20
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/interworking.c
wpa_supplicant/wpa_supplicant.conf

index 0cc5f3949147a7a4f44742f2700944ffda743bc0..7d30e23c6d664bd407afd15b170070b13746c1f8 100644 (file)
@@ -199,7 +199,26 @@ Credentials can be pre-configured for automatic network selection:
 #      be used to configure alternative FQDNs that will be considered home
 #      networks.
 #
+# home_ois: Home OI(s)
+#      This string field contains one or more comma delimited OIs (hexdump)
+#      identifying the access the access points that support authentication
+#      with this credential. There are an alternative to the use of the realm
+#      parameter. When using Home OIs to match the network, the EAP parameters
+#      need to be pre-configured with the credentials since the NAI Realm
+#      information may not be available or fetched.
+#      A successful authentication with the access point is possible as soon
+#      as at least one Home OI from the list matches an OI in the Roaming
+#      Consortium advertised by the access point.
+#      (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOI)
+#
+# required_home_ois: Required Home OI(s)
+#      This string field contains the set of Home OI(s) (hexdump) that are
+#      required to be advertised by the AP for the credential to be considered
+#      matching.
+#      (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOIRequired)
+#
 # roaming_consortium: Roaming Consortium OI
+#      Deprecated: use home_ois instead.
 #      If roaming_consortium_len is non-zero, this field contains the
 #      Roaming Consortium OI that can be used to determine which access
 #      points support authentication with this credential. This is an
@@ -209,6 +228,7 @@ Credentials can be pre-configured for automatic network selection:
 #      may not be available or fetched.
 #
 # required_roaming_consortium: Required Roaming Consortium OI
+#      Deprecated: use required_home_ois instead.
 #      If required_roaming_consortium_len is non-zero, this field contains the
 #      Roaming Consortium OI that is required to be advertised by the AP for
 #      the credential to be considered matching.
@@ -325,7 +345,7 @@ Credentials can be pre-configured for automatic network selection:
 #      password="password"
 #      ca_cert="/etc/wpa_supplicant/ca.pem"
 #      domain="example.com"
-#      roaming_consortium=223344
+#      home_ois="223344"
 #      roaming_consortiums="112233,4455667788,aabbcc"
 #      eap=TTLS
 #      phase2="auth=MSCHAPV2"
index 82e3390abba4c4e3629c637f47fbd6ab4c455505..2754ad8331ede5f0f4a9d73757638a8cb3ca9afe 100644 (file)
@@ -3532,53 +3532,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;
+static int
+wpa_config_set_cred_ois(u8 cred_ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN],
+                       size_t cred_ois_len[MAX_ROAMING_CONS],
+                       unsigned int *cred_num_ois,
+                       const char *value)
+{
+       u8 ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+       size_t ois_len[MAX_ROAMING_CONS];
+       unsigned int num_ois = 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));
+       len = os_strlen(value);
+       if (len / 2 < 3) {
+               wpa_printf(MSG_ERROR,
+                          "Invalid organisation identifier (OI) list: %s",
+                          value);
+               return -1;
+       }
+
+       os_memset(ois, 0, sizeof(ois));
+       os_memset(ois_len, 0, sizeof(ois_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 ||
+               if (len / 2 < 3 || (len & 1) != 0 ||
                    len / 2 > MAX_ROAMING_CONS_OI_LEN ||
                    hexstr2bin(pos,
-                              roaming_consortiums[num_roaming_consortiums],
+                              ois[num_ois],
                               len / 2) < 0) {
                        wpa_printf(MSG_INFO,
-                                  "Invalid roaming_consortiums entry: %s",
+                                  "Invalid organisation identifier (OI) entry: %s",
                                   pos);
                        return -1;
                }
-               roaming_consortiums_len[num_roaming_consortiums] = len / 2;
-               num_roaming_consortiums++;
+               ois_len[num_ois] = len / 2;
+               num_ois++;
 
                if (!end)
                        break;
 
-               if (num_roaming_consortiums >= MAX_ROAMING_CONS) {
+               if (num_ois >= MAX_ROAMING_CONS) {
                        wpa_printf(MSG_INFO,
-                                  "Too many roaming_consortiums OIs");
+                                  "Too many OIs");
                        return -1;
                }
 
                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;
+       os_memcpy(cred_ois, ois, sizeof(ois));
+       os_memcpy(cred_ois_len, ois_len, sizeof(ois_len));
+       *cred_num_ois = num_ois;
 
        return 0;
 }
@@ -3813,36 +3822,70 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
        }
 
        if (os_strcmp(var, "roaming_consortium") == 0) {
-               if (len < 3 || len > sizeof(cred->roaming_consortium)) {
+               if (len < 3 || len > sizeof(cred->home_ois[0])) {
                        wpa_printf(MSG_ERROR, "Line %d: invalid "
                                   "roaming_consortium length %d (3..15 "
                                   "expected)", line, (int) len);
                        os_free(val);
                        return -1;
                }
-               os_memcpy(cred->roaming_consortium, val, len);
-               cred->roaming_consortium_len = len;
+               wpa_printf(MSG_WARNING,
+                          "Line %d: option roaming_consortium is deprecated and will be removed in the future",
+                          line);
+               os_memcpy(cred->home_ois[0], val, len);
+               cred->home_ois_len[0] = len;
+               cred->num_home_ois = 1;
                os_free(val);
                return 0;
        }
 
        if (os_strcmp(var, "required_roaming_consortium") == 0) {
-               if (len < 3 || len > sizeof(cred->required_roaming_consortium))
-               {
+               if (len < 3 || len > sizeof(cred->required_home_ois[0])) {
                        wpa_printf(MSG_ERROR, "Line %d: invalid "
                                   "required_roaming_consortium length %d "
                                   "(3..15 expected)", line, (int) len);
                        os_free(val);
                        return -1;
                }
-               os_memcpy(cred->required_roaming_consortium, val, len);
-               cred->required_roaming_consortium_len = len;
+               wpa_printf(MSG_WARNING,
+                          "Line %d: option required_roaming_consortium is deprecated and will be removed in the future",
+                          line);
+               os_memcpy(cred->required_home_ois[0], val, len);
+               cred->required_home_ois_len[0] = len;
+               cred->num_required_home_ois = 1;
                os_free(val);
                return 0;
        }
 
+       if (os_strcmp(var, "home_ois") == 0) {
+               res = wpa_config_set_cred_ois(cred->home_ois,
+                                             cred->home_ois_len,
+                                             &cred->num_home_ois,
+                                             val);
+               if (res < 0)
+                       wpa_printf(MSG_ERROR, "Line %d: invalid home_ois",
+                                  line);
+               os_free(val);
+               return res;
+       }
+
+       if (os_strcmp(var, "required_home_ois") == 0) {
+               res = wpa_config_set_cred_ois(cred->required_home_ois,
+                                             cred->required_home_ois_len,
+                                             &cred->num_required_home_ois,
+                                             val);
+               if (res < 0)
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid required_home_ois", line);
+               os_free(val);
+               return res;
+       }
+
        if (os_strcmp(var, "roaming_consortiums") == 0) {
-               res = wpa_config_set_cred_roaming_consortiums(cred, val);
+               res = wpa_config_set_cred_ois(cred->roaming_consortiums,
+                                             cred->roaming_consortiums_len,
+                                             &cred->num_roaming_consortiums,
+                                             val);
                if (res < 0)
                        wpa_printf(MSG_ERROR,
                                   "Line %d: invalid roaming_consortiums",
@@ -4154,14 +4197,14 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
                size_t buflen;
                char *buf;
 
-               if (!cred->roaming_consortium_len)
+               if (!cred->num_home_ois || !cred->home_ois_len[0])
                        return NULL;
-               buflen = cred->roaming_consortium_len * 2 + 1;
+               buflen = cred->home_ois_len[0] * 2 + 1;
                buf = os_malloc(buflen);
                if (buf == NULL)
                        return NULL;
-               wpa_snprintf_hex(buf, buflen, cred->roaming_consortium,
-                                cred->roaming_consortium_len);
+               wpa_snprintf_hex(buf, buflen, cred->home_ois[0],
+                                cred->home_ois_len[0]);
                return buf;
        }
 
@@ -4169,14 +4212,64 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
                size_t buflen;
                char *buf;
 
-               if (!cred->required_roaming_consortium_len)
+               if (!cred->num_required_home_ois ||
+                   !cred->required_home_ois_len[0])
                        return NULL;
-               buflen = cred->required_roaming_consortium_len * 2 + 1;
+               buflen = cred->required_home_ois_len[0] * 2 + 1;
                buf = os_malloc(buflen);
                if (buf == NULL)
                        return NULL;
-               wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium,
-                                cred->required_roaming_consortium_len);
+               wpa_snprintf_hex(buf, buflen, cred->required_home_ois[0],
+                                cred->required_home_ois_len[0]);
+               return buf;
+       }
+
+       if (os_strcmp(var, "home_ois") == 0) {
+               size_t buflen;
+               char *buf, *pos;
+               size_t i;
+
+               if (!cred->num_home_ois)
+                       return NULL;
+               buflen = cred->num_home_ois * MAX_ROAMING_CONS_OI_LEN * 2 + 1;
+               buf = os_malloc(buflen);
+               if (!buf)
+                       return NULL;
+               pos = buf;
+               for (i = 0; i < cred->num_home_ois; i++) {
+                       if (i > 0)
+                               *pos++ = ',';
+                       pos += wpa_snprintf_hex(
+                               pos, buf + buflen - pos,
+                               cred->home_ois[i],
+                               cred->home_ois_len[i]);
+               }
+               *pos = '\0';
+               return buf;
+       }
+
+       if (os_strcmp(var, "required_home_ois") == 0) {
+               size_t buflen;
+               char *buf, *pos;
+               size_t i;
+
+               if (!cred->num_required_home_ois)
+                       return NULL;
+               buflen = cred->num_required_home_ois *
+                       MAX_ROAMING_CONS_OI_LEN * 2 + 1;
+               buf = os_malloc(buflen);
+               if (!buf)
+                       return NULL;
+               pos = buf;
+               for (i = 0; i < cred->num_required_home_ois; i++) {
+                       if (i > 0)
+                               *pos++ = ',';
+                       pos += wpa_snprintf_hex(
+                               pos, buf + buflen - pos,
+                               cred->required_home_ois[i],
+                               cred->required_home_ois_len[i]);
+               }
+               *pos = '\0';
                return buf;
        }
 
index e2394bfa71095c2d1f9e92f09fac230fcc485685..33a609b9f76fdbb50d19c594001ca64c840607fb 100644 (file)
@@ -259,36 +259,50 @@ struct wpa_cred {
        size_t num_domain;
 
        /**
-        * roaming_consortium - Roaming Consortium OI
+        * home_ois - Home OIs
         *
-        * If roaming_consortium_len is non-zero, this field contains the
-        * Roaming Consortium OI that can be used to determine which access
-        * points support authentication with this credential. This is an
-        * alternative to the use of the realm parameter. When using Roaming
-        * Consortium to match the network, the EAP parameters need to be
-        * pre-configured with the credential since the NAI Realm information
-        * may not be available or fetched.
+        * If num_home_ois is non-zero, this field contains the set of Home OIs
+        * that can be use to determine which access points support
+        * authentication with this credential. These are an alternative to the
+        * use of the realm parameter. When using Home OIs to match the network,
+        * the EAP parameters need to be pre-configured with the credentials
+        * since the NAI Realm information may not be available or fetched.
+        * A successful authentication with the access point is possible as soon
+        * as at least one Home OI from the list matches an OI in the Roaming
+        * Consortium list advertised by the access point.
+        * (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOI)
         */
-       u8 roaming_consortium[15];
+       u8 home_ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
 
        /**
-        * roaming_consortium_len - Length of roaming_consortium
+        * home_ois_len - Length of home_ois[i]
         */
-       size_t roaming_consortium_len;
+       size_t home_ois_len[MAX_ROAMING_CONS];
 
        /**
-        * required_roaming_consortium - Required Roaming Consortium OI
+        * num_home_ois - Number of entries in home_ois
+        */
+       unsigned int num_home_ois;
+
+       /**
+        * required_home_ois - Required Home OI(s)
         *
-        * If required_roaming_consortium_len is non-zero, this field contains
-        * the Roaming Consortium OI that is required to be advertised by the AP
-        * for the credential to be considered matching.
+        * If required_home_ois_len is non-zero, this field contains the set of
+        * Home OI(s) that are required to be advertised by the AP for the
+        * credential to be considered matching.
+        * (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOIRequired)
+        */
+       u8 required_home_ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+
+       /**
+        * required_home_ois_len - Length of required_home_ois
         */
-       u8 required_roaming_consortium[15];
+       size_t required_home_ois_len[MAX_ROAMING_CONS];
 
        /**
-        * required_roaming_consortium_len - Length of required_roaming_consortium
+        * num_required_home_ois - Number of entries in required_home_ois
         */
-       size_t required_roaming_consortium_len;
+       unsigned int num_required_home_ois;
 
        /**
         * roaming_consortiums - Roaming Consortium OI(s) memberships
index 4e001dd0012a6550f5a6a4a1c4e84f1510759e7d..dbc04e13d59ed82553279ea79390e8f6195d5cf8 100644 (file)
@@ -922,12 +922,6 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
        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,
@@ -1003,12 +997,32 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
                }
        }
 
-       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->num_home_ois) {
+               size_t j;
+
+               fprintf(f, "\thome_ois=\"");
+               for (i = 0; i < cred->num_home_ois; i++) {
+                       if (i > 0)
+                               fprintf(f, ",");
+                       for (j = 0; j < cred->home_ois_len[i]; j++)
+                               fprintf(f, "%02x",
+                                       cred->home_ois[i][j]);
+               }
+               fprintf(f, "\"\n");
+       }
+
+       if (cred->num_required_home_ois) {
+               size_t j;
+
+               fprintf(f, "\trequired_home_ois=\"");
+               for (i = 0; i < cred->num_required_home_ois; i++) {
+                       if (i > 0)
+                               fprintf(f, ",");
+                       for (j = 0; j < cred->required_home_ois_len[i]; j++)
+                               fprintf(f, "%02x",
+                                       cred->required_home_ois[i][j]);
+               }
+               fprintf(f, "\"\n");
        }
 
        if (cred->num_roaming_consortiums) {
index 6ae21737d4da9d30ad52eb2dd5bd2236cb53b1fa..e33f3617ac08ab22a3578654d3fa5e3d955dd02c 100644 (file)
@@ -144,9 +144,9 @@ static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s)
        struct wpa_cred *cred;
 
        for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
-               if (cred->roaming_consortium_len)
+               if (cred->num_home_ois)
                        return 1;
-               if (cred->required_roaming_consortium_len)
+               if (cred->num_required_home_ois)
                        return 1;
                if (cred->num_roaming_consortiums)
                        return 1;
@@ -1097,8 +1097,7 @@ fail:
 }
 
 
-static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id,
-                                           size_t rc_len)
+static int oi_element_match(const u8 *ie, const u8 *oi, size_t oi_len)
 {
        const u8 *pos, *end;
        u8 lens;
@@ -1123,24 +1122,24 @@ static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id,
        if ((lens & 0x0f) + (lens >> 4) > end - pos)
                return 0;
 
-       if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
+       if ((lens & 0x0f) == oi_len && os_memcmp(pos, oi, oi_len) == 0)
                return 1;
        pos += lens & 0x0f;
 
-       if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
+       if ((lens >> 4) == oi_len && os_memcmp(pos, oi, oi_len) == 0)
                return 1;
        pos += lens >> 4;
 
-       if (pos < end && (size_t) (end - pos) == rc_len &&
-           os_memcmp(pos, rc_id, rc_len) == 0)
+       if (pos < end && (size_t) (end - pos) == oi_len &&
+           os_memcmp(pos, oi, oi_len) == 0)
                return 1;
 
        return 0;
 }
 
 
-static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
-                                        const u8 *rc_id, size_t rc_len)
+static int oi_anqp_match(const struct wpabuf *anqp, const u8 *oi,
+                        size_t oi_len)
 {
        const u8 *pos, *end;
        u8 len;
@@ -1156,7 +1155,7 @@ static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
                len = *pos++;
                if (len > end - pos)
                        break;
-               if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
+               if (len == oi_len && os_memcmp(pos, oi, oi_len) == 0)
                        return 1;
                pos += len;
        }
@@ -1165,11 +1164,26 @@ static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
 }
 
 
-static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
-                                   const u8 *rc_id, size_t rc_len)
+static int oi_match(const u8 *ie, const struct wpabuf *anqp,
+                   const u8 *oi, size_t oi_len)
 {
-       return roaming_consortium_element_match(ie, rc_id, rc_len) ||
-               roaming_consortium_anqp_match(anqp, rc_id, rc_len);
+       return oi_element_match(ie, oi, oi_len) ||
+               oi_anqp_match(anqp, oi, oi_len);
+}
+
+
+static int cred_home_ois_match(const u8 *ie, const struct wpabuf *anqp,
+                              const struct wpa_cred *cred) {
+       unsigned int i;
+
+       /* There's a match if at least one of the home OI matches. */
+       for (i = 0; i < cred->num_home_ois; i++) {
+               if (oi_match(ie, anqp, cred->home_ois[i],
+                            cred->home_ois_len[i]))
+                       return 1;
+       }
+
+       return 0;
 }
 
 
@@ -1180,9 +1194,8 @@ static int cred_roaming_consortiums_match(const u8 *ie,
        unsigned int i;
 
        for (i = 0; i < cred->num_roaming_consortiums; i++) {
-               if (roaming_consortium_match(ie, anqp,
-                                            cred->roaming_consortiums[i],
-                                            cred->roaming_consortiums_len[i]))
+               if (oi_match(ie, anqp, cred->roaming_consortiums[i],
+                            cred->roaming_consortiums_len[i]))
                        return 1;
        }
 
@@ -1193,8 +1206,9 @@ static int cred_roaming_consortiums_match(const u8 *ie,
 static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
 {
        const u8 *ie;
+       unsigned int i;
 
-       if (cred->required_roaming_consortium_len == 0)
+       if (cred->num_required_home_ois == 0)
                return 0;
 
        ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
@@ -1203,11 +1217,16 @@ static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
            (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
                return 1;
 
-       return !roaming_consortium_match(ie,
-                                        bss->anqp ?
-                                        bss->anqp->roaming_consortium : NULL,
-                                        cred->required_roaming_consortium,
-                                        cred->required_roaming_consortium_len);
+       /* According to Passpoint specification, there must be a match for
+        * each required home OI provided. */
+       for (i = 0; i < cred->num_required_home_ois; i++) {
+               if (!oi_match(ie, bss->anqp ?
+                             bss->anqp->roaming_consortium : NULL,
+                             cred->required_home_ois[i],
+                             cred->required_home_ois_len[i]))
+                       return 1;
+       }
+       return 0;
 }
 
 
@@ -1407,26 +1426,24 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
                return NULL;
 
        for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
-               if (cred->roaming_consortium_len == 0 &&
+               if (cred->num_home_ois == 0 &&
+                   cred->num_required_home_ois == 0 &&
                    cred->num_roaming_consortiums == 0)
                        continue;
 
                if (!cred->eap_method)
                        continue;
 
-               if ((cred->roaming_consortium_len == 0 ||
-                    !roaming_consortium_match(ie, anqp,
-                                              cred->roaming_consortium,
-                                              cred->roaming_consortium_len)) &&
-                   !cred_roaming_consortiums_match(ie, anqp, cred) &&
-                   (cred->required_roaming_consortium_len == 0 ||
-                    !roaming_consortium_match(
-                            ie, anqp, cred->required_roaming_consortium,
-                            cred->required_roaming_consortium_len)))
+               /* If there's required home OIs, there must be a match for each
+                * required OI (see Passpoint v3.2 - 9.1.2 - RequiredHomeOI). */
+               if (cred->num_required_home_ois > 0 &&
+                   cred_no_required_oi_match(cred, bss))
                        continue;
 
-               if (cred_no_required_oi_match(cred, bss))
+               if (!cred_home_ois_match(ie, anqp, cred) &&
+                   !cred_roaming_consortiums_match(ie, anqp, cred))
                        continue;
+
                if (!ignore_bw && cred_below_min_backhaul(wpa_s, cred, bss))
                        continue;
                if (!ignore_bw && cred_over_max_bss_load(wpa_s, cred, bss))
@@ -1641,9 +1658,8 @@ static int interworking_connect_roaming_consortium(
        ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
        anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
        for (i = 0; (ie || anqp) && i < cred->num_roaming_consortiums; i++) {
-               if (!roaming_consortium_match(
-                           ie, anqp, cred->roaming_consortiums[i],
-                           cred->roaming_consortiums_len[i]))
+               if (!oi_match(ie, anqp, cred->roaming_consortiums[i],
+                             cred->roaming_consortiums_len[i]))
                        continue;
 
                ssid->roaming_consortium_selection =
index 29e6a9710accd3379ae6accbf16073f6f246c839..1bb3cc18b7e0823e7d833c5c8808c81b531e1f3b 100644 (file)
@@ -683,7 +683,26 @@ fast_reauth=1
 #      be used to configure alternative FQDNs that will be considered home
 #      networks.
 #
+# home_ois: Home OI(s)
+#      This string field contains one or more comma delimited OIs (hexdump)
+#      identifying the access the access points that support authentication
+#      with this credential. There are an alternative to the use of the realm
+#      parameter. When using Home OIs to match the network, the EAP parameters
+#      need to be pre-configured with the credentials since the NAI Realm
+#      information may not be available or fetched.
+#      A successful authentication with the access point is possible as soon
+#      as at least one Home OI from the list matches an OI in the Roaming
+#      Consortium advertised by the access point.
+#      (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOI)
+#
+# required_home_ois: Required Home OI(s)
+#      This string field contains the set of Home OI(s) (hexdump) that are
+#      required to be advertised by the AP for the credential to be considered
+#      matching.
+#      (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOIRequired)
+#
 # roaming_consortium: Roaming Consortium OI
+#      Deprecated: use home_ois instead.
 #      If roaming_consortium_len is non-zero, this field contains the
 #      Roaming Consortium OI that can be used to determine which access
 #      points support authentication with this credential. This is an
@@ -693,6 +712,7 @@ fast_reauth=1
 #      may not be available or fetched.
 #
 # required_roaming_consortium: Required Roaming Consortium OI
+#      Deprecated: use required_home_ois instead.
 #      If required_roaming_consortium_len is non-zero, this field contains the
 #      Roaming Consortium OI that is required to be advertised by the AP for
 #      the credential to be considered matching.
@@ -798,7 +818,7 @@ fast_reauth=1
 #      password="password"
 #      ca_cert="/etc/wpa_supplicant/ca.pem"
 #      domain="example.com"
-#      roaming_consortium=223344
+#      home_ois="223344"
 #      eap=TTLS
 #      phase2="auth=MSCHAPV2"
 #}