Parcourir la source

WPS: Moved Credential building to use struct wps_credential

This makes it easier to store old AP settings into wps->cred (and allow
them to modified and taken into use in the future). Separation between
Credential and AP Settings building is also cleaner in this design.
Jouni Malinen il y a 16 ans
Parent
commit
3f42d42c07
1 fichiers modifiés avec 103 ajouts et 93 suppressions
  1. 103 93
      src/wps/wps_registrar.c

+ 103 - 93
src/wps/wps_registrar.c

@@ -758,7 +758,8 @@ static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg)
 }
 
 
-static int wps_build_cred_network_idx(struct wps_data *wps, struct wpabuf *msg)
+static int wps_build_cred_network_idx(struct wpabuf *msg,
+				      struct wps_credential *cred)
 {
 	wpa_printf(MSG_DEBUG, "WPS:  * Network Index");
 	wpabuf_put_be16(msg, ATTR_NETWORK_INDEX);
@@ -768,96 +769,73 @@ static int wps_build_cred_network_idx(struct wps_data *wps, struct wpabuf *msg)
 }
 
 
-static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg)
+static int wps_build_cred_ssid(struct wpabuf *msg,
+			       struct wps_credential *cred)
 {
 	wpa_printf(MSG_DEBUG, "WPS:  * SSID");
 	wpabuf_put_be16(msg, ATTR_SSID);
-	wpabuf_put_be16(msg, wps->wps->ssid_len);
-	wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len);
+	wpabuf_put_be16(msg, cred->ssid_len);
+	wpabuf_put_data(msg, cred->ssid, cred->ssid_len);
 	return 0;
 }
 
 
-static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg)
+static int wps_build_cred_auth_type(struct wpabuf *msg,
+				    struct wps_credential *cred)
 {
 	wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type (0x%x)",
-		   wps->auth_type);
+		   cred->auth_type);
 	wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
 	wpabuf_put_be16(msg, 2);
-	wpabuf_put_be16(msg, wps->auth_type);
+	wpabuf_put_be16(msg, cred->auth_type);
 	return 0;
 }
 
 
-static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg)
+static int wps_build_cred_encr_type(struct wpabuf *msg,
+				    struct wps_credential *cred)
 {
 	wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type (0x%x)",
-		   wps->encr_type);
+		   cred->encr_type);
 	wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
 	wpabuf_put_be16(msg, 2);
-	wpabuf_put_be16(msg, wps->encr_type);
+	wpabuf_put_be16(msg, cred->encr_type);
 	return 0;
 }
 
 
-static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg)
+static int wps_build_cred_network_key(struct wpabuf *msg,
+				      struct wps_credential *cred)
 {
 	wpa_printf(MSG_DEBUG, "WPS:  * Network Key");
 	wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
-	if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap) {
-		u8 r[16];
-		/* Generate a random passphrase */
-		if (os_get_random(r, sizeof(r)) < 0)
-			return -1;
-		os_free(wps->new_psk);
-		wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
-		if (wps->new_psk == NULL)
-			return -1;
-		wps->new_psk_len--; /* remove newline */
-		while (wps->new_psk_len &&
-		       wps->new_psk[wps->new_psk_len - 1] == '=')
-			wps->new_psk_len--;
-		wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase",
-				      wps->new_psk, wps->new_psk_len);
-		wpabuf_put_be16(msg, wps->new_psk_len);
-		wpabuf_put_data(msg, wps->new_psk, wps->new_psk_len);
-	} else if (wps->wps->network_key) {
-		wpabuf_put_be16(msg, wps->wps->network_key_len);
-		wpabuf_put_data(msg, wps->wps->network_key,
-				wps->wps->network_key_len);
-	} else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
-		char hex[65];
-		/* Generate a random per-device PSK */
-		os_free(wps->new_psk);
-		wps->new_psk_len = 32;
-		wps->new_psk = os_malloc(wps->new_psk_len);
-		if (wps->new_psk == NULL)
-			return -1;
-		if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) {
-			os_free(wps->new_psk);
-			wps->new_psk = NULL;
-			return -1;
-		}
-		wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
-				wps->new_psk, wps->new_psk_len);
-		wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk,
-				 wps->new_psk_len);
-		wpabuf_put_be16(msg, wps->new_psk_len * 2);
-		wpabuf_put_data(msg, hex, wps->new_psk_len * 2);
-	} else {
-		/* No Network Key */
-		wpabuf_put_be16(msg, 0);
-	}
+	wpabuf_put_be16(msg, cred->key_len);
+	wpabuf_put_data(msg, cred->key, cred->key_len);
 	return 0;
 }
 
 
-static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg)
+static int wps_build_cred_mac_addr(struct wpabuf *msg,
+				   struct wps_credential *cred)
 {
 	wpa_printf(MSG_DEBUG, "WPS:  * MAC Address");
 	wpabuf_put_be16(msg, ATTR_MAC_ADDR);
 	wpabuf_put_be16(msg, ETH_ALEN);
-	wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN);
+	wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN);
+	return 0;
+}
+
+
+static int wps_build_credential(struct wpabuf *msg,
+				struct wps_credential *cred)
+{
+	if (wps_build_cred_network_idx(msg, cred) ||
+	    wps_build_cred_ssid(msg, cred) ||
+	    wps_build_cred_auth_type(msg, cred) ||
+	    wps_build_cred_encr_type(msg, cred) ||
+	    wps_build_cred_network_key(msg, cred) ||
+	    wps_build_cred_mac_addr(msg, cred))
+		return -1;
 	return 0;
 }
 
@@ -865,14 +843,12 @@ static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg)
 static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
 {
 	struct wpabuf *cred;
-	int ap_settings;
 
-	ap_settings = !wps->wps->ap;
+	wpa_printf(MSG_DEBUG, "WPS:  * Credential");
+	os_memset(&wps->cred, 0, sizeof(wps->cred));
 
-	if (ap_settings)
-		wpa_printf(MSG_DEBUG, "WPS:  * AP Settings");
-	else
-		wpa_printf(MSG_DEBUG, "WPS:  * Credential");
+	os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
+	wps->cred.ssid_len = wps->wps->ssid_len;
 
 	/* Select the best authentication and encryption type */
 	if (wps->auth_type & WPS_AUTH_WPA2PSK)
@@ -888,6 +864,7 @@ static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
 			   wps->auth_type);
 		return -1;
 	}
+	wps->cred.auth_type = wps->auth_type;
 
 	if (wps->auth_type == WPS_AUTH_WPA2PSK ||
 	    wps->auth_type == WPS_AUTH_WPAPSK) {
@@ -911,30 +888,75 @@ static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
 			return -1;
 		}
 	}
+	wps->cred.encr_type = wps->encr_type;
+	os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN);
+
+	if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap) {
+		u8 r[16];
+		/* Generate a random passphrase */
+		if (os_get_random(r, sizeof(r)) < 0)
+			return -1;
+		os_free(wps->new_psk);
+		wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
+		if (wps->new_psk == NULL)
+			return -1;
+		wps->new_psk_len--; /* remove newline */
+		while (wps->new_psk_len &&
+		       wps->new_psk[wps->new_psk_len - 1] == '=')
+			wps->new_psk_len--;
+		wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase",
+				      wps->new_psk, wps->new_psk_len);
+		os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
+		wps->cred.key_len = wps->new_psk_len;
+	} else if (wps->wps->network_key) {
+		os_memcpy(wps->cred.key, wps->wps->network_key,
+			  wps->wps->network_key_len);
+		wps->cred.key_len = wps->wps->network_key_len;
+	} else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
+		char hex[65];
+		/* Generate a random per-device PSK */
+		os_free(wps->new_psk);
+		wps->new_psk_len = 32;
+		wps->new_psk = os_malloc(wps->new_psk_len);
+		if (wps->new_psk == NULL)
+			return -1;
+		if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) {
+			os_free(wps->new_psk);
+			wps->new_psk = NULL;
+			return -1;
+		}
+		wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
+				wps->new_psk, wps->new_psk_len);
+		wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk,
+				 wps->new_psk_len);
+		os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2);
+		wps->cred.key_len = wps->new_psk_len * 2;
+	}
 
 	cred = wpabuf_alloc(200);
 	if (cred == NULL)
 		return -1;
 
