1COAP_ENDPOINT_SERVER(3)         libcoap Manual         COAP_ENDPOINT_SERVER(3)
2
3
4

NAME

6       coap_endpoint_server, coap_context_set_pki,
7       coap_context_set_pki_root_cas, coap_context_set_psk2,
8       coap_new_endpoint, coap_free_endpoint, coap_endpoint_set_default_mtu,
9       coap_join_mcast_group_intf, coap_mcast_per_resource - Work with CoAP
10       server endpoints
11

SYNOPSIS

13       #include <coap3/coap.h>
14
15       int coap_context_set_pki(coap_context_t *context, const coap_dtls_pki_t
16       *setup_data);
17
18       int coap_context_set_pki_root_cas(coap_context_t *context, const char
19       *ca_file, const char *ca_dir);
20
21       int coap_context_set_psk2(coap_context_t *context, coap_dtls_spsk_t
22       *setup_data);
23
24       coap_endpoint_t *coap_new_endpoint(coap_context_t *context, const
25       coap_address_t *listen_addr, coap_proto_t proto);
26
27       void coap_free_endpoint(coap_endpoint_t *endpoint);
28
29       void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned
30       mtu);
31
32       int coap_join_mcast_group_intf(coap_context_t *context, const char
33       *groupname, const char *ifname);
34
35       void coap_mcast_per_resource(coap_context_t *context);
36
37       For specific (D)TLS library support, link with -lcoap-3-notls,
38       -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls or
39       -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default
40       (D)TLS library support.
41

DESCRIPTION

