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 5, 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_gethostbyname ,
88.Fn cap_gethostbyname2 ,
89.Fn cap_gethostbyaddr
90and
91.Fn cap_getnameinfo
92provide a set of APIs equivalent to
93.Xr bind 2 ,
94.Xr connect 2 ,
95.Xr gethostbyname 3 ,
96.Xr gethostbyname2 3 ,
97.Xr gethostbyaddr 3
98and
99.Xr getnameinfo 3
100except that a connection to the
101.Nm system.net
102service needs to be provided.
103.Sh LIMITS
104By default, the cap_net capability provides unrestricted access to the network
105namespace.
106Applications typically only require access to a small portion of the network
107namespace:
108The
109.Fn cap_net_limit
110function can be used to restrict access to the network.
111The
112.Fn cap_net_limit_init
113returns an opaque limit handle used to store a list of capabilities.
114The
115.Fv mode
116restricts the functionality of the service.
117Modes are encoded using the following flags:
118.Pp
119.Bd -literal -offset indent -compact
120CAPNET_ADDR2NAME		reverse DNS lookups are allowed with
121				cap_getnameinfo
122CAPNET_NAME2ADDR		name resolution is allowed with
123				cap_getaddrinfo
124CAPNET_DEPRECATED_ADDR2NAME	reverse DNS lookups are allowed with
125				cap_gethostbyaddr
126CAPNET_DEPRECATED_NAME2ADDR	name resolution is allowed with
127				cap_gethostbyname and cap_gethostbyname2
128CAPNET_BIND			bind syscall is allowed
129CAPNET_CONNECT			connect syscall is allowed
130CAPNET_CONNECTDNS		connect syscall is allowed to the values
131				returned from previous call to
132				the cap_getaddrinfo or cap_gethostbyname
133.Ed
134.Pp
135.Fn cap_net_limit_addr2name_family
136limits the
137.Fn cap_getnameinfo
138and
139.Fn cap_gethostbyaddr
140to do reverse DNS lookups to specific family (AF_INET, AF_INET6, etc.)
141.Pp
142.Fn cap_net_limit_addr2name
143limits the
144.Fn cap_getnameinfo
145and
146.Fn cap_gethostbyaddr
147to do reverse DNS lookups only on those specific structures.
148.Pp
149.Fn cap_net_limit_name2addr_family
150limits the
151.Fn cap_getaddrinfo ,
152.Fn cap_gethostbyname
153and
154.Fn cap_gethostbyname2
155to do the name resolution on specific family (AF_INET, AF_INET6, etc.)
156.Pp
157.Fn cap_net_limit_addr2name
158restricts
159.Fn cap_getaddrinfo ,
160.Fn cap_gethostbyname
161and
162.Fn cap_gethostbyname2
163to a set of domains.
164.Pp
165.Fn cap_net_limit_bind
166limits
167.Fn cap_bind
168to bind only on those specific structures.
169.Pp
170.Fn cap_net_limit_connect
171limits
172.Fn cap_connect
173to connect only on those specific structures.
174If the CAPNET_CONNECTDNS is set the limits are extended to the values returned
175by
176.Fn cap_getaddrinfo ,
177.Fn cap_gethostbyname
178and
179.Fn cap_gethostbyname2
180In case of the
181.Fn cap_getaddrinfo
182the restriction is strict.
183In case of the
184.Fn cap_gethostbyname
185and
186.Fn cap_gethostbyname2
187any port will be accepted in the
188.Fn cap_connect
189function.
190.Pp
191The
192.Fn cap_net_limit
193will consume and apply the limits.
194.Pp
195Once a set of limits is applied, subsequent calls to
196.Fn cap_net_limit
197will fail unless the new set is a subset of the current set.
198.Pp
199If the
200.Fn cap_net_limit
201was not called the rights may be freed using
202.Fn cap_net_free .
203Multiple calls to
204.Fn cap_net_limit_addr2name_family ,
205.Fn cap_net_limit_addr2name ,
206.Fn cap_net_limit_name2addr_family ,
207.Fn cap_net_limit_name2addr ,
208.Fn cap_net_limit_connect ,
209and
210.Fn cap_net_limit_bind
211is supported, each call is extending preview capabilities.
212.Sh EXAMPLES
213The following example first opens a capability to casper and then uses this
214capability to create the
215.Nm system.net
216casper service and uses it to resolve a host and connect to it.
217.Bd -literal
218cap_channel_t *capcas, *capnet;
219cap_net_limit_t *limit;
220int familylimit, error, s;
221const char *host = "example.com";
222struct addrinfo hints, *res;
223
224/* Open capability to Casper. */
225capcas = cap_init();
226if (capcas == NULL)
227	err(1, "Unable to contact Casper");
228
229/* Cache NLA for gai_strerror. */
230caph_cache_catpages();
231
232/* Enter capability mode sandbox. */
233if (caph_enter_casper() < 0)
234	err(1, "Unable to enter capability mode");
235
236/* Use Casper capability to create capability to the system.net service. */
237capnet = cap_service_open(capcas, "system.net");
238if (capnet == NULL)
239	err(1, "Unable to open system.net service");
240
241/* Close Casper capability. */
242cap_close(capcas);
243
244/* Limit system.net to reserve IPv4 addresses, to host example.com . */
245limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR | CAPNET_CONNECTDNS);
246if (limit == NULL)
247	err(1, "Unable to create limits.");
248cap_net_limit_name2addr(limit, host, "80");
249familylimit = AF_INET;
250cap_net_limit_name2addr_family(limit, &familylimit, 1);
251if (cap_net_limit(limit) < 0)
252	err(1, "Unable to apply limits.");
253
254/* Find IP addresses for the given host. */
255memset(&hints, 0, sizeof(hints));
256hints.ai_family = AF_INET;
257hints.ai_socktype = SOCK_STREAM;
258
259error = cap_getaddrinfo(capnet, host, "80", &hints, &res);
260if (error != 0)
261	errx(1, "cap_getaddrinfo(): %s: %s", host, gai_strerror(error));
262
263s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
264if (s < 0)
265	err(1, "Unable to create socket");
266
267if (cap_connect(capnet, s, res->ai_addr,  res->ai_addrlen) < 0)
268	err(1, "Unable to connect to host");
269.Ed
270.Sh SEE ALSO
271.Xr bind 2 ,
272.Xr cap_enter 2 ,
273.Xr connect 2 ,
274.Xr caph_enter 3 ,
275.Xr err 3 ,
276.Xr gethostbyaddr 3 ,
277.Xr gethostbyname 3 ,
278.Xr gethostbyname2 3 ,
279.Xr getnameinfo 3 ,
280.Xr capsicum 4 ,
281.Xr nv 9
282.Sh AUTHORS
283.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org
284