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