1.\" Copyright (c) 2020 Mariusz Zaborski <oshogbo@FreeBSD.org>
2.\"
3.\" Redistribution and use in source and binary forms, with or without
4.\" modification, are permitted provided that the following conditions
5.\" are met:
6.\" 1. Redistributions of source code must retain the above copyright
7.\"    notice, this list of conditions and the following disclaimer.
8.\" 2. Redistributions in binary form must reproduce the above copyright
9.\"    notice, this list of conditions and the following disclaimer in the
10.\"    documentation and/or other materials provided with the distribution.
11.\"
12.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
13.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
16.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22.\" SUCH DAMAGE.
23.\"
24.Dd December 6, 2023
25.Dt CAP_NET 3
26.Os
27.Sh NAME
28.Nm cap_bind ,
29.Nm cap_connect ,
30.Nm cap_getaddrinfo ,
31.Nm cap_gethostbyaddr ,
32.Nm cap_gethostbyname ,
33.Nm cap_gethostbyname2 ,
34.Nm cap_getnameinfo ,
35.Nm cap_net_free ,
36.Nm cap_net_limit ,
37.Nm cap_net_limit_addr2name ,
38.Nm cap_net_limit_addr2name_family ,
39.Nm cap_net_limit_bind ,
40.Nm cap_net_limit_connect ,
41.Nm cap_net_limit_init ,
42.Nm cap_net_limit_name2addr ,
43.Nm cap_net_limit_name2addr_family ,
44.Nd "library for networking in capability mode"
45.Sh LIBRARY
46.Lb libcap_net
47.Sh SYNOPSIS
48.In sys/nv.h
49.In libcasper.h
50.In casper/cap_net.h
51.Ft int
52.Fn cap_bind "cap_channel_t *chan" "int s" "const struct sockaddr *addr" "socklen_t addrlen"
53.Ft int
54.Fn cap_connect "cap_channel_t *chan" "int s" "const struct sockaddr *name" "socklen_t namelen"
55.Ft int
56.Fn cap_getaddrinfo "cap_channel_t *chan" "const char *hostname" "const char *servname" "const struct addrinfo *hints" "struct addrinfo **res"
57.Ft int
58.Fn cap_getnameinfo "cap_channel_t *chan" "const struct sockaddr *sa" "socklen_t salen" "char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags"
59.Ft "struct hostent *"
60.Fn cap_gethostbyname "const cap_channel_t *chan" "const char *name"
61.Ft "struct hostent *"
62.Fn cap_gethostbyname2 "const cap_channel_t *chan" "const char *name" "int af"
63.Ft "struct hostent *"
64.Fn cap_gethostbyaddr "const cap_channel_t *chan" "const void *addr" "socklen_t len" "int af"
65.Ft "cap_net_limit_t *"
66.Fn cap_net_limit_init "cap_channel_t *chan" "uint64_t mode"
67.Ft int
68.Fn cap_net_limit "cap_net_limit_t *limit"
69.Ft void
70.Fn cap_net_free "cap_net_limit_t *limit"
71.Ft "cap_net_limit_t *"
72.Fn cap_net_limit_addr2name_family "cap_net_limit_t *limit" "int *family" "size_t size"
73.Ft "cap_net_limit_t *"
74.Fn cap_net_limit_addr2name "cap_net_limit_t *limit" "const struct sockaddr *sa" "socklen_t salen"
75.Ft "cap_net_limit_t *"
76.Fn cap_net_limit_name2addr_family "cap_net_limit_t *limit" "int *family" "size_t size"
77.Ft "cap_net_limit_t *"
78.Fn cap_net_limit_name2addr "cap_net_limit_t *limit" "const char *name" "const char *serv"
79.Ft "cap_net_limit_t *"
80.Fn cap_net_limit_connect "cap_net_limit_t *limit" "const struct sockaddr *sa" "socklen_t salen"
81.Ft "cap_net_limit_t *"
82.Fn cap_net_limit_bind "cap_net_limit_t *limit" "const struct sockaddr *sa" "socklen_t salen"
83.Sh DESCRIPTION
84The functions
85.Fn cap_bind ,
86.Fn cap_connect ,
87.Fn cap_getaddrinfo ,
88.Fn cap_getnameinfo ,
89.Fn cap_gethostbyname ,
90.Fn cap_gethostbyname2 ,
91and
92.Fn cap_gethostbyaddr
93provide a set of APIs equivalent to
94.Xr bind 2 ,
95.Xr connect 2 ,
96.Xr getaddrinfo 3 ,
97.Xr getnameinfo 3 ,
98.Xr gethostbyname 3 ,
99.Xr gethostbyname2 3 ,
100and
101.Xr gethostbyaddr 3
102except that a connection to the
103.Nm system.net
104service needs to be provided.
105.Pp
106These functions, as well as
107.Fn cap_net_limit ,
108are reentrant but not thread-safe.
109That is, they may be called from separate threads only with different
110.Vt cap_channel_t
111arguments or with synchronization.
112.Sh LIMITS
113By default, the cap_net capability provides unrestricted access to the network
114namespace.
115Applications typically only require access to a small portion of the network
116namespace:
117The
118.Fn cap_net_limit
119function can be used to restrict access to the network.
120The
121.Fn cap_net_limit_init
122returns an opaque limit handle used to store a list of capabilities.
123The
124.Fv mode
125restricts the functionality of the service.
126Modes are encoded using the following flags:
127.Pp
128.Bd -literal -offset indent -compact
129CAPNET_ADDR2NAME		reverse DNS lookups are allowed with
130				cap_getnameinfo
131CAPNET_NAME2ADDR		name resolution is allowed with
132				cap_getaddrinfo
133CAPNET_DEPRECATED_ADDR2NAME	reverse DNS lookups are allowed with
134				cap_gethostbyaddr
135CAPNET_DEPRECATED_NAME2ADDR	name resolution is allowed with
136				cap_gethostbyname and cap_gethostbyname2
137CAPNET_BIND			bind syscall is allowed
138CAPNET_CONNECT			connect syscall is allowed
139CAPNET_CONNECTDNS		connect syscall is allowed to the values
140				returned from previous call to
141				the cap_getaddrinfo or cap_gethostbyname
142.Ed
143.Pp
144.Fn cap_net_limit_addr2name_family
145limits the
146.Fn cap_getnameinfo
147and
148.Fn cap_gethostbyaddr
149to do reverse DNS lookups to specific family (AF_INET, AF_INET6, etc.)
150.Pp
151.Fn cap_net_limit_addr2name
152limits the
153.Fn cap_getnameinfo
154and
155.Fn cap_gethostbyaddr
156to do reverse DNS lookups only on those specific structures.
157.Pp
158.Fn cap_net_limit_name2addr_family
159limits the
160.Fn cap_getaddrinfo ,
161.Fn cap_gethostbyname
162and
163.Fn cap_gethostbyname2
164to do the name resolution on specific family (AF_INET, AF_INET6, etc.)
165.Pp
166.Fn cap_net_limit_addr2name
167restricts
168.Fn cap_getaddrinfo ,
169.Fn cap_gethostbyname
170and
171.Fn cap_gethostbyname2
172to a set of domains.
173.Pp
174.Fn cap_net_limit_bind
175limits
176.Fn cap_bind
177to bind only on those specific structures.
178.Pp
179.Fn cap_net_limit_connect
180limits
181.Fn cap_connect
182to connect only on those specific structures.
183If the CAPNET_CONNECTDNS is set the limits are extended to the values returned
184by
185.Fn cap_getaddrinfo ,
186.Fn cap_gethostbyname
187and
188.Fn cap_gethostbyname2
189In case of the
190.Fn cap_getaddrinfo
191the restriction is strict.
192In case of the
193.Fn cap_gethostbyname
194and
195.Fn cap_gethostbyname2
196any port will be accepted in the
197.Fn cap_connect
198function.
199.Pp
200The
201.Fn cap_net_limit
202will consume and apply the limits.
203.Pp
204Once a set of limits is applied, subsequent calls to
205.Fn cap_net_limit
206will fail unless the new set is a subset of the current set.
207.Pp
208If the
209.Fn cap_net_limit
210was not called the rights may be freed using
211.Fn cap_net_free .
212Multiple calls to
213.Fn cap_net_limit_addr2name_family ,
214.Fn cap_net_limit_addr2name ,
215.Fn cap_net_limit_name2addr_family ,
216.Fn cap_net_limit_name2addr ,
217.Fn cap_net_limit_connect ,
218and
219.Fn cap_net_limit_bind
220is supported, each call is extending preview capabilities.
221.Sh EXAMPLES
222The following example first opens a capability to casper and then uses this
223capability to create the
224.Nm system.net
225casper service and uses it to resolve a host and connect to it.
226.Bd -literal
227cap_channel_t *capcas, *capnet;
228cap_net_limit_t *limit;
229int familylimit, error, s;
230const char *host = "example.com";
231struct addrinfo hints, *res;
232
233/* Open capability to Casper. */
234capcas = cap_init();
235if (capcas == NULL)
236	err(1, "Unable to contact Casper");
237
238/* Cache NLA for gai_strerror. */
239caph_cache_catpages();
240
241/* Enter capability mode sandbox. */
242if (caph_enter_casper() < 0)
243	err(1, "Unable to enter capability mode");
244
245/* Use Casper capability to create capability to the system.net service. */
246capnet = cap_service_open(capcas, "system.net");
247if (capnet == NULL)
248	err(1, "Unable to open system.net service");
249
250/* Close Casper capability. */
251cap_close(capcas);
252
253/* Limit system.net to reserve IPv4 addresses, to host example.com . */
254limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR | CAPNET_CONNECTDNS);
255if (limit == NULL)
256	err(1, "Unable to create limits.");
257cap_net_limit_name2addr(limit, host, "80");
258familylimit = AF_INET;
259cap_net_limit_name2addr_family(limit, &familylimit, 1);
260if (cap_net_limit(limit) < 0)
261	err(1, "Unable to apply limits.");
262
263/* Find IP addresses for the given host. */
264memset(&hints, 0, sizeof(hints));
265hints.ai_family = AF_INET;
266hints.ai_socktype = SOCK_STREAM;
267
268error = cap_getaddrinfo(capnet, host, "80", &hints, &res);
269if (error != 0)
270	errx(1, "cap_getaddrinfo(): %s: %s", host, gai_strerror(error));
271
272s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
273if (s < 0)
274	err(1, "Unable to create socket");
275
276if (cap_connect(capnet, s, res->ai_addr,  res->ai_addrlen) < 0)
277	err(1, "Unable to connect to host");
278.Ed
279.Sh SEE ALSO
280.Xr bind 2 ,
281.Xr cap_enter 2 ,
282.Xr connect 2 ,
283.Xr caph_enter 3 ,
284.Xr err 3 ,
285.Xr gethostbyaddr 3 ,
286.Xr gethostbyname 3 ,
287.Xr gethostbyname2 3 ,
288.Xr getnameinfo 3 ,
289.Xr capsicum 4 ,
290.Xr nv 9
291.Sh AUTHORS
292.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org
293