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