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