Skip to content

Commit 451d773

Browse files
author
Tero Heinonen
committed
Timer to remove secure sessions after alert is sent but not received.
1 parent ba4e77d commit 451d773

File tree

8 files changed

+169
-65
lines changed

8 files changed

+169
-65
lines changed

source/coap_connection_handler.c

Lines changed: 99 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@
1111
#include "socket_api.h"
1212
#include "net_interface.h"
1313
#include "eventOS_event_timer.h"
14+
#include "coap_service_api_internal.h"
1415

1516
#define TRACE_GROUP "ThCH"
1617

18+
typedef enum session_state_e {
19+
SECURE_SESSION_HANDSHAKE_ONGOING = 0,
20+
SECURE_SESSION_OK,
21+
SECURE_SESSION_ALERT_SENT
22+
}session_state_t;
23+
1724
typedef struct internal_socket_s {
1825
coap_conn_handler_t *parent;
1926

@@ -59,7 +66,8 @@ typedef struct secure_session {
5966

6067
secure_timer_t timer;
6168

62-
bool secure_done;
69+
session_state_t session_state;
70+
uint32_t session_start_timestamp;
6371
ns_list_link_t link;
6472
} secure_session_t;
6573

@@ -81,10 +89,49 @@ static secure_session_t *secure_session_find_by_timer_id(int8_t timer_id)
8189
return this;
8290
}
8391

92+
static void secure_session_delete(secure_session_t *this)
93+
{
94+
if (this) {
95+
ns_list_remove(&secure_session_list, this);
96+
if( this->sec_handler ){
97+
coap_security_destroy(this->sec_handler);
98+
this->sec_handler = NULL;
99+
}
100+
if(this->timer.timer){
101+
eventOS_timeout_cancel(this->timer.timer);
102+
}
103+
ns_dyn_mem_free(this);
104+
this = NULL;
105+
}
106+
107+
return;
108+
}
109+
84110
static secure_session_t *secure_session_create(internal_socket_t *parent, uint8_t *address_ptr, uint16_t port)
85111
{
112+
if(!address_ptr){
113+
return NULL;
114+
}
115+
116+
if(MAX_SECURE_SESSION_COUNT <= ns_list_count(&secure_session_list)){
117+
// Seek & destroy oldest session where close notify have been sent
118+
secure_session_t *to_be_removed = NULL;
119+
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
120+
if(cur_ptr->session_state == SECURE_SESSION_ALERT_SENT){
121+
if(!to_be_removed || cur_ptr->session_start_timestamp < to_be_removed->session_start_timestamp){
122+
to_be_removed = cur_ptr;
123+
}
124+
}
125+
}
126+
if(!to_be_removed){
127+
return NULL;
128+
}
129+
130+
secure_session_delete(to_be_removed);
131+
}
132+
86133
secure_session_t *this = ns_dyn_mem_alloc(sizeof(secure_session_t));
87-
if (!this || !address_ptr) {
134+
if (!this) {
88135
return NULL;
89136
}
90137
memset(this, 0, sizeof(secure_session_t));
@@ -108,29 +155,12 @@ static secure_session_t *secure_session_create(internal_socket_t *parent, uint8_
108155
}
109156
this->parent = parent;
110157

111-
this->secure_done = false;
158+
this->session_state = SECURE_SESSION_HANDSHAKE_ONGOING;
112159
ns_list_add_to_start(&secure_session_list, this);
113-
// hack_save_remote_address(address_ptr, port); //TODO not bad hack
160+
114161
return this;
115162
}
116163

117-
static void secure_session_delete(secure_session_t *this)
118-
{
119-
if (this) {
120-
ns_list_remove(&secure_session_list, this);
121-
if( this->sec_handler ){
122-
coap_security_destroy(this->sec_handler);
123-
this->sec_handler = NULL;
124-
}
125-
if(this->timer.timer){
126-
eventOS_timeout_cancel(this->timer.timer);
127-
}
128-
ns_dyn_mem_free(this);
129-
this = NULL;
130-
}
131-
132-
return;
133-
}
134164