43       This man page focuses on the setting up of a CoAP server endpoint. For
44       a CoAP client endpoint, see coap_endpoint_client(3).
45
46       The CoAP stack’s global state is stored in a coap_context_t Context
47       object. Resources, Endpoints and Sessions are associated with this
48       context object. There can be more than one coap_context_t object per
49       application, it is up to the application to manage each one
50       accordingly.
51
52       A CoAP Session maintains the state of an ongoing connection between a
53       Client and Server which is stored in a coap_session_t Session object. A
54       CoAP session is tracked by local port, CoAP protocol, remote IP address
55       and remote port.
56
57       The Session network traffic can be encrypted or un-encrypted if there
58       is an underlying TLS library.
59
60       If TLS is going to be used for encrypting the network traffic, then the
61       TLS information for Pre-Shared Keys (PSK) or Public Key Infrastructure
62       (PKI) needs to be configured before any network traffic starts to flow.
63       For Servers, this has to be done before the Endpoint is created, for
64       Clients, this is done during the Client Session set up.
65
66       For Servers, all the encryption information is held internally by the
67       TLS Context level and the CoAP Context level as the Server is listening
68       for new incoming traffic based on the Endpoint definition. The TLS and
69       CoAP session will not get built until the new traffic starts, which is
70       done by the libcoap library.
71
72       In principle the set-up sequence for CoAP Servers looks like
73
74           coap_new_context()
75           coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI
76           coap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required
77           coap_new_endpoint()
78
79       Multiple endpoints can be set up per Context, each listening for a new
80       traffic flow with different TCP/UDP protocols, TLS protocols, port
81       numbers etc. When a new traffic flow is started, then the CoAP library
82       will create and start a new server session.
83
84       The coap_context_set_pki() function, for a specific context, is used to
85       configure the TLS context using the setup_data variables as defined in
86       the coap_dtls_pki_t structure - see coap_encryption(3).
87
88       The coap_context_set_pki_root_cas() function is used to define a set of
89       root CAs to be used instead of the default set of root CAs provided as
90       a part of the TLS library. ca_file points to a PEM encoded file
91       containing the list of CAs. ca_file can be NULL. _ca_dir points to a
92       directory containing a set of PEM encoded files containing rootCAs.
93       ca_dir can be NULL. One or both of ca_file and ca_dir must be set.
94       NOTE: Some TLS libraries send the full list of CAs added by this
95       function during the (D)TLS session setup handshakes. To stop this,
96       either provide a single CA using the ca_file definition in pki_key in
97       setup_data variable when calling coap_context_set_pki(), or set
98       check_common_ca to 0 in _setup_data variable. See coap_encryption(3).
99
100       The coap_context_set_psk2() function is used to configure the TLS
101       context using the setup_data variables as defined in the
102       coap_dtls_spsk_t structure - see coap_encryption(3). This function can
103       only be used for servers as setup_data provides a hint, not an
104       identity.
105
106       The coap_new_endpoint() function creates a new endpoint for context
107       that is listening for new traffic on the IP address and port number
108       defined by listen_addr. If the port number is 0, then the default CoAP
109       port is used. Different CoAP protocols can be defined for proto - the
110       current supported list is:
111
112           COAP_PROTO_UDP
113           COAP_PROTO_DTLS
114           COAP_PROTO_TCP
115           COAP_PROTO_TLS
116
117       coap_tcp_is_supported(), coap_dtls_is_supported() and
118       coap_tls_is_supported() can be used for checking whether the underlying
119       TCP or (D)TLS protocol support is available. See coap_tls_library(3)
120       for further information.
121
122       When traffic starts to come in from a client, a server CoAP Session is
123       created associated with this endpoint. This CoAP Session is created
124       with a reference count of 0. This means that if the server session is
125       not used for 5 minutes, then it will get completely freed off. See
126       coap_session_reference(3) and coap_session_release(3) for further
127       information.
128
129       The coap_free_endpoint() function must be used to free off the
130       endpoint. It clears out all the sessions associated with this endpoint.
131
132       The coap_endpoint_set_default_mtu() function is used to set the MTU
133       size (the maximum message size) of the data in a packet, excluding any
134       IP or TCP/UDP overhead to mtu for the endpoint. A sensible default is
135       1280.
136
137       The coap_join_mcast_group_intf() function is used to join the currently
138       defined endpoints that are UDP, associated with context, to the defined
139       multicast group groupname. If ifname is not NULL, then the multicast
140       group is associated with this interface, otherwise the underlying O/S
141       will choose the first appropriate interface. When the endpoint is freed
142       off, the associated multicast group will be removed. The registered
143       multicast addresses for CoAP are 224.0.1.187, ff0x::fd (Variable-Scope)
144       - i.e. ff02::fd (Link-Local) and ff05::fd (Site-Local).
145
146       The coap_mcast_per_resource() function enables mcast to be controlled
147       on a per resource basis giving the server application flexibility in
148       how to respond to mcast requests. With this enabled, this is done
149       through additional flag definitions when setting up each resource.
150

RETURN VALUES

152       coap_context_set_pki(), coap_context_set_pki_root_cas() and
153       coap_context_set_psk2() functions return 1 on success, 0 on failure.
154
155       coap_new_endpoint() function returns a newly created endpoint or NULL
156       if there is a creation failure.
157
158       coap_join_mcast_group_intf() returns 0 on success, -1 on failure.
159

EXAMPLES

