Commit Graph
401 Commits
Author SHA1 Message Date
Olaf Bergmann b79a43de30 net.c: Fix use-after-free in coap_cancel()
When a subscription is canceled, coap_cancel() iterates through the
resources and deletes the observer. In addition, all outstanding
messages for this observer are removed from the send queue.

With commit 5b1a8f67, the session object associated with the deleted
observer may be automatically released by coap_delete_observer().
Therefore, coap_cancel_all_messages() must be invoked on the session
before deletion.

Fixes CID 1484386 found by Coverity scan.
2019-07-26 10:36:32 +02:00
obgm f2ce60e185 Merge pull request #355 from mrdeep1/fix_common_name
Rename get_common_name_from_cert() to get_san_or_cn_from_cert()
2019-07-25 13:45:43 +02:00
obgm 4f91bce186 Merge pull request #357 from mrdeep1/icmp_unreachable
Split COAP_NACK_RST into COAP_NACK_RST and COAP_NACK_ICMP_ISSUE
2019-07-25 13:41:49 +02:00
obgm b1266898c6 Merge pull request #378 from mrdeep1/session_lookup
Make sessions list hashed to make lookups faster
2019-07-25 11:14:53 +02:00
Jon Shallow a27ec8b3d1 Report event COAP_EVENT_DTLS_CLOSED when idle (D)TLS session times out
When an idle server (D)TLS session times out, no event is reported to a
defined event handler.  COAP_EVENT_DTLS_CLOSED is reported whenever there is
a read / write issue, and this fix also reports the event COAP_EVENT_DTLS_CLOSED
when the (D)TLS session is closed.

Some extra code had to be added in to prevent event COAP_EVENT_DTLS_CLOSED
being reported twice.

src/coap_gnutls.c:
src/coap_openssl.c:
src/coap_tinydtls.c:

Report event COAP_EVENT_DTLS_CLOSED when coap_dtls_free_session() and
coap_tls_free_session() are called.

src/coap_session.c:

Do not log spurious (D)TLS Alert packets received after session is closed.
2019-07-24 14:36:20 +02:00
Jon Shallow f06172d71e Make sessions list hashed to make lookups faster
Make endpoint->sessions and context->sessions a hashed chain of sessions
based on a key comprising of local and remote addresses and ports instead of
a linked list that has to be linearly searched.

include/coap2/coap_io.h:
include/coap2/coap_session.h:

Create a new struct coap_addr_tuple_t for the local and remote addresses/ports
to be used as the hash key.  Update coap_packet_t and coap_session_t
appropriately.

Create SESSIONS_* macros to Add, Delete, Find and Iterate through the hashed
chain.

examples/coap-rd.c:
src/coap_io.c:
src/coap_io_lwip.c:
src/coap_openssl.c:
src/coap_session.c:
src/coap_tinydtls.c:
src/net.c:
src/resource.c:

Update with the new struct element names and replace the LL_* functions with
SESSIONS_* as appropriate.

Update coap_endpoint_get_session() to use SESSIONS_FIND() for fast lookup.

Future work is to review all the SESSIONS_ITER* and see if they can be sped up
as well.
2019-07-24 14:25:38 +02:00
Jon Shallow 54d52221ba Split COAP_NACK_RST into COAP_NACK_RST and COAP_NACK_ICMP_ISSUE
As COAP_NACK_RST is used for
1. ICMP Port Unreachable message is received
2. CoAP reply RST message.
there needs to be a way to differentiate between these conditions.

If there is detected to be an ICMP response issue to sending a UDP
packet, report this as COAP_NACK_ICMP_ISSUE instead of COAP_NACK_RST.

If the reported issue to coap_session_disconnected() is COAP_NACK_ICMP_ISSUE,
then make sure that the packet (plain or DTLS) gets re-transmitted.

As hinted in #131 discussion, retry of the packet should be attempted,
(as per https://tools.ietf.org/html/rfc7252#section-4.2 ICMP Unreachable)
this fix will cause the plain packet to get retransmitted up to the maximum
retry count if type CON.

Likewise, DTLS will get restarted up to the maximum retry count if type CON.

examples/client.c:

Include COAP_NACK_ICMP_ISSUE in the nack_handler.

include/coap2/coap_io.h:

Add in COAP_NACK_ICMP_ISSUE to coap_nack_reason_t.

src/coap_session.c:

Update coap_session_disconnected() so that plain/DTLS can restart.

src/net.c:

Fix coap_wait_ack() to exponentially back off the re-transmit times.

Update coap_read_session() to report COAP_NACK_ICMP_ISSUE instead of
COAP_NACK_RST.

man/coap_handler.txt.in:

Update documentation
2019-07-19 12:35:49 +02:00
Jon Shallow 55aeaa6cc1 Update Keepalive support to include unreliable sessions
Add in support for both reliable and unreliable sessions when calling
coap_context_set_keepalive().

include/coap2/coap_session.h:

Track the last ping mid in coap_session_t.

src/coap_io.c:
src/coap_session.c:

Support both reliable and unreliable sending of pings in coap_write().

src/net.c:

Determine whether RST packet response is associated with a CoAP Empty Ping
that was sent and handle accordingly.

configure.ac:
examples/client.c:
include/coap2/net.h:
man/Makefile.am:
man/coap-client.txt.in:
man/coap.txt.in:
man/coap_handler.txt.in:
man/coap_keepalive.txt.in: (New)
man/coap_observe.txt.in:

Add in a new man page (coap_keepalive).
Update documentation to remove references to TCP and reliable only.
2019-07-11 11:14:15 +02:00
Jon Shallow 3a6f9e8499 net.c: Start new coap_context with a random message identifier
This is done by calling prng_init() with a non-zero value in coap_startup().

Change 7fb4ace2b7 modified the parameter to
prng_init() from a computed value to 0 when the code was re-organized.

This change uses the current time in microseconds as the seed to prng_init().

include/coap2/coap_time.h:

Add in coap_ticks_to_rt_us() support for lwIP and Contiki

src/net.c:

Update call to prng_init() in coap_startup() to use time in microsecs as the
seed parameter

See #373 where the issue was raised.
2019-07-05 15:32:06 +02:00
Jon Shallow 0aa8cde1ad coap_time.c: Make coap_ticks() more accurate than to the nearest second
With
define Q(frac,fval) ((coap_tick_t)(((1 << (frac)) * (fval))))
and
tmp = SHR_FP(tv.tv_nsec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000000.0)), FRAC);

The Q function always returns 0 in error - e.g.

(gdb) p ((coap_tick_t)(((1 << (FRAC))*((COAP_TICKS_PER_SECOND/1000000000.0)))))
$6 = 0
(gdb) p ((((1 << (FRAC))*((COAP_TICKS_PER_SECOND/1000000000.0)))))
$7 = 0.001024

whereas we need the value 0.001024 to multiple with tv_nsec.

This change fixes this by moving the coap_tick_t from Q to SHR_FP.

Found when debugging #374
2019-07-04 14:44:59 +01:00
obgm 27eec0c1c5 Merge pull request #350 from lewixliu/develop
Fixed two minor bugs in endpoint free and session address update
2019-06-28 17:11:41 +02:00
obgm 5b1d753da0 Merge pull request #365 from mrdeep1/dtls_retry
Fix GnuTLS DTLS retries when Client Hello is not responded to
2019-06-28 12:19:45 +02:00
Jon Shallow cc63387dad Fix memory leak in GnuTLS client that does not have security defined
If a CoAP client using GnuTLS does not have PSK or PKI security defined
but communicatioes with coaps:// with a CoAP server that has PKI defined,
then there is a memory leak when the session is closed down.

src/coap_gnutls.c:

