Interworking: Add support for multiple credentials
This replaces the global home_* parameters with a list of credentials that can be configured similarly to network blocks. For example: cred={ realm="example.com" username="user@example.com" password="password" ca_cert="/etc/wpa_supplicant/ca.pem" domain="example.com" } cred={ imsi="310026-000000000" milenage="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123" } Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
9914c96feb
commit
1bb7b8e84c
4 changed files with 321 additions and 126 deletions
|
@ -1774,6 +1774,19 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_config_free_cred(struct wpa_cred *cred)
|
||||||
|
{
|
||||||
|
os_free(cred->realm);
|
||||||
|
os_free(cred->username);
|
||||||
|
os_free(cred->password);
|
||||||
|
os_free(cred->ca_cert);
|
||||||
|
os_free(cred->imsi);
|
||||||
|
os_free(cred->milenage);
|
||||||
|
os_free(cred->domain);
|
||||||
|
os_free(cred);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_config_free - Free configuration data
|
* wpa_config_free - Free configuration data
|
||||||
* @config: Configuration data from wpa_config_read()
|
* @config: Configuration data from wpa_config_read()
|
||||||
|
@ -1787,6 +1800,7 @@ void wpa_config_free(struct wpa_config *config)
|
||||||
struct wpa_config_blob *blob, *prevblob;
|
struct wpa_config_blob *blob, *prevblob;
|
||||||
#endif /* CONFIG_NO_CONFIG_BLOBS */
|
#endif /* CONFIG_NO_CONFIG_BLOBS */
|
||||||
struct wpa_ssid *ssid, *prev = NULL;
|
struct wpa_ssid *ssid, *prev = NULL;
|
||||||
|
struct wpa_cred *cred, *cprev;
|
||||||
|
|
||||||
ssid = config->ssid;
|
ssid = config->ssid;
|
||||||
while (ssid) {
|
while (ssid) {
|
||||||
|
@ -1795,6 +1809,13 @@ void wpa_config_free(struct wpa_config *config)
|
||||||
wpa_config_free_ssid(prev);
|
wpa_config_free_ssid(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cred = config->cred;
|
||||||
|
while (cred) {
|
||||||
|
cprev = cred;
|
||||||
|
cred = cred->next;
|
||||||
|
wpa_config_free_cred(cprev);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_NO_CONFIG_BLOBS
|
#ifndef CONFIG_NO_CONFIG_BLOBS
|
||||||
blob = config->blobs;
|
blob = config->blobs;
|
||||||
prevblob = NULL;
|
prevblob = NULL;
|
||||||
|
@ -1819,13 +1840,6 @@ void wpa_config_free(struct wpa_config *config)
|
||||||
os_free(config->config_methods);
|
os_free(config->config_methods);
|
||||||
os_free(config->p2p_ssid_postfix);
|
os_free(config->p2p_ssid_postfix);
|
||||||
os_free(config->pssid);
|
os_free(config->pssid);
|
||||||
os_free(config->home_realm);
|
|
||||||
os_free(config->home_username);
|
|
||||||
os_free(config->home_password);
|
|
||||||
os_free(config->home_ca_cert);
|
|
||||||
os_free(config->home_imsi);
|
|
||||||
os_free(config->home_milenage);
|
|
||||||
os_free(config->home_domain);
|
|
||||||
os_free(config);
|
os_free(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2197,6 +2211,67 @@ void wpa_config_update_psk(struct wpa_ssid *ssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
|
||||||
|
const char *value, int line)
|
||||||
|
{
|
||||||
|
char *val;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
val = wpa_config_parse_string(value, &len);
|
||||||
|
if (val == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (os_strcmp(var, "realm") == 0) {
|
||||||
|
os_free(cred->realm);
|
||||||
|
cred->realm = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "username") == 0) {
|
||||||
|
os_free(cred->username);
|
||||||
|
cred->username = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "password") == 0) {
|
||||||
|
os_free(cred->password);
|
||||||
|
cred->password = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "ca_cert") == 0) {
|
||||||
|
os_free(cred->ca_cert);
|
||||||
|
cred->ca_cert = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "imsi") == 0) {
|
||||||
|
os_free(cred->imsi);
|
||||||
|
cred->imsi = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "milenage") == 0) {
|
||||||
|
os_free(cred->milenage);
|
||||||
|
cred->milenage = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "domain") == 0) {
|
||||||
|
os_free(cred->domain);
|
||||||
|
cred->domain = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line) {
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
|
||||||
|
line, var);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_NO_CONFIG_BLOBS
|
#ifndef CONFIG_NO_CONFIG_BLOBS
|
||||||
/**
|
/**
|
||||||
* wpa_config_get_blob - Get a named configuration blob
|
* wpa_config_get_blob - Get a named configuration blob
|
||||||
|
@ -2589,13 +2664,6 @@ static const struct global_parse_data global_fields[] = {
|
||||||
{ INT_RANGE(filter_ssids, 0, 1), 0 },
|
{ INT_RANGE(filter_ssids, 0, 1), 0 },
|
||||||
{ INT(max_num_sta), 0 },
|
{ INT(max_num_sta), 0 },
|
||||||
{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
|
{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
|
||||||
{ STR(home_realm), 0 },
|
|
||||||
{ STR(home_username), 0 },
|
|
||||||
{ STR(home_password), 0 },
|
|
||||||
{ STR(home_ca_cert), 0 },
|
|
||||||
{ STR(home_imsi), 0 },
|
|
||||||
{ STR(home_milenage), 0 },
|
|
||||||
{ STR(home_domain), 0 },
|
|
||||||
{ INT_RANGE(interworking, 0, 1), 0 },
|
{ INT_RANGE(interworking, 0, 1), 0 },
|
||||||
{ FUNC(hessid), 0 },
|
{ FUNC(hessid), 0 },
|
||||||
{ INT_RANGE(access_network_type, 0, 15), 0 }
|
{ INT_RANGE(access_network_type, 0, 15), 0 }
|
||||||
|
|
|
@ -28,6 +28,67 @@
|
||||||
#include "wps/wps.h"
|
#include "wps/wps.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct wpa_cred {
|
||||||
|
/**
|
||||||
|
* next - Next credential in the list
|
||||||
|
*
|
||||||
|
* This pointer can be used to iterate over all credentials. The head
|
||||||
|
* of this list is stored in the cred field of struct wpa_config.
|
||||||
|
*/
|
||||||
|
struct wpa_cred *next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id - Unique id for the credential
|
||||||
|
*
|
||||||
|
* This identifier is used as a unique identifier for each credential
|
||||||
|
* block when using the control interface. Each credential is allocated
|
||||||
|
* an id when it is being created, either when reading the
|
||||||
|
* configuration file or when a new credential is added through the
|
||||||
|
* control interface.
|
||||||
|
*/
|
||||||
|
int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* realm - Home Realm for Interworking
|
||||||
|
*/
|
||||||
|
char *realm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* username - Username for Interworking network selection
|
||||||
|
*/
|
||||||
|
char *username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* password - Password for Interworking network selection
|
||||||
|
*/
|
||||||
|
char *password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ca_cert - CA certificate for Interworking network selection
|
||||||
|
*/
|
||||||
|
char *ca_cert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* imsi - IMSI in <MCC> | <MNC> | '-' | <MSIN> format
|
||||||
|
*/
|
||||||
|
char *imsi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* milenage - Milenage parameters for SIM/USIM simulator in
|
||||||
|
* <Ki>:<OPc>:<SQN> format
|
||||||
|
*/
|
||||||
|
char *milenage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* domain - Home service provider FQDN
|
||||||
|
*
|
||||||
|
* This is used to compare against the Domain Name List to figure out
|
||||||
|
* whether the AP is operated by the Home SP.
|
||||||
|
*/
|
||||||
|
char *domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define CFG_CHANGED_DEVICE_NAME BIT(0)
|
#define CFG_CHANGED_DEVICE_NAME BIT(0)
|
||||||
#define CFG_CHANGED_CONFIG_METHODS BIT(1)
|
#define CFG_CHANGED_CONFIG_METHODS BIT(1)
|
||||||
#define CFG_CHANGED_DEVICE_TYPE BIT(2)
|
#define CFG_CHANGED_DEVICE_TYPE BIT(2)
|
||||||
|
@ -71,6 +132,13 @@ struct wpa_config {
|
||||||
*/
|
*/
|
||||||
int num_prio;
|
int num_prio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cred - Head of the credential list
|
||||||
|
*
|
||||||
|
* This is the head for the list of all the configured credentials.
|
||||||
|
*/
|
||||||
|
struct wpa_cred *cred;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eapol_version - IEEE 802.1X/EAPOL version number
|
* eapol_version - IEEE 802.1X/EAPOL version number
|
||||||
*
|
*
|
||||||
|
@ -447,45 +515,6 @@ struct wpa_config {
|
||||||
* Homogeneous ESS. This is used only if interworking is enabled.
|
* Homogeneous ESS. This is used only if interworking is enabled.
|
||||||
*/
|
*/
|
||||||
u8 hessid[ETH_ALEN];
|
u8 hessid[ETH_ALEN];
|
||||||
|
|
||||||
/**
|
|
||||||
* home_realm - Home Realm for Interworking
|
|
||||||
*/
|
|
||||||
char *home_realm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* home_username - Username for Interworking network selection
|
|
||||||
*/
|
|
||||||
char *home_username;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* home_password - Password for Interworking network selection
|
|
||||||
*/
|
|
||||||
char *home_password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* home_ca_cert - CA certificate for Interworking network selection
|
|
||||||
*/
|
|
||||||
char *home_ca_cert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* home_imsi - IMSI in <MCC> | <MNC> | '-' | <MSIN> format
|
|
||||||
*/
|
|
||||||
char *home_imsi;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* home_milenage - Milenage parameters for SIM/USIM simulator in
|
|
||||||
* <Ki>:<OPc>:<SQN> format
|
|
||||||
*/
|
|
||||||
char *home_milenage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* home_domain - Home service provider FQDN
|
|
||||||
*
|
|
||||||
* This is used to compare against the Domain Name List to figure out
|
|
||||||
* whether the AP is operated by the Home SP.
|
|
||||||
*/
|
|
||||||
char *home_domain;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -518,6 +547,10 @@ void wpa_config_set_blob(struct wpa_config *config,
|
||||||
void wpa_config_free_blob(struct wpa_config_blob *blob);
|
void wpa_config_free_blob(struct wpa_config_blob *blob);
|
||||||
int wpa_config_remove_blob(struct wpa_config *config, const char *name);
|
int wpa_config_remove_blob(struct wpa_config *config, const char *name);
|
||||||
|
|
||||||
|
void wpa_config_free_cred(struct wpa_cred *cred);
|
||||||
|
int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
|
||||||
|
const char *value, int line);
|
||||||
|
|
||||||
struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
|
struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
|
||||||
const char *driver_param);
|
const char *driver_param);
|
||||||
#ifndef CONFIG_NO_STDOUT_DEBUG
|
#ifndef CONFIG_NO_STDOUT_DEBUG
|
||||||
|
|
|
@ -178,6 +178,61 @@ static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpa_cred * wpa_config_read_cred(FILE *f, int *line, int id)
|
||||||
|
{
|
||||||
|
struct wpa_cred *cred;
|
||||||
|
int errors = 0, end = 0;
|
||||||
|
char buf[256], *pos, *pos2;
|
||||||
|
|
||||||
|
wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new cred block", *line);
|
||||||
|
cred = os_zalloc(sizeof(*cred));
|
||||||
|
if (cred == NULL)
|
||||||
|
return NULL;
|
||||||
|
cred->id = id;
|
||||||
|
|
||||||
|
while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
|
||||||
|
if (os_strcmp(pos, "}") == 0) {
|
||||||
|
end = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos2 = os_strchr(pos, '=');
|
||||||
|
if (pos2 == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: Invalid cred line "
|
||||||
|
"'%s'.", *line, pos);
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pos2++ = '\0';
|
||||||
|
if (*pos2 == '"') {
|
||||||
|
if (os_strchr(pos2 + 1, '"') == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: invalid "
|
||||||
|
"quotation '%s'.", *line, pos2);
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpa_config_set_cred(cred, pos, pos2, *line) < 0)
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!end) {
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: cred block was not "
|
||||||
|
"terminated properly.", *line);
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors) {
|
||||||
|
wpa_config_free_cred(cred);
|
||||||
|
cred = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cred;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_NO_CONFIG_BLOBS
|
#ifndef CONFIG_NO_CONFIG_BLOBS
|
||||||
static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
|
static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
|
||||||
const char *name)
|
const char *name)
|
||||||
|
@ -267,8 +322,10 @@ struct wpa_config * wpa_config_read(const char *name)
|
||||||
char buf[256], *pos;
|
char buf[256], *pos;
|
||||||
int errors = 0, line = 0;
|
int errors = 0, line = 0;
|
||||||
struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
|
struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
|
||||||
|
struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL;
|
||||||
struct wpa_config *config;
|
struct wpa_config *config;
|
||||||
int id = 0;
|
int id = 0;
|
||||||
|
int cred_id = 0;
|
||||||
|
|
||||||
config = wpa_config_alloc_empty(NULL, NULL);
|
config = wpa_config_alloc_empty(NULL, NULL);
|
||||||
if (config == NULL)
|
if (config == NULL)
|
||||||
|
@ -302,6 +359,20 @@ struct wpa_config * wpa_config_read(const char *name)
|
||||||
errors++;
|
errors++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (os_strcmp(pos, "cred={") == 0) {
|
||||||
|
cred = wpa_config_read_cred(f, &line, cred_id++);
|
||||||
|
if (cred == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: failed to "
|
||||||
|
"parse cred block.", line);
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cred_head == NULL) {
|
||||||
|
cred_head = cred_tail = cred;
|
||||||
|
} else {
|
||||||
|
cred_tail->next = cred;
|
||||||
|
cred_tail = cred;
|
||||||
|
}
|
||||||
#ifndef CONFIG_NO_CONFIG_BLOBS
|
#ifndef CONFIG_NO_CONFIG_BLOBS
|
||||||
} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
|
} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
|
||||||
if (wpa_config_process_blob(config, f, &line, pos + 12)
|
if (wpa_config_process_blob(config, f, &line, pos + 12)
|
||||||
|
@ -322,6 +393,7 @@ struct wpa_config * wpa_config_read(const char *name)
|
||||||
|
|
||||||
config->ssid = head;
|
config->ssid = head;
|
||||||
wpa_config_debug_dump_networks(config);
|
wpa_config_debug_dump_networks(config);
|
||||||
|
config->cred = cred_head;
|
||||||
|
|
||||||
#ifndef WPA_IGNORE_CONFIG_ERRORS
|
#ifndef WPA_IGNORE_CONFIG_ERRORS
|
||||||
if (errors) {
|
if (errors) {
|
||||||
|
@ -712,18 +784,6 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
|
||||||
if (config->disassoc_low_ack)
|
if (config->disassoc_low_ack)
|
||||||
fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack);
|
fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack);
|
||||||
#ifdef CONFIG_INTERWORKING
|
#ifdef CONFIG_INTERWORKING
|
||||||
if (config->home_realm)
|
|
||||||
fprintf(f, "home_realm=%s\n", config->home_realm);
|
|
||||||
if (config->home_username)
|
|
||||||
fprintf(f, "home_username=%s\n", config->home_username);
|
|
||||||
if (config->home_password)
|
|
||||||
fprintf(f, "home_password=%s\n", config->home_password);
|
|
||||||
if (config->home_ca_cert)
|
|
||||||
fprintf(f, "home_ca_cert=%s\n", config->home_ca_cert);
|
|
||||||
if (config->home_imsi)
|
|
||||||
fprintf(f, "home_imsi=%s\n", config->home_imsi);
|
|
||||||
if (config->home_milenage)
|
|
||||||
fprintf(f, "home_milenage=%s\n", config->home_milenage);
|
|
||||||
if (config->interworking)
|
if (config->interworking)
|
||||||
fprintf(f, "interworking=%u\n", config->interworking);
|
fprintf(f, "interworking=%u\n", config->interworking);
|
||||||
if (!is_zero_ether_addr(config->hessid))
|
if (!is_zero_ether_addr(config->hessid))
|
||||||
|
|
|
@ -416,15 +416,16 @@ static int nai_realm_cred_username(struct nai_realm_eap *eap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s,
|
static struct nai_realm_eap * nai_realm_find_eap(struct wpa_cred *cred,
|
||||||
struct nai_realm *realm)
|
struct nai_realm *realm)
|
||||||
{
|
{
|
||||||
u8 e;
|
u8 e;
|
||||||
|
|
||||||
if (wpa_s->conf->home_username == NULL ||
|
if (cred == NULL ||
|
||||||
wpa_s->conf->home_username[0] == '\0' ||
|
cred->username == NULL ||
|
||||||
wpa_s->conf->home_password == NULL ||
|
cred->username[0] == '\0' ||
|
||||||
wpa_s->conf->home_password[0] == '\0')
|
cred->password == NULL ||
|
||||||
|
cred->password[0] == '\0')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (e = 0; e < realm->eap_count; e++) {
|
for (e = 0; e < realm->eap_count; e++) {
|
||||||
|
@ -571,9 +572,23 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss)
|
struct wpa_bss *bss)
|
||||||
{
|
{
|
||||||
#ifdef INTERWORKING_3GPP
|
#ifdef INTERWORKING_3GPP
|
||||||
|
struct wpa_cred *cred;
|
||||||
struct wpa_ssid *ssid;
|
struct wpa_ssid *ssid;
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
|
|
||||||
|
if (bss->anqp_3gpp == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
|
||||||
|
if (cred->imsi == NULL || !cred->imsi[0] ||
|
||||||
|
cred->milenage == NULL || !cred->milenage[0])
|
||||||
|
continue;
|
||||||
|
if (plmn_id_match(bss->anqp_3gpp, cred->imsi))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cred == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
|
ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
|
||||||
if (ie == NULL)
|
if (ie == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -598,14 +613,14 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
|
||||||
wpa_printf(MSG_DEBUG, "EAP-SIM not supported");
|
wpa_printf(MSG_DEBUG, "EAP-SIM not supported");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (set_root_nai(ssid, wpa_s->conf->home_imsi, '1') < 0) {
|
if (set_root_nai(ssid, cred->imsi, '1') < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Failed to set Root NAI");
|
wpa_printf(MSG_DEBUG, "Failed to set Root NAI");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpa_s->conf->home_milenage && wpa_s->conf->home_milenage[0]) {
|
if (cred->milenage && cred->milenage[0]) {
|
||||||
if (wpa_config_set_quoted(ssid, "password",
|
if (wpa_config_set_quoted(ssid, "password",
|
||||||
wpa_s->conf->home_milenage) < 0)
|
cred->milenage) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
} else {
|
} else {
|
||||||
/* TODO: PIN */
|
/* TODO: PIN */
|
||||||
|
@ -613,9 +628,8 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpa_s->conf->home_password && wpa_s->conf->home_password[0] &&
|
if (cred->password && cred->password[0] &&
|
||||||
wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_password)
|
wpa_config_set_quoted(ssid, "password", cred->password) < 0)
|
||||||
< 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
wpa_s->disconnected = 0;
|
wpa_s->disconnected = 0;
|
||||||
|
@ -634,6 +648,7 @@ fail:
|
||||||
|
|
||||||
int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
{
|
{
|
||||||
|
struct wpa_cred *cred;
|
||||||
struct wpa_ssid *ssid;
|
struct wpa_ssid *ssid;
|
||||||
struct nai_realm *realm;
|
struct nai_realm *realm;
|
||||||
struct nai_realm_eap *eap = NULL;
|
struct nai_realm_eap *eap = NULL;
|
||||||
|
@ -641,7 +656,7 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
char buf[100];
|
char buf[100];
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
|
|
||||||
if (bss == NULL)
|
if (wpa_s->conf->cred == NULL || bss == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
|
ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
|
||||||
if (ie == NULL || ie[1] == 0) {
|
if (ie == NULL || ie[1] == 0) {
|
||||||
|
@ -657,10 +672,14 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if (!nai_realm_match(&realm[i], wpa_s->conf->home_realm))
|
if (!nai_realm_match(&realm[i], cred->realm))
|
||||||
continue;
|
continue;
|
||||||
eap = nai_realm_find_eap(wpa_s, &realm[i]);
|
eap = nai_realm_find_eap(cred, &realm[i]);
|
||||||
|
if (eap)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (eap)
|
if (eap)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -701,11 +720,11 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (eap->method == EAP_TYPE_TTLS &&
|
if (eap->method == EAP_TYPE_TTLS &&
|
||||||
wpa_s->conf->home_username && wpa_s->conf->home_username[0]) {
|
cred->username && cred->username[0]) {
|
||||||
const char *pos;
|
const char *pos;
|
||||||
char *anon;
|
char *anon;
|
||||||
/* Use anonymous NAI in Phase 1 */
|
/* Use anonymous NAI in Phase 1 */
|
||||||
pos = os_strchr(wpa_s->conf->home_username, '@');
|
pos = os_strchr(cred->username, '@');
|
||||||
if (pos) {
|
if (pos) {
|
||||||
size_t buflen = 9 + os_strlen(pos) + 1;
|
size_t buflen = 9 + os_strlen(pos) + 1;
|
||||||
anon = os_malloc(buflen);
|
anon = os_malloc(buflen);
|
||||||
|
@ -725,14 +744,12 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
os_free(anon);
|
os_free(anon);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpa_s->conf->home_username && wpa_s->conf->home_username[0] &&
|
if (cred->username && cred->username[0] &&
|
||||||
wpa_config_set_quoted(ssid, "identity",
|
wpa_config_set_quoted(ssid, "identity", cred->username) < 0)
|
||||||
wpa_s->conf->home_username) < 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (wpa_s->conf->home_password && wpa_s->conf->home_password[0] &&
|
if (cred->password && cred->password[0] &&
|
||||||
wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_password)
|
wpa_config_set_quoted(ssid, "password", cred->password) < 0)
|
||||||
< 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
switch (eap->method) {
|
switch (eap->method) {
|
||||||
|
@ -776,9 +793,8 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpa_s->conf->home_ca_cert && wpa_s->conf->home_ca_cert[0] &&
|
if (cred->ca_cert && cred->ca_cert[0] &&
|
||||||
wpa_config_set_quoted(ssid, "ca_cert", wpa_s->conf->home_ca_cert) <
|
wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0)
|
||||||
0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
nai_realm_free(realm, count);
|
nai_realm_free(realm, count);
|
||||||
|
@ -800,29 +816,34 @@ fail:
|
||||||
static int interworking_credentials_available_3gpp(
|
static int interworking_credentials_available_3gpp(
|
||||||
struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
struct wpa_cred *cred;
|
||||||
|
int ret;
|
||||||
|
|
||||||
#ifdef INTERWORKING_3GPP
|
#ifdef INTERWORKING_3GPP
|
||||||
if (bss->anqp_3gpp == NULL)
|
if (bss->anqp_3gpp == NULL)
|
||||||
return ret;
|
return 0;
|
||||||
|
|
||||||
if (wpa_s->conf->home_imsi == NULL || !wpa_s->conf->home_imsi[0] ||
|
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
|
||||||
wpa_s->conf->home_milenage == NULL ||
|
if (cred->imsi == NULL || !cred->imsi[0] ||
|
||||||
!wpa_s->conf->home_milenage[0])
|
cred->milenage == NULL || !cred->milenage[0])
|
||||||
return ret;
|
continue;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from " MACSTR,
|
wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from "
|
||||||
MAC2STR(bss->bssid));
|
MACSTR, MAC2STR(bss->bssid));
|
||||||
ret = plmn_id_match(bss->anqp_3gpp, wpa_s->conf->home_imsi);
|
ret = plmn_id_match(bss->anqp_3gpp, cred->imsi);
|
||||||
wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not ");
|
wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not ");
|
||||||
|
if (ret)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
#endif /* INTERWORKING_3GPP */
|
#endif /* INTERWORKING_3GPP */
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int interworking_credentials_available_realm(
|
static int interworking_credentials_available_realm(
|
||||||
struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
{
|
{
|
||||||
|
struct wpa_cred *cred;
|
||||||
struct nai_realm *realm;
|
struct nai_realm *realm;
|
||||||
u16 count, i;
|
u16 count, i;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
@ -830,7 +851,7 @@ static int interworking_credentials_available_realm(
|
||||||
if (bss->anqp_nai_realm == NULL)
|
if (bss->anqp_nai_realm == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (wpa_s->conf->home_realm == NULL)
|
if (wpa_s->conf->cred == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "Interworking: Parsing NAI Realm list from "
|
wpa_printf(MSG_DEBUG, "Interworking: Parsing NAI Realm list from "
|
||||||
|
@ -842,14 +863,21 @@ static int interworking_credentials_available_realm(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
|
||||||
if (!nai_realm_match(&realm[i], wpa_s->conf->home_realm))
|
if (cred->realm == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (nai_realm_find_eap(wpa_s, &realm[i])) {
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (!nai_realm_match(&realm[i], cred->realm))
|
||||||
|
continue;
|
||||||
|
if (nai_realm_find_eap(cred, &realm[i])) {
|
||||||
found++;
|
found++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
nai_realm_free(realm, count);
|
nai_realm_free(realm, count);
|
||||||
|
|
||||||
|
@ -895,33 +923,39 @@ static int domain_name_list_contains(struct wpabuf *domain_names,
|
||||||
static int interworking_home_sp(struct wpa_supplicant *wpa_s,
|
static int interworking_home_sp(struct wpa_supplicant *wpa_s,
|
||||||
struct wpabuf *domain_names)
|
struct wpabuf *domain_names)
|
||||||
{
|
{
|
||||||
|
struct wpa_cred *cred;
|
||||||
#ifdef INTERWORKING_3GPP
|
#ifdef INTERWORKING_3GPP
|
||||||
char nai[100], *realm;
|
char nai[100], *realm;
|
||||||
#endif /* INTERWORKING_3GPP */
|
#endif /* INTERWORKING_3GPP */
|
||||||
|
|
||||||
if (domain_names == NULL)
|
if (domain_names == NULL || wpa_s->conf->cred == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
|
||||||
#ifdef INTERWORKING_3GPP
|
#ifdef INTERWORKING_3GPP
|
||||||
if (wpa_s->conf->home_imsi &&
|
if (cred->imsi &&
|
||||||
build_root_nai(nai, wpa_s->conf->home_imsi, 0) == 0) {
|
build_root_nai(nai, cred->imsi, 0) == 0) {
|
||||||
realm = os_strchr(nai, '@');
|
realm = os_strchr(nai, '@');
|
||||||
if (realm)
|
if (realm)
|
||||||
realm++;
|
realm++;
|
||||||
wpa_printf(MSG_DEBUG, "Interworking: Search for match with "
|
wpa_printf(MSG_DEBUG, "Interworking: Search for match "
|
||||||
"SIM/USIM domain %s", realm);
|
"with SIM/USIM domain %s", realm);
|
||||||
if (realm && domain_name_list_contains(domain_names, realm))
|
if (realm &&
|
||||||
|
domain_name_list_contains(domain_names, realm))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif /* INTERWORKING_3GPP */
|
#endif /* INTERWORKING_3GPP */
|
||||||
|
|
||||||
if (wpa_s->conf->home_domain == NULL)
|
if (cred->domain == NULL)
|
||||||
return -1;
|
continue;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "Interworking: Search for match with "
|
wpa_printf(MSG_DEBUG, "Interworking: Search for match with "
|
||||||
"home SP FQDN %s", wpa_s->conf->home_domain);
|
"home SP FQDN %s", cred->domain);
|
||||||
return domain_name_list_contains(domain_names,
|
if (domain_name_list_contains(domain_names, cred->domain))
|
||||||
wpa_s->conf->home_domain);
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue