1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "wifi_provision_internal.h"
5
6 #if defined(AWSS_SUPPORT_AHA)
7 #define WIFI_APINFO_LIST_LEN (512)
8 #define DEV_SIMPLE_ACK_LEN (64)
9
10 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
11 extern "C" {
12 #endif
13
wifimgr_process_mcast_get_device_info(void * ctx,void * resource,void * remote,void * request)14 int wifimgr_process_mcast_get_device_info(void *ctx, void *resource,
15 void *remote, void *request)
16 {
17 return process_get_device_info(ctx, resource, remote, request, 1,
18 AWSS_NOTIFY_DEV_RAND_SIGN);
19 }
20
wifimgr_process_ucast_get_device_info(void * ctx,void * resource,void * remote,void * request)21 int wifimgr_process_ucast_get_device_info(void *ctx, void *resource,
22 void *remote, void *request)
23 {
24 return process_get_device_info(ctx, resource, remote, request, 0,
25 AWSS_NOTIFY_DEV_RAND_SIGN);
26 }
27 #define WLAN_CONNECTION_TIMEOUT (30 * 1000) /* 30 seconds */
28 int switch_ap_done = 0;
29
30 void zconfig_force_destroy(void);
wifimgr_process_switch_ap_request(void * ctx,void * resource,void * remote,void * request)31 int wifimgr_process_switch_ap_request(void *ctx, void *resource, void *remote,
32 void *request)
33 {
34 char ssid[PLATFORM_MAX_SSID_LEN * 2 + 1] = { 0 },
35 passwd[PLATFORM_MAX_PASSWD_LEN +
36 1] = { 0 };
37 int str_len = 0, success = 1, i = 0, len = 0, enc_lvl = SEC_LVL_OPEN;
38 char req_msg_id[MSG_REQ_ID_LEN] = { 0 };
39 char *str = NULL, *buf = NULL;
40 char bssid[ETH_ALEN] = { 0 };
41 char msg[128] = { 0 };
42 char ssid_found = 0;
43 char token_found = 0;
44 char topic[TOPIC_LEN_MAX] = { 0 };
45 uint8_t token[RANDOM_MAX_LEN + 1] = { 0 };
46 static char switch_ap_parsed = 0;
47 if (switch_ap_parsed != 0)
48 return SHUB_ERR;
49
50 switch_ap_parsed = 1;
51
52 buf = awss_cmp_get_coap_payload(request, &len);
53 str = json_get_value_by_name(buf, len, "id", &str_len, 0);
54 memcpy(req_msg_id, str,
55 str_len > MSG_REQ_ID_LEN - 1 ? MSG_REQ_ID_LEN - 1 : str_len);
56 awss_debug("switch ap, len:%u, %s\r\n", len, buf);
57 buf = json_get_value_by_name(buf, len, "params", &len, 0);
58
59 do {
60 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, 200,
61 "\"success\"");
62
63 str_len = 0;
64 str = json_get_value_by_name(buf, len, "ssid", &str_len, 0);
65 awss_debug("ssid, len:%u, %s\r\n", str_len, str != NULL ? str : "NULL");
66 if (str && (str_len < PLATFORM_MAX_SSID_LEN)) {
67 memcpy(ssid, str, str_len);
68 ssid_found = 1;
69 }
70
71 if (!ssid_found) {
72 str_len = 0;
73 str = json_get_value_by_name(buf, len, "xssid", &str_len, 0);
74 if (str && (str_len < PLATFORM_MAX_SSID_LEN * 2 - 1)) {
75 uint8_t decoded[OS_MAX_SSID_LEN] = { 0 };
76 int len = str_len / 2;
77 memcpy(ssid, str, str_len);
78 utils_str_to_hex(ssid, str_len, decoded, OS_MAX_SSID_LEN);
79 memcpy(ssid, (const char *)decoded, len);
80 ssid[len] = '\0';
81 } else {
82 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -1,
83 "\"ssid error\"");
84 success = 0;
85 break;
86 }
87 }
88
89 str_len = 0;
90 str = json_get_value_by_name(buf, len, "bssid", &str_len, 0);
91 if (str)
92 os_wifi_str2mac(str, bssid);
93
94 str_len = 0;
95 str = json_get_value_by_name(buf, len, "cipherType", &str_len, 0);
96 if (!str) {
97 success = 0;
98 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4,
99 "\"no security level error\"");
100 break;
101 }
102
103 enc_lvl = atoi(str);
104 if (enc_lvl != awss_get_encrypt_type()) {
105 success = 0;
106 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4,
107 "\"security level error\"");
108 break;
109 }
110
111 str_len = 0;
112 str = json_get_value_by_name(buf, len, "token", &str_len, 0);
113 if (str &&
114 str_len == RANDOM_MAX_LEN * 2) { /*token len equal to random len*/
115 utils_str_to_hex(str, str_len, (unsigned char *)token,
116 RANDOM_MAX_LEN);
117 token_found = 1;
118 }
119
120 str_len = 0;
121 str = json_get_value_by_name(buf, len, "passwd", &str_len, 0);
122 /* TODO: empty passwd is allow? json parse "passwd":"" result is NULL?
123 */
124 switch (enc_lvl) {
125 case SEC_LVL_AES256:
126 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4,
127 "\"aes256 not support\"");
128 success = 0;
129 break;
130 default:
131 break;
132 }
133
134 if (success == 0)
135 break;
136
137 if (0 == enc_lvl) {
138 if (str_len < PLATFORM_MAX_PASSWD_LEN) {
139 memcpy(passwd, str, str_len);
140 } else {
141 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -2,
142 "\"passwd len error\"");
143 success = 0;
144 }
145 } else {
146 if (str_len < (PLATFORM_MAX_PASSWD_LEN * 2) - 1) {
147 char encoded[PLATFORM_MAX_PASSWD_LEN * 2 + 1] = { 0 };
148 memcpy(encoded, str, str_len);
149 aes_decrypt_string(encoded, passwd, str_len, 0,
150 awss_get_encrypt_type(), 1,
151 (const char *)aes_random);
152 } else {
153 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -3,
154 "\"passwd len error\"");
155 AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX,
156 AWSS_STATIS_TYPE_PASSWD_ERR);
157 success = 0;
158 }
159 }
160
161 if (success && is_utf8(passwd, strlen(passwd)) == 0) {
162 HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id,
163 enc_lvl == SEC_LVL_OPEN ? -2 : -3,
164 "\"passwd content error\"");
165 AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX,
166 AWSS_STATIS_TYPE_PASSWD_ERR);
167 success = 0;
168 }
169 } while (0);
170
171 awss_devinfo_notify_stop();
172 #ifndef DEV_BIND_DISABLE_NOTIFY
173 awss_dev_bind_notify_stop();
174 #endif
175 awss_debug("Sending message to app: %s", msg);
176 awss_debug("switch to ap: '%s'", ssid);
177 awss_build_topic((const char *)TOPIC_AWSS_SWITCHAP, topic, TOPIC_LEN_MAX);
178 for (i = 0; i < 5; i++) {
179 if (0 != awss_cmp_coap_send_resp(msg, strlen(msg), remote, topic,
180 request, NULL, NULL, 0)) {
181 awss_debug("sending failed.");
182 } else {
183 awss_debug("sending succeeded.");
184 }
185 }
186
187 HAL_SleepMs(1000);
188
189 if (!success)
190 goto SWITCH_AP_END;
191 #ifdef AWSS_SUPPORT_APLIST
192 do {
193 struct ap_info *aplist = NULL;
194 aplist = zconfig_get_apinfo_by_ssid((uint8_t *)ssid);
195 awss_debug("connect '%s'", ssid);
196 if (aplist) {
197 memcpy(bssid, aplist->mac, ETH_ALEN);
198 awss_debug("bssid: %02x:%02x:%02x:%02x:%02x:%02x", bssid[0],
199 bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
200 }
201 } while (0);
202 #endif
203 AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX,
204 AWSS_STATIS_TYPE_TIME_START);
205
206 if (0 != awss_connect(ssid, passwd, (uint8_t *)bssid, ETH_ALEN,
207 token_found == 1 ? token : NULL,
208 token_found == 1 ? RANDOM_MAX_LEN : 0)) {
209 } else {
210 AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX,
211 AWSS_STATIS_TYPE_TIME_SUC);
212 AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_TIME_SUC);
213 switch_ap_done = 1;
214
215 zconfig_force_destroy();
216 if (token_found == 0) {
217 produce_random(aes_random, sizeof(aes_random));
218 }
219 }
220 awss_debug("connect '%s' %s\r\n", ssid,
221 switch_ap_done == 1 ? "success" : "fail");
222
223 SWITCH_AP_END:
224 switch_ap_parsed = 0;
225 return SHUB_OK;
226 }
227
228 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
229 }
230 #endif
231 #endif
232