xref: /xnu-11215.61.5/bsd/netinet6/nd6_send.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
1*4f1223e8SApple OSS Distributions /*
2*4f1223e8SApple OSS Distributions  * Copyright (c) 2013-2021 Apple Inc. All rights reserved.
3*4f1223e8SApple OSS Distributions  *
4*4f1223e8SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*4f1223e8SApple OSS Distributions  *
6*4f1223e8SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*4f1223e8SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*4f1223e8SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*4f1223e8SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*4f1223e8SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*4f1223e8SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*4f1223e8SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*4f1223e8SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*4f1223e8SApple OSS Distributions  *
15*4f1223e8SApple OSS Distributions  * Please obtain a copy of the License at
16*4f1223e8SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*4f1223e8SApple OSS Distributions  *
18*4f1223e8SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*4f1223e8SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*4f1223e8SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*4f1223e8SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*4f1223e8SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*4f1223e8SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*4f1223e8SApple OSS Distributions  * limitations under the License.
25*4f1223e8SApple OSS Distributions  *
26*4f1223e8SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*4f1223e8SApple OSS Distributions  */
28*4f1223e8SApple OSS Distributions 
29*4f1223e8SApple OSS Distributions #include <sys/types.h>
30*4f1223e8SApple OSS Distributions #include <sys/malloc.h>
31*4f1223e8SApple OSS Distributions #include <sys/proc.h>
32*4f1223e8SApple OSS Distributions #include <sys/sysctl.h>
33*4f1223e8SApple OSS Distributions #include <sys/syslog.h>
34*4f1223e8SApple OSS Distributions 
35*4f1223e8SApple OSS Distributions #include <net/if.h>
36*4f1223e8SApple OSS Distributions 
37*4f1223e8SApple OSS Distributions #include <netinet/in.h>
38*4f1223e8SApple OSS Distributions #include <netinet6/in6_var.h>
39*4f1223e8SApple OSS Distributions #include <netinet/ip6.h>
40*4f1223e8SApple OSS Distributions #include <netinet6/ip6_var.h>
41*4f1223e8SApple OSS Distributions #include <netinet6/nd6.h>
42*4f1223e8SApple OSS Distributions 
43*4f1223e8SApple OSS Distributions #if CONFIG_MACF
44*4f1223e8SApple OSS Distributions #include <sys/kauth.h>
45*4f1223e8SApple OSS Distributions #include <security/mac_framework.h>
46*4f1223e8SApple OSS Distributions #endif
47*4f1223e8SApple OSS Distributions 
48*4f1223e8SApple OSS Distributions SYSCTL_DECL(_net_inet6);        /* Note: Not in any common header. */
49*4f1223e8SApple OSS Distributions 
50*4f1223e8SApple OSS Distributions SYSCTL_NODE(_net_inet6, OID_AUTO, send, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
51*4f1223e8SApple OSS Distributions     "IPv6 Secure Neighbor Discovery");
52*4f1223e8SApple OSS Distributions 
53*4f1223e8SApple OSS Distributions static int nd6_send_opmode = ND6_SEND_OPMODE_CGA_QUIET;
54*4f1223e8SApple OSS Distributions SYSCTL_INT(_net_inet6_send, OID_AUTO, opmode, CTLFLAG_RW | CTLFLAG_LOCKED,
55*4f1223e8SApple OSS Distributions     &nd6_send_opmode, 0, "configured SEND operating mode");
56*4f1223e8SApple OSS Distributions 
57*4f1223e8SApple OSS Distributions int nd6_send_opstate = ND6_SEND_OPMODE_DISABLED;
58*4f1223e8SApple OSS Distributions SYSCTL_INT(_net_inet6_send, OID_AUTO, opstate, CTLFLAG_RD | CTLFLAG_LOCKED,
59*4f1223e8SApple OSS Distributions     &nd6_send_opstate, 0, "current SEND operating state");
60*4f1223e8SApple OSS Distributions 
61*4f1223e8SApple OSS Distributions static int sysctl_cga_parameters SYSCTL_HANDLER_ARGS;
62*4f1223e8SApple OSS Distributions 
63*4f1223e8SApple OSS Distributions SYSCTL_PROC(_net_inet6_send, OID_AUTO, cga_parameters,
64*4f1223e8SApple OSS Distributions     CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
65*4f1223e8SApple OSS Distributions     sysctl_cga_parameters, "S,nd6_send_nodecfg", "");
66*4f1223e8SApple OSS Distributions 
67*4f1223e8SApple OSS Distributions /*
68*4f1223e8SApple OSS Distributions  * The size of the buffer is sufficient to contain a public key, its size in
69*4f1223e8SApple OSS Distributions  * machine binary type for the kernel, and the CGA precalc for the global
70*4f1223e8SApple OSS Distributions  * scope. This interface is not a public API, so we don't anticipate that the
71*4f1223e8SApple OSS Distributions  * userland and the kernel will be mismatched between ILP32 and LP64.
72*4f1223e8SApple OSS Distributions  */
73*4f1223e8SApple OSS Distributions #define SYSCTL_CGA_PARAMETERS_BUFFER_SIZE \
74*4f1223e8SApple OSS Distributions 	(2 * (sizeof (u_int16_t) + IN6_CGA_KEY_MAXSIZE) + \
75*4f1223e8SApple OSS Distributions 	sizeof (struct in6_cga_prepare))
76*4f1223e8SApple OSS Distributions 
77*4f1223e8SApple OSS Distributions static int
78*4f1223e8SApple OSS Distributions sysctl_cga_parameters SYSCTL_HANDLER_ARGS
79*4f1223e8SApple OSS Distributions {
80*4f1223e8SApple OSS Distributions #pragma unused(oidp, arg1)
81*4f1223e8SApple OSS Distributions 	u_int namelen;
82*4f1223e8SApple OSS Distributions 	char *oldp, *newp;
83*4f1223e8SApple OSS Distributions 	const char *fin;
84*4f1223e8SApple OSS Distributions 	struct in6_cga_nodecfg cfg;
85*4f1223e8SApple OSS Distributions 	struct iovec *__single iov;
86*4f1223e8SApple OSS Distributions 	int error;
87*4f1223e8SApple OSS Distributions 	char *buffer;
88*4f1223e8SApple OSS Distributions 	u_int16_t u16;
89*4f1223e8SApple OSS Distributions 
90*4f1223e8SApple OSS Distributions 	namelen = arg2;
91*4f1223e8SApple OSS Distributions 	if (namelen != 0) {
92*4f1223e8SApple OSS Distributions 		log(LOG_ERR, "%s: name length err [len=%u]\n", __func__,
93*4f1223e8SApple OSS Distributions 		    namelen);
94*4f1223e8SApple OSS Distributions 		return EINVAL;
95*4f1223e8SApple OSS Distributions 	}
96*4f1223e8SApple OSS Distributions 
97*4f1223e8SApple OSS Distributions 	if (req->newlen > SYSCTL_CGA_PARAMETERS_BUFFER_SIZE) {
98*4f1223e8SApple OSS Distributions 		log(LOG_ERR, "%s: input buffer size error [len=%zu]\n",
99*4f1223e8SApple OSS Distributions 		    __func__, req->newlen);
100*4f1223e8SApple OSS Distributions 		return EINVAL;
101*4f1223e8SApple OSS Distributions 	}
102*4f1223e8SApple OSS Distributions 
103*4f1223e8SApple OSS Distributions #if CONFIG_MACF
104*4f1223e8SApple OSS Distributions 	error = mac_system_check_info(current_cached_proc_cred(req->p),
105*4f1223e8SApple OSS Distributions 	    "net.inet6.send.cga_parameters");
106*4f1223e8SApple OSS Distributions 	if (error != 0) {
107*4f1223e8SApple OSS Distributions 		log(LOG_ERR, "%s: mac_system_check_info denied.\n", __func__);
108*4f1223e8SApple OSS Distributions 		return EPERM;
109*4f1223e8SApple OSS Distributions 	}
110*4f1223e8SApple OSS Distributions #endif
111*4f1223e8SApple OSS Distributions 
112*4f1223e8SApple OSS Distributions 	buffer = (char *)kalloc_data(SYSCTL_CGA_PARAMETERS_BUFFER_SIZE,
113*4f1223e8SApple OSS Distributions 	    Z_WAITOK | Z_ZERO);
114*4f1223e8SApple OSS Distributions 	if (buffer == NULL) {
115*4f1223e8SApple OSS Distributions 		log(LOG_ERR, "%s: could not allocate marshaling buffer.\n",
116*4f1223e8SApple OSS Distributions 		    __func__);
117*4f1223e8SApple OSS Distributions 		return ENOMEM;
118*4f1223e8SApple OSS Distributions 	}
119*4f1223e8SApple OSS Distributions 
120*4f1223e8SApple OSS Distributions 	in6_cga_node_lock();
121*4f1223e8SApple OSS Distributions 
122*4f1223e8SApple OSS Distributions 	if (req->oldptr != USER_ADDR_NULL && req->oldlen > 0) {
123*4f1223e8SApple OSS Distributions 		oldp = buffer;
124*4f1223e8SApple OSS Distributions 		fin = &buffer[SYSCTL_CGA_PARAMETERS_BUFFER_SIZE];
125*4f1223e8SApple OSS Distributions 		if (req->oldlen < SYSCTL_CGA_PARAMETERS_BUFFER_SIZE) {
126*4f1223e8SApple OSS Distributions 			fin = &buffer[req->oldlen];
127*4f1223e8SApple OSS Distributions 		}
128*4f1223e8SApple OSS Distributions 
129*4f1223e8SApple OSS Distributions 		in6_cga_query(&cfg);
130*4f1223e8SApple OSS Distributions 		iov = &cfg.cga_pubkey;
131*4f1223e8SApple OSS Distributions 		if (iov->iov_len > 0) {
132*4f1223e8SApple OSS Distributions 			VERIFY(iov->iov_len < UINT16_MAX);
133*4f1223e8SApple OSS Distributions 
134*4f1223e8SApple OSS Distributions 			if (&oldp[sizeof(cfg.cga_prepare)] <= fin) {
135*4f1223e8SApple OSS Distributions 				bcopy(&cfg.cga_prepare, oldp,
136*4f1223e8SApple OSS Distributions 				    sizeof(cfg.cga_prepare));
137*4f1223e8SApple OSS Distributions 			}
138*4f1223e8SApple OSS Distributions 			oldp += sizeof(cfg.cga_prepare);
139*4f1223e8SApple OSS Distributions 
140*4f1223e8SApple OSS Distributions 			if (&oldp[sizeof(u16)] < fin) {
141*4f1223e8SApple OSS Distributions 				u16 = (u_int16_t) iov->iov_len;
142*4f1223e8SApple OSS Distributions 				bcopy(&u16, oldp, sizeof(u16));
143*4f1223e8SApple OSS Distributions 			}
144*4f1223e8SApple OSS Distributions 			oldp += sizeof(u16);
145*4f1223e8SApple OSS Distributions 
146*4f1223e8SApple OSS Distributions 			if (&oldp[iov->iov_len] < fin) {
147*4f1223e8SApple OSS Distributions 				bcopy(__unsafe_forge_bidi_indexable(void *, iov->iov_base, iov->iov_len), oldp, iov->iov_len);
148*4f1223e8SApple OSS Distributions 			}
149*4f1223e8SApple OSS Distributions 			oldp += iov->iov_len;
150*4f1223e8SApple OSS Distributions 
151*4f1223e8SApple OSS Distributions 			if (oldp > fin) {
152*4f1223e8SApple OSS Distributions 				req->oldlen = oldp - buffer;
153*4f1223e8SApple OSS Distributions 				log(LOG_ERR, "%s: marshalled data too large.\n",
154*4f1223e8SApple OSS Distributions 				    __func__);
155*4f1223e8SApple OSS Distributions 				error = ENOMEM;
156*4f1223e8SApple OSS Distributions 				goto done;
157*4f1223e8SApple OSS Distributions 			}
158*4f1223e8SApple OSS Distributions 		}
159*4f1223e8SApple OSS Distributions 
160*4f1223e8SApple OSS Distributions 		error = SYSCTL_OUT(req, buffer, oldp - buffer);
161*4f1223e8SApple OSS Distributions 		if (error) {
162*4f1223e8SApple OSS Distributions 			goto done;
163*4f1223e8SApple OSS Distributions 		}
164*4f1223e8SApple OSS Distributions 	}
165*4f1223e8SApple OSS Distributions 
166*4f1223e8SApple OSS Distributions 	if (req->newptr == USER_ADDR_NULL) {
167*4f1223e8SApple OSS Distributions 		goto done;
168*4f1223e8SApple OSS Distributions 	}
169*4f1223e8SApple OSS Distributions 
170*4f1223e8SApple OSS Distributions 	error = proc_suser(current_proc());
171*4f1223e8SApple OSS Distributions 	if (error) {
172*4f1223e8SApple OSS Distributions 		goto done;
173*4f1223e8SApple OSS Distributions 	}
174*4f1223e8SApple OSS Distributions 
175*4f1223e8SApple OSS Distributions 	if (req->newlen == 0) {
176*4f1223e8SApple OSS Distributions 		in6_cga_stop();
177*4f1223e8SApple OSS Distributions 		nd6_send_opstate = ND6_SEND_OPMODE_DISABLED;
178*4f1223e8SApple OSS Distributions 		goto done;
179*4f1223e8SApple OSS Distributions 	}
180*4f1223e8SApple OSS Distributions 
181*4f1223e8SApple OSS Distributions 	error = SYSCTL_IN(req, buffer, req->newlen);
182*4f1223e8SApple OSS Distributions 	if (error) {
183*4f1223e8SApple OSS Distributions 		goto done;
184*4f1223e8SApple OSS Distributions 	}
185*4f1223e8SApple OSS Distributions 
186*4f1223e8SApple OSS Distributions 	newp = buffer;
187*4f1223e8SApple OSS Distributions 	fin = &buffer[req->newlen];
188*4f1223e8SApple OSS Distributions 
189*4f1223e8SApple OSS Distributions 	bzero(&cfg, sizeof cfg);
190*4f1223e8SApple OSS Distributions 
191*4f1223e8SApple OSS Distributions 	if (&newp[sizeof(cfg.cga_prepare)] <= fin) {
192*4f1223e8SApple OSS Distributions 		bcopy(newp, &cfg.cga_prepare, sizeof(cfg.cga_prepare));
193*4f1223e8SApple OSS Distributions 	}
194*4f1223e8SApple OSS Distributions 	newp += sizeof(cfg.cga_prepare);
195*4f1223e8SApple OSS Distributions 
196*4f1223e8SApple OSS Distributions 	iov = &cfg.cga_privkey;
197*4f1223e8SApple OSS Distributions 	if (&newp[sizeof(u16)] < fin) {
198*4f1223e8SApple OSS Distributions 		bcopy(newp, &u16, sizeof(u16));
199*4f1223e8SApple OSS Distributions 		iov->iov_len = u16;
200*4f1223e8SApple OSS Distributions 
201*4f1223e8SApple OSS Distributions 		if (iov->iov_len > IN6_CGA_KEY_MAXSIZE) {
202*4f1223e8SApple OSS Distributions 			error = EINVAL;
203*4f1223e8SApple OSS Distributions 			goto done;
204*4f1223e8SApple OSS Distributions 		}
205*4f1223e8SApple OSS Distributions 	}
206*4f1223e8SApple OSS Distributions 	newp += sizeof(u16);
207*4f1223e8SApple OSS Distributions 
208*4f1223e8SApple OSS Distributions 	iov->iov_base = newp;
209*4f1223e8SApple OSS Distributions 	newp += iov->iov_len;
210*4f1223e8SApple OSS Distributions 
211*4f1223e8SApple OSS Distributions 	iov = &cfg.cga_pubkey;
212*4f1223e8SApple OSS Distributions 	if (&newp[sizeof(u16)] < fin) {
213*4f1223e8SApple OSS Distributions 		bcopy(newp, &u16, sizeof(u16));
214*4f1223e8SApple OSS Distributions 		iov->iov_len = u16;
215*4f1223e8SApple OSS Distributions 
216*4f1223e8SApple OSS Distributions 		if (iov->iov_len > IN6_CGA_KEY_MAXSIZE) {
217*4f1223e8SApple OSS Distributions 			error = EINVAL;
218*4f1223e8SApple OSS Distributions 			goto done;
219*4f1223e8SApple OSS Distributions 		}
220*4f1223e8SApple OSS Distributions 	}
221*4f1223e8SApple OSS Distributions 	newp += sizeof(u16);
222*4f1223e8SApple OSS Distributions 
223*4f1223e8SApple OSS Distributions 	iov->iov_base = newp;
224*4f1223e8SApple OSS Distributions 	newp += iov->iov_len;
225*4f1223e8SApple OSS Distributions 
226*4f1223e8SApple OSS Distributions 	if (newp > fin) {
227*4f1223e8SApple OSS Distributions 		log(LOG_ERR, "%s: input too large [octets=%ld].\n", __func__,
228*4f1223e8SApple OSS Distributions 		    newp - fin);
229*4f1223e8SApple OSS Distributions 		error = ENOMEM;
230*4f1223e8SApple OSS Distributions 		goto done;
231*4f1223e8SApple OSS Distributions 	}
232*4f1223e8SApple OSS Distributions 
233*4f1223e8SApple OSS Distributions 	error = in6_cga_start(&cfg);
234*4f1223e8SApple OSS Distributions 	if (!error) {
235*4f1223e8SApple OSS Distributions 		nd6_send_opstate = nd6_send_opmode;
236*4f1223e8SApple OSS Distributions 	} else {
237*4f1223e8SApple OSS Distributions 		log(LOG_ERR, "%s: in6_cga_start error=%d.\n", __func__,
238*4f1223e8SApple OSS Distributions 		    error);
239*4f1223e8SApple OSS Distributions 	}
240*4f1223e8SApple OSS Distributions 
241*4f1223e8SApple OSS Distributions done:
242*4f1223e8SApple OSS Distributions 	in6_cga_node_unlock();
243*4f1223e8SApple OSS Distributions 	kfree_data(buffer, SYSCTL_CGA_PARAMETERS_BUFFER_SIZE);
244*4f1223e8SApple OSS Distributions 	return error;
245*4f1223e8SApple OSS Distributions }
246*4f1223e8SApple OSS Distributions 
247*4f1223e8SApple OSS Distributions /* End of file */
248