1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 
7 #include "alcs_internal.h"
8 #include "alcs_api_internal.h"
9 #include "CoAPExport.h"
10 #include "linkkit/alcs_api.h"
11 #include "alcs_mqtt.h"
12 #include "alcs_adapter.h"
13 #include "CoAPPlatform.h"
14 #include "CoAPExport.h"
15 #include "iotx_alcs.h"
16 
17 char *DEFAULT_AC = "Xtau@iot";
18 char *DEFAULT_AS = "Yx3DdsyetbSezlvc";
19 void *g_adapter_handle = NULL;
20 void *g_coap_handle = NULL;
21 
22 typedef enum {
23     ALCS_LOCALSETUP_SUCCESS,
24     ALCS_LOCALSETUP_ERROR
25 } localsetup_status;
26 
__alcs_localsetup_kv_set(const char * key,const void * val,int len,int sync)27 static localsetup_status __alcs_localsetup_kv_set(const char *key,
28                                                   const void *val, int len,
29                                                   int sync)
30 {
31     if (HAL_Kv_Set(key, val, len, sync) != 0) {
32         return ALCS_LOCALSETUP_ERROR;
33     }
34 
35     COAP_INFO("ALCS KV Set, Key: %s, Val: %s, Len: %d", key, (char *)val, len);
36     return ALCS_LOCALSETUP_SUCCESS;
37 }
38 
__alcs_localsetup_kv_get(const char * key,void * buffer,int * buffer_len)39 static localsetup_status __alcs_localsetup_kv_get(const char *key, void *buffer,
40                                                   int *buffer_len)
41 {
42     int rc = -1;
43 
44     rc = HAL_Kv_Get(key, buffer, buffer_len);
45     if (rc != 0) {
46         COAP_WRN("HAL_Kv_Get('%s') = %d (!= 0), return %d", key, rc,
47                  ALCS_LOCALSETUP_ERROR);
48         return ALCS_LOCALSETUP_ERROR;
49     }
50 
51     COAP_INFO("ALCS KV Get, Key: %s", key);
52 
53     return ALCS_LOCALSETUP_SUCCESS;
54 }
55 
__alcs_localsetup_kv_del(const char * key)56 static localsetup_status __alcs_localsetup_kv_del(const char *key)
57 {
58     if (HAL_Kv_Del(key) != 0) {
59         return ALCS_LOCALSETUP_ERROR;
60     }
61 
62     COAP_INFO("ALCS KV Del, Key: %s", key);
63 
64     return ALCS_LOCALSETUP_SUCCESS;
65 }
66 
__fill_key(const char * pk,uint16_t pk_len,const char * dn,uint16_t dn_len,char key_md5_hexstr[33])67 static localsetup_status __fill_key(const char *pk, uint16_t pk_len,
68                                     const char *dn, uint16_t dn_len,
69                                     char key_md5_hexstr[33])
70 {
71     uint8_t key_md5[16] = { 0 };
72     char key_source[IOTX_PRODUCT_KEY_LEN + 1 + IOTX_DEVICE_NAME_LEN + 1 + 3] = {
73         0
74     };
75 
76     if (pk == NULL || pk_len >= IOTX_PRODUCT_KEY_LEN + 1 || dn == NULL ||
77         dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
78         COAP_ERR("Invalid Parameter");
79         return ALCS_LOCALSETUP_ERROR;
80     }
81 
82     /* Calculate Key */
83     HAL_Snprintf(key_source, sizeof(key_source), "%.*s%.*s", pk_len, pk, dn_len,
84                  dn);
85 
86     utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
87     alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
88     return ALCS_LOCALSETUP_SUCCESS;
89 }
90 
__alcs_localsetup_ac_as_save(const char * pk,uint16_t pk_len,const char * dn,uint16_t dn_len,const char * prefix,uint16_t prefix_len,const char * secret,uint16_t secret_len)91 static localsetup_status __alcs_localsetup_ac_as_save(
92     const char *pk, uint16_t pk_len, const char *dn, uint16_t dn_len,
93     const char *prefix, uint16_t prefix_len, const char *secret,
94     uint16_t secret_len)
95 {
96     char key_md5_hexstr[33] = { 0 };
97     char *value = NULL;
98     int rt;
99     if (prefix == NULL || secret == NULL) {
100         COAP_ERR("Invalid Parameter");
101         return ALCS_LOCALSETUP_ERROR;
102     }
103 
104     rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
105     if (rt != ALCS_LOCALSETUP_SUCCESS) {
106         return rt;
107     }
108 
109     /* Calculate Value */
110     value = ALCS_ADAPTER_malloc(prefix_len + secret_len + 3);
111     if (value == NULL) {
112         COAP_ERR("No Enough Memory");
113         return ALCS_LOCALSETUP_ERROR;
114     }
115     memset(value, 0, prefix_len + secret_len + 3);
116 
117     value[0] = prefix_len;
118     value[1] = secret_len;
119     HAL_Snprintf(&value[2], prefix_len + secret_len + 1, "%.*s%.*s", prefix_len,
120                  prefix, secret_len, secret);
121 
122     if (ALCS_LOCALSETUP_SUCCESS !=
123         __alcs_localsetup_kv_set(key_md5_hexstr, value,
124                                  prefix_len + secret_len + 3, 1)) {
125         COAP_WRN("ALCS KV Set Prefix And Secret Fail");
126         ALCS_free(value);
127         return ALCS_LOCALSETUP_ERROR;
128     }
129 
130     ALCS_free(value);
131     return ALCS_LOCALSETUP_SUCCESS;
132 }
133 
alcs_localsetup_ac_as_load(const char * pk,uint16_t pk_len,const char * dn,uint16_t dn_len,char * prefix,int prefix_len,char * secret,int secret_len)134 localsetup_status alcs_localsetup_ac_as_load(const char *pk, uint16_t pk_len,
135                                              const char *dn, uint16_t dn_len,
136                                              char *prefix, int prefix_len,
137                                              char *secret, int secret_len)
138 {
139     char key_md5_hexstr[33] = { 0 };
140     char value[128] = { 0 };
141     int value_len = sizeof(value);
142 
143     int rt;
144     if (prefix == NULL || secret == NULL) {
145         COAP_ERR("Invalid Parameter");
146         return ALCS_LOCALSETUP_ERROR;
147     }
148 
149     rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
150     if (rt != ALCS_LOCALSETUP_SUCCESS) {
151         return rt;
152     }
153 
154     /* Get Value */
155     if (ALCS_LOCALSETUP_SUCCESS !=
156         __alcs_localsetup_kv_get(key_md5_hexstr, value, &value_len)) {
157         COAP_WRN("ALCS KV Get local Prefix And Secret Fail");
158         return ALCS_LOCALSETUP_ERROR;
159     }
160 
161     if (value[0] >= prefix_len || value[1] >= secret_len) {
162         COAP_ERR("insuffient buffer!");
163         return ALCS_LOCALSETUP_ERROR;
164     }
165 
166     memset(prefix, 0, prefix_len);
167     memcpy(prefix, &value[2], value[0]);
168     memset(secret, 0, secret_len);
169     memcpy(secret, &value[2 + value[0]], value[1]);
170     return ALCS_LOCALSETUP_SUCCESS;
171 }
172 
__alcs_localsetup_ac_as_del(const char * pk,uint16_t pk_len,const char * dn,uint16_t dn_len)173 static localsetup_status __alcs_localsetup_ac_as_del(const char *pk,
174                                                      uint16_t pk_len,
175                                                      const char *dn,
176                                                      uint16_t dn_len)
177 {
178     char key_md5_hexstr[33] = { 0 };
179     int rt;
180     rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
181     if (rt != ALCS_LOCALSETUP_SUCCESS) {
182         return rt;
183     }
184 
185     if (ALCS_LOCALSETUP_SUCCESS != __alcs_localsetup_kv_del(key_md5_hexstr)) {
186         COAP_ERR("ALCS KV Get local Prefix And Secret Fail");
187         return ALCS_LOCALSETUP_ERROR;
188     }
189 
190     return ALCS_LOCALSETUP_SUCCESS;
191 }
192 
alcs_service_cb_setup(CoAPContext * context,const char * paths,NetworkAddr * remote,CoAPMessage * message)193 static void alcs_service_cb_setup(CoAPContext *context, const char *paths,
194                                   NetworkAddr *remote, CoAPMessage *message)
195 {
196     char payload[128];
197     char *id = NULL, *p;
198     int idlen = 0, len, aclen, aslen, pklen, dnlen;
199     char *ac = NULL, *as = NULL, *pk = NULL, *dn = dn;
200     bool success = 0;
201     char *err_msg = NULL;
202     char configValueBack, acBack, asBack;
203     char *str_pos, *entry;
204     int entry_len, type;
205     iotx_alcs_msg_t rsp_msg;
206 
207     COAP_DEBUG("alcs_service_cb_setup, path:%s", paths);
208     do {
209         if (!remote || !message) {
210             COAP_DEBUG("alcs_service_cb_setup, param is NULL!");
211             err_msg = "invalid package";
212             break;
213         }
214 
215         id = json_get_value_by_name((char *)message->payload,
216                                     message->payloadlen, "id", &idlen,
217                                     (int *)NULL);
218         p = json_get_value_by_name((char *)message->payload,
219                                    message->payloadlen, "params", &len,
220                                    (int *)NULL);
221         if (!p || !len) {
222             err_msg = "params is not found";
223             break;
224         }
225 
226         p = json_get_value_by_name(p, len, "configValue", &len, (int *)NULL);
227         if (!p || !len) {
228             err_msg = "configValue is not found";
229             break;
230         }
231 
232         backup_json_str_last_char(p, len, configValueBack);
233 
234         json_array_for_each_entry(p, len, str_pos, entry, entry_len, type)
235         {
236             COAP_DEBUG("entry:%.*s", entry_len, entry);
237             ac = json_get_value_by_name(entry, entry_len, "authCode", &aclen,
238                                         (int *)NULL);
239             as = json_get_value_by_name(entry, entry_len, "authSecret", &aslen,
240                                         (int *)NULL);
241             pk = json_get_value_by_name(entry, entry_len, "productKey", &pklen,
242                                         (int *)NULL);
243             dn = json_get_value_by_name(entry, entry_len, "deviceName", &dnlen,
244                                         (int *)NULL);
245             break;
246         } /* end json_array_for_each_entry */
247         restore_json_str_last_char(p, len, configValueBack);
248 
249         if (!ac || !aclen || !as || !aslen || !pk || !pklen || !dn || !dnlen) {
250             err_msg = "authinfo is not found";
251             break;
252         }
253 
254         /* save */
255         backup_json_str_last_char(ac, aclen, acBack);
256         backup_json_str_last_char(as, aslen, asBack);
257         __alcs_localsetup_ac_as_del(pk, pklen, dn, dnlen);
258         __alcs_localsetup_ac_as_save(pk, pklen, dn, dnlen, ac, aclen, as,
259                                      aslen);
260 
261         alcs_add_svr_key(g_coap_handle, ac, as, LOCALSETUP);
262 
263         restore_json_str_last_char(ac, aclen, acBack);
264         restore_json_str_last_char(as, aslen, asBack) success = 1;
265 
266     } while (0);
267 
268     if (success) {
269         HAL_Snprintf(payload, sizeof(payload), "{\"id\":\"%.*s\",\"code\":200}",
270                      idlen, id ? id : "");
271     } else {
272         HAL_Snprintf(payload, sizeof(payload),
273                      "{\"id\":\"%.*s\",\"code\":400,\"msg\":\"%s\"}", idlen,
274                      id ? id : "", err_msg);
275         COAP_ERR("alcs_service_cb_setup, %s", err_msg);
276     }
277 
278     memset(&rsp_msg, 0, sizeof(iotx_alcs_msg_t));
279 
280     rsp_msg.msg_code = ITOX_ALCS_COAP_MSG_CODE_205_CONTENT;
281     rsp_msg.msg_type = IOTX_ALCS_MESSAGE_TYPE_CON;
282     rsp_msg.payload = (unsigned char *)payload;
283     rsp_msg.payload_len = strlen(payload);
284     rsp_msg.ip = (char *)(remote ? remote->addr : NULL);
285     rsp_msg.port = remote ? remote->port : 5683;
286     rsp_msg.uri = (char *)paths;
287 
288     if (message) {
289         iotx_alcs_send_Response(g_adapter_handle, &rsp_msg,
290                                 message->header.tokenlen, message->token);
291     }
292 }
293 
alcs_localsetup_register_resource(void * adapter_handle,char * pk,char * dn)294 static void alcs_localsetup_register_resource(void *adapter_handle, char *pk,
295                                               char *dn)
296 {
297     iotx_alcs_res_t alcs_res;
298     char uri[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 24];
299 
300     if (adapter_handle == NULL || pk == NULL ||
301         strlen(pk) > IOTX_PRODUCT_KEY_LEN || dn == NULL ||
302         strlen(dn) > IOTX_DEVICE_NAME_LEN) {
303         return;
304     }
305 
306     HAL_Snprintf(uri, sizeof(uri), "/dev/%s/%s/core/service/setup", pk, dn);
307 
308     memset(&alcs_res, 0, sizeof(iotx_alcs_res_t));
309     alcs_res.uri = uri;
310     alcs_res.msg_ct = IOTX_ALCS_MESSAGE_CT_APP_JSON;
311     alcs_res.msg_perm = IOTX_ALCS_MESSAGE_PERM_GET | IOTX_ALCS_MESSAGE_PERM_PUT;
312     alcs_res.maxage = 60;
313     alcs_res.need_auth = 1;
314     alcs_res.callback = alcs_service_cb_setup;
315 
316     iotx_alcs_register_resource(adapter_handle, &alcs_res);
317 }
318 
alcs_localsetup_init(void * adapter_handle,void * coap_handler,char * pk,char * dn)319 void alcs_localsetup_init(void *adapter_handle, void *coap_handler, char *pk,
320                           char *dn)
321 {
322     char prefix[10];
323     char secret[64];
324     g_adapter_handle = adapter_handle;
325     g_coap_handle = coap_handler;
326     alcs_localsetup_register_resource(adapter_handle, pk, dn);
327 
328     if (alcs_localsetup_ac_as_load(pk, strlen(pk), dn, strlen(dn), prefix,
329                                    sizeof(prefix), secret,
330                                    sizeof(secret)) != ALCS_LOCALSETUP_SUCCESS) {
331         alcs_add_svr_key(g_coap_handle, DEFAULT_AC, DEFAULT_AS, LOCALDEFAULT);
332     } else {
333         alcs_add_svr_key(g_coap_handle, prefix, secret, LOCALSETUP);
334     }
335 }
336 
alcs_localsetup_add_sub_device(void * adapter_handle,char * pk,char * dn)337 void alcs_localsetup_add_sub_device(void *adapter_handle, char *pk, char *dn)
338 {
339     alcs_localsetup_register_resource(adapter_handle, pk, dn);
340 }
341