Free off PKI credentials if a client and PSK or PKI was not explicitly
defined in coap_dtls_free_gnutls_env().
2019-06-27 14:52:58 +01:00
obgm d1642c3e68 Merge pull request #361 from mrdeep1/block2_well-known_core
Fix final data size in last BLOCK2 response for .well-known/core
2019-06-27 15:32:36 +02:00
obgm 39b2505a2e Merge pull request #367 from mrdeep1/fix_openssl_1_1_1c
Stop valgrind errors when using OpenSSL 1.1.1c
2019-06-27 14:07:34 +02:00
obgm 5f5ab48e34 Merge pull request #340 from mrdeep1/cancel_rst_observe
Fix RST deleting observer for non-confirmable observe
2019-06-26 14:39:25 +02:00
Jon Shallow ff8f8d2c6b Stop valgrind errors when using OpenSSL 1.1.1c
Issue introduced by OpenSSL 1.1.1c causes valgrind errors to be reported.  See
https://www.mail-archive.com/openssl-commits@openssl.org/msg21701.html and
https://github.com/openssl/openssl/pull/8606 which did not make 1.1.1c

scripts/build.sh:
tests/valgrind_suppression:

Temporarily suppress valgrind errors when SSL_CTS_new() is called when running
the tests.

Note: This suppression will also need to be applied when running valgrind
against other CoAP executables using OpenSSL 1.1.1c to prevent the valgrind
errors getting reported.

src/coap_openssl.c:

memset cookie_secret to 0 to stop valgrind warning.
2019-06-25 20:26:43 +01:00
Jon Shallow 3a50a29ced Fix GnuTLS DTLS retries when Client Hello is not responded to
GnuTLS currently does not retry to send the Client Hello packets if there was
no (Server Hello) response.  This was never correctly implemented.

src/coap_gnutls.c:

Fix receive_timout() so that it differentiates between DTLS and TLS.
If DTLS, if data has already been read in, indicate this.
if this is a coap_dtls_handle_timeout() call, only check readfds
(writefds will always be true, causing confusion).

Set DTLS timeouts where appropriate.

Update coap_dtls_*_timeout() functions to return the correct values.

include/coap2/coap_dtls.h:
src/coap_gnutls.c:
src/coap_io.c:
src/coap_notls.c:
src/coap_openssl.c:
src/coap_tinydtls.c:

Add in coap_tick_t now parameter to coap_dtls_get_timeout() for better
accuracy.
2019-06-21 16:51:01 +01:00
Jon Shallow d84ac69b67 Fix final data size in last BLOCK2 response for .well-known/core
src/net.c:

Corect the length for the final block size.

Add in an ETAG and SIZE2 option into the response as suggested by RFC7959.

examples/client.c:

Warn if URI path is too long for internal buffer (found when testing that
a large WellKnown response triggered sending BLOCK2 correctly).

Increase internal buffersize to allow longer URIs.

To reproduce issue

coap-client -b 256 coap://127.0.0.1/.well-known/core

As reported by Zafi Ramarosandratana.  See #360 which this fixes.
2019-06-20 12:35:57 +01:00
LewixLiu b511257724 Remove endpoint from context list when free 2019-06-04 23:14:34 +08:00
LewixLiu 80b2bef1b1 Correct the copy address direction 2019-06-04 23:14:29 +08:00
obgm e7349da198 Merge pull request #348 from mrdeep1/message_id
Remove unused message_id from coap_context_t and coap_async_t
2019-06-04 14:34:48 +02:00
obgm 1a5f75e3c8 Merge pull request #356 from mrdeep1/no_listening_server
Fix handling ICMP Port Unreachable messages
2019-06-04 14:26:43 +02:00
Jon Shallow b1ebb503b4 Fix handling ICMP Port Unreachable messages
Once a ICMP Port Unreachable message is received, the session is
disconnected by a call to coap_session_disconnect().  However if the session
is of type CON,  the logic currently tries to retransmit the packet, but
nothing gets sent out.

src/coap_session.c:

Make sure that any entries on the context->sendqueue for the disconnected
session are removed.

examples/client.c:

Add in a Nack handler so that the client immediately exits on the session
disconnect.  Additionally this also tidies up the exit after transmission
retries.
2019-06-03 20:58:08 +01:00
Jon Shallow 388fe8ff31 Rename get_common_name_from_cert() to get_san_or_cn_from_cert()
src/coap_openssl.c:

Give the function that abstracts the Subject Alternative Name (SAN),
or the CN= if SAN is not available, a better descriptive name to prevent
possible confusion.
2019-06-03 16:07:39 +01:00
Olaf Bergmann a2c3cc54e3 coap_session.c: Fix format string for size_t argument
This change removes a compiler warning caused by a wrong format string
argument in debug output.
2019-05-09 15:35:52 +02:00
Olaf Bergmann 552fc37cde coap_debug.c: Improve len parameter handling for inet_ntop()
Commit 32e219a has resolved an issue with the size parameter for
inet_ntop() in a way that introduces errors on certain Linux
platforms. This change now passes the exact size for AF_INET
and AF_INET6 to fix that.
2019-05-09 14:09:41 +02:00
Jon Shallow 93e558ba02 Remove unused message_id from coap_context_t and coap_async_t
It appears that message_id was left in coap_context_t and coap_async_t
when coap_session_t was created.

include/coap2/async.h:
include/coap2/net.h:

Remove message_id.

src/net.c:

No longer just set message_id.
2019-05-06 15:51:23 +01:00
obgm a5f434e685 Merge pull request #337 from mrdeep1/have_struct_cmsghdr
Handle platforms that do not have 'struct cmsghdr' defined
2019-04-26 15:35:53 +02:00
Jon Shallow 173f160498 Handle platforms that do not have 'struct cmsghdr' defined
configure.ac:

Test for the presence of 'struct cmsghdr' and set HAVE_STRUCT_CMSGHDR
if appropriate.

src/coap_io.c:

Revert to recvfrom() and sendto() if HAVE_STRUCT_CMSGHDR is not defined,
instead of using recvmsg() and sendmsg().
2019-04-26 13:34:16 +01:00
Jon Shallow 3829cd6137 Fix DTLS session loss when multiple connections in a short time
endpoint->hello is used to hold the 5 tuple etc. information about a new
connection that has come in.  Once the DTLS handshake has been completed
a new coap_session_t is created for the ongoing encrypted work.

However, if a second new DTLS request comes in before the first session
has completed the DTLS handshakes, it will overwrite the endpoint->hello
information causing the first request to stall / get lost.

GnuTLS already has to check that the initial DTLS packet is a Client Hello
before starting up a GnuTLS session, so moving this logic up a level to
the initial DTLS packet makes sense to create a coap_session_t at this
point and getting rid of the temporary endpoint->hello gets rid of this
issue.

Makefile.am:

Replace coap_endpoint_new_dtls_session with coap_session_new_dtls_session

include/coap2/coap_session.h:

Remove coap_session_t hello;
Replace coap_endpoint_new_dtls_session with coap_session_new_dtls_session

src/coap_gnutls.c:

Remove references to endpoint->hello
Remove Client Hello check code (move it to coap_endpoint_get_session())

src/coap_io.c:

Remove references to freeing off ep->hello

src/coap_session.c:

Remove endpoint->hello code.
Check for Client Hello in coap_endpoint_get_session() if no session, is DTLS
and don't build coap_session if not a Client Hello.
Otherwise, always build a new coap_session.

Timeout Client Hello session if inactive to prevent a DoS.

Replace coap_endpoint_new_dtls_session with coap_session_new_dtls_session

src/coap_net.c:

Replace coap_endpoint_new_dtls_session with coap_session_new_dtls_session
2019-04-26 12:45:58 +01:00
Jon Shallow 7a4d2db8f3 Fix RST deleting observer for non-confirmable observe
Code works as expected for confirmable observes as the sent pdu is
retained for potential re-transmission.

For non-confirmable observes, the RST is seen in the response packet but
previously had no way of finding the observe/subscription to cancel.

Keep the last sent message id in coap_subscription_t (as tid) and when the
RST comes in, search for the subscription that has the same message id as
the pdu and remove that subscription.

include/coap2/subscribe.h:

Add in tid to coap_subscription_t (as per coap_pdu_t).

src/net.c:

Match tid in incoming RST pdu with a subscription.  If found, delete the
subscription.

src/resource.c:

Save tid in both pdu and subscription when sending off an observe response.

To test code, make the following temporary change to coap-client

