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 - Work with CoAP server endpoints
10

SYNOPSIS

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

DESCRIPTION

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

RETURN VALUES

144       coap_context_set_pki(), coap_context_set_pki_root_cas() and
145       coap_context_set_psk2() functions return 1 on success, 0 on failure.
146
147       coap_new_endpoint() function returns a newly created endpoint or NULL
148       if there is a creation failure.
149
150       coap_join_mcast_group_intf() returns 0 on success, -1 on failure.
151

EXAMPLES

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

SEE ALSO

531       coap_block(3), coap_context(3), coap_encryption(3),
532       coap_endpoint_client()3), coap_resource(3), coap_session(3) and
533       coap_tls_library(3)
534

FURTHER INFORMATION

536       See "RFC7252: The Constrained Application Protocol (CoAP)" for further
537       information.
538

BUGS

540       Please report bugs on the mailing list for libcoap:
541       libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
542       https://github.com/obgm/libcoap/issues
543

AUTHORS

545       The libcoap project <libcoap-developers@lists.sourceforge.net>
546
547
548
549coap_endpoint_server 4.3.0        01/20/2022           COAP_ENDPOINT_SERVER(3)
Impressum