-	if (wps_build_cred_network_idx(wps, cred) ||
-	    wps_build_cred_ssid(wps, cred) ||
-	    wps_build_cred_auth_type(wps, cred) ||
-	    wps_build_cred_encr_type(wps, cred) ||
-	    wps_build_cred_network_key(wps, cred) ||
-	    wps_build_cred_mac_addr(wps, cred)) {
+	if (wps_build_credential(cred, &wps->cred)) {
 		wpabuf_free(cred);
 		return -1;
 	}
 
-	if (ap_settings) {
-		wpabuf_put_buf(msg, cred);
-		wpabuf_free(cred);
-	} else {
-		wpabuf_put_be16(msg, ATTR_CRED);
-		wpabuf_put_be16(msg, wpabuf_len(cred));
-		wpabuf_put_buf(msg, cred);
-		wpabuf_free(cred);
-	}
+	wpabuf_put_be16(msg, ATTR_CRED);
+	wpabuf_put_be16(msg, wpabuf_len(cred));
+	wpabuf_put_buf(msg, cred);
+	wpabuf_free(cred);
+
+	return 0;
+}
+
+
+static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg)
+{
+	wpa_printf(MSG_DEBUG, "WPS:  * AP Settings");
+
+	if (wps_build_credential(msg, &wps->cred))
+		return -1;
 
 	return 0;
 }
@@ -1106,7 +1128,8 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
 	if (wps_build_version(msg) ||
 	    wps_build_msg_type(msg, WPS_M8) ||
 	    wps_build_enrollee_nonce(wps, msg) ||
-	    wps_build_cred(wps, plain) ||
+	    (wps->wps->ap && wps_build_cred(wps, plain)) ||
+	    (!wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
 	    wps_build_key_wrap_auth(wps, plain) ||
 	    wps_build_encr_settings(wps, msg, plain) ||
 	    wps_build_authenticator(wps, msg)) {
@@ -1659,13 +1682,11 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
 static int wps_process_ap_settings_r(struct wps_data *wps,
 				     struct wps_parse_attr *attr)
 {
-	struct wps_credential cred;
-
 	if (wps->wps->ap)
 		return 0;
 
 	/* AP Settings Attributes in M7 when Enrollee is an AP */
-	if (wps_process_ap_settings(attr, &cred) < 0)
+	if (wps_process_ap_settings(attr, &wps->cred) < 0)
 		return -1;
 
 	wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP");
@@ -1674,17 +1695,6 @@ static int wps_process_ap_settings_r(struct wps_data *wps,
 	 * TODO: Provide access to AP settings and allow changes before sending
 	 * out M8. For now, just copy the settings unchanged into M8.
 	 */
-	wps->auth_type = cred.auth_type;
-	wps->encr_type = cred.encr_type;
-	os_memcpy(wps->wps->ssid, cred.ssid, cred.ssid_len);
-	wps->wps->ssid_len = cred.ssid_len;
-	os_memcpy(wps->mac_addr_e, cred.mac_addr, ETH_ALEN);
-	os_free(wps->wps->network_key);
-	wps->wps->network_key = os_malloc(cred.key_len);
-	if (wps->wps->network_key) {
-		os_memcpy(wps->wps->network_key, cred.key, cred.key_len);
-		wps->wps->network_key_len = cred.key_len;
-	}
 
 	return 0;
 }