diff --git a/examples/client.c b/examples/client.c
index 4d3e4c7..0020b68 100644
--- a/examples/client.c
+++ b/examples/client.c
@@ -348,7 +348,8 @@ message_handler(struct coap_context_t *ctx,
 #endif

   /* check if this is a response to our original request */
-  if (!check_token(received)) {
+static int count = 0;
+  if (!check_token(received) || ++count == 5) {
     /* drop if this was just some message, or send RST in case of notification */
     if (!sent && (received->type == COAP_MESSAGE_CON ||
                   received->type == COAP_MESSAGE_NON))

and run (coap-server running on the same host)

coap-client -N -s 10 coap://127.0.0.1/time
2019-04-25 08:45:19 +01:00
Olaf Bergmann e0c6df7703 net.c: Include netdb.h only if HAVE_NETDB_H is defined
Platforms that do not have getaddrinfo() most likely do not have
the netdb.h include file as well.
This change includes netdb.h only if HAVE_NETDB_H is defined
(usually by configure).
2019-04-17 15:45:29 +02:00
Olaf Bergmann 32e219a9fc coap_debug.c: Fix len parameter for inet_ntop()
On RIOT, inet_ntop() expects the size parameter to reflect the
length of the given address. A larger value causes inet_ntop()
to return ENOSPC.

This change passes the address size as a workaround, or the actual
number of remaining bytes in the output buffer in case less than
address size bytes remain.
2019-04-17 13:37:27 +02:00
obgm 106eb9edc9 Merge pull request #325 from mrdeep1/constrained_stack
For limited stacks, remove large items off the stack and make them static
2019-04-16 18:05:45 +02:00
obgm 1d484849e8 Merge pull request #312 from mrdeep1/group_reg
Fix mcast registrations when using TCP
2019-04-12 15:09:20 +02:00
Jon Shallow fda991f541 Fix mcast registrations when using TCP
As coap-server now sets up 2 (or 4) endpoints, UDP and TCP based, all
subsequent endpoints are pre-pended to the ctx->endpoint list. Thus
ctx->endpoint will always be TCP based.  Setting IPV6_JOIN_GROUP on a TCP
socket is a no-no.

As join() is complex function, it should be within libcoap so as to not require
detailed knowledge of how internal structures work (which really should be
opaque to the application writer).

include/coap2/net.h:
src/net.c:
libcoap-2.map:
libcoap-2.sym:
Create coap_join_mcast_group() in src/net.c (as it is a network layer
function using the (fixed) join() code. (Iterate through the ctx->endpoint list
looking for UDP based endpoints and only do the IPV6_JOIN_GROUP on them.)
There is no support for WITH_CONTIKI or WITH_LWIP at this point (returns -1).

examples/coap-server.c:
Remove join() code and replace call to join() with coap_join_mcast_group()

examples/coap-rd.c:
Remove join() code and replace call to join() with coap_join_mcast_group()

man/coap-rd.txt.in:
Correct a typo in the coap-ed man page
2019-04-12 13:54:50 +01:00
Jon Shallow cb18375df7 For limited stacks, remove large items off the stack and make them static
When there is a limited stack size, having large data items on the stack
can easily cause stack overflows.

This makes integration with any constrained stack O/S a lot easier.

include/coap2/coap_mutex.h:

Create coap_ mutex functions which are platform independent to protect
the (now) static variables if compiled with "-DCOAP_CONSTRAINED_STACK=1"

Makefile.am:

Include include/coap2/coap_mutex.h for distribution

coap_config.h.contiki:
coap_config.h.lwip:

As CONTIKI and LWIP have constrained stacks, set
"#define COAP_CONSTRAINED_STACK 1"

src/coap_debug.c:
src/coap_io.c:
src/net.c:

coap_show_pdu()
coap_log_impl()
coap_run_once()
coap_read_session()
coap_read_endpoint()
Move large data items out of the functions' stack and make them static
variables (defined within the function) if COAP_CONSTRAINED_STACK is defined.
Protect the usage of these static variables by mutexes.

Note: if "-DCOAP_CONSTRAINED_STACK=0" is used, then the stack will not
be constrained.
2019-04-11 15:53:21 +01:00
Jon Shallow bc789edff8 coap_free_endpoint does not clean up tinydtls encryption sessions
Following on from #324 where coap_session_mfree() had to be moved in
coap_session_free() to correctly allow for tinydtls cleanup, session->endpoint
and session->context should not be cleared out prior to call of
coap_sesson_free() in coap_free_endpoint().

src/coap_session.c:

Remove lines setting session->endpoint and session->context to NULL
2019-04-11 10:47:17 +01:00
Jon Shallow a106ecc319 Fix #321 was not correctly implemented
While #321 prevented a core dump, that fix still caused memory corruption.

src/coap_gnutls.c:

Correct the code to correctly NULL terminate the created username.
2019-04-07 17:48:46 +01:00
obgm af1d602486 Merge pull request #327 from mrdeep1/contiki_lwip
server (lwip & contiki) run out of sessions
2019-04-05 16:19:02 +02:00
obgm 303be16e86 Merge pull request #317 from mrdeep1/cmsg_checks
packet->ifindex has random values if recvmsg() does not update msg_control
2019-04-05 15:49:16 +02:00
Jon Shallow 10b1b17aec server (lwip & contiki) run out of sessions
As a server, idle sessions are left around in case the client wants to do
further work using the same 5 tuple IP information.
With constrained systems, the number of sessions is limited, and so it is
easy to run out of sessions.

src/coap_session.c:

If there is an idle session, context->max_idle_sessions is not set and
a new session cannot be created, free off the oldest session and retry
the creation again.

examples/contiki/README:
examples/lwip/README:

Tidy up the documentation
2019-04-05 14:30:12 +01:00
Jon Shallow 1158541f63 dtls_send_to_peer: cannot find local interface reported on coap_session_free
In coap_session_free(), as coap_session_mfree() is called after
the session has been deleted out the endpoint or context sessions,
dtls_send_to_peer() is unable to find the session to send out the
Alert/Warning Close Notify message packet.

src/coap_session.c:

Move coap_session_mfree() to before setting deleting session out of endpoint or context sessions in coap_session_free().

Note: TinyDTLS has been separately updated to not report ALRT on a
Close Notify - see https://github.com/eclipse/tinydtls/pull/5.
2019-04-05 13:56:03 +01:00
Jon Shallow d6562e8b59 Client crashes in gnutls psk setup
src/coap_gnutls.c:

Correct typo when null terminating username.
2019-03-31 20:33:46 +01:00
Ivan Grokhotkov 9783d4ed91 coap_debug.c: fix format warning when compiling with GCC 8
When compiling libcoap with format truncation warnings enabled,
GCC warns about the potential issue with "%u.%02u" format string,
since the first argument may produce more than one byte of output:

    error: '%02u' directive output may be truncated writing 2 bytes
    into a region of size between 0 and 3 [-Werror=format-truncation=]

The first argument (class) is limited to 3 bits according to the
specification. Mask the higher bits to fix the warning.
2019-03-28 16:03:44 +08:00
Jon Shallow 9ad9ad0bb5 packet->ifindex has random values if recvmsg() does not update msg_control
packet is allocated on the stack in coap_read_session(), and so is
uninitialized when processed by coap_network_read().  If there is not an
appropriate cmsg entry in mhdr.msg_control when returning from recvmsg()
packet->ifindex (nor for that matter packet->dst) does not get updated.

src/coap_io.c:

Preset mhdr.msg_control initial cmsghdr with invalid information and an
oversize length so that underlying recvmsg() implementations (e.g. minimal
IoT implementations) that do not update mhdr.msg_control's data, or do not
update it with the destination IP of the packet are correctly handled.
2019-03-20 17:06:53 +01:00
Olaf Bergmann a363e01214 coap_openssl.c: Additional NULL pointer check
This change fixes an inconsistency detected by Coverity scan
(CID 1479021).
2019-03-20 15:48:37 +01:00
Olaf Bergmann 2922c19970 updated copyright information
Touched dates in files where significant changes occurred in 2019.
2019-03-02 11:43:59 +01:00
yr2004 e269b87151 option.c: memset the node when a new optlist node is created
memset the node when a new optlist node is created, because the node->next maybe not NULL, so if it creates a new optlist node, and delete it, and then create it again, error will be occurred
2019-03-01 16:03:00 +01:00