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