135165
static void clear_secure_sessions(internal_socket_t *this){
136166
if( this ){
@@ -220,12 +250,12 @@ static void int_socket_delete(internal_socket_t *this)
220250
ns_dyn_mem_free(this->data);
221251
this->data = NULL;
222252
}
253+
if(this->parent){
254+
ns_dyn_mem_free(this->parent);
255+
}
223256
ns_dyn_mem_free(this);
224-
this = NULL;
225257
}
226258
}
227-
228-
return;
229259
}
230260

231261
static internal_socket_t *int_socket_find_by_socket_id(int8_t id)
@@ -414,7 +444,7 @@ static void secure_recv_sckt_msg(void *cb_res)
414444
tr_err("secure_recv_sckt_msg session creation failed - OOM");
415445
return;
416446
}
417-
447+
session->session_start_timestamp = coap_service_get_internal_timer_ticks();
418448
// Start handshake
419449
if( !session->sec_handler->_is_started ){
420450
uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64);
@@ -430,13 +460,13 @@ static void secure_recv_sckt_msg(void *cb_res)
430460
ns_dyn_mem_free(pw);
431461
}else{
432462
//Continue handshake
433-
if( !session->secure_done ){
463+
if(session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
434464
int ret = coap_security_handler_continue_connecting(session->sec_handler);
435465
// Handshake done
436466
if(ret == 0){
437467
eventOS_timeout_cancel(session->timer.timer);
438468
session->timer.timer = NULL;
439-
session->secure_done = true;
469+
session->session_state = SECURE_SESSION_OK;
440470
if( sock->parent->_security_done_cb ){
441471
sock->parent->_security_done_cb(sock->listen_socket, src_address.address,
442472
src_address.identifier,
@@ -473,7 +503,7 @@ static void recv_sckt_msg(void *cb_res)
473503
internal_socket_t *sock = int_socket_find_by_socket_id(sckt_data->socket_id);
474504
ns_address_t src_address;
475505
if( sock && read_data(sckt_data, sock, &src_address) == 0 ){
476-
if( sock->parent->_recv_cb ){
506+
if(sock->parent && sock->parent->_recv_cb){
477507
sock->parent->_recv_cb(sock->listen_socket, src_address.address, src_address.identifier, sock->data, sock->data_len);
478508
}
479509
ns_dyn_mem_free(sock->data);
@@ -514,6 +544,9 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
514544
tr_err("coap_connection_handler_virtual_recv session creation failed - OOM");
515545
return -1;
516546
}
547+
548+
session->session_start_timestamp = coap_service_get_internal_timer_ticks();
549+
517550
if( !session->sec_handler->_is_started ){
518551
uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64);
519552
uint8_t pw_len;
@@ -531,10 +564,10 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
531564
return -1;
532565
}
533566
}else{
534-
if( !session->secure_done ){
567+
if(session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
535568
int ret = coap_security_handler_continue_connecting(session->sec_handler);
536569
if(ret == 0){
537-
session->secure_done = true;
570+
session->session_state = SECURE_SESSION_OK;
538571
if( handler->_security_done_cb ){
539572
handler->_security_done_cb(sock->listen_socket,
540573
address, port,
@@ -598,19 +631,16 @@ coap_conn_handler_t *connection_handler_create(receive_from_socket_cb *recv_from
598631
handler->_recv_cb = recv_from_cb;
599632
handler->_send_cb = send_to_cb;
600633

601-
// handler->sec_conn_closed_cb = sec_conn_closed_cb;
602634
handler->_get_password_cb = pw_cb;
603635
handler->_security_done_cb = done_cb;
604636

605637
return handler;
606638
}
607-
608639
void connection_handler_destroy(coap_conn_handler_t *handler)
609640
{
610641
if(handler){
611-
int_socket_delete(handler->socket);
612-
handler->socket = NULL;
613-
ns_dyn_mem_free(handler);
642+
int_socket_delete(handler->socket);
643+
ns_dyn_mem_free(handler);
614644
}
615645
}
616646

@@ -621,6 +651,8 @@ void connection_handler_close_secure_connection( coap_conn_handler_t *handler, u
621651
secure_session_t *session = secure_session_find( handler->socket, destination_addr_ptr, port);
622652
if( session ){
623653
coap_security_send_close_alert( session->sec_handler );
654+
session->session_state = SECURE_SESSION_ALERT_SENT;
655+
session->session_start_timestamp = coap_service_get_internal_timer_ticks();
624656
}
625657
}
626658
}
@@ -642,15 +674,18 @@ int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16
642674
internal_socket_t *current = !use_ephemeral_port?int_socket_find(listen_port, is_secure, is_real_socket, bypassSec):NULL;
643675
if(!current){
644676
handler->socket = int_socket_create(listen_port, use_ephemeral_port, is_secure, is_real_socket, bypassSec);
645-
if( !handler->socket ){
677+
if(!handler->socket){
678+
return -1;
679+
}
680+
handler->socket->parent = ns_dyn_mem_alloc(sizeof(coap_conn_handler_t));
681+
if(!handler->socket->parent){
682+
int_socket_delete(handler->socket);
646683
return -1;
647684
}
648-
handler->socket->parent = handler;
685+
*handler->socket->parent = *handler;
649686
}else{
650687
current->usage_counter++;
651688
handler->socket = current;
652-
//handler->parent cannot be set here!
653-
//this will be always problematic if 2 or more secure sockets try to share a same port!
654689
}
655690
return 0;
656691
}
@@ -665,12 +700,13 @@ int coap_connection_handler_send_data(coap_conn_handler_t *handler, ns_address_t
665700
memcpy(handler->socket->dest_addr.address, dest_addr->address, 16);
666701
handler->socket->dest_addr.identifier = dest_addr->identifier;
667702
handler->socket->dest_addr.type = dest_addr->type;
668-
secure_session_t *session = secure_session_find( handler->socket, dest_addr->address, dest_addr->identifier);
703+
secure_session_t *session = secure_session_find(handler->socket, dest_addr->address, dest_addr->identifier);
669704
if( !session ){
670705
session = secure_session_create(handler->socket, dest_addr->address, dest_addr->identifier);
671706
if( !session ){
672707
return -1;
673708
}
709+
session->session_start_timestamp = coap_service_get_internal_timer_ticks();
674710
memcpy( handler->socket->dest_addr.address, dest_addr->address, 16 );
675711
handler->socket->dest_addr.identifier = dest_addr->identifier;
676712
handler->socket->dest_addr.type = dest_addr->type;
@@ -693,8 +729,9 @@ int coap_connection_handler_send_data(coap_conn_handler_t *handler, ns_address_t
693729
ns_dyn_mem_free(pw);
694730
return -1;
695731
}
696-
}else if( session->secure_done ){
732+
}else if( session->session_state == SECURE_SESSION_OK ){
697733
if( coap_security_handler_send_message(session->sec_handler, data_ptr, data_len ) > 0 ){
734+
session->session_start_timestamp = coap_service_get_internal_timer_ticks();
698735
return 0;
699736
}
700737
}
@@ -736,3 +773,24 @@ int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_
736773

737774
return 0;
738775
}
776+
777+
/* No need to call every second - call rather like every minute (SECURE_SESSION_CLEAN_INTERVAL sets this) */
778+
void coap_connection_handler_exec(uint32_t time)
779+
{
780+
if(ns_list_count(&secure_session_list)){
781+
// Seek & destroy old sessions where close notify have been sent
782+
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
783+
if(cur_ptr->session_state == SECURE_SESSION_ALERT_SENT ||
784+
cur_ptr->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
785+
if((cur_ptr->session_start_timestamp + CLOSED_SECURE_SESSION_TIMEOUT) <= time){
786+
secure_session_delete(cur_ptr);
787+
}
788+
}
789+
if(cur_ptr->session_state == SECURE_SESSION_OK){
790+
if((cur_ptr->session_start_timestamp + OPEN_SECURE_SESSION_TIMEOUT) <= time){
791+
secure_session_delete(cur_ptr);
792+
}
793+
}
794+
}
795+
}
796+
}

source/coap_service_api.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "common_functions.h"
2121
#include "coap_connection_handler.h"
2222
#include "net_interface.h"
23+
#include "coap_service_api_internal.h"
2324

2425
static int16_t coap_service_coap_msg_process(int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len);
2526
static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr);
@@ -159,12 +160,14 @@ static void service_event_handler(arm_event_s *event)
159160
if (event->event_type == ARM_LIB_TASKLET_INIT_EVENT) {
160161
tr_debug("service tasklet initialised");
161162
/*initialize coap service and listen socket*/
162-
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
163163
}
164164
if (event->event_type == ARM_LIB_SYSTEM_TIMER_EVENT && event->event_id == COAP_TICK_TIMER) {
165165
coap_message_handler_exec(coap_service_handle, coap_ticks++);
166-
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
166+
if(coap_ticks && !coap_ticks % SECURE_SESSION_CLEAN_INTERVAL){
167+
coap_connection_handler_exec(coap_ticks);
168+
}
167169
}
170+
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
168171
}
169172

170173
static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr)
@@ -299,11 +302,12 @@ int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_
299302
tasklet_id = eventOS_event_handler_create(&service_event_handler, ARM_LIB_TASKLET_INIT_EVENT);
300303
}
301304

302-
this->conn_handler = connection_handler_create(recv_cb, send_cb/*, sec_conn_closed_cb*/, get_passwd_cb, sec_done_cb);
305+
this->conn_handler = connection_handler_create(recv_cb, send_cb, get_passwd_cb, sec_done_cb);
303306
if(!this->conn_handler){
304307
ns_dyn_mem_free(this);
305308
return -1;
306309
}
310+
307311
if (0 > coap_connection_handler_open_connection(this->conn_handler, listen_port, ((this->service_options & COAP_SERVICE_OPTIONS_EPHEMERAL_PORT) == COAP_SERVICE_OPTIONS_EPHEMERAL_PORT),
308312
((this->service_options & COAP_SERVICE_OPTIONS_SECURE) == COAP_SERVICE_OPTIONS_SECURE),
309313
((this->service_options & COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET) != COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET),
@@ -333,10 +337,8 @@ void coap_service_delete(int8_t service_id)
333337
return;
334338
}
335339

336-
//TODO: There might be an issue with shared sockets, when deleting!!
337340
if (this->conn_handler){
338341
connection_handler_destroy(this->conn_handler);
339-
this->conn_handler = NULL;
340342
}
341343

342344
//TODO clear all transactions
@@ -464,3 +466,8 @@ int8_t coap_service_set_handshake_timeout(int8_t service_id, uint32_t min, uint3
464466

465467
return coap_connection_handler_set_timeout(this->conn_handler, min, max);
466468
}
469+
470+
uint32_t coap_service_get_internal_timer_ticks(void)
471+
{
472+
return coap_ticks;
473+
}

source/include/coap_connection_handler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
#include <stddef.h>
2424
#include <stdbool.h>
2525
#include "ns_address.h"
26+
#include "coap_service_api_internal.h"
27+
28+
#define MAX_SECURE_SESSION_COUNT 3
29+
#define CLOSED_SECURE_SESSION_TIMEOUT 3600 // Seconds
30+
#define OPEN_SECURE_SESSION_TIMEOUT 18000 // Seconds
31+
#define SECURE_SESSION_CLEAN_INTERVAL 60 // Seconds
2632

2733
struct internal_socket_s;
2834

@@ -60,4 +66,6 @@ bool coap_connection_handler_socket_belongs_to(coap_conn_handler_t *handler, int
6066

6167
int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_t min, uint32_t max);
6268

69+
void coap_connection_handler_exec(uint32_t time);
70+
6371
#endif
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2016 ARM Limited. All Rights Reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#ifndef __COAP_SERVICE_API_INTERNAL_H__
20+
#define __COAP_SERVICE_API_INTERNAL_H__
21+
22+
23+
uint32_t coap_service_get_internal_timer_ticks(void);
24+
25+
#endif

0 commit comments

Comments
 (0)