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