161       CoAP Server Non-Encrypted Setup
162
163           #include <coap3/coap.h>
164
165           static coap_context_t *
166           setup_server_context (void) {
167             coap_endpoint_t *endpoint;
168             coap_address_t listen_addr;
169             coap_context_t *context = coap_new_context(NULL);
170
171             if (!context)
172               return NULL;
173             /* See coap_block(3) */
174             coap_context_set_block_mode(context,
175                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
176
177
178             coap_address_init(&listen_addr);
179             listen_addr.addr.sa.sa_family = AF_INET;
180             listen_addr.addr.sin.sin_port = htons (5683);
181
182             endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP);
183             if (!endpoint) {
184               coap_free_context(context);
185               return NULL;
186             }
187
188             /* Initialize resources - See coap_resource(3) init_resources() example */
189
190             return context;
191           }
192
193       CoAP Server DTLS PKI Setup
194
195           #include <coap3/coap.h>
196
197           typedef struct valid_cns_t {
198             size_t count;
199             char **cn_list;
200           } valid_cns_t;
201
202           /*
203            * Common Name (CN) Callback verifier
204            */
205           static int
206           verify_cn_callback(const char *cn,
207                              const uint8_t *asn1_public_cert,
208                              size_t asn1_length,
209                              coap_session_t *c_session,
210                              unsigned depth,
211                              int validated,
212                              void *arg
213           ) {
214             valid_cns_t *valid_cn_list = (valid_cns_t*)arg;
215             size_t i;
216             /* Remove (void) definition if variable is used */
217             (void)asn1_public_cert;
218             (void)asn1_length;
219             (void)c_session;
220             (void)depth;
221             (void)validated;
222
223             /* Check that the CN is valid */
224             for (i = 0; i < valid_cn_list->count; i++) {
225               if (!strcasecmp(cn, valid_cn_list->cn_list[i])) {
226                 return 1;
227               }
228             }
229             return 0;
230           }
231
232           typedef struct sni_def_t {
233             char* sni;
234             coap_dtls_key_t key;
235           } sni_def_t;
236
237           typedef struct valid_snis_t {
238             size_t count;
239             sni_def_t *sni_list;
240           } valid_snis_t;
241
242           /*
243            * Subject Name Identifier (SNI) callback verifier
244            */
245           static coap_dtls_key_t *
246           verify_pki_sni_callback(const char *sni,
247                                   void *arg
248           ) {
249             valid_snis_t *valid_sni_list = (valid_snis_t *)arg;
250             size_t i;
251
252             /* Check that the SNI is valid */
253             for (i = 0; i < valid_sni_list->count; i++) {
254               if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
255                 return &valid_sni_list->sni_list[i].key;
256               }
257             }
258             return NULL;
259           }
260
261           /*
262            * Set up PKI encryption information
263            */
264           static coap_context_t *
265           setup_server_context_pki (const char *public_cert_file,
266                                     const char *private_key_file,
267                                     const char *ca_file,
268                                     valid_cns_t *valid_cn_list,
269                                     valid_snis_t *valid_sni_list
270           ) {
271             coap_endpoint_t *endpoint;
272             coap_address_t listen_addr;
273             coap_dtls_pki_t dtls_pki;
274             coap_context_t *context;
275
276             /* See coap_tls_library(3) */
277             if (!coap_dtls_is_supported())
278               return NULL;
279
280             context = coap_new_context(NULL);
281             if (!context)
282               return NULL;
283             /* See coap_block(3) */
284             coap_context_set_block_mode(context,
285                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
286
287
288             memset (&dtls_pki, 0, sizeof (dtls_pki));
289
290             /* see coap_encryption(3) */
291             dtls_pki.version                 = COAP_DTLS_PKI_SETUP_VERSION;
292             dtls_pki.verify_peer_cert        = 1;
293             dtls_pki.check_common_ca         = 1;
294             dtls_pki.allow_self_signed       = 1;
295             dtls_pki.allow_expired_certs     = 1;
296             dtls_pki.cert_chain_validation   = 1;
297             dtls_pki.cert_chain_verify_depth = 1;
298             dtls_pki.check_cert_revocation   = 1;
299             dtls_pki.allow_no_crl            = 1;
300             dtls_pki.allow_expired_crl       = 1;
301             dtls_pki.allow_bad_md_hash       = 0;
302             dtls_pki.allow_short_rsa_length  = 0;
303             dtls_pki.is_rpk_not_cert         = 0; /* Set to 1 if RPK */
304             dtls_pki.validate_cn_call_back   = verify_cn_callback;
305             dtls_pki.cn_call_back_arg        = valid_cn_list;
306             dtls_pki.validate_sni_call_back  = verify_pki_sni_callback;
307             dtls_pki.sni_call_back_arg       = valid_sni_list;
308             dtls_pki.additional_tls_setup_call_back = NULL;
309             dtls_pki.client_sni              = NULL;
310             dtls_pki.pki_key.key_type        = COAP_PKI_KEY_PEM;
311             dtls_pki.pki_key.key.pem.ca_file = ca_file;
312             dtls_pki.pki_key.key.pem.public_cert = public_cert_file;
313             dtls_pki.pki_key.key.pem.private_key = private_key_file;
314
315             if (coap_context_set_pki(context, &dtls_pki)) {
316               coap_free_context(context);
317               return NULL;
318             }
319
320             coap_address_init(&listen_addr);
321             listen_addr.addr.sa.sa_family = AF_INET;
322             listen_addr.addr.sin.sin_port = htons (5684);
323
324             endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
325             if (!endpoint) {
326               coap_free_context(context);
327               return NULL;
328             }
329
330             /* Initialize resources - See coap_resource(3) init_resources() example */
331
332             return context;
333           }
334
335       CoAP Server DTLS PSK Setup
336
337           #include <coap3/coap.h>
338
339           typedef struct id_def_t {
340             char* id;
341             coap_bin_const_t key;
342           } id_def_t;
343
344           typedef struct valid_ids_t {
345             int count;
346             id_def_t *id_list;
347           } valid_ids_t;
348
349           /*
350            * PSK Identity Pre-Shared Key selection Callback function
351            */
352           static const coap_bin_const_t *
353           verify_id_callback(coap_bin_const_t *identity,
354                              coap_session_t *c_session,
355                              void *arg
356           ) {
357             valid_ids_t *valid_id_list = (valid_ids_t*)arg;
358             int i;
359             /* Remove (void) definition if variable is used */
360             (void)c_session;
361
362             /* Check that the Identity is valid */
363             for (i = 0; i < valid_id_list->count; i++) {
364               if (!strcasecmp((const char*)identity->s, valid_id_list->id_list[i].id)) {
365                 return &valid_id_list->id_list[i].key;
366               }
367             }
368             return NULL;
369           }
370
371           typedef struct sni_psk_def_t {
372             char* sni;
373             coap_dtls_spsk_info_t psk_info;
374           } sni_psk_def_t;
375
376           typedef struct valid_psk_snis_t {
377             int count;
378             sni_psk_def_t *sni_list;
379           } valid_psk_snis_t;
380
381           /*
382            * PSK Subject Name Identifier (SNI) callback verifier
383            */
384           static const coap_dtls_spsk_info_t *
385           verify_psk_sni_callback(const char *sni,
386                                   coap_session_t *c_session,
387                                   void *arg
388           ) {
389             valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg;
390             int i;
391             /* Remove (void) definition if variable is used */
392             (void)c_session;
393
394             /* Check that the SNI is valid */
395             for (i = 0; i < valid_sni_list->count; i++) {
396               if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
397                 return &valid_sni_list->sni_list[i].psk_info;
398               }
399             }
400             return NULL;
401           }
402
403           static coap_context_t *
404           setup_server_context_psk (const char *hint,
405                                     const uint8_t *key,
406                                     unsigned int key_len,
407                                     valid_ids_t *valid_id_list,
408                                     valid_psk_snis_t *valid_sni_list
409           ) {
410             coap_endpoint_t *endpoint;
411             coap_address_t listen_addr;
412             coap_context_t *context;
413             coap_dtls_spsk_t dtls_psk;
414
415             /* See coap_tls_library(3) */
416             if (!coap_dtls_is_supported())
417               return NULL;
418
419             context = coap_new_context(NULL);
420             if (!context)
421               return NULL;
422             /* See coap_block(3) */
423             coap_context_set_block_mode(context,
424                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
425
426
427             memset (&dtls_psk, 0, sizeof (dtls_psk));
428
429             /* see coap_encryption(3) */
430             dtls_psk.version                 = COAP_DTLS_SPSK_SETUP_VERSION;
431             dtls_psk.validate_id_call_back   = verify_id_callback;
432             dtls_psk.id_call_back_arg        = valid_id_list;
433             dtls_psk.validate_sni_call_back  = verify_psk_sni_callback;
434             dtls_psk.sni_call_back_arg       = valid_sni_list;
435             dtls_psk.psk_info.hint.s         = (const uint8_t*)hint;
436             dtls_psk.psk_info.hint.length    = hint ? strlen(hint) : 0;
437             dtls_psk.psk_info.key.s          = key;
438             dtls_psk.psk_info.key.length     = key_len;
439
440             if (coap_context_set_psk2(context, &dtls_psk)) {
441               coap_free_context(context);
442               return NULL;
443             }
444
445             coap_address_init(&listen_addr);
446             listen_addr.addr.sa.sa_family = AF_INET;
447             listen_addr.addr.sin.sin_port = htons (5684);
448
449             endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
450             if (!endpoint) {
451               coap_free_context(context);
452               return NULL;
453             }
454
455             /* Initialize resources - See coap_resource(3) init_resources() example */
456
457             return context;
458           }
459
460       CoAP Client DTLS PSK Setup
461
462           #include <coap3/coap.h>
463
464           #include <stdio.h>
465
466           #ifndef min
467           #define min(a,b) ((a) < (b) ? (a) : (b))
468           #endif
469
470           static const coap_dtls_cpsk_info_t *
471           verify_ih_callback(coap_str_const_t *hint,
472                              coap_session_t *c_session,
473                              void *arg
474           ) {
475             coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg;
476             char lhint[COAP_DTLS_HINT_LENGTH];
477             /* Remove (void) definition if variable is used */
478             (void)c_session;
479
480             snprintf(lhint, sizeof(lhint), "%.*s", (int)hint->length, hint->s);
481             coap_log(LOG_INFO, "Identity Hint '%s' provided\n", lhint);
482
483             /* Just use the defined information for now as passed in by arg */
484             return psk_info;
485           }
486
487           static coap_dtls_cpsk_t dtls_psk;
488           static char client_sni[256];
489
490           static coap_session_t *
491           setup_client_session_psk (const char *uri,
492                                     struct in_addr ip_address,
493                                     const uint8_t *identity,
494                                     unsigned int identity_len,
495                                     const uint8_t *key,
496                                     unsigned int key_len
497           ) {
498             coap_session_t *session;
499             coap_address_t server;
500             coap_context_t *context = coap_new_context(NULL);
501
502             if (!context)
503               return NULL;
504             /* See coap_block(3) */
505             coap_context_set_block_mode(context,
506                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
507
508
509             coap_address_init(&server);
510             server.addr.sa.sa_family = AF_INET;
511             server.addr.sin.sin_addr = ip_address;
512             server.addr.sin.sin_port = htons (5684);
513
514             /* See coap_encryption(3) */
515             memset (&dtls_psk, 0, sizeof(dtls_psk));
516             dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION;
517             dtls_psk.validate_ih_call_back = verify_ih_callback;
518             dtls_psk.ih_call_back_arg = &dtls_psk.psk_info;
519             if (uri)
520               memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1));
521             else
522               memcpy(client_sni, "localhost", 9);
523             dtls_psk.client_sni = client_sni;
524             dtls_psk.psk_info.identity.s = identity;
525             dtls_psk.psk_info.identity.length = identity_len;
526             dtls_psk.psk_info.key.s = key;
527             dtls_psk.psk_info.key.length = key_len;
528             session = coap_new_client_session_psk2(context, NULL, &server,
529                                                   COAP_PROTO_DTLS, &dtls_psk);
530             if (!session) {
531               coap_free_context(context);
532               return NULL;
533             }
534             /* The context is in session->context */
535             return session;
536           }
537

SEE ALSO

539       coap_block(3), coap_context(3), coap_encryption(3),
540       coap_endpoint_client(3), coap_resource(3), coap_session(3) and
541       coap_tls_library(3)
542

FURTHER INFORMATION

544       See "RFC7252: The Constrained Application Protocol (CoAP)" for further
545       information.
546

BUGS

548       Please report bugs on the mailing list for libcoap:
549       libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
550       https://github.com/obgm/libcoap/issues
551

AUTHORS

553       The libcoap project <libcoap-developers@lists.sourceforge.net>
554
555
556
557coap_endpoint_server 4.3.1        11/24/2022           COAP_ENDPOINT_SERVER(3)
Impressum