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.\" $FreeBSD$
25.\"
26.Dd November 15, 2021
27.Dt CAP_NET 3
28.Os
29.Sh NAME
30.Nm cap_bind ,
31.Nm cap_connect ,
32.Nm cap_getaddrinfo ,
33.Nm cap_gethostbyaddr ,
34.Nm cap_gethostbyname ,
35.Nm cap_gethostbyname2 ,
36.Nm cap_getnameinfo ,
37.Nm cap_net_free ,
38.Nm cap_net_limit ,
39.Nm cap_net_limit_addr2name ,
40.Nm cap_net_limit_addr2name_family ,
41.Nm cap_net_limit_bind ,
42.Nm cap_net_limit_connect ,
43.Nm cap_net_limit_init ,
44.Nm cap_net_limit_name2addr ,
45.Nm cap_net_limit_name2addr_family ,
46.Nd "library for networking in capability mode"
47.Sh LIBRARY
48.Lb libcap_net
49.Sh SYNOPSIS
50.In sys/nv.h
51.In libcasper.h
52.In casper/cap_net.h
53.Ft int
54.Fn cap_bind "cap_channel_t *chan" "int s" "const struct sockaddr *addr" "socklen_t addrlen"
55.Ft int
56.Fn cap_connect "cap_channel_t *chan" "int s" "const struct sockaddr *name" "socklen_t namelen"
57.Ft int
58.Fn cap_getaddrinfo "cap_channel_t *chan" "const char *hostname" "const char *servname" "const struct addrinfo *hints" "struct addrinfo **res"
59.Ft int
60.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"
61.Ft "struct hostent *"
62.Fn cap_gethostbyname "const cap_channel_t *chan" "const char *name"
63.Ft "struct hostent *"
64.Fn cap_gethostbyname2 "const cap_channel_t *chan" "const char *name" "int af"
65.Ft "struct hostent *"
66.Fn cap_gethostbyaddr "const cap_channel_t *chan" "const void *addr" "socklen_t len" "int af"
67.Ft "cap_net_limit_t *"
68.Fn cap_net_limit_init "cap_channel_t *chan" "uint64_t mode"
69.Ft int
70.Fn cap_net_limit "cap_net_limit_t *limit"
71.Ft void
72.Fn cap_net_free "cap_net_limit_t *limit"
73.Ft "cap_net_limit_t *"
74.Fn cap_net_limit_addr2name_family "cap_net_limit_t *limit" "int *family" "size_t size"
75.Ft "cap_net_limit_t *"
76.Fn cap_net_limit_addr2name "cap_net_limit_t *limit" "const struct sockaddr *sa" "socklen_t salen"
77.Ft "cap_net_limit_t *"
78.Fn cap_net_limit_name2addr_family "cap_net_limit_t *limit" "int *family" "size_t size"
79.Ft "cap_net_limit_t *"
80.Fn cap_net_limit_name2addr "cap_net_limit_t *limit" "const char *name" "const char *serv"
81.Ft "cap_net_limit_t *"
82.Fn cap_net_limit_connect "cap_net_limit_t *limit" "const struct sockaddr *sa" "socklen_t salen"
83.Ft "cap_net_limit_t *"
84.Fn cap_net_limit_bind "cap_net_limit_t *limit" "const struct sockaddr *sa" "socklen_t salen"
85.Sh DESCRIPTION
86The functions
87.Fn cap_bind ,
88.Fn cap_connect ,
89.Fn cap_gethostbyname ,
90.Fn cap_gethostbyname2 ,
91.Fn cap_gethostbyaddr
92and
93.Fn cap_getnameinfo
94provide a set of APIs equivalent to
95.Xr bind 2 ,
96.Xr connect 2 ,
97.Xr gethostbyname 3 ,
98.Xr gethostbyname2 3 ,
99.Xr gethostbyaddr 3
100and
101.Xr getnameinfo 3
102except that a connection to the
103.Nm system.net
104service needs to be provided.
105.Sh LIMITS
106By default, the cap_net capability provides unrestricted access to the network
107namespace.
108Applications typically only require access to a small portion of the network
109namespace:
110The
111.Fn cap_net_limit
112function can be used to restrict access to the network.
113The
114.Fn cap_net_limit_init
115returns an opaque limit handle used to store a list of capabilities.
116The
117.Fv mode
118restricts the functionality of the service.
119Modes are encoded using the following flags:
120.Pp
121.Bd -literal -offset indent -compact
122CAPNET_ADDR2NAME		reverse DNS lookups are allowed with
123				cap_getnameinfo
124CAPNET_NAME2ADDR		name resolution is allowed with
125				cap_getaddrinfo
126CAPNET_DEPRECATED_ADDR2NAME	reverse DNS lookups are allowed with
127				cap_gethostbyaddr
128CAPNET_DEPRECATED_NAME2ADDR	name resolution is allowed with
129				cap_gethostbyname and cap_gethostbyname2
130CAPNET_BIND			bind syscall is allowed
131CAPNET_CONNECT			connect syscall is allowed
132CAPNET_CONNECTDNS		connect syscall is allowed to the values
133				returned from privies call to
134				the cap_getaddrinfo or cap_gethostbyname
135.Ed
136.Pp
137.Fn cap_net_limit_addr2name_family
138limits the
139.Fn cap_getnameinfo
140and
141.Fn cap_gethostbyaddr
142to do reverse DNS lookups to specific family (AF_INET, AF_INET6, etc.)
143.Pp
144.Fn cap_net_limit_addr2name
145limits the
146.Fn cap_getnameinfo
147and
148.Fn cap_gethostbyaddr
149to do reverse DNS lookups only on those specific structures.
150.Pp
151.Fn cap_net_limit_name2addr_family
152limits the
153.Fn cap_getaddrinfo ,
154.Fn cap_gethostbyname
155and
156.Fn cap_gethostbyname2
157to do the name resolution on specific family (AF_INET, AF_INET6, etc.)
158.Pp
159.Fn cap_net_limit_addr2name
160restricts
161.Fn cap_getaddrinfo ,
162.Fn cap_gethostbyname
163and
164.Fn cap_gethostbyname2
165to a set of domains.
166.Pp
167.Fn cap_net_limit_bind
168limits
169.Fn cap_bind
170to bind only on those specific structures.
171.Pp
172.Fn cap_net_limit_connect
173limits
174.Fn cap_connect
175to connect only on those specific structures.
176If the CAPNET_CONNECTDNS is set the limits are extended to the values returned
177by
178.Fn cap_getaddrinfo ,
179.Fn cap_gethostbyname
180and
181.Fn cap_gethostbyname2
182In case of the
183.Fn cap_getaddrinfo
184the restriction is strict.
185In case of the
186.Fn cap_gethostbyname
187and
188.Fn cap_gethostbyname2
189any port will be accepted in the
190.Fn cap_connect
191function.
192.Pp
193.Fn cap_net_limit
194applies a set of sysctl limits to the capability, denying access to sysctl
195variables not belonging to the set.
196.Pp
197Once a set of limits is applied, subsequent calls to
198.Fn cap_net_limit
199will fail unless the new set is a subset of the current set.
200.Pp
201The
202.Fn cap_net_limit
203will consume the limits.
204If the
205.Fn cap_net_limit
206was not called the rights may be freed using
207.Fn cap_net_free .
208Multiple calls to
209.Fn cap_net_limit_addr2name_family ,
210.Fn cap_net_limit_addr2name ,
211.Fn cap_net_limit_name2addr_family ,
212.Fn cap_net_limit_name2addr ,
213.Fn cap_net_limit_connect ,
214and
215.Fn cap_net_limit_bind
216is supported, each call is extending preview capabilities.
217.Sh EXAMPLES
218The following example first opens a capability to casper and then uses this
219capability to create the
220.Nm system.net
221casper service and uses it to resolve a host and connect to it.
222.Bd -literal
223cap_channel_t *capcas, *capnet;
224cap_net_limit_t *limit;
225int familylimit, error, s;
226const char *host = "example.com";
227struct addrinfo hints, *res;
228
229/* Open capability to Casper. */
230capcas = cap_init();
231if (capcas == NULL)
232	err(1, "Unable to contact Casper");
233
234/* Cache NLA for gai_strerror. */
235caph_cache_catpages();
236
237/* Enter capability mode sandbox. */
238if (caph_enter_casper() < 0)
239	err(1, "Unable to enter capability mode");
240
241/* Use Casper capability to create capability to the system.net service. */
242capnet = cap_service_open(capcas, "system.net");
243if (capnet == NULL)
244	err(1, "Unable to open system.net service");
245
246/* Close Casper capability. */
247cap_close(capcas);
248
249/* Limit system.net to reserve IPv4 addresses, to host example.com . */
250limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR | CAPNET_CONNECTDNS);
251if (limit == NULL)
252	err(1, "Unable to create limits.");
253cap_net_limit_name2addr(limit, host, "80");
254familylimit = AF_INET;
255cap_net_limit_name2addr_family(limit, &familylimit, 1);
256if (cap_net_limit(limit) < 0)
257	err(1, "Unable to apply limits.");
258
259/* Find IP addresses for the given host. */
260memset(&hints, 0, sizeof(hints));
261hints.ai_family = AF_INET;
262hints.ai_socktype = SOCK_STREAM;
263
264error = cap_getaddrinfo(capnet, host, "80", &hints, &res);
265if (error != 0)
266	errx(1, "cap_getaddrinfo(): %s: %s", host, gai_strerror(error));
267
268s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
269if (s < 0)
270	err(1, "Unable to create socket");
271
272if (cap_connect(capnet, s, res->ai_addr,  res->ai_addrlen) < 0)
273	err(1, "Unable to connect to host");
274.Ed
275.Sh SEE ALSO
276.Xr bind 2 ,
277.Xr cap_enter 2 ,
278.Xr connect 2 ,
279.Xr caph_enter 3 ,
280.Xr err 3 ,
281.Xr gethostbyaddr 3 ,
282.Xr gethostbyname 3 ,
283.Xr gethostbyname2 3 ,
284.Xr getnameinfo 3 ,
285.Xr capsicum 4 ,
286.Xr nv 9
287.Sh AUTHORS
288.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org
289