1// -*- mode:doc; -*- 2// vim: set syntax=asciidoc,tw=0: 3 4coap_endpoint_server(3) 5======================= 6:doctype: manpage 7:man source: coap_endpoint_server 8:man version: @PACKAGE_VERSION@ 9:man manual: libcoap Manual 10 11NAME 12---- 13coap_endpoint_server, 14coap_context_set_pki, 15coap_context_set_pki_root_cas, 16coap_context_set_psk2, 17coap_new_endpoint, 18coap_free_endpoint, 19coap_endpoint_set_default_mtu, 20coap_join_mcast_group_intf 21- Work with CoAP server endpoints 22 23SYNOPSIS 24-------- 25*#include <coap@LIBCOAP_API_VERSION@/coap.h>* 26 27*int coap_context_set_pki(coap_context_t *_context_, 28const coap_dtls_pki_t *_setup_data_);* 29 30*int coap_context_set_pki_root_cas(coap_context_t *_context_, 31const char *_ca_file_, const char *_ca_dir_);* 32 33*int coap_context_set_psk2(coap_context_t *_context_, 34coap_dtls_spsk_t *setup_data);* 35 36*coap_endpoint_t *coap_new_endpoint(coap_context_t *_context_, 37const coap_address_t *_listen_addr_, coap_proto_t _proto_);* 38 39*void coap_free_endpoint(coap_endpoint_t *_endpoint_);* 40 41*void coap_endpoint_set_default_mtu(coap_endpoint_t *_endpoint_, 42unsigned _mtu_);* 43 44*int coap_join_mcast_group_intf(coap_context_t *_context_, 45const char *_groupname_, const char *_ifname_);* 46 47For specific (D)TLS library support, link with 48*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, 49*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* 50or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with 51*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. 52 53DESCRIPTION 54----------- 55This man page focuses on the setting up of a CoAP server endpoint. For a CoAP 56client endpoint, see *coap_endpoint_client*(3). 57 58The CoAP stack's global state is stored in a coap_context_t Context object. 59Resources, Endpoints and Sessions are associated with this context object. 60There can be more than one coap_context_t object per application, it is up to 61the application to manage each one accordingly. 62 63A CoAP Session maintains the state of an ongoing connection between a Client 64and Server which is stored in a coap_session_t Session object. A CoAP session 65is tracked by local port, CoAP protocol, remote IP address and remote port. 66 67The Session network traffic can be encrypted or un-encrypted if there is an 68underlying TLS library. 69 70If TLS is going to be used for encrypting the network traffic, then the TLS 71information for Pre-Shared Keys (PSK) or Public Key Infrastructure (PKI) needs 72to be configured before any network traffic starts to flow. For Servers, this 73has to be done before the Endpoint is created, for Clients, this is done 74during the Client Session set up. 75 76For Servers, all the encryption information is held internally by the TLS 77Context level and the CoAP Context level as the Server is listening for new 78incoming traffic based on the Endpoint definition. The TLS and CoAP session 79will not get built until the new traffic starts, which is done by the libcoap 80library. 81 82In principle the set-up sequence for CoAP Servers looks like 83---- 84coap_new_context() 85coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI 86coap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required 87coap_new_endpoint() 88---- 89 90Multiple endpoints can be set up per Context, each listening for a new traffic 91flow with different TCP/UDP protocols, TLS protocols, port numbers etc. When a 92new traffic flow is started, then the CoAP library will create and start a new 93server session. 94 95The *coap_context_set_pki*() function, for a specific _context_, is used to 96configure the TLS context using the _setup_data_ variables as defined in the 97coap_dtls_pki_t structure - see *coap_encryption*(3). 98 99The *coap_context_set_pki_root_cas*() function is used to define a set of 100root CAs to be used instead of the default set of root CAs provided as a part 101of the TLS library. _ca_file_ points to a PEM encoded file containing the 102list of CAs. _ca_file can be NULL. _ca_dir_ points to a directory 103containing a set of PEM encoded files containing rootCAs. _ca_dir_ can be 104NULL. One or both of _ca_file_ and _ca_dir_ must be set. + 105*NOTE:* Some TLS libraries send the full list of CAs added by this function 106during the (D)TLS session setup handshakes. To stop this, either provide a 107single CA using the _ca_file_ definition in _pki_key_ in _setup_data_ variable 108when calling *coap_context_set_pki*(), or set _check_common_ca to 0 in 109_setup_data_ variable. See *coap_encryption*(3). 110 111The *coap_context_set_psk2*() function is used to configure the TLS context 112using the _setup_data_ variables as defined in the 113coap_dtls_spsk_t structure - see *coap_encryption*(3). 114This function can only be used for servers as _setup_data_ provides 115a _hint_, not an _identity_. 116 117The *coap_new_endpoint*() function creates a new endpoint for _context_ that 118is listening for new traffic on the IP address and port number defined by 119_listen_addr_. If the port number is 0, then the default CoAP port is used. 120Different CoAP protocols can be defined for _proto_ - the current supported 121list is: 122 123[source, c] 124---- 125COAP_PROTO_UDP 126COAP_PROTO_DTLS 127COAP_PROTO_TCP 128COAP_PROTO_TLS 129---- 130 131*coap_tcp_is_supported*(), *coap_dtls_is_supported*() and 132*coap_tls_is_supported*() can be used for checking whether the underlying 133TCP or (D)TLS protocol support is available. See *coap_tls_library(3)* for 134further information. 135 136When traffic starts to come in from a client, a server CoAP Session is created 137associated with this endpoint. This CoAP Session is created with a reference 138count of 0. This means that if the server session is not used for 5 minutes, 139then it will get completely freed off. See coap_session_reference(3) and 140coap_session_release(3) for further information. 141 142The *coap_free_endpoint*() function must be used to free off the _endpoint_. 143It clears out all the sessions associated with this endpoint. 144 145The *coap_endpoint_set_default_mtu*() function is used to set the MTU size 146(the maximum message size) of the data in a packet, excluding any IP or 147TCP/UDP overhead to _mtu_ for the _endpoint_. A sensible default is 1280. 148 149The *coap_join_mcast_group_intf*() function is used to join the currently 150defined endpoints that are UDP, associated with _context_, to the defined 151multicast group _groupname_. If _ifname_ is not NULL, then the multicast group 152is associated with this interface, otherwise the underlying O/S will choose the 153first appropriate interface. When the endpoint is freed off, the associated 154multicast group will be removed. The registered multicast addresses for CoAP 155are 224.0.1.187, ff0x::fd (Variable-Scope) - i.e. ff02::fd (Link-Local) and 156ff05::fd (Site-Local). 157 158RETURN VALUES 159------------- 160*coap_context_set_pki*(), *coap_context_set_pki_root_cas*() and 161*coap_context_set_psk2*() functions return 1 on success, 0 on failure. 162 163*coap_new_endpoint*() function returns a newly created endpoint or 164NULL if there is a creation failure. 165 166*coap_join_mcast_group_intf*() returns 0 on success, -1 on failure. 167 168EXAMPLES 169-------- 170*CoAP Server Non-Encrypted Setup* 171 172[source, c] 173---- 174#include <coap@LIBCOAP_API_VERSION@/coap.h> 175 176static coap_context_t * 177setup_server_context (void) { 178 coap_endpoint_t *endpoint; 179 coap_address_t listen_addr; 180 coap_context_t *context = coap_new_context(NULL); 181 182 if (!context) 183 return NULL; 184 /* See coap_block(3) */ 185 coap_context_set_block_mode(context, 186 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 187 188 189 coap_address_init(&listen_addr); 190 listen_addr.addr.sa.sa_family = AF_INET; 191 listen_addr.addr.sin.sin_port = htons (5683); 192 193 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP); 194 if (!endpoint) { 195 coap_free_context(context); 196 return NULL; 197 } 198 199 /* Initialize resources - See coap_resource(3) init_resources() example */ 200 201 return context; 202} 203---- 204 205*CoAP Server DTLS PKI Setup* 206[source, c] 207---- 208#include <coap@LIBCOAP_API_VERSION@/coap.h> 209 210typedef struct valid_cns_t { 211 size_t count; 212 char **cn_list; 213} valid_cns_t; 214 215/* 216 * Common Name (CN) Callback verifier 217 */ 218static int 219verify_cn_callback(const char *cn, 220 const uint8_t *asn1_public_cert, 221 size_t asn1_length, 222 coap_session_t *c_session, 223 unsigned depth, 224 int validated, 225 void *arg 226) { 227 valid_cns_t *valid_cn_list = (valid_cns_t*)arg; 228 size_t i; 229 /* Remove (void) definition if variable is used */ 230 (void)asn1_public_cert; 231 (void)asn1_length; 232 (void)c_session; 233 (void)depth; 234 (void)validated; 235 236 /* Check that the CN is valid */ 237 for (i = 0; i < valid_cn_list->count; i++) { 238 if (!strcasecmp(cn, valid_cn_list->cn_list[i])) { 239 return 1; 240 } 241 } 242 return 0; 243} 244 245typedef struct sni_def_t { 246 char* sni; 247 coap_dtls_key_t key; 248} sni_def_t; 249 250typedef struct valid_snis_t { 251 size_t count; 252 sni_def_t *sni_list; 253} valid_snis_t; 254 255/* 256 * Subject Name Identifier (SNI) callback verifier 257 */ 258static coap_dtls_key_t * 259verify_pki_sni_callback(const char *sni, 260 void *arg 261) { 262 valid_snis_t *valid_sni_list = (valid_snis_t *)arg; 263 size_t i; 264 265 /* Check that the SNI is valid */ 266 for (i = 0; i < valid_sni_list->count; i++) { 267 if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { 268 return &valid_sni_list->sni_list[i].key; 269 } 270 } 271 return NULL; 272} 273 274/* 275 * Set up PKI encryption information 276 */ 277static coap_context_t * 278setup_server_context_pki (const char *public_cert_file, 279 const char *private_key_file, 280 const char *ca_file, 281 valid_cns_t *valid_cn_list, 282 valid_snis_t *valid_sni_list 283) { 284 coap_endpoint_t *endpoint; 285 coap_address_t listen_addr; 286 coap_dtls_pki_t dtls_pki; 287 coap_context_t *context; 288 289 /* See coap_tls_library(3) */ 290 if (!coap_dtls_is_supported()) 291 return NULL; 292 293 context = coap_new_context(NULL); 294 if (!context) 295 return NULL; 296 /* See coap_block(3) */ 297 coap_context_set_block_mode(context, 298 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 299 300 301 memset (&dtls_pki, 0, sizeof (dtls_pki)); 302 303 /* see coap_encryption(3) */ 304 dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; 305 dtls_pki.verify_peer_cert = 1; 306 dtls_pki.check_common_ca = 1; 307 dtls_pki.allow_self_signed = 1; 308 dtls_pki.allow_expired_certs = 1; 309 dtls_pki.cert_chain_validation = 1; 310 dtls_pki.cert_chain_verify_depth = 1; 311 dtls_pki.check_cert_revocation = 1; 312 dtls_pki.allow_no_crl = 1; 313 dtls_pki.allow_expired_crl = 1; 314 dtls_pki.allow_bad_md_hash = 0; 315 dtls_pki.allow_short_rsa_length = 0; 316 dtls_pki.is_rpk_not_cert = 0; /* Set to 1 if RPK */ 317 dtls_pki.validate_cn_call_back = verify_cn_callback; 318 dtls_pki.cn_call_back_arg = valid_cn_list; 319 dtls_pki.validate_sni_call_back = verify_pki_sni_callback; 320 dtls_pki.sni_call_back_arg = valid_sni_list; 321 dtls_pki.additional_tls_setup_call_back = NULL; 322 dtls_pki.client_sni = NULL; 323 dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; 324 dtls_pki.pki_key.key.pem.ca_file = ca_file; 325 dtls_pki.pki_key.key.pem.public_cert = public_cert_file; 326 dtls_pki.pki_key.key.pem.private_key = private_key_file; 327 328 if (coap_context_set_pki(context, &dtls_pki)) { 329 coap_free_context(context); 330 return NULL; 331 } 332 333 coap_address_init(&listen_addr); 334 listen_addr.addr.sa.sa_family = AF_INET; 335 listen_addr.addr.sin.sin_port = htons (5684); 336 337 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); 338 if (!endpoint) { 339 coap_free_context(context); 340 return NULL; 341 } 342 343 /* Initialize resources - See coap_resource(3) init_resources() example */ 344 345 return context; 346} 347---- 348 349*CoAP Server DTLS PSK Setup* 350[source, c] 351---- 352#include <coap@LIBCOAP_API_VERSION@/coap.h> 353 354typedef struct id_def_t { 355 char* id; 356 coap_bin_const_t key; 357} id_def_t; 358 359typedef struct valid_ids_t { 360 int count; 361 id_def_t *id_list; 362} valid_ids_t; 363 364/* 365 * PSK Identity Pre-Shared Key selection Callback function 366 */ 367static const coap_bin_const_t * 368verify_id_callback(coap_bin_const_t *identity, 369 coap_session_t *c_session, 370 void *arg 371) { 372 valid_ids_t *valid_id_list = (valid_ids_t*)arg; 373 int i; 374 /* Remove (void) definition if variable is used */ 375 (void)c_session; 376 377 /* Check that the Identity is valid */ 378 for (i = 0; i < valid_id_list->count; i++) { 379 if (!strcasecmp((const char*)identity->s, valid_id_list->id_list[i].id)) { 380 return &valid_id_list->id_list[i].key; 381 } 382 } 383 return NULL; 384} 385 386typedef struct sni_psk_def_t { 387 char* sni; 388 coap_dtls_spsk_info_t psk_info; 389} sni_psk_def_t; 390 391typedef struct valid_psk_snis_t { 392 int count; 393 sni_psk_def_t *sni_list; 394} valid_psk_snis_t; 395 396/* 397 * PSK Subject Name Identifier (SNI) callback verifier 398 */ 399static const coap_dtls_spsk_info_t * 400verify_psk_sni_callback(const char *sni, 401 coap_session_t *c_session, 402 void *arg 403) { 404 valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg; 405 int i; 406 /* Remove (void) definition if variable is used */ 407 (void)c_session; 408 409 /* Check that the SNI is valid */ 410 for (i = 0; i < valid_sni_list->count; i++) { 411 if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { 412 return &valid_sni_list->sni_list[i].psk_info; 413 } 414 } 415 return NULL; 416} 417 418static coap_context_t * 419setup_server_context_psk (const char *hint, 420 const uint8_t *key, 421 unsigned int key_len, 422 valid_ids_t *valid_id_list, 423 valid_psk_snis_t *valid_sni_list 424) { 425 coap_endpoint_t *endpoint; 426 coap_address_t listen_addr; 427 coap_context_t *context; 428 coap_dtls_spsk_t dtls_psk; 429 430 /* See coap_tls_library(3) */ 431 if (!coap_dtls_is_supported()) 432 return NULL; 433 434 context = coap_new_context(NULL); 435 if (!context) 436 return NULL; 437 /* See coap_block(3) */ 438 coap_context_set_block_mode(context, 439 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 440 441 442 memset (&dtls_psk, 0, sizeof (dtls_psk)); 443 444 /* see coap_encryption(3) */ 445 dtls_psk.version = COAP_DTLS_SPSK_SETUP_VERSION; 446 dtls_psk.validate_id_call_back = verify_id_callback; 447 dtls_psk.id_call_back_arg = valid_id_list; 448 dtls_psk.validate_sni_call_back = verify_psk_sni_callback; 449 dtls_psk.sni_call_back_arg = valid_sni_list; 450 dtls_psk.psk_info.hint.s = (const uint8_t*)hint; 451 dtls_psk.psk_info.hint.length = hint ? strlen(hint) : 0; 452 dtls_psk.psk_info.key.s = key; 453 dtls_psk.psk_info.key.length = key_len; 454 455 if (coap_context_set_psk2(context, &dtls_psk)) { 456 coap_free_context(context); 457 return NULL; 458 } 459 460 coap_address_init(&listen_addr); 461 listen_addr.addr.sa.sa_family = AF_INET; 462 listen_addr.addr.sin.sin_port = htons (5684); 463 464 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); 465 if (!endpoint) { 466 coap_free_context(context); 467 return NULL; 468 } 469 470 /* Initialize resources - See coap_resource(3) init_resources() example */ 471 472 return context; 473} 474---- 475 476*CoAP Client DTLS PSK Setup* 477[source, c] 478---- 479#include <coap@LIBCOAP_API_VERSION@/coap.h> 480 481#include <stdio.h> 482 483#ifndef min 484#define min(a,b) ((a) < (b) ? (a) : (b)) 485#endif 486 487static const coap_dtls_cpsk_info_t * 488verify_ih_callback(coap_str_const_t *hint, 489 coap_session_t *c_session, 490 void *arg 491) { 492 coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg; 493 char lhint[COAP_DTLS_HINT_LENGTH]; 494 /* Remove (void) definition if variable is used */ 495 (void)c_session; 496 497 snprintf(lhint, sizeof(lhint), "%.*s", (int)hint->length, hint->s); 498 coap_log(LOG_INFO, "Identity Hint '%s' provided\n", lhint); 499 500 /* Just use the defined information for now as passed in by arg */ 501 return psk_info; 502} 503 504static coap_dtls_cpsk_t dtls_psk; 505static char client_sni[256]; 506 507static coap_session_t * 508setup_client_session_psk (const char *uri, 509 struct in_addr ip_address, 510 const uint8_t *identity, 511 unsigned int identity_len, 512 const uint8_t *key, 513 unsigned int key_len 514) { 515 coap_session_t *session; 516 coap_address_t server; 517 coap_context_t *context = coap_new_context(NULL); 518 519 if (!context) 520 return NULL; 521 /* See coap_block(3) */ 522 coap_context_set_block_mode(context, 523 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 524 525 526 coap_address_init(&server); 527 server.addr.sa.sa_family = AF_INET; 528 server.addr.sin.sin_addr = ip_address; 529 server.addr.sin.sin_port = htons (5684); 530 531 /* See coap_encryption(3) */ 532 memset (&dtls_psk, 0, sizeof(dtls_psk)); 533 dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; 534 dtls_psk.validate_ih_call_back = verify_ih_callback; 535 dtls_psk.ih_call_back_arg = &dtls_psk.psk_info; 536 if (uri) 537 memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1)); 538 else 539 memcpy(client_sni, "localhost", 9); 540 dtls_psk.client_sni = client_sni; 541 dtls_psk.psk_info.identity.s = identity; 542 dtls_psk.psk_info.identity.length = identity_len; 543 dtls_psk.psk_info.key.s = key; 544 dtls_psk.psk_info.key.length = key_len; 545 session = coap_new_client_session_psk2(context, NULL, &server, 546 COAP_PROTO_DTLS, &dtls_psk); 547 if (!session) { 548 coap_free_context(context); 549 return NULL; 550 } 551 /* The context is in session->context */ 552 return session; 553} 554 555---- 556 557SEE ALSO 558-------- 559*coap_block*(3), *coap_context*(3), *coap_encryption*(3), 560*coap_endpoint_client*()3), *coap_resource*(3), *coap_session*(3) and 561*coap_tls_library*(3) 562 563FURTHER INFORMATION 564------------------- 565See "RFC7252: The Constrained Application Protocol (CoAP)" for further 566information. 567 568BUGS 569---- 570Please report bugs on the mailing list for libcoap: 571libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at 572https://github.com/obgm/libcoap/issues 573 574AUTHORS 575------- 576The libcoap project <libcoap-developers@lists.sourceforge.net> 577