1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5
6 #include "alcs_internal.h"
7 #include "alcs_api_internal.h"
8 #include "CoAPPlatform.h"
9 #include "CoAPResource.h"
10 #include "alcs_internal.h"
11 #ifdef LOG_REPORT_TO_CLOUD
12 #include "iotx_log_report.h"
13 #endif
14 #define RES_FORMAT "{\"id\":\"%.*s\",\"code\":%d,\"data\":{%s}}"
15
16 #ifdef ALCS_SERVER_ENABLED
17
18 int sessionid_seed = 0xff;
19 static int default_heart_expire = 120000;
20
utils_hmac_sha1_base64(const char * msg,int msg_len,const char * key,int key_len,char * digest,int * digest_len)21 void utils_hmac_sha1_base64(const char *msg, int msg_len, const char *key,
22 int key_len, char *digest, int *digest_len)
23 {
24 char buf[20];
25 uint32_t outlen;
26 utils_hmac_sha1_hex(msg, msg_len, buf, key, key_len);
27
28 utils_base64encode((unsigned char *)buf, 20, *digest_len,
29 (unsigned char *)digest, &outlen);
30 *digest_len = outlen;
31 }
32
alcs_rec_auth_select(CoAPContext * ctx,const char * paths,NetworkAddr * from,CoAPMessage * resMsg)33 void alcs_rec_auth_select(CoAPContext *ctx, const char *paths,
34 NetworkAddr *from, CoAPMessage *resMsg)
35 {
36 int seqlen, datalen;
37 char *seq, *data;
38 char *targetKey = "";
39 int targetLen = 0;
40 auth_list *lst = NULL;
41 char *accesskeys;
42 int keylen;
43 char back;
44 char *str_pos, *entry;
45 int entry_len, type;
46 CoAPMessage msg;
47 char keybuf[32];
48 char payloadbuf[512];
49 CoAPLenString token = { resMsg->header.tokenlen, resMsg->token };
50 CoAPLenString payload;
51
52 /* int res_code = 200; */
53 COAP_DEBUG("receive data:%.*s", resMsg->payloadlen, resMsg->payload);
54
55 do {
56 if (!req_payload_parser((const char *)resMsg->payload,
57 resMsg->payloadlen, &seq, &seqlen, &data,
58 &datalen)) {
59 break;
60 }
61 lst = get_list(ctx);
62
63 accesskeys =
64 json_get_value_by_name(data, datalen, "accessKeys", &keylen, NULL);
65 if (!accesskeys || !keylen) {
66 break;
67 }
68 COAP_DEBUG("accessKeys:%.*s", keylen, accesskeys);
69
70 backup_json_str_last_char(accesskeys, keylen, back);
71 json_array_for_each_entry(accesskeys, keylen, str_pos, entry, entry_len,
72 type)
73 {
74 svr_key_item *node = NULL, *next = NULL;
75 svr_group_item *gnode = NULL, *gnext = NULL;
76 COAP_DEBUG("entry:%.*s", entry_len, entry);
77 list_for_each_entry_safe(node, next, &lst->lst_svr, lst,
78 svr_key_item)
79 {
80 COAP_DEBUG("keyprefix:%s", node->keyInfo.keyprefix);
81 if (strstr(entry, node->keyInfo.keyprefix) == entry) {
82 COAP_DEBUG("target keyprefix:%s", entry);
83 targetKey = entry;
84 targetLen = entry_len;
85 break;
86 }
87 }
88 if (targetKey) {
89 break;
90 }
91
92 list_for_each_entry_safe(gnode, gnext, &lst->lst_svr_group, lst,
93 svr_group_item)
94 {
95 COAP_DEBUG("keyprefix:%s", gnode->keyInfo.keyprefix);
96 if (strstr(entry, gnode->keyInfo.keyprefix) == entry) {
97 COAP_DEBUG("target keyprefix:%s", entry);
98 targetKey = entry;
99 targetLen = entry_len;
100 break;
101 }
102 }
103 if (targetKey) {
104 break;
105 }
106 }
107 restore_json_str_last_char(accesskeys, keylen, back);
108
109 } while (0);
110
111 COAP_DEBUG("key:%s", targetKey);
112
113 HAL_Snprintf(keybuf, sizeof(keybuf), "\"accessKey\":\"%.*s\"", targetLen,
114 targetKey);
115
116 HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq,
117 targetKey ? 200 : COAP_MSG_CODE_401_UNAUTHORIZED, keybuf);
118 payload.data = (unsigned char *)payloadbuf;
119 payload.len = strlen(payloadbuf);
120
121 alcs_msg_init(ctx, &msg, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_ACK,
122 0, &payload, NULL);
123 alcs_sendrsp(ctx, from, &msg, 1, resMsg->header.msgid, &token);
124 }
125
is_legal_key(CoAPContext * ctx,const char * keyprefix,int prefixlen,const char * keyseq,int seqlen,int * res_code)126 svr_key_info *is_legal_key(CoAPContext *ctx, const char *keyprefix,
127 int prefixlen, const char *keyseq, int seqlen,
128 int *res_code)
129 {
130 auth_list *lst = get_list(ctx);
131 COAP_INFO("islegal prefix:%.*s, seq:%.*s", prefixlen, keyprefix, seqlen,
132 keyseq);
133
134 if (lst) {
135 COAP_DEBUG("find devices");
136 HAL_MutexLock(lst->list_mutex);
137
138 if (lst->revocation) {
139 int len = strlen(lst->revocation);
140 int i;
141 for (i = 0; i < len; i += KEYSEQ_LEN) {
142 if (strncmp(keyseq, lst->revocation + i, seqlen) == 0) {
143 HAL_MutexUnlock(lst->list_mutex);
144 *res_code = ALCS_AUTH_REVOCATE;
145 COAP_INFO("accesskey is revocated");
146 return NULL;
147 }
148 }
149 }
150
151 if (list_empty(&lst->lst_svr)) {
152 COAP_INFO("ALCS_AUTH_AUTHLISTEMPTY:%d\r\n",
153 ALCS_AUTH_AUTHLISTEMPTY);
154 *res_code = ALCS_AUTH_AUTHLISTEMPTY;
155 } else {
156 svr_key_item *node = NULL, *next = NULL;
157 svr_group_item *gnode = NULL, *gnext = NULL;
158 list_for_each_entry_safe(node, next, &lst->lst_svr, lst,
159 svr_key_item)
160 {
161 COAP_DEBUG("node prefix:%s", node->keyInfo.keyprefix);
162 if (strlen(node->keyInfo.keyprefix) == prefixlen &&
163 strncmp(keyprefix, node->keyInfo.keyprefix, prefixlen) ==
164 0) {
165 *res_code = ALCS_AUTH_OK;
166 HAL_MutexUnlock(lst->list_mutex);
167 return &node->keyInfo;
168 }
169 }
170 list_for_each_entry_safe(gnode, gnext, &lst->lst_svr_group, lst,
171 svr_group_item)
172 {
173 COAP_DEBUG("node prefix:%s", gnode->keyInfo.keyprefix);
174 if (strlen(gnode->keyInfo.keyprefix) == prefixlen &&
175 strncmp(keyprefix, gnode->keyInfo.keyprefix, prefixlen) ==
176 0) {
177 *res_code = ALCS_AUTH_OK;
178 HAL_MutexUnlock(lst->list_mutex);
179 return &gnode->keyInfo;
180 }
181 }
182
183 COAP_INFO("ALCS_AUTH_UNMATCHPREFIX:%d\r\n",
184 ALCS_AUTH_UNMATCHPREFIX);
185 *res_code = ALCS_AUTH_UNMATCHPREFIX;
186 }
187
188 HAL_MutexUnlock(lst->list_mutex);
189 }
190
191 return NULL;
192 }
193
alcs_rec_auth(CoAPContext * ctx,const char * paths,NetworkAddr * from,CoAPMessage * resMsg)194 void alcs_rec_auth(CoAPContext *ctx, const char *paths, NetworkAddr *from,
195 CoAPMessage *resMsg)
196 {
197 int seqlen, datalen;
198 char *seq, *data;
199 int res_code = 200;
200 char body[200] = { 0 };
201 char *accesskey, *randomkey, *sign;
202 int tmplen;
203 char *keyprefix;
204 char *keyseq;
205 char accessToken[64];
206 int tokenlen;
207 int randomkeylen;
208 char buf[40];
209 int calc_sign_len;
210 int pklen, dnlen;
211 char *pk;
212 char *dn;
213 char tmp1;
214 char tmp2;
215 svr_key_info *item;
216 AlcsDeviceKey devKey;
217 session_item *session;
218 CoAPMessage message;
219 char payloadbuf[512];
220 CoAPLenString payload;
221 CoAPLenString token;
222 COAP_INFO("receive data:%.*s, from:%s", resMsg->payloadlen, resMsg->payload,
223 from->addr);
224
225 do {
226 if (!req_payload_parser((const char *)resMsg->payload,
227 resMsg->payloadlen, &seq, &seqlen, &data,
228 &datalen)) {
229 break;
230 }
231
232 accesskey =
233 json_get_value_by_name(data, datalen, "accessKey", &tmplen, NULL);
234 COAP_INFO("accesskey:%.*s", tmplen, accesskey);
235
236 if (!accesskey || tmplen != KEYPREFIX_LEN + 1 + 1 + KEYSEQ_LEN) {
237 break;
238 }
239
240 keyprefix = accesskey;
241 keyseq = accesskey + KEYPREFIX_LEN + 1 + 1;
242
243 item = is_legal_key(ctx, keyprefix, KEYPREFIX_LEN, keyseq, KEYSEQ_LEN,
244 &res_code);
245 if (!item) {
246 COAP_INFO("islegal return null");
247 break;
248 }
249
250 tokenlen = sizeof(accessToken);
251 utils_hmac_sha1_base64(accesskey, tmplen, item->secret,
252 strlen(item->secret), accessToken, &tokenlen);
253
254 COAP_INFO("accessToken:%.*s", tokenlen, accessToken);
255 randomkey = json_get_value_by_name(data, datalen, "randomKey",
256 &randomkeylen, NULL);
257 if (!randomkey || !randomkeylen) {
258 res_code = ALCS_AUTH_INVALIDPARAM;
259 break;
260 }
261
262 /*calc sign, save in buf*/
263
264 calc_sign_len = sizeof(buf);
265 utils_hmac_sha1_base64(randomkey, randomkeylen, accessToken, tokenlen,
266 buf, &calc_sign_len);
267
268 COAP_INFO("calc randomKey:%.*s,token:%.*s,sign:%.*s", randomkeylen,
269 randomkey, tokenlen, accessToken, calc_sign_len, buf);
270
271 sign = json_get_value_by_name(data, datalen, "sign", &tmplen, NULL);
272 if (!sign || tmplen != calc_sign_len ||
273 strncmp(sign, buf, calc_sign_len)) {
274 res_code = ALCS_AUTH_ILLEGALSIGN;
275 break;
276 }
277
278 pk = json_get_value_by_name(data, datalen, "prodKey", &pklen, NULL);
279 dn = json_get_value_by_name(data, datalen, "deviceName", &dnlen, NULL);
280
281 if (!pk || !pklen || !dn || !dnlen) {
282 res_code = ALCS_AUTH_INVALIDPARAM;
283 break;
284 }
285 tmp1 = pk[pklen];
286 tmp2 = dn[dnlen];
287 pk[pklen] = 0;
288 dn[dnlen] = 0;
289
290 memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
291 memcpy(&devKey.addr, from, sizeof(NetworkAddr));
292 devKey.pk = pk;
293 devKey.dn = dn;
294 session = get_svr_session(ctx, &devKey);
295
296 if (!session) {
297 char path[100] = { 0 };
298 struct list_head *svr_head;
299 session = (session_item *)coap_malloc(sizeof(session_item));
300 gen_random_key((unsigned char *)session->randomKey, RANDOMKEY_LEN);
301 session->sessionId = ++sessionid_seed;
302
303 strncpy(path, pk, sizeof(path));
304 strncat(path, dn, sizeof(path) - strlen(path) - 1);
305 CoAPPathMD5_sum(path, strlen(path), session->pk_dn,
306 PK_DN_CHECKSUM_LEN);
307
308 memcpy(&session->addr, from, sizeof(NetworkAddr));
309 COAP_INFO("new session, addr:%s, port:%d", session->addr.addr,
310 session->addr.port);
311 svr_head = get_svr_session_list(ctx);
312 list_add_tail(&session->lst, svr_head);
313 }
314
315 pk[pklen] = tmp1;
316 dn[dnlen] = tmp2;
317
318 HAL_Snprintf(buf, sizeof(buf), "%.*s%s", randomkeylen, randomkey,
319 session->randomKey);
320 utils_hmac_sha1_hex(buf, strlen(buf), session->sessionKey, accessToken,
321 tokenlen);
322
323 /*calc sign, save in buf*/
324 calc_sign_len = sizeof(buf);
325 utils_hmac_sha1_base64(session->randomKey, RANDOMKEY_LEN, accessToken,
326 tokenlen, buf, &calc_sign_len);
327 HAL_Snprintf(body, sizeof(body),
328 "\"sign\":\"%.*s\",\"randomKey\":\"%s\",\"sessionId\":%d,"
329 "\"expire\":86400",
330 calc_sign_len, buf, session->randomKey,
331 session->sessionId);
332
333 session->authed_time = HAL_UptimeMs();
334 session->heart_time = session->authed_time;
335 /* ??? */
336 /* result = 1; */
337
338 } while (0);
339
340 HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq,
341 res_code, body);
342 payload.len = strlen(payloadbuf);
343 payload.data = (unsigned char *)payloadbuf;
344 alcs_msg_init(ctx, &message, COAP_MSG_CODE_205_CONTENT,
345 COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
346 token.len = resMsg->header.tokenlen;
347 token.data = resMsg->token;
348 alcs_sendrsp(ctx, from, &message, 1, resMsg->header.msgid, &token);
349 }
350
alcs_remove_low_priority_key(CoAPContext * ctx,ServerKeyPriority priority)351 static int alcs_remove_low_priority_key(CoAPContext *ctx,
352 ServerKeyPriority priority)
353 {
354 auth_list *lst = get_list(ctx);
355 svr_key_item *node = NULL, *next = NULL;
356
357 HAL_MutexLock(lst->list_mutex);
358
359 list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item)
360 {
361 if (node->keyInfo.priority < priority) {
362 coap_free(node->keyInfo.secret);
363 list_del(&node->lst);
364 coap_free(node);
365 --lst->svr_count;
366 }
367 }
368 HAL_MutexUnlock(lst->list_mutex);
369
370 return COAP_SUCCESS;
371 }
372
add_svr_key(CoAPContext * ctx,const char * keyprefix,const char * secret,bool isGroup,ServerKeyPriority priority)373 static int add_svr_key(CoAPContext *ctx, const char *keyprefix,
374 const char *secret, bool isGroup,
375 ServerKeyPriority priority)
376 {
377 auth_list *lst = get_list(ctx);
378 svr_key_item *node = NULL, *next = NULL;
379 svr_key_item *item;
380 COAP_INFO("add_svr_key\n");
381 if (!lst || lst->svr_count >= KEY_MAXCOUNT ||
382 strlen(keyprefix) != KEYPREFIX_LEN) {
383 return COAP_ERROR_INVALID_LENGTH;
384 }
385 alcs_remove_low_priority_key(ctx, priority);
386
387 HAL_MutexLock(lst->list_mutex);
388 list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item)
389 {
390 if (node->keyInfo.priority > priority) {
391 /* find high priority key */
392 HAL_MutexUnlock(lst->list_mutex);
393 return COAP_ERROR_UNSUPPORTED;
394 }
395 }
396
397 item = (svr_key_item *)coap_malloc(sizeof(svr_key_item));
398
399 if (!item) {
400 HAL_MutexUnlock(lst->list_mutex);
401 return COAP_ERROR_MALLOC;
402 }
403 memset(item, 0, sizeof(svr_key_item));
404 item->keyInfo.secret = (char *)coap_malloc(strlen(secret) + 1);
405 if (!item->keyInfo.secret) {
406 HAL_MutexUnlock(lst->list_mutex);
407 coap_free(item);
408 return COAP_ERROR_MALLOC;
409 }
410 memset(item->keyInfo.secret, 0, strlen(secret) + 1);
411 strcpy(item->keyInfo.secret, secret);
412
413 memcpy(item->keyInfo.keyprefix, keyprefix, KEYPREFIX_LEN);
414 item->keyInfo.priority = priority;
415
416 list_add_tail(&item->lst, &lst->lst_svr);
417 ++lst->svr_count;
418 HAL_MutexUnlock(lst->list_mutex);
419
420 return COAP_SUCCESS;
421 }
422
alcs_add_svr_key(CoAPContext * ctx,const char * keyprefix,const char * secret,ServerKeyPriority priority)423 int alcs_add_svr_key(CoAPContext *ctx, const char *keyprefix,
424 const char *secret, ServerKeyPriority priority)
425 {
426 COAP_INFO("alcs_add_svr_key, priority=%d", priority);
427 return add_svr_key(ctx, keyprefix, secret, 0, priority);
428 }
429
alcs_remove_svr_key(CoAPContext * ctx,const char * keyprefix)430 int alcs_remove_svr_key(CoAPContext *ctx, const char *keyprefix)
431 {
432 auth_list *lst = get_list(ctx);
433 svr_key_item *node = NULL, *next = NULL;
434
435 HAL_MutexLock(lst->list_mutex);
436
437 list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item)
438 {
439 if (strcmp(node->keyInfo.keyprefix, keyprefix) == 0) {
440 coap_free(node->keyInfo.secret);
441 list_del(&node->lst);
442 coap_free(node);
443 --lst->svr_count;
444 break;
445 }
446 }
447 HAL_MutexUnlock(lst->list_mutex);
448
449 return COAP_SUCCESS;
450 }
451
alcs_set_revocation(CoAPContext * ctx,const char * seqlist)452 int alcs_set_revocation(CoAPContext *ctx, const char *seqlist)
453 {
454 auth_list *lst = get_list(ctx);
455 int len;
456
457 HAL_MutexLock(lst->list_mutex);
458
459 len = seqlist ? strlen(seqlist) : 0;
460 if (lst->revocation) {
461 coap_free(lst->revocation);
462 lst->revocation = NULL;
463 }
464
465 if (len > 0) {
466 lst->revocation = (char *)coap_malloc(len + 1);
467 strcpy(lst->revocation, seqlist);
468 }
469 HAL_MutexUnlock(lst->list_mutex);
470
471 return COAP_SUCCESS;
472 }
473
474 /* ----------------------------------------- */
475
send_err_rsp(CoAPContext * ctx,NetworkAddr * addr,int code,CoAPMessage * request)476 void send_err_rsp(CoAPContext *ctx, NetworkAddr *addr, int code,
477 CoAPMessage *request)
478 {
479 CoAPMessage sendMsg;
480 CoAPLenString payload = { 0 };
481 CoAPLenString token;
482 alcs_msg_init(ctx, &sendMsg, code, COAP_MESSAGE_TYPE_ACK, 0, &payload,
483 NULL);
484 token.len = request->header.tokenlen;
485 token.data = request->token;
486 alcs_sendrsp(ctx, addr, &sendMsg, 1, request->header.msgid, &token);
487 }
488
call_cb(CoAPContext * context,const char * path,NetworkAddr * remote,CoAPMessage * message,const char * key,char * buf,CoAPRecvMsgHandler cb)489 void call_cb(CoAPContext *context, const char *path, NetworkAddr *remote,
490 CoAPMessage *message, const char *key, char *buf,
491 CoAPRecvMsgHandler cb)
492 {
493 CoAPMessage tmpMsg;
494 memcpy(&tmpMsg, message, sizeof(CoAPMessage));
495
496 if (key && buf) {
497 int len = alcs_decrypt((const char *)message->payload,
498 message->payloadlen, key, buf);
499 tmpMsg.payload = (unsigned char *)buf;
500 tmpMsg.payloadlen = len;
501 #ifdef LOG_REPORT_TO_CLOUD
502 get_msgid(buf, 0);
503 #endif
504 } else {
505 tmpMsg.payload = NULL;
506 tmpMsg.payloadlen = 0;
507 }
508
509 cb(context, path, remote, &tmpMsg);
510 }
511
get_resource_by_path(const char * path)512 static secure_resource_cb_item *get_resource_by_path(const char *path)
513 {
514 secure_resource_cb_item *node, *next;
515 char path_calc[MAX_PATH_CHECKSUM_LEN] = { 0 };
516 CoAPPathMD5_sum(path, strlen(path), path_calc, MAX_PATH_CHECKSUM_LEN);
517
518 list_for_each_entry_safe(node, next, &secure_resource_cb_head, lst,
519 secure_resource_cb_item)
520 {
521 if (node->path_type == PATH_NORMAL) {
522 if (memcmp(node->path, path_calc, MAX_PATH_CHECKSUM_LEN) == 0) {
523 return node;
524 }
525 } else if (strlen(node->filter_path) > 0) {
526 if (CoAPResource_topicFilterMatch(node->filter_path, path) == 0) {
527 return node;
528 }
529 }
530 }
531
532 COAP_ERR("receive unknown request, path:%s", path);
533 return NULL;
534 }
535
recv_msg_handler(CoAPContext * context,const char * path,NetworkAddr * remote,CoAPMessage * message)536 void recv_msg_handler(CoAPContext *context, const char *path,
537 NetworkAddr *remote, CoAPMessage *message)
538 {
539 secure_resource_cb_item *node = get_resource_by_path(path);
540 struct list_head *sessions;
541 session_item *session;
542 unsigned int obsVal;
543
544 unsigned int sessionId = 0;
545 CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
546 COAP_DEBUG("recv_msg_handler, sessionID:%d", (int)sessionId);
547 if (!node) {
548 return;
549 }
550 sessions = get_svr_session_list(context);
551 session = get_session_by_checksum(sessions, remote, node->pk_dn);
552 if (!session || session->sessionId != sessionId) {
553 send_err_rsp(context, remote, COAP_MSG_CODE_401_UNAUTHORIZED, message);
554 COAP_ERR("need auth, path:%s, from:%s", path, remote->addr);
555 return;
556 }
557
558 if (CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &obsVal) ==
559 COAP_SUCCESS) {
560 if (obsVal == 0) {
561 CoAPObsServer_add(context, path, remote, message);
562 }
563 }
564
565 if (message->payloadlen < 256) {
566 char buf[256];
567 call_cb(context, path, remote, message, session->sessionKey, buf,
568 node->cb);
569 } else {
570 char *buf = (char *)coap_malloc(message->payloadlen);
571 if (buf) {
572 call_cb(context, path, remote, message, session->sessionKey, buf,
573 node->cb);
574 coap_free(buf);
575 }
576 }
577 }
578
alcs_resource_register_secure(CoAPContext * context,const char * pk,const char * dn,const char * path,unsigned short permission,unsigned int ctype,unsigned int maxage,CoAPRecvMsgHandler callback)579 int alcs_resource_register_secure(CoAPContext *context, const char *pk,
580 const char *dn, const char *path,
581 unsigned short permission, unsigned int ctype,
582 unsigned int maxage,
583 CoAPRecvMsgHandler callback)
584 {
585 secure_resource_cb_item *node = NULL, *next_node = NULL;
586 char pk_dn[100] = { 0 };
587 int dup = 0;
588 secure_resource_cb_item *item;
589
590 COAP_INFO("alcs_resource_register_secure");
591 item =
592 (secure_resource_cb_item *)coap_malloc(sizeof(secure_resource_cb_item));
593 if (item == NULL) {
594 return -1;
595 }
596 memset(item, 0, sizeof(secure_resource_cb_item));
597 item->cb = callback;
598 item->path_type = PATH_NORMAL;
599 if (strstr(path, "/#") != NULL) {
600 item->path_type = PATH_FILTER;
601 } else {
602 CoAPPathMD5_sum(path, strlen(path), item->path, MAX_PATH_CHECKSUM_LEN);
603 }
604 list_for_each_entry_safe(node, next_node, &secure_resource_cb_head, lst,
605 secure_resource_cb_item)
606 {
607 if (item->path_type == PATH_NORMAL && node->path_type == PATH_NORMAL) {
608 if (memcmp(node->path, item->path, MAX_PATH_CHECKSUM_LEN) == 0) {
609 dup = 1;
610 }
611 } else if (item->path_type == PATH_FILTER &&
612 node->path_type == PATH_FILTER) {
613 if (strncmp(node->filter_path, path, strlen(path)) == 0) {
614 dup = 1;
615 }
616 }
617 }
618 if (dup == 0) {
619 if (item->path_type == PATH_FILTER) {
620 item->filter_path = coap_malloc(strlen(path) + 1);
621 if (item->filter_path == NULL) {
622 coap_free(item);
623 return -1;
624 }
625 memset(item->filter_path, 0, strlen(path) + 1);
626 strncpy(item->filter_path, path, strlen(path));
627 }
628
629 strncpy(pk_dn, pk, sizeof(pk_dn) - 1);
630 strncat(pk_dn, dn, sizeof(pk_dn) - strlen(pk_dn) - 1);
631
632 CoAPPathMD5_sum(pk_dn, strlen(pk_dn), item->pk_dn, PK_DN_CHECKSUM_LEN);
633
634 list_add_tail(&item->lst, &secure_resource_cb_head);
635 } else {
636 coap_free(item);
637 }
638
639 return CoAPResource_register(context, path, permission, ctype, maxage,
640 &recv_msg_handler);
641 }
642
alcs_resource_cb_deinit(void)643 void alcs_resource_cb_deinit(void)
644 {
645 secure_resource_cb_item *del_item = NULL;
646
647 list_for_each_entry(del_item, &secure_resource_cb_head, lst,
648 secure_resource_cb_item)
649 {
650 list_del(&del_item->lst);
651 if (del_item->path_type == PATH_FILTER) {
652 coap_free(del_item->filter_path);
653 }
654 coap_free(del_item);
655 del_item =
656 list_entry(&secure_resource_cb_head, secure_resource_cb_item, lst);
657 }
658 }
659
alcs_auth_list_deinit(void)660 void alcs_auth_list_deinit(void)
661 {
662 svr_key_item *del_item = NULL, *next_item = NULL;
663 session_item *del_session_item = NULL, *next_session_item = NULL;
664 device_auth_list *dev_lst = get_device(context);
665 auth_list *auth_list_ctx = &dev_lst->lst_auth;
666
667 list_for_each_entry_safe(del_item, next_item, &auth_list_ctx->lst_svr, lst,
668 svr_key_item)
669 {
670 list_del(&del_item->lst);
671 if (del_item->keyInfo.secret) {
672 coap_free(del_item->keyInfo.secret);
673 }
674 coap_free(del_item);
675 }
676 if (auth_list_ctx->revocation) {
677 coap_free(auth_list_ctx->revocation);
678 auth_list_ctx->revocation = NULL;
679 }
680
681 list_for_each_entry_safe(del_session_item, next_session_item,
682 &dev_lst->lst_svr_sessions, lst, session_item)
683 {
684 list_del(&del_session_item->lst);
685 coap_free(del_session_item);
686 }
687 }
688
alcs_rec_heart_beat(CoAPContext * ctx,const char * path,NetworkAddr * remote,CoAPMessage * request)689 void alcs_rec_heart_beat(CoAPContext *ctx, const char *path,
690 NetworkAddr *remote, CoAPMessage *request)
691 {
692 struct list_head *ctl_head = get_svr_session_list(ctx);
693 session_item *session = NULL;
694 session_item *node = NULL, *next = NULL;
695 int seqlen, datalen;
696 char *seq, *data;
697 CoAPMessage msg;
698 char databuf[32];
699 char payloadbuf[128];
700 CoAPLenString payload;
701
702 COAP_DEBUG("alcs_rec_heart_beat");
703 if (!ctl_head || list_empty(ctl_head)) {
704 return;
705 }
706
707 list_for_each_entry_safe(node, next, ctl_head, lst, session_item)
708 {
709 if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
710 node->heart_time = HAL_UptimeMs();
711 session = node;
712 }
713 }
714
715 if (!session) {
716 COAP_INFO("receive stale heart beat");
717 }
718
719 if (!req_payload_parser((const char *)request->payload, request->payloadlen,
720 &seq, &seqlen, &data, &datalen)) {
721 /* do nothing */
722 }
723
724 if (session) {
725 HAL_Snprintf(databuf, sizeof(databuf), "\"delayTime\":%d",
726 default_heart_expire / 1000);
727 HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq,
728 200, databuf);
729 } else {
730 HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq,
731 ALCS_HEART_FAILAUTH, "");
732 }
733
734 payload.data = (unsigned char *)payloadbuf;
735 payload.len = strlen(payloadbuf);
736 alcs_msg_init(ctx, &msg, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_CON,
737 0, &payload, NULL);
738 if (session) {
739 msg.header.msgid = request->header.msgid;
740 msg.header.tokenlen = request->header.tokenlen;
741 memcpy(&msg.token, request->token, request->header.tokenlen);
742 internal_secure_send(ctx, session, remote, &msg, 1, NULL);
743 } else {
744 CoAPLenString token = { request->header.tokenlen, request->token };
745 alcs_sendrsp(ctx, remote, &msg, 1, request->header.msgid, &token);
746 }
747 alcs_msg_deinit(&msg);
748 }
749
observe_data_encrypt(CoAPContext * ctx,const char * path,NetworkAddr * from,CoAPMessage * message,CoAPLenString * src,CoAPLenString * dest)750 int observe_data_encrypt(CoAPContext *ctx, const char *path, NetworkAddr *from,
751 CoAPMessage *message, CoAPLenString *src,
752 CoAPLenString *dest)
753 {
754 secure_resource_cb_item *node = get_resource_by_path(path);
755 struct list_head *sessions;
756 session_item *session;
757 COAP_DEBUG("observe_data_encrypt, src:%.*s", src->len, src->data);
758 if (!node) {
759 return COAP_ERROR_NOT_FOUND;
760 }
761
762 sessions = get_svr_session_list(ctx);
763 session = get_session_by_checksum(sessions, from, node->pk_dn);
764
765 if (session) {
766 dest->len = (src->len & 0xfffffff0) + 16;
767 dest->data = (unsigned char *)coap_malloc(dest->len);
768 alcs_encrypt((const char *)src->data, src->len, session->sessionKey,
769 dest->data);
770 CoAPUintOption_add(message, COAP_OPTION_SESSIONID, session->sessionId);
771 return COAP_SUCCESS;
772 }
773
774 return COAP_ERROR_NOT_FOUND;
775 }
776
on_svr_auth_timer(CoAPContext * ctx)777 void on_svr_auth_timer(CoAPContext *ctx)
778 {
779 struct list_head *head = get_svr_session_list(ctx);
780 int tick;
781 session_item *node = NULL, *next = NULL;
782
783 if (!head || list_empty(head)) {
784 return;
785 }
786 /* COAP_INFO ("on_svr_auth_timer:%d", (int)HAL_UptimeMs()); */
787
788 /* device_auth_list* dev = get_device (ctx); */
789 tick = HAL_UptimeMs();
790
791 list_for_each_entry_safe(node, next, head, lst, session_item)
792 {
793 if (node->sessionId && node->heart_time + default_heart_expire < tick) {
794 COAP_ERR("heart beat timeout");
795 remove_session(ctx, node);
796 }
797 }
798 }
799 #endif
800