diff options
author | Andrej Shadura <andrewsh@debian.org> | 2019-01-29 18:02:07 +0100 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2019-01-29 18:02:07 +0100 |
commit | bf44a8f269f77f3309920b07f126d2c9b1ee5682 (patch) | |
tree | 2a8cd30abda02a1ddba290f253cc11819b732cef /src | |
parent | 5ca62411f15be39ebe3d78d7ce53ab17fd07f6d4 (diff) |
New upstream version 2.7+git20190128+0c1e29f
Diffstat (limited to 'src')
-rw-r--r-- | src/ap/ap_config.c | 76 | ||||
-rw-r--r-- | src/ap/ap_config.h | 4 | ||||
-rw-r--r-- | src/ap/authsrv.c | 10 | ||||
-rw-r--r-- | src/ap/ctrl_iface_ap.c | 8 | ||||
-rw-r--r-- | src/ap/ieee802_11_shared.c | 21 | ||||
-rw-r--r-- | src/ap/sta_info.c | 44 | ||||
-rw-r--r-- | src/ap/sta_info.h | 2 | ||||
-rw-r--r-- | src/ap/wnm_ap.c | 7 | ||||
-rw-r--r-- | src/ap/wpa_auth.c | 13 | ||||
-rw-r--r-- | src/ap/wpa_auth.h | 1 | ||||
-rw-r--r-- | src/ap/wpa_auth_ft.c | 2 | ||||
-rw-r--r-- | src/common/qca-vendor.h | 14 | ||||
-rw-r--r-- | src/crypto/tls.h | 1 | ||||
-rw-r--r-- | src/crypto/tls_openssl.c | 67 | ||||
-rw-r--r-- | src/p2p/p2p.h | 5 |
15 files changed, 262 insertions, 13 deletions
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 95a3476..9611dc0 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -259,6 +259,12 @@ static int hostapd_config_read_wpa_psk(const char *fname, { FILE *f; char buf[128], *pos; + const char *keyid; + char *context; + char *context2; + char *token; + char *name; + char *value; int line = 0, ret = 0, len, ok; u8 addr[ETH_ALEN]; struct hostapd_wpa_psk *psk; @@ -288,9 +294,35 @@ static int hostapd_config_read_wpa_psk(const char *fname, if (buf[0] == '\0') continue; - if (hwaddr_aton(buf, addr)) { + context = NULL; + keyid = NULL; + while ((token = str_token(buf, " ", &context))) { + if (!os_strchr(token, '=')) + break; + context2 = NULL; + name = str_token(token, "=", &context2); + value = str_token(token, "", &context2); + if (!value) + value = ""; + if (!os_strcmp(name, "keyid")) { + keyid = value; + } else { + wpa_printf(MSG_ERROR, + "Unrecognized '%s=%s' on line %d in '%s'", + name, value, line, fname); + ret = -1; + break; + } + } + + if (ret == -1) + break; + + if (!token) + token = ""; + if (hwaddr_aton(token, addr)) { wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " - "line %d in '%s'", buf, line, fname); + "line %d in '%s'", token, line, fname); ret = -1; break; } @@ -306,15 +338,14 @@ static int hostapd_config_read_wpa_psk(const char *fname, else os_memcpy(psk->addr, addr, ETH_ALEN); - pos = buf + 17; - if (*pos == '\0') { + pos = str_token(buf, "", &context); + if (!pos) { wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", line, fname); os_free(psk); ret = -1; break; } - pos++; ok = 0; len = os_strlen(pos); @@ -333,6 +364,18 @@ static int hostapd_config_read_wpa_psk(const char *fname, break; } + if (keyid) { + len = os_strlcpy(psk->keyid, keyid, sizeof(psk->keyid)); + if ((size_t) len >= sizeof(psk->keyid)) { + wpa_printf(MSG_ERROR, + "PSK keyid too long on line %d in '%s'", + line, fname); + os_free(psk); + ret = -1; + break; + } + } + psk->next = ssid->wpa_psk; ssid->wpa_psk = psk; } @@ -1168,3 +1211,26 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss, } } } + + +int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf) +{ + int with_id = 0, without_id = 0; + struct sae_password_entry *pw; + + if (conf->ssid.wpa_passphrase) + without_id = 1; + + for (pw = conf->sae_passwords; pw; pw = pw->next) { + if (pw->identifier) + with_id = 1; + else + without_id = 1; + if (with_id && without_id) + break; + } + + if (with_id && !without_id) + return 2; + return with_id; +} diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 990d0d1..6963df4 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -134,6 +134,7 @@ struct hostapd_vlan { }; #define PMK_LEN 32 +#define KEYID_LEN 32 #define MIN_PASSPHRASE_LEN 8 #define MAX_PASSPHRASE_LEN 63 struct hostapd_sta_wpa_psk_short { @@ -147,6 +148,7 @@ struct hostapd_sta_wpa_psk_short { struct hostapd_wpa_psk { struct hostapd_wpa_psk *next; int group; + char keyid[KEYID_LEN]; u8 psk[PMK_LEN]; u8 addr[ETH_ALEN]; u8 p2p_dev_addr[ETH_ALEN]; @@ -390,6 +392,7 @@ struct hostapd_bss_config { char *private_key_passwd; int check_crl; int check_crl_strict; + unsigned int crl_reload_interval; unsigned int tls_session_lifetime; unsigned int tls_flags; char *ocsp_stapling_response; @@ -880,5 +883,6 @@ hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type); int hostapd_config_check(struct hostapd_config *conf, int full_config); void hostapd_set_security_params(struct hostapd_bss_config *bss, int full_config); +int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf); #endif /* HOSTAPD_CONFIG_H */ diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index d93b967..1bb3d9f 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -201,6 +201,16 @@ int authsrv_init(struct hostapd_data *hapd) os_memset(&conf, 0, sizeof(conf)); conf.tls_session_lifetime = hapd->conf->tls_session_lifetime; + if (hapd->conf->crl_reload_interval > 0 && + hapd->conf->check_crl <= 0) { + wpa_printf(MSG_INFO, + "Cannot enable CRL reload functionality - it depends on check_crl being set"); + } else if (hapd->conf->crl_reload_interval > 0) { + conf.crl_reload_interval = + hapd->conf->crl_reload_interval; + wpa_printf(MSG_INFO, + "Enabled CRL reload functionality"); + } conf.tls_flags = hapd->conf->tls_flags; conf.event_cb = authsrv_tls_event; conf.cb_ctx = hapd; diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 21b813e..3128aed 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -207,6 +207,7 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, char *buf, size_t buflen) { int len, res, ret, i; + const char *keyid; if (!sta) return 0; @@ -341,6 +342,13 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, len += ret; } + keyid = ap_sta_wpa_get_keyid(hapd, sta); + if (keyid) { + ret = os_snprintf(buf + len, buflen - len, "keyid=%s\n", keyid); + if (!os_snprintf_error(buflen - len, ret)) + len += ret; + } + return len; } diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 82bc086..d70d6c1 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -372,6 +372,21 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) *pos |= 0x01; #endif /* CONFIG_FILS */ break; + case 10: /* Bits 80-87 */ +#ifdef CONFIG_SAE + if (hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) { + int in_use = hostapd_sae_pw_id_in_use(hapd->conf); + + if (in_use) + *pos |= 0x02; /* Bit 81 - SAE Password + * Identifiers In Use */ + if (in_use == 2) + *pos |= 0x04; /* Bit 82 - SAE Password + * Identifiers Used Exclusively */ + } +#endif /* CONFIG_SAE */ + break; } } @@ -411,6 +426,12 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10) len = 10; #endif /* CONFIG_FILS */ +#ifdef CONFIG_SAE + if (len < 11 && hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + hostapd_sae_pw_id_in_use(hapd->conf)) + len = 11; +#endif /* CONFIG_SAE */ if (len < hapd->iface->extended_capa_len) len = hapd->iface->extended_capa_len; if (len == 0) diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 06f9afc..8858a34 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1163,6 +1163,32 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_IEEE80211W */ +const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct hostapd_wpa_psk *psk; + struct hostapd_ssid *ssid; + const u8 *pmk; + int pmk_len; + + ssid = &hapd->conf->ssid; + + pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); + if (!pmk || pmk_len != PMK_LEN) + return NULL; + + for (psk = ssid->wpa_psk; psk; psk = psk->next) + if (os_memcmp(pmk, psk->psk, PMK_LEN) == 0) + break; + if (!psk) + return NULL; + if (!psk || !psk->keyid[0]) + return NULL; + + return psk->keyid; +} + + void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, int authorized) { @@ -1201,7 +1227,11 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, sta->addr, authorized, dev_addr); if (authorized) { + const char *keyid; + char keyid_buf[100]; char ip_addr[100]; + + keyid_buf[0] = '\0'; ip_addr[0] = '\0'; #ifdef CONFIG_P2P if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { @@ -1212,14 +1242,20 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_P2P */ - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s", - buf, ip_addr); + keyid = ap_sta_wpa_get_keyid(hapd, sta); + if (keyid) { + os_snprintf(keyid_buf, sizeof(keyid_buf), + " keyid=%s", keyid); + } + + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s", + buf, ip_addr, keyid_buf); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, - AP_STA_CONNECTED "%s%s", - buf, ip_addr); + AP_STA_CONNECTED "%s%s%s", + buf, ip_addr, keyid_buf); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index fe68369..ee3f628 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -324,6 +324,8 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta, void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); +const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd, + struct sta_info *sta); void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, const u8 *addr, u16 reason); diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index d9c1690..27c69d3 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -255,6 +255,13 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd, return; } + if (len < 1) { + wpa_printf(MSG_DEBUG, + "WNM: Ignore too short WNM-Sleep Mode Request from " + MACSTR, MAC2STR(addr)); + return; + } + dialog_token = *pos++; while (pos + 1 < frm + len) { u8 ie_len = pos[1]; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 543880e..8e2b48e 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -873,6 +873,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, data, data_len) == 0) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; ok = 1; break; } @@ -2724,6 +2726,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, sm->last_rx_eapol_key, sm->last_rx_eapol_key_len) == 0) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; ok = 1; break; } @@ -4135,6 +4139,15 @@ int wpa_auth_get_pairwise(struct wpa_state_machine *sm) } +const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) +{ + if (!sm) + return NULL; + *len = sm->pmk_len; + return sm->PMK; +} + + int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) { if (sm == NULL) diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 7192845..e61648d 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -349,6 +349,7 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen); void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth); int wpa_auth_pairwise_set(struct wpa_state_machine *sm); int wpa_auth_get_pairwise(struct wpa_state_machine *sm); +const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len); int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 60f0786..ac736f0 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2638,6 +2638,8 @@ static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm, os_memcpy(out_pmk_r1, pmk_r1, PMK_LEN); if (out_pairwise) *out_pairwise = pairwise; + os_memcpy(sm->PMK, pmk, PMK_LEN); + sm->pmk_len = PMK_LEN; if (out_vlan && wpa_ft_get_vlan(sm->wpa_auth, sm->addr, out_vlan) < 0) { wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index ddec4e3..6f5b87e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -42,8 +42,12 @@ enum qca_radiotap_vendor_ids { * * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Recommendation of frequency * ranges to avoid to reduce issues due to interference or internal - * co-existence information in the driver. The event data structure is - * defined in struct qca_avoid_freq_list. + * co-existence information in the driver. These frequencies aim to + * minimize the traffic but not to totally avoid the traffic. That said + * for a P2P use case, these frequencies are allowed for the P2P + * discovery/negotiation but avoid the group to get formed on these + * frequencies. The event data structure is defined in + * struct qca_avoid_freq_list. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: Command to check driver support * for DFS offloading. @@ -848,6 +852,12 @@ enum qca_wlan_vendor_attr { * to report the corresponding antenna index to the chain RSSI value */ QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO = 40, + /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command to report + * the specific antenna EVM value (unsigned 32 bit value). With a + * determinate group of antennas, the driver specifies the EVM value + * for each antenna ID, and application extract them in user space. + */ + QCA_WLAN_VENDOR_ATTR_CHAIN_EVM = 41, /* keep last */ QCA_WLAN_VENDOR_ATTR_AFTER_LAST, diff --git a/src/crypto/tls.h b/src/crypto/tls.h index e13444a..413cccd 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -82,6 +82,7 @@ struct tls_config { int cert_in_cb; const char *openssl_ciphers; unsigned int tls_session_lifetime; + unsigned int crl_reload_interval; unsigned int tls_flags; void (*event_cb)(void *ctx, enum tls_event ev, diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index cb70e2c..99caa68 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -214,7 +214,11 @@ static struct tls_context *tls_global = NULL; struct tls_data { SSL_CTX *ssl; unsigned int tls_session_lifetime; + int check_crl; int check_crl_strict; + char *ca_cert; + unsigned int crl_reload_interval; + struct os_reltime crl_last_reload; }; struct tls_connection { @@ -305,6 +309,37 @@ static void tls_show_errors(int level, const char *func, const char *txt) #endif /* CONFIG_NO_STDOUT_DEBUG */ +static X509_STORE * tls_crl_cert_reload(const char *ca_cert, int check_crl) +{ + int flags; + X509_STORE *store; + + store = X509_STORE_new(); + if (!store) { + wpa_printf(MSG_DEBUG, + "OpenSSL: %s - failed to allocate new certificate store", + __func__); + return NULL; + } + + if (ca_cert && X509_STORE_load_locations(store, ca_cert, NULL) != 1) { + tls_show_errors(MSG_WARNING, __func__, + "Failed to load root certificates"); + X509_STORE_free(store); + return NULL; + } + + if (check_crl) + flags = X509_V_FLAG_CRL_CHECK; + if (check_crl == 2) + flags |= X509_V_FLAG_CRL_CHECK_ALL; + + X509_STORE_set_flags(store, flags); + + return store; +} + + #ifdef CONFIG_NATIVE_WINDOWS /* Windows CryptoAPI and access to certificate stores */ @@ -993,8 +1028,10 @@ void * tls_init(const struct tls_config *conf) return NULL; } data->ssl = ssl; - if (conf) + if (conf) { data->tls_session_lifetime = conf->tls_session_lifetime; + data->crl_reload_interval = conf->crl_reload_interval; + } SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2); SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3); @@ -1076,6 +1113,7 @@ void tls_deinit(void *ssl_ctx) os_free(context); if (data->tls_session_lifetime > 0) SSL_CTX_flush_sessions(ssl, 0); + os_free(data->ca_cert); SSL_CTX_free(ssl); tls_openssl_ref_count--; @@ -1471,8 +1509,28 @@ struct tls_connection * tls_connection_init(void *ssl_ctx) SSL_CTX *ssl = data->ssl; struct tls_connection *conn; long options; + X509_STORE *new_cert_store; + struct os_reltime now; struct tls_context *context = SSL_CTX_get_app_data(ssl); + /* Replace X509 store if it is time to update CRL. */ + if (data->crl_reload_interval > 0 && os_get_reltime(&now) == 0 && + os_reltime_expired(&now, &data->crl_last_reload, + data->crl_reload_interval)) { + wpa_printf(MSG_INFO, + "OpenSSL: Flushing X509 store with ca_cert file"); + new_cert_store = tls_crl_cert_reload(data->ca_cert, + data->check_crl); + if (!new_cert_store) { + wpa_printf(MSG_ERROR, + "OpenSSL: Error replacing X509 store with ca_cert file"); + } else { + /* Replace old store */ + SSL_CTX_set_cert_store(ssl, new_cert_store); + data->crl_last_reload = now; + } + } + conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; @@ -2393,6 +2451,9 @@ static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert) SSL_CTX_set_client_CA_list(ssl_ctx, SSL_load_client_CA_file(ca_cert)); #endif /* OPENSSL_NO_STDIO */ + + os_free(data->ca_cert); + data->ca_cert = os_strdup(ca_cert); } return 0; @@ -2417,7 +2478,9 @@ int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict) flags |= X509_V_FLAG_CRL_CHECK_ALL; X509_STORE_set_flags(cs, flags); + data->check_crl = check_crl; data->check_crl_strict = strict; + os_get_reltime(&data->crl_last_reload); } return 0; } @@ -2804,7 +2867,7 @@ static int tls_connection_client_cert(struct tls_connection *conn, return 0; } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) if (SSL_use_certificate_chain_file(conn->ssl, client_cert) == 1) { ERR_clear_error(); wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_chain_file" diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index fac5ce0..dd2c25d 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -104,6 +104,11 @@ struct p2p_go_neg_results { unsigned int vht_center_freq2; /** + * he - Indicates if IEEE 802.11ax HE is enabled + */ + int he; + + /** * ssid - SSID of the group */ u8 ssid[SSID_MAX_LEN]; |