# 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
# 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.
# 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"
}
-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;
}
}
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",
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;
}
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;
}
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
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,
}
}
- 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) {
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;
}
-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;
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;
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;
}
}
-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;
}
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;
}
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);
(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;
}
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))
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 =
# 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
# 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.
# password="password"
# ca_cert="/etc/wpa_supplicant/ca.pem"
# domain="example.com"
-# roaming_consortium=223344
+# home_ois="223344"
# eap=TTLS
# phase2="auth=MSCHAPV2"
#}