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