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