Skip to content

Commit

Permalink
Connection-ID: Only change source port when CID has been negotiated
Browse files Browse the repository at this point in the history
Only support changing the client's source port if the DTLS library
has support / configured for CID.

Used when debugging server handling source address changes and CID
is in use.

Add in support for TinyDTLS (Client only) if TinyDTLS is patched
appropriately (not currently available on TinyDTLS main branch).

Add in new function coap_dtls_cid_is_supported().
  • Loading branch information
mrdeep1 committed Aug 4, 2024
1 parent 9656876 commit 8b12795
Show file tree
Hide file tree
Showing 18 changed files with 349 additions and 23 deletions.
8 changes: 6 additions & 2 deletions examples/coap-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1924,8 +1924,12 @@ main(int argc, char **argv) {
coap_register_nack_handler(ctx, nack_handler);
if (the_token.length > COAP_TOKEN_DEFAULT_MAX)
coap_context_set_max_token_size(ctx, the_token.length);
if (cid_every)
coap_context_set_cid_tuple_change(ctx, cid_every);
if (cid_every) {
if (!coap_context_set_cid_tuple_change(ctx, cid_every)) {
coap_log_warn("coap_context_set_cid_tuple_change: "
"Unable to set CID tuple change\n");
}
}

session = get_session(ctx,
node_str[0] ? node_str : NULL,
Expand Down
2 changes: 2 additions & 0 deletions include/coap3/coap_dtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
* @{
*/

int coap_dtls_cid_is_supported(void);

typedef struct coap_dtls_pki_t coap_dtls_pki_t;

#ifndef COAP_DTLS_HINT_LENGTH
Expand Down
11 changes: 11 additions & 0 deletions include/coap3/coap_dtls_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,17 @@ int coap_dtls_define_issue(coap_define_issue_key_t type,
coap_dtls_key_t *key,
const coap_dtls_role_t role,
int ret);

/**
* Set the Connection ID client tuple frequency change for testing CIDs.
*
* @param context The coap_context_t object.
* @param every Change the client's source port @p every packets sent.
*
* @return @c 1 if frequency change set (CID supported), else @c 0.
*/
int coap_dtls_set_cid_tuple_change(coap_context_t *context, uint8_t every);

/** @} */

#endif /* COAP_DTLS_INTERNAL_H */
4 changes: 3 additions & 1 deletion include/coap3/coap_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,10 @@ void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds);
*
* @param context The coap_context_t object.
* @param every Change the client's source port @p every packets sent.
*
* @return @c 1 if frequency change set (CID supported), else @c 0.
*/
void coap_context_set_cid_tuple_change(coap_context_t *context, uint8_t every);
int coap_context_set_cid_tuple_change(coap_context_t *context, uint8_t every);

/**
* Set the maximum token size (RFC8974).
Expand Down
4 changes: 4 additions & 0 deletions include/coap3/coap_session_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ struct coap_session_t {
#endif /* COAP_OSCORE_SUPPORT */
volatile uint8_t max_token_checked; /**< Check for max token size
coap_ext_token_check_t */
#if COAP_CLIENT_SUPPORT
uint8_t negotiated_cid; /**< Set for a client if CID negotiated */
#endif /* COAP_CLIENT_SUPPORT */
uint8_t is_dtls13; /**< Set if session is DTLS1.3 */
coap_mid_t remote_test_mid; /**< mid used for checking remote
support */
uint32_t max_token_size; /**< Largest token size supported RFC8974 */
Expand Down
1 change: 1 addition & 0 deletions libcoap-3.map
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ global:
coap_delete_str_const;
coap_delete_string;
coap_delete_uri;
coap_dtls_cid_is_supported;
coap_dtls_get_log_level;
coap_dtls_is_supported;
coap_dtls_pkcs11_is_supported;
Expand Down
1 change: 1 addition & 0 deletions libcoap-3.sym
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ coap_delete_resource
coap_delete_str_const
coap_delete_string
coap_delete_uri
coap_dtls_cid_is_supported
coap_dtls_get_log_level
coap_dtls_is_supported
coap_dtls_pkcs11_is_supported
Expand Down
7 changes: 5 additions & 2 deletions man/coap_context.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ size_t _max_token_size_);*

*void *coap_context_get_app_data(const coap_context_t *_context_);*

*void coap_context_set_cid_tuple_change(coap_context_t *_context_context, uint8_t _every_);*
*int coap_context_set_cid_tuple_change(coap_context_t *_context_context, uint8_t _every_);*

For specific (D)TLS library support, link with
*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
Expand Down Expand Up @@ -190,7 +190,8 @@ pointer previously defined by *coap_context_set_app_data*().

The *coap_context_set_cid_tuple_change*() function is used to define to a client
to force the client's port to change _every_ packets sent, providing the ability
to test a CID (RFC9146) enabled server.
to test a CID (RFC9146) enabled server. Only supported by DTLS libraries that
support CID.

RETURN VALUES
-------------
Expand All @@ -211,6 +212,8 @@ out an idle server session.

*coap_context_get_app_data*() returns a previously defined pointer.

*coap_context_set_cid_tuple_change*() returns 1 on success, else 0;

SEE ALSO
--------
*coap_session*(3)
Expand Down
4 changes: 3 additions & 1 deletion src/coap_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,7 @@ coap_string_tls_support(char *buffer, size_t bufsize) {
const int have_pki = coap_dtls_pki_is_supported();
const int have_pkcs11 = coap_dtls_pkcs11_is_supported();
const int have_rpk = coap_dtls_rpk_is_supported();
const int have_cid = coap_dtls_cid_is_supported();
const int have_oscore = coap_oscore_is_supported();
const int have_ws = coap_ws_is_supported();

Expand All @@ -1241,13 +1242,14 @@ coap_string_tls_support(char *buffer, size_t bufsize) {
return buffer;
}
snprintf(buffer, bufsize,
"(%sDTLS and %sTLS support; %sPSK, %sPKI, %sPKCS11, and %sRPK support)\n(%sOSCORE)\n(%sWebSockets)",
"(%sDTLS and %sTLS support; %sPSK, %sPKI, %sPKCS11, %sRPK and %sCID support)\n(%sOSCORE)\n(%sWebSockets)",
have_dtls ? "" : "No ",
have_tls ? "" : "no ",
have_psk ? "" : "no ",
have_pki ? "" : "no ",
have_pkcs11 ? "" : "no ",
have_rpk ? "" : "no ",
have_cid ? "" : "no ",
have_oscore ? "Have " : "No ",
have_ws ? "Have " : "No ");
return buffer;
Expand Down
18 changes: 18 additions & 0 deletions src/coap_gnutls.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,24 @@ coap_dtls_rpk_is_supported(void) {
#endif /* GNUTLS_VERSION_NUMBER < 0x030606 */
}

/*
* return 0 failed
* 1 passed
*/
int
coap_dtls_cid_is_supported(void) {
return 0;
}

#if COAP_CLIENT_SUPPORT
int
coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
(void)c_context;
(void)every;
return 0;
}
#endif /* COAP_CLIENT_SUPPORT */

coap_tls_version_t *
coap_get_tls_library_version(void) {
static coap_tls_version_t version;
Expand Down
3 changes: 2 additions & 1 deletion src/coap_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -782,8 +782,9 @@ static uint32_t cid_track_counter;
static void
coap_test_cid_tuple_change(coap_session_t *session) {
if (session->type == COAP_SESSION_TYPE_CLIENT &&
session->negotiated_cid &&
session->state == COAP_SESSION_STATE_ESTABLISHED &&
COAP_PROTO_NOT_RELIABLE(session->proto) && session->context->testing_cids) {
session->proto == COAP_PROTO_DTLS && session->context->testing_cids) {
if ((++cid_track_counter) % session->context->testing_cids == 0) {
coap_address_t local_if = session->addr_info.local;
uint16_t port = coap_address_get_port(&local_if);
Expand Down
52 changes: 52 additions & 0 deletions src/coap_mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,31 @@ do_mbedtls_handshake(coap_session_t *c_session,
coap_log_debug("* %s: Mbed TLS established\n",
coap_session_str(c_session));
ret = 1;
#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
#if COAP_CLIENT_SUPPORT
if (c_session->type == COAP_SESSION_TYPE_CLIENT &&
c_session->proto == COAP_PROTO_DTLS) {
coap_mbedtls_context_t *m_context;

m_context = (coap_mbedtls_context_t *)c_session->context->dtls_context;
if ((m_context->psk_pki_enabled & IS_PSK && c_session->cpsk_setup_data.use_cid) ||
m_context->setup_data.use_cid) {
unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX];
int enabled;
size_t peer_cid_len;

/* See whether CID was negotiated */
if (mbedtls_ssl_get_peer_cid(&m_env->ssl, &enabled, peer_cid, &peer_cid_len) == 0 &&
enabled == MBEDTLS_SSL_CID_ENABLED) {
c_session->negotiated_cid = 1;
} else {
coap_log_info("** %s: CID was not negotiated\n", coap_session_str(c_session));
c_session->negotiated_cid = 0;
}
}
}
#endif /* COAP_CLIENT_SUPPORT */
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
break;
case MBEDTLS_ERR_SSL_WANT_READ:
case MBEDTLS_ERR_SSL_WANT_WRITE:
Expand Down Expand Up @@ -1886,6 +1911,33 @@ coap_dtls_rpk_is_supported(void) {
return 0;
}

/*
* return 0 failed
* 1 passed
*/
int
coap_dtls_cid_is_supported(void) {
#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
return 1;
#else /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
return 0;
#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
}

#if COAP_CLIENT_SUPPORT
int
coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
c_context->testing_cids = every;
return 1;
#else /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
(void)c_context;
(void)every;
return 0;
#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
}
#endif /* COAP_CLIENT_SUPPORT */

void *
coap_dtls_new_context(coap_context_t *c_context) {
coap_mbedtls_context_t *m_context;
Expand Down
5 changes: 3 additions & 2 deletions src/coap_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,13 +459,14 @@ coap_context_set_keepalive(coap_context_t *context, unsigned int seconds) {
context->ping_timeout = seconds;
}

void
int
coap_context_set_cid_tuple_change(coap_context_t *context, uint8_t every) {
#if COAP_CLIENT_SUPPORT
context->testing_cids = every;
return coap_dtls_set_cid_tuple_change(context, every);
#else /* ! COAP_CLIENT_SUPPORT */
(void)context;
(void)every;
return 0;
#endif /* ! COAP_CLIENT_SUPPORT */
}

Expand Down
18 changes: 18 additions & 0 deletions src/coap_notls.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,24 @@ coap_dtls_rpk_is_supported(void) {
return 0;
}

/*
* return 0 failed
* 1 passed
*/
int
coap_dtls_cid_is_supported(void) {
return 0;
}

#if COAP_CLIENT_SUPPORT
int
coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
(void)c_context;
(void)every;
return 0;
}
#endif /* COAP_CLIENT_SUPPORT */

coap_tls_version_t *
coap_get_tls_library_version(void) {
static coap_tls_version_t version;
Expand Down
18 changes: 18 additions & 0 deletions src/coap_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,24 @@ coap_dtls_rpk_is_supported(void) {
return 0;
}

/*
* return 0 failed
* 1 passed
*/
int
coap_dtls_cid_is_supported(void) {
return 0;
}

#if COAP_CLIENT_SUPPORT
int
coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
(void)c_context;
(void)every;
return 0;
}
#endif /* COAP_CLIENT_SUPPORT */

coap_tls_version_t *
coap_get_tls_library_version(void) {
static coap_tls_version_t version;
Expand Down
16 changes: 12 additions & 4 deletions src/coap_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,7 @@ coap_endpoint_get_session(coap_endpoint_t *endpoint,
#define DTLS_HT_CLIENT_HELLO 1 /* Client Hello handshake type */
#define DTLS_CT_CID 25 /* Content Type Connection ID */
#define OFF_CID 11 /* offset of CID in dtls_record_handshake_t */
#define OFF_CID_DTLS13 1 /* offset of CID in DTLS1.3 Unified Header */

const uint8_t *payload = (const uint8_t *)packet->payload;
size_t length = packet->length;
Expand All @@ -1157,18 +1158,24 @@ coap_endpoint_get_session(coap_endpoint_t *endpoint,
OFF_HANDSHAKE_TYPE + 1);
return NULL;
}
if (payload[OFF_CONTENT_TYPE] == DTLS_CT_CID) {
if ((payload[OFF_CONTENT_TYPE] & 0x30) == 0x30 ||
payload[OFF_CONTENT_TYPE] == DTLS_CT_CID) {
/* Client may have changed its IP address */
int changed = 0;

SESSIONS_ITER(endpoint->sessions, session, rtmp) {
if (session->client_cid) {
if (memcmp(session->client_cid->s, &payload[OFF_CID],
session->client_cid->length) == 0) {
if ((session->is_dtls13 && (payload[OFF_CONTENT_TYPE] & 0x30) == 0x30 &&
memcmp(session->client_cid->s, &payload[OFF_CID_DTLS13],
session->client_cid->length) == 0) ||
(!session->is_dtls13 && payload[OFF_CONTENT_TYPE] == DTLS_CT_CID &&
memcmp(session->client_cid->s, &payload[OFF_CID],
session->client_cid->length) == 0)) {
/* Updating IP address */
coap_log_info("***%s: CID: Old Client Session\n", coap_session_str(session));
SESSIONS_DELETE(endpoint->sessions, session);
session->addr_info = packet->addr_info;
memcpy(&session->addr_hash, &addr_hash, sizeof(session->addr_hash));
SESSIONS_ADD(endpoint->sessions, session);
coap_log_info("***%s: CID: New Client Session\n", coap_session_str(session));
return session;
Expand All @@ -1184,7 +1191,8 @@ coap_endpoint_get_session(coap_endpoint_t *endpoint,
/* only log if not a late alert */
if (payload[OFF_CONTENT_TYPE] != DTLS_CT_ALERT)
coap_log_debug("coap_dtls_hello: ContentType %d Handshake %d dropped\n",
payload[OFF_CONTENT_TYPE], payload[OFF_HANDSHAKE_TYPE]);
payload[OFF_CONTENT_TYPE],
payload[OFF_HANDSHAKE_TYPE]);
return NULL;
}
}
Expand Down
Loading

0 comments on commit 8b12795

Please sign in to comment.