1/* 2 * Copyright (c) 2013-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <string.h> 30#include <sys/systm.h> 31#include <sys/types.h> 32#include <sys/syslog.h> 33#include <sys/queue.h> 34#include <sys/malloc.h> 35#include <libkern/OSMalloc.h> 36#include <sys/kernel.h> 37#include <sys/kern_control.h> 38#include <sys/mbuf.h> 39#include <sys/kpi_mbuf.h> 40#include <sys/proc_uuid_policy.h> 41#include <net/if.h> 42#include <sys/protosw.h> 43#include <sys/socket.h> 44#include <sys/socketvar.h> 45#include <netinet/ip.h> 46#include <netinet/ip6.h> 47#include <netinet/tcp.h> 48#include <netinet/udp.h> 49#include <netinet/in_pcb.h> 50#include <net/flowhash.h> 51#include <net/if_var.h> 52#include <sys/kauth.h> 53#include <sys/sysctl.h> 54#include <sys/sysproto.h> 55#include <sys/priv.h> 56#include <net/necp.h> 57 58/* 59 * NECP - Network Extension Control Policy database 60 * ------------------------------------------------ 61 * The goal of this module is to allow clients connecting via a 62 * kernel control socket to create high-level policy sessions, which 63 * are ingested into low-level kernel policies that control and tag 64 * traffic at the application, socket, and IP layers. 65 * 66 * ------------------------------------------------ 67 * Sessions 68 * ------------------------------------------------ 69 * Each session owns a list of session policies, each of which can 70 * specify any combination of conditions and a single result. Each 71 * session also has a priority level (such as High, Default, or Low) 72 * which is requested by the client. Based on the requested level, 73 * a session order value is assigned to the session, which will be used 74 * to sort kernel policies generated by the session. The session client 75 * can specify the sub-order for each policy it creates which will be 76 * used to further sort the kernel policies. 77 * 78 * Kernel Control Socket --> 1 necp_session --> list of necp_session_policy structs 79 * 80 * ------------------------------------------------ 81 * Kernel Policies 82 * ------------------------------------------------ 83 * Whenever a session send the Apply command, its policies are ingested 84 * and generate kernel policies. There are two phases of kernel policy 85 * ingestion. 86 * 87 * 1. The session policy is parsed to create kernel policies at the socket 88 * and IP layers, when applicable. For example, a policy that requires 89 * all traffic from App1 to Pass will generate a socket kernel policy to 90 * match App1 and mark packets with ID1, and also an IP policy to match 91 * ID1 and let the packet pass. This is handled in necp_apply_policy. The 92 * resulting kernel policies are added to the global socket and IP layer 93 * policy lists. 94 * necp_session_policy --> necp_kernel_socket_policy and necp_kernel_ip_output_policy 95 * || || 96 * \/ \/ 97 * necp_kernel_socket_policies necp_kernel_ip_output_policies 98 * 99 * 2. Once the global lists of kernel policies have been filled out, each 100 * list is traversed to create optimized sub-lists ("Maps") which are used during 101 * data-path evaluation. IP policies are sent into necp_kernel_ip_output_policies_map, 102 * which hashes incoming packets based on marked socket-layer policies, and removes 103 * duplicate or overlapping polcies. Socket policies are sent into two maps, 104 * necp_kernel_socket_policies_map and necp_kernel_socket_policies_app_layer_map. 105 * The app layer map is used for policy checks coming in from user space, and is one 106 * list with duplicate and overlapping policies removed. The socket map hashes based 107 * on app UUID, and removes duplicate and overlapping policies. 108 * necp_kernel_socket_policy --> necp_kernel_socket_policies_app_layer_map 109 * |-> necp_kernel_socket_policies_map 110 * 111 * necp_kernel_ip_output_policies --> necp_kernel_ip_output_policies_map 112 * 113 * ------------------------------------------------ 114 * Drop All Level 115 * ------------------------------------------------ 116 * The Drop All Level is a sysctl that controls the level at which policies are allowed 117 * to override a global drop rule. If the value is 0, no drop rule is applied. If the value 118 * is 1, all traffic is dropped. If the value is greater than 1, all kernel policies created 119 * by a session with a priority level better than (numerically less than) the 120 * Drop All Level will allow matching traffic to not be dropped. The Drop All Level is 121 * dynamically interpreted into necp_drop_all_order, which specifies the equivalent assigned 122 * session orders to be dropped. 123 */ 124 125u_int32_t necp_drop_all_order = 0; 126u_int32_t necp_drop_all_level = 0; 127 128u_int32_t necp_pass_loopback = 1; // 0=Off, 1=On 129u_int32_t necp_pass_keepalives = 1; // 0=Off, 1=On 130 131u_int32_t necp_debug = 0; // 0=None, 1=Basic, 2=EveryMatch 132 133static int sysctl_handle_necp_level SYSCTL_HANDLER_ARGS; 134 135SYSCTL_NODE(_net, OID_AUTO, necp, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "NECP"); 136SYSCTL_INT(_net_necp, NECPCTL_PASS_LOOPBACK, pass_loopback, CTLFLAG_LOCKED | CTLFLAG_RW, &necp_pass_loopback, 0, ""); 137SYSCTL_INT(_net_necp, NECPCTL_PASS_KEEPALIVES, pass_keepalives, CTLFLAG_LOCKED | CTLFLAG_RW, &necp_pass_keepalives, 0, ""); 138SYSCTL_INT(_net_necp, NECPCTL_DEBUG, debug, CTLFLAG_LOCKED | CTLFLAG_RW, &necp_debug, 0, ""); 139SYSCTL_PROC(_net_necp, NECPCTL_DROP_ALL_LEVEL, drop_all_level, CTLTYPE_INT | CTLFLAG_LOCKED | CTLFLAG_RW, &necp_drop_all_level, 0, &sysctl_handle_necp_level, "IU", ""); 140 141#define NECPLOG(level, format, ...) do { \ 142 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \ 143} while (0) 144 145#define NECPLOG0(level, msg) do { \ 146 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: %s\n", __FUNCTION__, msg); \ 147} while (0) 148 149#define LIST_INSERT_SORTED_ASCENDING(head, elm, field, sortfield, tmpelm) do { \ 150 if (LIST_EMPTY((head)) || (LIST_FIRST(head)->sortfield >= (elm)->sortfield)) { \ 151 LIST_INSERT_HEAD((head), elm, field); \ 152 } else { \ 153 LIST_FOREACH(tmpelm, head, field) { \ 154 if (LIST_NEXT(tmpelm, field) == NULL || LIST_NEXT(tmpelm, field)->sortfield >= (elm)->sortfield) { \ 155 LIST_INSERT_AFTER(tmpelm, elm, field); \ 156 break; \ 157 } \ 158 } \ 159 } \ 160} while (0) 161 162#define LIST_INSERT_SORTED_TWICE_ASCENDING(head, elm, field, firstsortfield, secondsortfield, tmpelm) do { \ 163 if (LIST_EMPTY((head)) || (LIST_FIRST(head)->firstsortfield > (elm)->firstsortfield) || ((LIST_FIRST(head)->firstsortfield == (elm)->firstsortfield) && (LIST_FIRST(head)->secondsortfield >= (elm)->secondsortfield))) { \ 164 LIST_INSERT_HEAD((head), elm, field); \ 165 } else { \ 166 LIST_FOREACH(tmpelm, head, field) { \ 167 if (LIST_NEXT(tmpelm, field) == NULL || (LIST_NEXT(tmpelm, field)->firstsortfield > (elm)->firstsortfield) || ((LIST_NEXT(tmpelm, field)->firstsortfield == (elm)->firstsortfield) && (LIST_NEXT(tmpelm, field)->secondsortfield >= (elm)->secondsortfield))) { \ 168 LIST_INSERT_AFTER(tmpelm, elm, field); \ 169 break; \ 170 } \ 171 } \ 172 } \ 173} while (0) 174 175#define LIST_INSERT_SORTED_THRICE_ASCENDING(head, elm, field, firstsortfield, secondsortfield, thirdsortfield, tmpelm) do { \ 176 if (LIST_EMPTY((head)) || (LIST_FIRST(head)->firstsortfield > (elm)->firstsortfield) || ((LIST_FIRST(head)->firstsortfield == (elm)->firstsortfield) && (LIST_FIRST(head)->secondsortfield >= (elm)->secondsortfield)) || ((LIST_FIRST(head)->firstsortfield == (elm)->firstsortfield) && (LIST_FIRST(head)->secondsortfield == (elm)->secondsortfield) && (LIST_FIRST(head)->thirdsortfield >= (elm)->thirdsortfield))) { \ 177 LIST_INSERT_HEAD((head), elm, field); \ 178 } else { \ 179 LIST_FOREACH(tmpelm, head, field) { \ 180 if (LIST_NEXT(tmpelm, field) == NULL || (LIST_NEXT(tmpelm, field)->firstsortfield > (elm)->firstsortfield) || ((LIST_NEXT(tmpelm, field)->firstsortfield == (elm)->firstsortfield) && (LIST_NEXT(tmpelm, field)->secondsortfield >= (elm)->secondsortfield)) || ((LIST_NEXT(tmpelm, field)->firstsortfield == (elm)->firstsortfield) && (LIST_NEXT(tmpelm, field)->secondsortfield == (elm)->secondsortfield) && (LIST_NEXT(tmpelm, field)->thirdsortfield >= (elm)->thirdsortfield))) { \ 181 LIST_INSERT_AFTER(tmpelm, elm, field); \ 182 break; \ 183 } \ 184 } \ 185 } \ 186} while (0) 187 188#define NECP_KERNEL_CONDITION_ALL_INTERFACES 0x00001 189#define NECP_KERNEL_CONDITION_BOUND_INTERFACE 0x00002 190#define NECP_KERNEL_CONDITION_PROTOCOL 0x00004 191#define NECP_KERNEL_CONDITION_LOCAL_START 0x00008 192#define NECP_KERNEL_CONDITION_LOCAL_END 0x00010 193#define NECP_KERNEL_CONDITION_LOCAL_PREFIX 0x00020 194#define NECP_KERNEL_CONDITION_REMOTE_START 0x00040 195#define NECP_KERNEL_CONDITION_REMOTE_END 0x00080 196#define NECP_KERNEL_CONDITION_REMOTE_PREFIX 0x00100 197#define NECP_KERNEL_CONDITION_APP_ID 0x00200 198#define NECP_KERNEL_CONDITION_REAL_APP_ID 0x00400 199#define NECP_KERNEL_CONDITION_DOMAIN 0x00800 200#define NECP_KERNEL_CONDITION_ACCOUNT_ID 0x01000 201#define NECP_KERNEL_CONDITION_POLICY_ID 0x02000 202#define NECP_KERNEL_CONDITION_PID 0x04000 203#define NECP_KERNEL_CONDITION_UID 0x08000 204#define NECP_KERNEL_CONDITION_LAST_INTERFACE 0x10000 // Only set from packets looping between interfaces 205#define NECP_KERNEL_CONDITION_TRAFFIC_CLASS 0x20000 206#define NECP_KERNEL_CONDITION_ENTITLEMENT 0x40000 207 208struct necp_service_registration { 209 LIST_ENTRY(necp_service_registration) session_chain; 210 LIST_ENTRY(necp_service_registration) kernel_chain; 211 u_int32_t service_id; 212}; 213 214struct necp_session { 215 u_int32_t control_unit; 216 u_int32_t session_priority; // Descriptive priority rating 217 u_int32_t session_order; 218 219 bool proc_locked; // Messages must come from proc_uuid 220 uuid_t proc_uuid; 221 222 bool dirty; 223 LIST_HEAD(_policies, necp_session_policy) policies; 224 225 LIST_HEAD(_services, necp_service_registration) services; 226}; 227 228struct necp_socket_info { 229 pid_t pid; 230 uid_t uid; 231 union necp_sockaddr_union local_addr; 232 union necp_sockaddr_union remote_addr; 233 u_int32_t bound_interface_index; 234 u_int32_t traffic_class; 235 u_int16_t protocol; 236 u_int32_t application_id; 237 u_int32_t real_application_id; 238 u_int32_t account_id; 239 char *domain; 240 errno_t cred_result; 241}; 242 243static kern_ctl_ref necp_kctlref; 244static u_int32_t necp_family; 245static OSMallocTag necp_malloc_tag; 246static lck_grp_attr_t *necp_kernel_policy_grp_attr = NULL; 247static lck_attr_t *necp_kernel_policy_mtx_attr = NULL; 248static lck_grp_t *necp_kernel_policy_mtx_grp = NULL; 249decl_lck_rw_data(static, necp_kernel_policy_lock); 250 251static necp_policy_id necp_last_policy_id = 0; 252static necp_kernel_policy_id necp_last_kernel_policy_id = 0; 253static u_int32_t necp_last_uuid_id = 0; 254static u_int32_t necp_last_string_id = 0; 255 256/* 257 * On modification, invalidate cached lookups by bumping the generation count. 258 * Other calls will need to take the slowpath of taking 259 * the subsystem lock. 260 */ 261static volatile int32_t necp_kernel_socket_policies_gencount; 262#define BUMP_KERNEL_SOCKET_POLICIES_GENERATION_COUNT() do { \ 263 if (OSIncrementAtomic(&necp_kernel_socket_policies_gencount) == (INT32_MAX - 1)) { \ 264 necp_kernel_socket_policies_gencount = 1; \ 265 } \ 266} while (0) 267 268static u_int32_t necp_kernel_application_policies_condition_mask; 269static size_t necp_kernel_application_policies_count; 270static u_int32_t necp_kernel_socket_policies_condition_mask; 271static size_t necp_kernel_socket_policies_count; 272static size_t necp_kernel_socket_policies_non_app_count; 273static LIST_HEAD(_necpkernelsocketconnectpolicies, necp_kernel_socket_policy) necp_kernel_socket_policies; 274#define NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS 5 275#define NECP_SOCKET_MAP_APP_ID_TO_BUCKET(appid) (appid ? (appid%(NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS - 1) + 1) : 0) 276static struct necp_kernel_socket_policy **necp_kernel_socket_policies_map[NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS]; 277static struct necp_kernel_socket_policy **necp_kernel_socket_policies_app_layer_map; 278/* 279 * A note on policy 'maps': these are used for boosting efficiency when matching policies. For each dimension of the map, 280 * such as an ID, the 0 bucket is reserved for sockets/packets that do not have this parameter, while the other 281 * buckets lead to an array of policy pointers that form the list applicable when the (parameter%(NUM_BUCKETS - 1) + 1) == bucket_index. 282 * 283 * For example, a packet with policy ID of 7, when there are 4 ID buckets, will map to bucket (7%3 + 1) = 2. 284 */ 285 286static u_int32_t necp_kernel_ip_output_policies_condition_mask; 287static size_t necp_kernel_ip_output_policies_count; 288static size_t necp_kernel_ip_output_policies_non_id_count; 289static LIST_HEAD(_necpkernelipoutputpolicies, necp_kernel_ip_output_policy) necp_kernel_ip_output_policies; 290#define NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS 5 291#define NECP_IP_OUTPUT_MAP_ID_TO_BUCKET(id) (id ? (id%(NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS - 1) + 1) : 0) 292static struct necp_kernel_ip_output_policy **necp_kernel_ip_output_policies_map[NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS]; 293 294static struct necp_session *necp_create_session(u_int32_t control_unit); 295static void necp_delete_session(struct necp_session *session); 296 297static void necp_handle_policy_add(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 298static void necp_handle_policy_get(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 299static void necp_handle_policy_delete(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 300static void necp_handle_policy_apply_all(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 301static void necp_handle_policy_list_all(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 302static void necp_handle_policy_delete_all(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 303static void necp_handle_set_session_priority(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 304static void necp_handle_lock_session_to_proc(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 305static void necp_handle_register_service(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 306static void necp_handle_unregister_service(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset); 307 308static struct necp_session_policy *necp_policy_create(struct necp_session *session, necp_policy_order order, u_int8_t *conditions_array, size_t conditions_array_size, u_int8_t *result, size_t result_size); 309static struct necp_session_policy *necp_policy_find(struct necp_session *session, necp_policy_id policy_id); 310static bool necp_policy_mark_for_deletion(struct necp_session *session, struct necp_session_policy *policy); 311static bool necp_policy_mark_all_for_deletion(struct necp_session *session); 312static bool necp_policy_delete(struct necp_session *session, struct necp_session_policy *policy); 313static void necp_policy_apply_all(struct necp_session *session); 314 315static necp_kernel_policy_id necp_kernel_socket_policy_add(necp_policy_id parent_policy_id, necp_policy_order order, u_int32_t session_order, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_app_id cond_app_id, necp_app_id cond_real_app_id, u_int32_t cond_account_id, char *domain, pid_t cond_pid, uid_t cond_uid, ifnet_t cond_bound_interface, struct necp_policy_condition_tc_range cond_traffic_class, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter); 316static bool necp_kernel_socket_policy_delete(necp_kernel_policy_id policy_id); 317static bool necp_kernel_socket_policies_reprocess(void); 318static bool necp_kernel_socket_policies_update_uuid_table(void); 319static inline struct necp_kernel_socket_policy *necp_socket_find_policy_match_with_info_locked(struct necp_kernel_socket_policy **policy_search_array, struct necp_socket_info *info, necp_kernel_policy_filter *return_filter, necp_kernel_policy_result *return_service_action, necp_kernel_policy_service *return_service); 320 321static necp_kernel_policy_id necp_kernel_ip_output_policy_add(necp_policy_id parent_policy_id, necp_policy_order order, necp_policy_order suborder, u_int32_t session_order, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_kernel_policy_id cond_policy_id, ifnet_t cond_bound_interface, u_int32_t cond_last_interface_index, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter); 322static bool necp_kernel_ip_output_policy_delete(necp_kernel_policy_id policy_id); 323static bool necp_kernel_ip_output_policies_reprocess(void); 324 325static bool necp_is_addr_in_range(struct sockaddr *addr, struct sockaddr *range_start, struct sockaddr *range_end); 326static bool necp_is_range_in_range(struct sockaddr *inner_range_start, struct sockaddr *inner_range_end, struct sockaddr *range_start, struct sockaddr *range_end); 327static bool necp_is_addr_in_subnet(struct sockaddr *addr, struct sockaddr *subnet_addr, u_int8_t subnet_prefix); 328static int necp_addr_compare(struct sockaddr *sa1, struct sockaddr *sa2, int check_port); 329static bool necp_buffer_compare_with_bit_prefix(u_int8_t *p1, u_int8_t *p2, u_int32_t bits); 330static bool necp_is_loopback(struct sockaddr *local_addr, struct sockaddr *remote_addr, struct inpcb *inp, struct mbuf *packet); 331 332struct necp_uuid_id_mapping { 333 LIST_ENTRY(necp_uuid_id_mapping) chain; 334 uuid_t uuid; 335 u_int32_t id; 336 u_int32_t refcount; 337 u_int32_t table_refcount; // Add to UUID policy table count 338}; 339static size_t necp_num_uuid_app_id_mappings; 340static bool necp_uuid_app_id_mappings_dirty; 341#define NECP_UUID_APP_ID_HASH_SIZE 64 342static u_long necp_uuid_app_id_hash_mask; 343static u_long necp_uuid_app_id_hash_num_buckets; 344static LIST_HEAD(necp_uuid_id_mapping_head, necp_uuid_id_mapping) *necp_uuid_app_id_hashtbl, necp_uuid_service_id_list; // App map is real hash table, service map is just mapping 345#define APPUUIDHASH(uuid) (&necp_uuid_app_id_hashtbl[uuid[0] & necp_uuid_app_id_hash_mask]) // Assume first byte of UUIDs are evenly distributed 346static u_int32_t necp_create_uuid_app_id_mapping(uuid_t uuid, bool *allocated_mapping, bool uuid_policy_table); 347static bool necp_remove_uuid_app_id_mapping(uuid_t uuid, bool *removed_mapping, bool uuid_policy_table); 348 349static struct necp_uuid_id_mapping *necp_uuid_lookup_service_id_locked(uuid_t uuid); 350static struct necp_uuid_id_mapping *necp_uuid_lookup_uuid_with_service_id_locked(u_int32_t local_id); 351static u_int32_t necp_create_uuid_service_id_mapping(uuid_t uuid); 352static bool necp_remove_uuid_service_id_mapping(uuid_t uuid); 353 354struct necp_string_id_mapping { 355 LIST_ENTRY(necp_string_id_mapping) chain; 356 char *string; 357 necp_app_id id; 358 u_int32_t refcount; 359}; 360static LIST_HEAD(necp_string_id_mapping_list, necp_string_id_mapping) necp_account_id_list; 361static u_int32_t necp_create_string_to_id_mapping(struct necp_string_id_mapping_list *list, char *domain); 362static bool necp_remove_string_to_id_mapping(struct necp_string_id_mapping_list *list, char *domain); 363 364static LIST_HEAD(_necp_kernel_service_list, necp_service_registration) necp_registered_service_list; 365 366static char *necp_create_trimmed_domain(char *string, size_t length); 367static inline int necp_count_dots(char *string, size_t length); 368 369// Session order allocation 370static u_int32_t 371necp_allocate_new_session_order(u_int32_t priority, u_int32_t control_unit) 372{ 373 u_int32_t new_order = 0; 374 375 // For now, just allocate 1000 orders for each priority 376 if (priority == NECP_SESSION_PRIORITY_UNKNOWN || priority > NECP_SESSION_NUM_PRIORITIES) { 377 priority = NECP_SESSION_PRIORITY_DEFAULT; 378 } 379 380 // Use the control unit to decide the offset into the priority list 381 new_order = (control_unit) + ((priority - 1) * 1000); 382 383 return (new_order); 384} 385 386static inline u_int32_t 387necp_get_first_order_for_priority(u_int32_t priority) 388{ 389 return (((priority - 1) * 1000) + 1); 390} 391 392// Sysctl handler 393static int 394sysctl_handle_necp_level SYSCTL_HANDLER_ARGS 395{ 396#pragma unused(arg1, arg2) 397 int error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 398 if (necp_drop_all_level == 0) { 399 necp_drop_all_order = 0; 400 } else { 401 necp_drop_all_order = necp_get_first_order_for_priority(necp_drop_all_level); 402 } 403 return (error); 404} 405 406 407// Kernel Control functions 408static errno_t necp_register_control(void); 409static errno_t necp_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo); 410static errno_t necp_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo); 411static errno_t necp_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t m, int flags); 412static void necp_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags); 413static errno_t necp_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t *len); 414static errno_t necp_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t len); 415 416static bool necp_send_ctl_data(struct necp_session *session, u_int8_t *buffer, size_t buffer_size); 417 418errno_t 419necp_init(void) 420{ 421 errno_t result = 0; 422 423 result = necp_register_control(); 424 if (result != 0) { 425 goto done; 426 } 427 428 necp_kernel_policy_grp_attr = lck_grp_attr_alloc_init(); 429 if (necp_kernel_policy_grp_attr == NULL) { 430 NECPLOG0(LOG_ERR, "lck_grp_attr_alloc_init failed"); 431 result = ENOMEM; 432 goto done; 433 } 434 435 necp_kernel_policy_mtx_grp = lck_grp_alloc_init(NECP_CONTROL_NAME, necp_kernel_policy_grp_attr); 436 if (necp_kernel_policy_mtx_grp == NULL) { 437 NECPLOG0(LOG_ERR, "lck_grp_alloc_init failed"); 438 result = ENOMEM; 439 goto done; 440 } 441 442 necp_kernel_policy_mtx_attr = lck_attr_alloc_init(); 443 if (necp_kernel_policy_mtx_attr == NULL) { 444 NECPLOG0(LOG_ERR, "lck_attr_alloc_init failed"); 445 result = ENOMEM; 446 goto done; 447 } 448 449 lck_rw_init(&necp_kernel_policy_lock, necp_kernel_policy_mtx_grp, necp_kernel_policy_mtx_attr); 450 451 LIST_INIT(&necp_kernel_socket_policies); 452 LIST_INIT(&necp_kernel_ip_output_policies); 453 454 LIST_INIT(&necp_account_id_list); 455 456 LIST_INIT(&necp_uuid_service_id_list); 457 458 LIST_INIT(&necp_registered_service_list); 459 460 necp_uuid_app_id_hashtbl = hashinit(NECP_UUID_APP_ID_HASH_SIZE, M_NECP, &necp_uuid_app_id_hash_mask); 461 necp_uuid_app_id_hash_num_buckets = necp_uuid_app_id_hash_mask + 1; 462 necp_num_uuid_app_id_mappings = 0; 463 necp_uuid_app_id_mappings_dirty = FALSE; 464 465 necp_kernel_application_policies_condition_mask = 0; 466 necp_kernel_socket_policies_condition_mask = 0; 467 necp_kernel_ip_output_policies_condition_mask = 0; 468 469 necp_kernel_application_policies_count = 0; 470 necp_kernel_socket_policies_count = 0; 471 necp_kernel_socket_policies_non_app_count = 0; 472 necp_kernel_ip_output_policies_count = 0; 473 necp_kernel_ip_output_policies_non_id_count = 0; 474 475 necp_last_policy_id = 0; 476 necp_last_kernel_policy_id = 0; 477 478 necp_kernel_socket_policies_gencount = 1; 479 480 memset(&necp_kernel_socket_policies_map, 0, sizeof(necp_kernel_socket_policies_map)); 481 memset(&necp_kernel_ip_output_policies_map, 0, sizeof(necp_kernel_ip_output_policies_map)); 482 necp_kernel_socket_policies_app_layer_map = NULL; 483 484done: 485 if (result != 0) { 486 if (necp_kernel_policy_mtx_attr != NULL) { 487 lck_attr_free(necp_kernel_policy_mtx_attr); 488 necp_kernel_policy_mtx_attr = NULL; 489 } 490 if (necp_kernel_policy_mtx_grp != NULL) { 491 lck_grp_free(necp_kernel_policy_mtx_grp); 492 necp_kernel_policy_mtx_grp = NULL; 493 } 494 if (necp_kernel_policy_grp_attr != NULL) { 495 lck_grp_attr_free(necp_kernel_policy_grp_attr); 496 necp_kernel_policy_grp_attr = NULL; 497 } 498 if (necp_kctlref != NULL) { 499 ctl_deregister(necp_kctlref); 500 necp_kctlref = NULL; 501 } 502 } 503 return (result); 504} 505 506static errno_t 507necp_register_control(void) 508{ 509 struct kern_ctl_reg kern_ctl; 510 errno_t result = 0; 511 512 // Create a tag to allocate memory 513 necp_malloc_tag = OSMalloc_Tagalloc(NECP_CONTROL_NAME, OSMT_DEFAULT); 514 515 // Find a unique value for our interface family 516 result = mbuf_tag_id_find(NECP_CONTROL_NAME, &necp_family); 517 if (result != 0) { 518 NECPLOG(LOG_ERR, "mbuf_tag_id_find_internal failed: %d", result); 519 return (result); 520 } 521 522 bzero(&kern_ctl, sizeof(kern_ctl)); 523 strlcpy(kern_ctl.ctl_name, NECP_CONTROL_NAME, sizeof(kern_ctl.ctl_name)); 524 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0; 525 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; // Require root 526 kern_ctl.ctl_sendsize = 64 * 1024; 527 kern_ctl.ctl_recvsize = 64 * 1024; 528 kern_ctl.ctl_connect = necp_ctl_connect; 529 kern_ctl.ctl_disconnect = necp_ctl_disconnect; 530 kern_ctl.ctl_send = necp_ctl_send; 531 kern_ctl.ctl_rcvd = necp_ctl_rcvd; 532 kern_ctl.ctl_setopt = necp_ctl_setopt; 533 kern_ctl.ctl_getopt = necp_ctl_getopt; 534 535 result = ctl_register(&kern_ctl, &necp_kctlref); 536 if (result != 0) { 537 NECPLOG(LOG_ERR, "ctl_register failed: %d", result); 538 return (result); 539 } 540 541 return (0); 542} 543 544static errno_t 545necp_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo) 546{ 547#pragma unused(kctlref) 548 *unitinfo = necp_create_session(sac->sc_unit); 549 if (*unitinfo == NULL) { 550 // Could not allocate session 551 return (ENOBUFS); 552 } 553 554 return (0); 555} 556 557static errno_t 558necp_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo) 559{ 560#pragma unused(kctlref, unit) 561 struct necp_session *session = (struct necp_session *)unitinfo; 562 if (session != NULL) { 563 necp_policy_mark_all_for_deletion(session); 564 necp_policy_apply_all(session); 565 necp_delete_session((struct necp_session *)unitinfo); 566 } 567 568 return (0); 569} 570 571 572// Message handling 573static int 574necp_packet_find_tlv(mbuf_t packet, int offset, u_int8_t type, int *err, int next) 575{ 576 size_t cursor = offset; 577 int error = 0; 578 size_t curr_length; 579 u_int8_t curr_type; 580 581 *err = 0; 582 583 do { 584 if (!next) { 585 error = mbuf_copydata(packet, cursor, sizeof(curr_type), &curr_type); 586 if (error) { 587 *err = ENOENT; 588 return (-1); 589 } 590 } else { 591 next = 0; 592 curr_type = NECP_TLV_NIL; 593 } 594 595 if (curr_type != type) { 596 cursor += sizeof(curr_type); 597 error = mbuf_copydata(packet, cursor, sizeof(curr_length), &curr_length); 598 if (error) { 599 *err = error; 600 return (-1); 601 } 602 cursor += (sizeof(curr_length) + curr_length); 603 } 604 } while (curr_type != type); 605 606 return (cursor); 607} 608 609static int 610necp_packet_get_tlv_at_offset(mbuf_t packet, int tlv_offset, size_t buff_len, void *buff, size_t *value_size) 611{ 612 int error = 0; 613 size_t length; 614 615 if (tlv_offset < 0) { 616 return (error); 617 } 618 619 error = mbuf_copydata(packet, tlv_offset + sizeof(u_int8_t), sizeof(length), &length); 620 if (error) { 621 return (error); 622 } 623 624 if (value_size != NULL) { 625 *value_size = length; 626 } 627 628 if (buff != NULL && buff_len > 0) { 629 size_t to_copy = (length < buff_len) ? length : buff_len; 630 error = mbuf_copydata(packet, tlv_offset + sizeof(u_int8_t) + sizeof(length), to_copy, buff); 631 if (error) { 632 return (error); 633 } 634 } 635 636 return (0); 637} 638 639static int 640necp_packet_get_tlv(mbuf_t packet, int offset, u_int8_t type, size_t buff_len, void *buff, size_t *value_size) 641{ 642 int error = 0; 643 int tlv_offset; 644 645 tlv_offset = necp_packet_find_tlv(packet, offset, type, &error, 0); 646 if (tlv_offset < 0) { 647 return (error); 648 } 649 650 return (necp_packet_get_tlv_at_offset(packet, tlv_offset, buff_len, buff, value_size)); 651} 652 653static u_int8_t * 654necp_buffer_write_packet_header(u_int8_t *buffer, u_int8_t packet_type, u_int8_t flags, u_int32_t message_id) 655{ 656 ((struct necp_packet_header *)(void *)buffer)->packet_type = packet_type; 657 ((struct necp_packet_header *)(void *)buffer)->flags = flags; 658 ((struct necp_packet_header *)(void *)buffer)->message_id = message_id; 659 return (buffer + sizeof(struct necp_packet_header)); 660} 661 662static u_int8_t * 663necp_buffer_write_tlv(u_int8_t *buffer, u_int8_t type, size_t length, const void *value) 664{ 665 *(u_int8_t *)(buffer) = type; 666 *(size_t *)(void *)(buffer + sizeof(type)) = length; 667 if (length > 0) { 668 memcpy((u_int8_t *)(buffer + sizeof(type) + sizeof(length)), value, length); 669 } 670 671 return ((u_int8_t *)(buffer + sizeof(type) + sizeof(length) + length)); 672} 673 674static u_int8_t 675necp_buffer_get_tlv_type(u_int8_t *buffer, int tlv_offset) 676{ 677 u_int8_t *type = NULL; 678 679 if (buffer == NULL) { 680 return (0); 681 } 682 683 type = (u_int8_t *)((u_int8_t *)buffer + tlv_offset); 684 return (type ? *type : 0); 685} 686 687static size_t 688necp_buffer_get_tlv_length(u_int8_t *buffer, int tlv_offset) 689{ 690 size_t *length = NULL; 691 692 if (buffer == NULL) { 693 return (0); 694 } 695 696 length = (size_t *)(void *)((u_int8_t *)buffer + tlv_offset + sizeof(u_int8_t)); 697 return (length ? *length : 0); 698} 699 700static u_int8_t * 701necp_buffer_get_tlv_value(u_int8_t *buffer, int tlv_offset, size_t *value_size) 702{ 703 u_int8_t *value = NULL; 704 size_t length = necp_buffer_get_tlv_length(buffer, tlv_offset); 705 if (length == 0) { 706 return (value); 707 } 708 709 if (value_size) { 710 *value_size = length; 711 } 712 713 value = (u_int8_t *)((u_int8_t *)buffer + tlv_offset + sizeof(u_int8_t) + sizeof(size_t)); 714 return (value); 715} 716 717static int 718necp_buffer_find_tlv(u_int8_t *buffer, size_t buffer_length, int offset, u_int8_t type, int next) 719{ 720 size_t cursor = offset; 721 size_t curr_length; 722 u_int8_t curr_type; 723 724 do { 725 if (cursor >= buffer_length) { 726 return (-1); 727 } 728 if (!next) { 729 curr_type = necp_buffer_get_tlv_type(buffer, cursor); 730 } else { 731 next = 0; 732 curr_type = NECP_TLV_NIL; 733 } 734 if (curr_type != type) { 735 curr_length = necp_buffer_get_tlv_length(buffer, cursor); 736 cursor += (sizeof(curr_type) + sizeof(curr_length) + curr_length); 737 } 738 } while (curr_type != type); 739 740 return (cursor); 741} 742 743static bool 744necp_send_ctl_data(struct necp_session *session, u_int8_t *buffer, size_t buffer_size) 745{ 746 int error; 747 748 if (necp_kctlref == NULL || session == NULL || buffer == NULL || buffer_size == 0) { 749 return (FALSE); 750 } 751 752 error = ctl_enqueuedata(necp_kctlref, session->control_unit, buffer, buffer_size, CTL_DATA_EOR); 753 754 return (error == 0); 755} 756 757static bool 758necp_send_success_response(struct necp_session *session, u_int8_t packet_type, u_int32_t message_id) 759{ 760 bool success = TRUE; 761 u_int8_t *response = NULL; 762 u_int8_t *cursor = NULL; 763 size_t response_size = sizeof(struct necp_packet_header) + sizeof(u_int8_t) + sizeof(size_t); 764 MALLOC(response, u_int8_t *, response_size, M_NECP, M_WAITOK); 765 if (response == NULL) { 766 return (FALSE); 767 } 768 cursor = response; 769 cursor = necp_buffer_write_packet_header(cursor, packet_type, NECP_PACKET_FLAGS_RESPONSE, message_id); 770 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_NIL, 0, NULL); 771 772 if (!(success = necp_send_ctl_data(session, (u_int8_t *)response, response_size))) { 773 NECPLOG0(LOG_ERR, "Failed to send response"); 774 } 775 776 FREE(response, M_NECP); 777 return (success); 778} 779 780static bool 781necp_send_error_response(struct necp_session *session, u_int8_t packet_type, u_int32_t message_id, u_int32_t error) 782{ 783 bool success = TRUE; 784 u_int8_t *response = NULL; 785 u_int8_t *cursor = NULL; 786 size_t response_size = sizeof(struct necp_packet_header) + sizeof(u_int8_t) + sizeof(size_t) + sizeof(u_int32_t); 787 MALLOC(response, u_int8_t *, response_size, M_NECP, M_WAITOK); 788 if (response == NULL) { 789 return (FALSE); 790 } 791 cursor = response; 792 cursor = necp_buffer_write_packet_header(cursor, packet_type, NECP_PACKET_FLAGS_RESPONSE, message_id); 793 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_ERROR, sizeof(error), &error); 794 795 if (!(success = necp_send_ctl_data(session, (u_int8_t *)response, response_size))) { 796 NECPLOG0(LOG_ERR, "Failed to send response"); 797 } 798 799 FREE(response, M_NECP); 800 return (success); 801} 802 803static bool 804necp_send_policy_id_response(struct necp_session *session, u_int8_t packet_type, u_int32_t message_id, necp_policy_id policy_id) 805{ 806 bool success = TRUE; 807 u_int8_t *response = NULL; 808 u_int8_t *cursor = NULL; 809 size_t response_size = sizeof(struct necp_packet_header) + sizeof(u_int8_t) + sizeof(size_t) + sizeof(u_int32_t); 810 MALLOC(response, u_int8_t *, response_size, M_NECP, M_WAITOK); 811 if (response == NULL) { 812 return (FALSE); 813 } 814 cursor = response; 815 cursor = necp_buffer_write_packet_header(cursor, packet_type, NECP_PACKET_FLAGS_RESPONSE, message_id); 816 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_POLICY_ID, sizeof(policy_id), &policy_id); 817 818 if (!(success = necp_send_ctl_data(session, (u_int8_t *)response, response_size))) { 819 NECPLOG0(LOG_ERR, "Failed to send response"); 820 } 821 822 FREE(response, M_NECP); 823 return (success); 824} 825 826static errno_t 827necp_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t packet, int flags) 828{ 829#pragma unused(kctlref, unit, flags) 830 struct necp_session *session = (struct necp_session *)unitinfo; 831 struct necp_packet_header header; 832 int error = 0; 833 834 if (session == NULL) { 835 NECPLOG0(LOG_ERR, "Got a NULL session"); 836 error = EINVAL; 837 goto done; 838 } 839 840 if (mbuf_pkthdr_len(packet) < sizeof(header)) { 841 NECPLOG(LOG_ERR, "Got a bad packet, length (%lu) < sizeof header (%lu)", mbuf_pkthdr_len(packet), sizeof(header)); 842 error = EINVAL; 843 goto done; 844 } 845 846 error = mbuf_copydata(packet, 0, sizeof(header), &header); 847 if (error) { 848 NECPLOG(LOG_ERR, "mbuf_copydata failed for the header: %d", error); 849 error = ENOBUFS; 850 goto done; 851 } 852 853 if (session->proc_locked) { 854 // Verify that the calling process is allowed to send messages 855 uuid_t proc_uuid; 856 proc_getexecutableuuid(current_proc(), proc_uuid, sizeof(proc_uuid)); 857 if (uuid_compare(proc_uuid, session->proc_uuid) != 0) { 858 necp_send_error_response(session, header.packet_type, header.message_id, NECP_ERROR_INVALID_PROCESS); 859 goto done; 860 } 861 } 862 863 switch (header.packet_type) { 864 case NECP_PACKET_TYPE_POLICY_ADD: { 865 necp_handle_policy_add(session, header.message_id, packet, sizeof(header)); 866 break; 867 } 868 case NECP_PACKET_TYPE_POLICY_GET: { 869 necp_handle_policy_get(session, header.message_id, packet, sizeof(header)); 870 break; 871 } 872 case NECP_PACKET_TYPE_POLICY_DELETE: { 873 necp_handle_policy_delete(session, header.message_id, packet, sizeof(header)); 874 break; 875 } 876 case NECP_PACKET_TYPE_POLICY_APPLY_ALL: { 877 necp_handle_policy_apply_all(session, header.message_id, packet, sizeof(header)); 878 break; 879 } 880 case NECP_PACKET_TYPE_POLICY_LIST_ALL: { 881 necp_handle_policy_list_all(session, header.message_id, packet, sizeof(header)); 882 break; 883 } 884 case NECP_PACKET_TYPE_POLICY_DELETE_ALL: { 885 necp_handle_policy_delete_all(session, header.message_id, packet, sizeof(header)); 886 break; 887 } 888 case NECP_PACKET_TYPE_SET_SESSION_PRIORITY: { 889 necp_handle_set_session_priority(session, header.message_id, packet, sizeof(header)); 890 break; 891 } 892 case NECP_PACKET_TYPE_LOCK_SESSION_TO_PROC: { 893 necp_handle_lock_session_to_proc(session, header.message_id, packet, sizeof(header)); 894 break; 895 } 896 case NECP_PACKET_TYPE_REGISTER_SERVICE: { 897 necp_handle_register_service(session, header.message_id, packet, sizeof(header)); 898 break; 899 } 900 case NECP_PACKET_TYPE_UNREGISTER_SERVICE: { 901 necp_handle_unregister_service(session, header.message_id, packet, sizeof(header)); 902 break; 903 } 904 default: { 905 NECPLOG(LOG_ERR, "Received unknown message type %d", header.packet_type); 906 necp_send_error_response(session, header.packet_type, header.message_id, NECP_ERROR_UNKNOWN_PACKET_TYPE); 907 break; 908 } 909 } 910 911done: 912 mbuf_freem(packet); 913 return (error); 914} 915 916static void 917necp_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags) 918{ 919#pragma unused(kctlref, unit, unitinfo, flags) 920 return; 921} 922 923static errno_t 924necp_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t *len) 925{ 926#pragma unused(kctlref, unit, unitinfo, opt, data, len) 927 return (0); 928} 929 930static errno_t 931necp_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t len) 932{ 933#pragma unused(kctlref, unit, unitinfo, opt, data, len) 934 return (0); 935} 936 937// Session Management 938static struct necp_session * 939necp_create_session(u_int32_t control_unit) 940{ 941 struct necp_session *new_session = NULL; 942 943 MALLOC(new_session, struct necp_session *, sizeof(*new_session), M_NECP, M_WAITOK); 944 if (new_session == NULL) { 945 goto done; 946 } 947 if (necp_debug) { 948 NECPLOG(LOG_DEBUG, "Create NECP session, control unit %d", control_unit); 949 } 950 memset(new_session, 0, sizeof(*new_session)); 951 new_session->session_priority = NECP_SESSION_PRIORITY_UNKNOWN; 952 new_session->session_order = necp_allocate_new_session_order(new_session->session_priority, control_unit); 953 new_session->control_unit = control_unit; 954 new_session->dirty = FALSE; 955 LIST_INIT(&new_session->policies); 956 957done: 958 return (new_session); 959} 960 961static void 962necp_delete_session(struct necp_session *session) 963{ 964 if (session != NULL) { 965 struct necp_service_registration *service = NULL; 966 struct necp_service_registration *temp_service = NULL; 967 LIST_FOREACH_SAFE(service, &session->services, session_chain, temp_service) { 968 LIST_REMOVE(service, session_chain); 969 lck_rw_lock_exclusive(&necp_kernel_policy_lock); 970 LIST_REMOVE(service, kernel_chain); 971 lck_rw_done(&necp_kernel_policy_lock); 972 FREE(service, M_NECP); 973 } 974 if (necp_debug) { 975 NECPLOG0(LOG_DEBUG, "Deleted NECP session"); 976 } 977 FREE(session, M_NECP); 978 } 979} 980 981// Session Policy Management 982static inline u_int8_t 983necp_policy_result_get_type_from_buffer(u_int8_t *buffer, size_t length) 984{ 985 return ((buffer && length >= sizeof(u_int8_t)) ? buffer[0] : 0); 986} 987 988static inline size_t 989necp_policy_result_get_parameter_length_from_buffer(u_int8_t *buffer, size_t length) 990{ 991 return ((buffer && length > sizeof(u_int8_t)) ? (length - sizeof(u_int8_t)) : 0); 992} 993 994static inline u_int8_t * 995necp_policy_result_get_parameter_pointer_from_buffer(u_int8_t *buffer, size_t length) 996{ 997 return ((buffer && length > sizeof(u_int8_t)) ? (buffer + sizeof(u_int8_t)) : NULL); 998} 999 1000static bool 1001necp_policy_result_is_valid(u_int8_t *buffer, size_t length) 1002{ 1003 bool validated = FALSE; 1004 u_int8_t type = necp_policy_result_get_type_from_buffer(buffer, length); 1005 size_t parameter_length = necp_policy_result_get_parameter_length_from_buffer(buffer, length); 1006 switch (type) { 1007 case NECP_POLICY_RESULT_PASS: { 1008 validated = TRUE; 1009 break; 1010 } 1011 case NECP_POLICY_RESULT_SKIP: { 1012 if (parameter_length >= sizeof(u_int32_t)) { 1013 validated = TRUE; 1014 } 1015 break; 1016 } 1017 case NECP_POLICY_RESULT_DROP: { 1018 validated = TRUE; 1019 break; 1020 } 1021 case NECP_POLICY_RESULT_SOCKET_DIVERT: { 1022 if (parameter_length >= sizeof(u_int32_t)) { 1023 validated = TRUE; 1024 } 1025 break; 1026 } 1027 case NECP_POLICY_RESULT_SOCKET_SCOPED: { 1028 if (parameter_length > 0) { 1029 validated = TRUE; 1030 } 1031 break; 1032 } 1033 case NECP_POLICY_RESULT_IP_TUNNEL: { 1034 if (parameter_length > sizeof(u_int32_t)) { 1035 validated = TRUE; 1036 } 1037 break; 1038 } 1039 case NECP_POLICY_RESULT_SOCKET_FILTER: { 1040 if (parameter_length >= sizeof(u_int32_t)) { 1041 validated = TRUE; 1042 } 1043 break; 1044 } 1045 case NECP_POLICY_RESULT_TRIGGER: 1046 case NECP_POLICY_RESULT_TRIGGER_IF_NEEDED: 1047 case NECP_POLICY_RESULT_TRIGGER_SCOPED: 1048 case NECP_POLICY_RESULT_NO_TRIGGER_SCOPED: { 1049 if (parameter_length >= sizeof(uuid_t)) { 1050 validated = TRUE; 1051 } 1052 break; 1053 } 1054 default: { 1055 validated = FALSE; 1056 break; 1057 } 1058 } 1059 1060 if (necp_debug) { 1061 NECPLOG(LOG_DEBUG, "Policy result type %d, valid %d", type, validated); 1062 } 1063 1064 return (validated); 1065} 1066 1067static inline u_int8_t 1068necp_policy_condition_get_type_from_buffer(u_int8_t *buffer, size_t length) 1069{ 1070 return ((buffer && length >= sizeof(u_int8_t)) ? buffer[0] : 0); 1071} 1072 1073static inline u_int8_t 1074necp_policy_condition_get_flags_from_buffer(u_int8_t *buffer, size_t length) 1075{ 1076 return ((buffer && length >= (2 * sizeof(u_int8_t))) ? buffer[1] : 0); 1077} 1078 1079static inline size_t 1080necp_policy_condition_get_value_length_from_buffer(u_int8_t *buffer, size_t length) 1081{ 1082 return ((buffer && length >= (2 * sizeof(u_int8_t))) ? (length - (2 * sizeof(u_int8_t))) : 0); 1083} 1084 1085static inline u_int8_t * 1086necp_policy_condition_get_value_pointer_from_buffer(u_int8_t *buffer, size_t length) 1087{ 1088 return ((buffer && length > (2 * sizeof(u_int8_t))) ? (buffer + (2 * sizeof(u_int8_t))) : NULL); 1089} 1090 1091static inline bool 1092necp_policy_condition_is_default(u_int8_t *buffer, size_t length) 1093{ 1094 return (necp_policy_condition_get_type_from_buffer(buffer, length) == NECP_POLICY_CONDITION_DEFAULT); 1095} 1096 1097static inline bool 1098necp_policy_condition_is_application(u_int8_t *buffer, size_t length) 1099{ 1100 return (necp_policy_condition_get_type_from_buffer(buffer, length) == NECP_POLICY_CONDITION_APPLICATION); 1101} 1102 1103static inline bool 1104necp_policy_condition_requires_application(u_int8_t *buffer, size_t length) 1105{ 1106 u_int8_t type = necp_policy_condition_get_type_from_buffer(buffer, length); 1107 return (type == NECP_POLICY_CONDITION_REAL_APPLICATION || 1108 type == NECP_POLICY_CONDITION_ENTITLEMENT); 1109} 1110 1111static bool 1112necp_policy_condition_is_valid(u_int8_t *buffer, size_t length, u_int8_t policy_result_type) 1113{ 1114 bool validated = FALSE; 1115 bool result_cannot_have_ip_layer = (policy_result_type == NECP_POLICY_RESULT_SOCKET_DIVERT || 1116 policy_result_type == NECP_POLICY_RESULT_SOCKET_FILTER || 1117 policy_result_type == NECP_POLICY_RESULT_TRIGGER || 1118 policy_result_type == NECP_POLICY_RESULT_TRIGGER_IF_NEEDED || 1119 policy_result_type == NECP_POLICY_RESULT_TRIGGER_SCOPED || 1120 policy_result_type == NECP_POLICY_RESULT_NO_TRIGGER_SCOPED || 1121 policy_result_type == NECP_POLICY_RESULT_SOCKET_SCOPED) ? TRUE : FALSE; 1122 size_t condition_length = necp_policy_condition_get_value_length_from_buffer(buffer, length); 1123 u_int8_t *condition_value = necp_policy_condition_get_value_pointer_from_buffer(buffer, length); 1124 u_int8_t type = necp_policy_condition_get_type_from_buffer(buffer, length); 1125 u_int8_t flags = necp_policy_condition_get_flags_from_buffer(buffer, length); 1126 switch (type) { 1127 case NECP_POLICY_CONDITION_APPLICATION: 1128 case NECP_POLICY_CONDITION_REAL_APPLICATION: { 1129 if (!(flags & NECP_POLICY_CONDITION_FLAGS_NEGATIVE) && 1130 condition_length >= sizeof(uuid_t) && 1131 condition_value != NULL && 1132 !uuid_is_null(condition_value)) { 1133 validated = TRUE; 1134 } 1135 break; 1136 } 1137 case NECP_POLICY_CONDITION_DOMAIN: 1138 case NECP_POLICY_CONDITION_ACCOUNT: 1139 case NECP_POLICY_CONDITION_BOUND_INTERFACE: { 1140 if (condition_length > 0) { 1141 validated = TRUE; 1142 } 1143 break; 1144 } 1145 case NECP_POLICY_CONDITION_TRAFFIC_CLASS: { 1146 if (condition_length >= sizeof(struct necp_policy_condition_tc_range)) { 1147 validated = TRUE; 1148 } 1149 break; 1150 } 1151 case NECP_POLICY_CONDITION_DEFAULT: 1152 case NECP_POLICY_CONDITION_ALL_INTERFACES: 1153 case NECP_POLICY_CONDITION_ENTITLEMENT: { 1154 if (!(flags & NECP_POLICY_CONDITION_FLAGS_NEGATIVE)) { 1155 validated = TRUE; 1156 } 1157 break; 1158 } 1159 case NECP_POLICY_CONDITION_IP_PROTOCOL: { 1160 if (condition_length >= sizeof(u_int16_t)) { 1161 validated = TRUE; 1162 } 1163 break; 1164 } 1165 case NECP_POLICY_CONDITION_PID: { 1166 if (condition_length >= sizeof(pid_t) && 1167 condition_value != NULL && 1168 *((pid_t *)(void *)condition_value) != 0) { 1169 validated = TRUE; 1170 } 1171 break; 1172 } 1173 case NECP_POLICY_CONDITION_UID: { 1174 if (condition_length >= sizeof(uid_t)) { 1175 validated = TRUE; 1176 } 1177 break; 1178 } 1179 case NECP_POLICY_CONDITION_LOCAL_ADDR: 1180 case NECP_POLICY_CONDITION_REMOTE_ADDR: { 1181 if (!result_cannot_have_ip_layer && condition_length >= sizeof(struct necp_policy_condition_addr)) { 1182 validated = TRUE; 1183 } 1184 break; 1185 } 1186 case NECP_POLICY_CONDITION_LOCAL_ADDR_RANGE: 1187 case NECP_POLICY_CONDITION_REMOTE_ADDR_RANGE: { 1188 if (!result_cannot_have_ip_layer && condition_length >= sizeof(struct necp_policy_condition_addr_range)) { 1189 validated = TRUE; 1190 } 1191 break; 1192 } 1193 default: { 1194 validated = FALSE; 1195 break; 1196 } 1197 } 1198 1199 if (necp_debug) { 1200 NECPLOG(LOG_DEBUG, "Policy condition type %d, valid %d", type, validated); 1201 } 1202 1203 return (validated); 1204} 1205 1206static void 1207necp_handle_set_session_priority(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1208{ 1209 int error; 1210 struct necp_session_policy *policy = NULL; 1211 struct necp_session_policy *temp_policy = NULL; 1212 u_int32_t response_error = NECP_ERROR_INTERNAL; 1213 u_int32_t requested_session_priority = NECP_SESSION_PRIORITY_UNKNOWN; 1214 1215 // Read policy id 1216 error = necp_packet_get_tlv(packet, offset, NECP_TLV_SESSION_PRIORITY, sizeof(requested_session_priority), &requested_session_priority, NULL); 1217 if (error) { 1218 NECPLOG(LOG_ERR, "Failed to get session priority: %d", error); 1219 response_error = NECP_ERROR_INVALID_TLV; 1220 goto fail; 1221 } 1222 1223 if (session == NULL) { 1224 NECPLOG0(LOG_ERR, "Failed to find session"); 1225 response_error = NECP_ERROR_INTERNAL; 1226 goto fail; 1227 } 1228 1229 // Enforce special session priorities with entitlements 1230 if (requested_session_priority == NECP_SESSION_PRIORITY_CONTROL || 1231 requested_session_priority == NECP_SESSION_PRIORITY_PRIVILEGED_TUNNEL) { 1232 errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0); 1233 if (cred_result != 0) { 1234 NECPLOG(LOG_ERR, "Session does not hold necessary entitlement to claim priority level %d", requested_session_priority); 1235 goto fail; 1236 } 1237 } 1238 1239 if (session->session_priority != requested_session_priority) { 1240 session->session_priority = requested_session_priority; 1241 session->session_order = necp_allocate_new_session_order(session->session_priority, session->control_unit); 1242 session->dirty = TRUE; 1243 1244 // Mark all policies as needing updates 1245 LIST_FOREACH_SAFE(policy, &session->policies, chain, temp_policy) { 1246 policy->pending_update = TRUE; 1247 } 1248 } 1249 1250 necp_send_success_response(session, NECP_PACKET_TYPE_SET_SESSION_PRIORITY, message_id); 1251 return; 1252 1253fail: 1254 necp_send_error_response(session, NECP_PACKET_TYPE_SET_SESSION_PRIORITY, message_id, response_error); 1255} 1256 1257static void 1258necp_handle_lock_session_to_proc(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1259{ 1260#pragma unused(packet, offset) 1261 proc_getexecutableuuid(current_proc(), session->proc_uuid, sizeof(session->proc_uuid)); 1262 session->proc_locked = TRUE; 1263 necp_send_success_response(session, NECP_PACKET_TYPE_LOCK_SESSION_TO_PROC, message_id); 1264} 1265 1266static void 1267necp_handle_register_service(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1268{ 1269 int error; 1270 struct necp_service_registration *new_service = NULL; 1271 u_int32_t response_error = NECP_ERROR_INTERNAL; 1272 uuid_t service_uuid; 1273 uuid_clear(service_uuid); 1274 1275 if (session == NULL) { 1276 NECPLOG0(LOG_ERR, "Failed to find session"); 1277 response_error = NECP_ERROR_INTERNAL; 1278 goto fail; 1279 } 1280 1281 // Enforce entitlements 1282 errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0); 1283 if (cred_result != 0) { 1284 NECPLOG0(LOG_ERR, "Session does not hold necessary entitlement to register service"); 1285 goto fail; 1286 } 1287 1288 // Read service uuid 1289 error = necp_packet_get_tlv(packet, offset, NECP_TLV_SERVICE_UUID, sizeof(uuid_t), service_uuid, NULL); 1290 if (error) { 1291 NECPLOG(LOG_ERR, "Failed to get service UUID: %d", error); 1292 response_error = NECP_ERROR_INVALID_TLV; 1293 goto fail; 1294 } 1295 1296 MALLOC(new_service, struct necp_service_registration *, sizeof(*new_service), M_NECP, M_WAITOK); 1297 if (new_service == NULL) { 1298 NECPLOG0(LOG_ERR, "Failed to allocate service registration"); 1299 response_error = NECP_ERROR_INTERNAL; 1300 goto fail; 1301 } 1302 1303 lck_rw_lock_exclusive(&necp_kernel_policy_lock); 1304 memset(new_service, 0, sizeof(*new_service)); 1305 new_service->service_id = necp_create_uuid_service_id_mapping(service_uuid); 1306 LIST_INSERT_HEAD(&session->services, new_service, session_chain); 1307 LIST_INSERT_HEAD(&necp_registered_service_list, new_service, kernel_chain); 1308 lck_rw_done(&necp_kernel_policy_lock); 1309 1310 necp_send_success_response(session, NECP_PACKET_TYPE_REGISTER_SERVICE, message_id); 1311 return; 1312fail: 1313 necp_send_error_response(session, NECP_PACKET_TYPE_REGISTER_SERVICE, message_id, response_error); 1314} 1315 1316static void 1317necp_handle_unregister_service(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1318{ 1319 int error; 1320 struct necp_service_registration *service = NULL; 1321 struct necp_service_registration *temp_service = NULL; 1322 u_int32_t response_error = NECP_ERROR_INTERNAL; 1323 struct necp_uuid_id_mapping *mapping = NULL; 1324 uuid_t service_uuid; 1325 uuid_clear(service_uuid); 1326 1327 if (session == NULL) { 1328 NECPLOG0(LOG_ERR, "Failed to find session"); 1329 response_error = NECP_ERROR_INTERNAL; 1330 goto fail; 1331 } 1332 1333 // Read service uuid 1334 error = necp_packet_get_tlv(packet, offset, NECP_TLV_SERVICE_UUID, sizeof(uuid_t), service_uuid, NULL); 1335 if (error) { 1336 NECPLOG(LOG_ERR, "Failed to get service UUID: %d", error); 1337 response_error = NECP_ERROR_INVALID_TLV; 1338 goto fail; 1339 } 1340 1341 // Mark remove all matching services for this session 1342 lck_rw_lock_exclusive(&necp_kernel_policy_lock); 1343 mapping = necp_uuid_lookup_service_id_locked(service_uuid); 1344 if (mapping != NULL) { 1345 LIST_FOREACH_SAFE(service, &session->services, session_chain, temp_service) { 1346 if (service->service_id == mapping->id) { 1347 LIST_REMOVE(service, session_chain); 1348 LIST_REMOVE(service, kernel_chain); 1349 FREE(service, M_NECP); 1350 } 1351 } 1352 necp_remove_uuid_service_id_mapping(service_uuid); 1353 } 1354 lck_rw_done(&necp_kernel_policy_lock); 1355 1356 necp_send_success_response(session, NECP_PACKET_TYPE_REGISTER_SERVICE, message_id); 1357 return; 1358fail: 1359 necp_send_error_response(session, NECP_PACKET_TYPE_REGISTER_SERVICE, message_id, response_error); 1360} 1361 1362static void 1363necp_handle_policy_add(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1364{ 1365 bool has_default_condition = FALSE; 1366 bool has_non_default_condition = FALSE; 1367 bool has_application_condition = FALSE; 1368 bool requires_application_condition = FALSE; 1369 u_int8_t *conditions_array = NULL; 1370 size_t conditions_array_size = 0; 1371 int conditions_array_cursor; 1372 1373 int cursor; 1374 int error = 0; 1375 u_int32_t response_error = NECP_ERROR_INTERNAL; 1376 1377 necp_policy_order order = 0; 1378 struct necp_session_policy *policy = NULL; 1379 u_int8_t *policy_result = NULL; 1380 size_t policy_result_size = 0; 1381 1382 // Read policy order 1383 error = necp_packet_get_tlv(packet, offset, NECP_TLV_POLICY_ORDER, sizeof(order), &order, NULL); 1384 if (error) { 1385 NECPLOG(LOG_ERR, "Failed to get policy order: %d", error); 1386 response_error = NECP_ERROR_INVALID_TLV; 1387 goto fail; 1388 } 1389 1390 // Read policy result 1391 cursor = necp_packet_find_tlv(packet, offset, NECP_TLV_POLICY_RESULT, &error, 0); 1392 error = necp_packet_get_tlv_at_offset(packet, cursor, 0, NULL, &policy_result_size); 1393 if (error || policy_result_size == 0) { 1394 NECPLOG(LOG_ERR, "Failed to get policy result length: %d", error); 1395 response_error = NECP_ERROR_INVALID_TLV; 1396 goto fail; 1397 } 1398 MALLOC(policy_result, u_int8_t *, policy_result_size, M_NECP, M_WAITOK); 1399 if (policy_result == NULL) { 1400 NECPLOG(LOG_ERR, "Failed to allocate a policy result buffer (size %d)", policy_result_size); 1401 response_error = NECP_ERROR_INTERNAL; 1402 goto fail; 1403 } 1404 error = necp_packet_get_tlv_at_offset(packet, cursor, policy_result_size, policy_result, NULL); 1405 if (error) { 1406 NECPLOG(LOG_ERR, "Failed to get policy result: %d", error); 1407 response_error = NECP_ERROR_POLICY_RESULT_INVALID; 1408 goto fail; 1409 } 1410 if (!necp_policy_result_is_valid(policy_result, policy_result_size)) { 1411 NECPLOG0(LOG_ERR, "Failed to validate policy result"); 1412 response_error = NECP_ERROR_POLICY_RESULT_INVALID; 1413 goto fail; 1414 } 1415 1416 // Read policy conditions 1417 for (cursor = necp_packet_find_tlv(packet, offset, NECP_TLV_POLICY_CONDITION, &error, 0); 1418 cursor >= 0; 1419 cursor = necp_packet_find_tlv(packet, cursor, NECP_TLV_POLICY_CONDITION, &error, 1)) { 1420 size_t condition_size = 0; 1421 necp_packet_get_tlv_at_offset(packet, cursor, 0, NULL, &condition_size); 1422 1423 if (condition_size > 0) { 1424 conditions_array_size += (sizeof(u_int8_t) + sizeof(size_t) + condition_size); 1425 } 1426 } 1427 1428 if (conditions_array_size == 0) { 1429 NECPLOG0(LOG_ERR, "Failed to get policy conditions"); 1430 response_error = NECP_ERROR_INVALID_TLV; 1431 goto fail; 1432 } 1433 MALLOC(conditions_array, u_int8_t *, conditions_array_size, M_NECP, M_WAITOK); 1434 if (conditions_array == NULL) { 1435 NECPLOG(LOG_ERR, "Failed to allocate a policy conditions array (size %d)", conditions_array_size); 1436 response_error = NECP_ERROR_INTERNAL; 1437 goto fail; 1438 } 1439 1440 conditions_array_cursor = 0; 1441 for (cursor = necp_packet_find_tlv(packet, offset, NECP_TLV_POLICY_CONDITION, &error, 0); 1442 cursor >= 0; 1443 cursor = necp_packet_find_tlv(packet, cursor, NECP_TLV_POLICY_CONDITION, &error, 1)) { 1444 u_int8_t condition_type = NECP_TLV_POLICY_CONDITION; 1445 size_t condition_size = 0; 1446 necp_packet_get_tlv_at_offset(packet, cursor, 0, NULL, &condition_size); 1447 if (condition_size > 0 && condition_size <= (conditions_array_size - conditions_array_cursor)) { 1448 // Add type 1449 memcpy((conditions_array + conditions_array_cursor), &condition_type, sizeof(condition_type)); 1450 conditions_array_cursor += sizeof(condition_type); 1451 1452 // Add length 1453 memcpy((conditions_array + conditions_array_cursor), &condition_size, sizeof(condition_size)); 1454 conditions_array_cursor += sizeof(condition_size); 1455 1456 // Add value 1457 necp_packet_get_tlv_at_offset(packet, cursor, condition_size, (conditions_array + conditions_array_cursor), NULL); 1458 if (!necp_policy_condition_is_valid((conditions_array + conditions_array_cursor), condition_size, necp_policy_result_get_type_from_buffer(policy_result, policy_result_size))) { 1459 NECPLOG0(LOG_ERR, "Failed to validate policy condition"); 1460 response_error = NECP_ERROR_POLICY_CONDITIONS_INVALID; 1461 goto fail; 1462 } 1463 1464 if (necp_policy_condition_is_default((conditions_array + conditions_array_cursor), condition_size)) { 1465 has_default_condition = TRUE; 1466 } else { 1467 has_non_default_condition = TRUE; 1468 } 1469 if (has_default_condition && has_non_default_condition) { 1470 NECPLOG0(LOG_ERR, "Failed to validate conditions; contained default and non-default conditions"); 1471 response_error = NECP_ERROR_POLICY_CONDITIONS_INVALID; 1472 goto fail; 1473 } 1474 1475 if (necp_policy_condition_is_application((conditions_array + conditions_array_cursor), condition_size)) { 1476 has_application_condition = TRUE; 1477 } 1478 1479 if (necp_policy_condition_requires_application((conditions_array + conditions_array_cursor), condition_size)) { 1480 requires_application_condition = TRUE; 1481 } 1482 1483 conditions_array_cursor += condition_size; 1484 } 1485 } 1486 1487 if (requires_application_condition && !has_application_condition) { 1488 NECPLOG0(LOG_ERR, "Failed to validate conditions; did not contain application condition"); 1489 response_error = NECP_ERROR_POLICY_CONDITIONS_INVALID; 1490 goto fail; 1491 } 1492 1493 if ((policy = necp_policy_create(session, order, conditions_array, conditions_array_size, policy_result, policy_result_size)) == NULL) { 1494 response_error = NECP_ERROR_INTERNAL; 1495 goto fail; 1496 } 1497 1498 necp_send_policy_id_response(session, NECP_PACKET_TYPE_POLICY_ADD, message_id, policy->id); 1499 return; 1500 1501fail: 1502 if (policy_result != NULL) { 1503 FREE(policy_result, M_NECP); 1504 } 1505 if (conditions_array != NULL) { 1506 FREE(conditions_array, M_NECP); 1507 } 1508 1509 necp_send_error_response(session, NECP_PACKET_TYPE_POLICY_ADD, message_id, response_error); 1510} 1511 1512static void 1513necp_handle_policy_get(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1514{ 1515#pragma unused(offset) 1516 int error; 1517 u_int8_t *response = NULL; 1518 u_int8_t *cursor = NULL; 1519 u_int32_t response_error = NECP_ERROR_INTERNAL; 1520 necp_policy_id policy_id = 0; 1521 size_t order_tlv_size = 0; 1522 size_t result_tlv_size = 0; 1523 size_t response_size = 0; 1524 1525 struct necp_session_policy *policy = NULL; 1526 1527 // Read policy id 1528 error = necp_packet_get_tlv(packet, offset, NECP_TLV_POLICY_ID, sizeof(policy_id), &policy_id, NULL); 1529 if (error) { 1530 NECPLOG(LOG_ERR, "Failed to get policy id: %d", error); 1531 response_error = NECP_ERROR_INVALID_TLV; 1532 goto fail; 1533 } 1534 1535 policy = necp_policy_find(session, policy_id); 1536 if (policy == NULL || policy->pending_deletion) { 1537 NECPLOG(LOG_ERR, "Failed to find policy with id %d", policy_id); 1538 response_error = NECP_ERROR_POLICY_ID_NOT_FOUND; 1539 goto fail; 1540 } 1541 1542 order_tlv_size = sizeof(u_int8_t) + sizeof(size_t) + sizeof(necp_policy_order); 1543 result_tlv_size = (policy->result_size ? (sizeof(u_int8_t) + sizeof(size_t) + policy->result_size) : 0); 1544 response_size = sizeof(struct necp_packet_header) + order_tlv_size + result_tlv_size + policy->conditions_size; 1545 MALLOC(response, u_int8_t *, response_size, M_NECP, M_WAITOK); 1546 if (response == NULL) { 1547 necp_send_error_response(session, NECP_PACKET_TYPE_POLICY_LIST_ALL, message_id, NECP_ERROR_INTERNAL); 1548 return; 1549 } 1550 1551 cursor = response; 1552 cursor = necp_buffer_write_packet_header(cursor, NECP_PACKET_TYPE_POLICY_GET, NECP_PACKET_FLAGS_RESPONSE, message_id); 1553 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_POLICY_ORDER, sizeof(necp_policy_order), &policy->order); 1554 1555 if (result_tlv_size) { 1556 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_POLICY_RESULT, policy->result_size, &policy->result); 1557 } 1558 if (policy->conditions_size) { 1559 memcpy(((u_int8_t *)(void *)(cursor)), policy->conditions, policy->conditions_size); 1560 } 1561 1562 if (!necp_send_ctl_data(session, (u_int8_t *)response, response_size)) { 1563 NECPLOG0(LOG_ERR, "Failed to send response"); 1564 } 1565 1566 FREE(response, M_NECP); 1567 return; 1568 1569fail: 1570 necp_send_error_response(session, NECP_PACKET_TYPE_POLICY_GET, message_id, response_error); 1571} 1572 1573static void 1574necp_handle_policy_delete(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1575{ 1576 int error; 1577 u_int32_t response_error = NECP_ERROR_INTERNAL; 1578 necp_policy_id policy_id = 0; 1579 1580 struct necp_session_policy *policy = NULL; 1581 1582 // Read policy id 1583 error = necp_packet_get_tlv(packet, offset, NECP_TLV_POLICY_ID, sizeof(policy_id), &policy_id, NULL); 1584 if (error) { 1585 NECPLOG(LOG_ERR, "Failed to get policy id: %d", error); 1586 response_error = NECP_ERROR_INVALID_TLV; 1587 goto fail; 1588 } 1589 1590 policy = necp_policy_find(session, policy_id); 1591 if (policy == NULL || policy->pending_deletion) { 1592 NECPLOG(LOG_ERR, "Failed to find policy with id %d", policy_id); 1593 response_error = NECP_ERROR_POLICY_ID_NOT_FOUND; 1594 goto fail; 1595 } 1596 1597 necp_policy_mark_for_deletion(session, policy); 1598 1599 necp_send_success_response(session, NECP_PACKET_TYPE_POLICY_DELETE, message_id); 1600 return; 1601 1602fail: 1603 necp_send_error_response(session, NECP_PACKET_TYPE_POLICY_DELETE, message_id, response_error); 1604} 1605 1606static void 1607necp_handle_policy_apply_all(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1608{ 1609#pragma unused(packet, offset) 1610 necp_policy_apply_all(session); 1611 necp_send_success_response(session, NECP_PACKET_TYPE_POLICY_APPLY_ALL, message_id); 1612} 1613 1614static void 1615necp_handle_policy_list_all(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1616{ 1617#pragma unused(packet, offset) 1618 size_t tlv_size = (sizeof(u_int8_t) + sizeof(size_t) + sizeof(u_int32_t)); 1619 size_t response_size = 0; 1620 u_int8_t *response = NULL; 1621 u_int8_t *cursor = NULL; 1622 int num_policies = 0; 1623 int cur_policy_index = 0; 1624 struct necp_session_policy *policy; 1625 1626 LIST_FOREACH(policy, &session->policies, chain) { 1627 if (!policy->pending_deletion) { 1628 num_policies++; 1629 } 1630 } 1631 1632 // Create a response with one Policy ID TLV for each policy 1633 response_size = sizeof(struct necp_packet_header) + num_policies * tlv_size; 1634 MALLOC(response, u_int8_t *, response_size, M_NECP, M_WAITOK); 1635 if (response == NULL) { 1636 necp_send_error_response(session, NECP_PACKET_TYPE_POLICY_LIST_ALL, message_id, NECP_ERROR_INTERNAL); 1637 return; 1638 } 1639 1640 cursor = response; 1641 cursor = necp_buffer_write_packet_header(cursor, NECP_PACKET_TYPE_POLICY_LIST_ALL, NECP_PACKET_FLAGS_RESPONSE, message_id); 1642 1643 LIST_FOREACH(policy, &session->policies, chain) { 1644 if (!policy->pending_deletion && cur_policy_index < num_policies) { 1645 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_POLICY_ID, sizeof(u_int32_t), &policy->id); 1646 cur_policy_index++; 1647 } 1648 } 1649 1650 if (!necp_send_ctl_data(session, (u_int8_t *)response, response_size)) { 1651 NECPLOG0(LOG_ERR, "Failed to send response"); 1652 } 1653 1654 FREE(response, M_NECP); 1655} 1656 1657static void 1658necp_handle_policy_delete_all(struct necp_session *session, u_int32_t message_id, mbuf_t packet, int offset) 1659{ 1660#pragma unused(packet, offset) 1661 necp_policy_mark_all_for_deletion(session); 1662 necp_send_success_response(session, NECP_PACKET_TYPE_POLICY_DELETE_ALL, message_id); 1663} 1664 1665static necp_policy_id 1666necp_policy_get_new_id(void) 1667{ 1668 necp_policy_id newid = 0; 1669 1670 lck_rw_lock_exclusive(&necp_kernel_policy_lock); 1671 1672 necp_last_policy_id++; 1673 if (necp_last_policy_id < 1) { 1674 necp_last_policy_id = 1; 1675 } 1676 1677 newid = necp_last_policy_id; 1678 lck_rw_done(&necp_kernel_policy_lock); 1679 1680 if (newid == 0) { 1681 NECPLOG0(LOG_DEBUG, "Allocate policy id failed.\n"); 1682 return (0); 1683 } 1684 1685 return (newid); 1686} 1687 1688static struct necp_session_policy * 1689necp_policy_create(struct necp_session *session, necp_policy_order order, u_int8_t *conditions_array, size_t conditions_array_size, u_int8_t *result, size_t result_size) 1690{ 1691 struct necp_session_policy *new_policy = NULL; 1692 struct necp_session_policy *tmp_policy = NULL; 1693 1694 if (session == NULL || conditions_array == NULL || result == NULL || result_size == 0) { 1695 goto done; 1696 } 1697 1698 MALLOC_ZONE(new_policy, struct necp_session_policy *, sizeof(*new_policy), M_NECP_SESSION_POLICY, M_WAITOK); 1699 if (new_policy == NULL) { 1700 goto done; 1701 } 1702 1703 memset(new_policy, 0, sizeof(*new_policy)); 1704 new_policy->applied = FALSE; 1705 new_policy->pending_deletion = FALSE; 1706 new_policy->pending_update = FALSE; 1707 new_policy->order = order; 1708 new_policy->conditions = conditions_array; 1709 new_policy->conditions_size = conditions_array_size; 1710 new_policy->result = result; 1711 new_policy->result_size = result_size; 1712 new_policy->id = necp_policy_get_new_id(); 1713 1714 LIST_INSERT_SORTED_ASCENDING(&session->policies, new_policy, chain, order, tmp_policy); 1715 1716 session->dirty = TRUE; 1717 1718 if (necp_debug) { 1719 NECPLOG(LOG_DEBUG, "Created NECP policy, order %d", order); 1720 } 1721done: 1722 return (new_policy); 1723} 1724 1725static struct necp_session_policy * 1726necp_policy_find(struct necp_session *session, necp_policy_id policy_id) 1727{ 1728 struct necp_session_policy *policy = NULL; 1729 if (policy_id == 0) { 1730 return (NULL); 1731 } 1732 1733 LIST_FOREACH(policy, &session->policies, chain) { 1734 if (policy->id == policy_id) { 1735 return (policy); 1736 } 1737 } 1738 1739 return (NULL); 1740} 1741 1742static inline u_int8_t 1743necp_policy_get_result_type(struct necp_session_policy *policy) 1744{ 1745 return (policy ? necp_policy_result_get_type_from_buffer(policy->result, policy->result_size) : 0); 1746} 1747 1748static inline size_t 1749necp_policy_get_result_parameter_length(struct necp_session_policy *policy) 1750{ 1751 return (policy ? necp_policy_result_get_parameter_length_from_buffer(policy->result, policy->result_size) : 0); 1752} 1753 1754static bool 1755necp_policy_get_result_parameter(struct necp_session_policy *policy, u_int8_t *parameter_buffer, size_t parameter_buffer_length) 1756{ 1757 if (policy) { 1758 size_t parameter_length = necp_policy_result_get_parameter_length_from_buffer(policy->result, policy->result_size); 1759 if (parameter_buffer_length >= parameter_length) { 1760 u_int8_t *parameter = necp_policy_result_get_parameter_pointer_from_buffer(policy->result, policy->result_size); 1761 if (parameter && parameter_buffer) { 1762 memcpy(parameter_buffer, parameter, parameter_length); 1763 return (TRUE); 1764 } 1765 } 1766 } 1767 1768 return (FALSE); 1769} 1770 1771static bool 1772necp_policy_mark_for_deletion(struct necp_session *session, struct necp_session_policy *policy) 1773{ 1774 if (session == NULL || policy == NULL) { 1775 return (FALSE); 1776 } 1777 1778 policy->pending_deletion = TRUE; 1779 session->dirty = TRUE; 1780 1781 if (necp_debug) { 1782 NECPLOG0(LOG_DEBUG, "Marked NECP policy for removal"); 1783 } 1784 return (TRUE); 1785} 1786 1787static bool 1788necp_policy_mark_all_for_deletion(struct necp_session *session) 1789{ 1790 struct necp_session_policy *policy = NULL; 1791 struct necp_session_policy *temp_policy = NULL; 1792 1793 LIST_FOREACH_SAFE(policy, &session->policies, chain, temp_policy) { 1794 necp_policy_mark_for_deletion(session, policy); 1795 } 1796 1797 return (TRUE); 1798} 1799 1800static bool 1801necp_policy_delete(struct necp_session *session, struct necp_session_policy *policy) 1802{ 1803 if (session == NULL || policy == NULL) { 1804 return (FALSE); 1805 } 1806 1807 LIST_REMOVE(policy, chain); 1808 1809 if (policy->result) { 1810 FREE(policy->result, M_NECP); 1811 policy->result = NULL; 1812 } 1813 1814 if (policy->conditions) { 1815 FREE(policy->conditions, M_NECP); 1816 policy->conditions = NULL; 1817 } 1818 1819 FREE_ZONE(policy, sizeof(*policy), M_NECP_SESSION_POLICY); 1820 1821 if (necp_debug) { 1822 NECPLOG0(LOG_DEBUG, "Removed NECP policy"); 1823 } 1824 return (TRUE); 1825} 1826 1827static bool 1828necp_policy_unapply(struct necp_session_policy *policy) 1829{ 1830 int i = 0; 1831 if (policy == NULL) { 1832 return (FALSE); 1833 } 1834 1835 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 1836 1837 // Release local uuid mappings 1838 if (!uuid_is_null(policy->applied_app_uuid)) { 1839 bool removed_mapping = FALSE; 1840 if (necp_remove_uuid_app_id_mapping(policy->applied_app_uuid, &removed_mapping, TRUE) && removed_mapping) { 1841 necp_uuid_app_id_mappings_dirty = TRUE; 1842 necp_num_uuid_app_id_mappings--; 1843 } 1844 uuid_clear(policy->applied_app_uuid); 1845 } 1846 if (!uuid_is_null(policy->applied_real_app_uuid)) { 1847 necp_remove_uuid_app_id_mapping(policy->applied_real_app_uuid, NULL, FALSE); 1848 uuid_clear(policy->applied_real_app_uuid); 1849 } 1850 if (!uuid_is_null(policy->applied_service_uuid)) { 1851 necp_remove_uuid_service_id_mapping(policy->applied_service_uuid); 1852 uuid_clear(policy->applied_service_uuid); 1853 } 1854 1855 // Release string mappings 1856 if (policy->applied_account != NULL) { 1857 necp_remove_string_to_id_mapping(&necp_account_id_list, policy->applied_account); 1858 FREE(policy->applied_account, M_NECP); 1859 policy->applied_account = NULL; 1860 } 1861 1862 // Remove socket policies 1863 for (i = 0; i < MAX_KERNEL_SOCKET_POLICIES; i++) { 1864 if (policy->kernel_socket_policies[i] != 0) { 1865 necp_kernel_socket_policy_delete(policy->kernel_socket_policies[i]); 1866 policy->kernel_socket_policies[i] = 0; 1867 } 1868 } 1869 1870 // Remove IP output policies 1871 for (i = 0; i < MAX_KERNEL_IP_OUTPUT_POLICIES; i++) { 1872 if (policy->kernel_ip_output_policies[i] != 0) { 1873 necp_kernel_ip_output_policy_delete(policy->kernel_ip_output_policies[i]); 1874 policy->kernel_ip_output_policies[i] = 0; 1875 } 1876 } 1877 1878 policy->applied = FALSE; 1879 1880 return (TRUE); 1881} 1882 1883#define NECP_KERNEL_POLICY_SUBORDER_ID_TUNNEL_CONDITION 0 1884#define NECP_KERNEL_POLICY_SUBORDER_NON_ID_TUNNEL_CONDITION 1 1885#define NECP_KERNEL_POLICY_SUBORDER_ID_CONDITION 2 1886#define NECP_KERNEL_POLICY_SUBORDER_NON_ID_CONDITIONS 3 1887struct necp_policy_result_ip_tunnel { 1888 u_int32_t secondary_result; 1889 char interface_name[IFXNAMSIZ]; 1890} __attribute__((__packed__)); 1891 1892struct necp_policy_result_service { 1893 uuid_t identifier; 1894 u_int32_t data; 1895} __attribute__((__packed__)); 1896 1897static bool 1898necp_policy_apply(struct necp_session *session, struct necp_session_policy *policy) 1899{ 1900 bool socket_only_conditions = FALSE; 1901 bool socket_ip_conditions = FALSE; 1902 1903 bool socket_layer_non_id_conditions = FALSE; 1904 bool ip_output_layer_non_id_conditions = FALSE; 1905 bool ip_output_layer_id_condition = FALSE; 1906 bool ip_output_layer_tunnel_condition_from_id = FALSE; 1907 bool ip_output_layer_tunnel_condition_from_non_id = FALSE; 1908 necp_kernel_policy_id cond_ip_output_layer_id = NECP_KERNEL_POLICY_ID_NONE; 1909 1910 u_int32_t master_condition_mask = 0; 1911 u_int32_t master_condition_negated_mask = 0; 1912 ifnet_t cond_bound_interface = NULL; 1913 u_int32_t cond_account_id = 0; 1914 char *cond_domain = NULL; 1915 pid_t cond_pid = 0; 1916 uid_t cond_uid = 0; 1917 necp_app_id cond_app_id = 0; 1918 necp_app_id cond_real_app_id = 0; 1919 struct necp_policy_condition_tc_range cond_traffic_class; 1920 cond_traffic_class.start_tc = 0; 1921 cond_traffic_class.end_tc = 0; 1922 u_int16_t cond_protocol = 0; 1923 union necp_sockaddr_union cond_local_start; 1924 union necp_sockaddr_union cond_local_end; 1925 u_int8_t cond_local_prefix = 0; 1926 union necp_sockaddr_union cond_remote_start; 1927 union necp_sockaddr_union cond_remote_end; 1928 u_int8_t cond_remote_prefix = 0; 1929 size_t offset = 0; 1930 u_int8_t ultimate_result = 0; 1931 u_int32_t secondary_result = 0; 1932 necp_kernel_policy_result_parameter secondary_result_parameter; 1933 memset(&secondary_result_parameter, 0, sizeof(secondary_result_parameter)); 1934 u_int32_t cond_last_interface_index = 0; 1935 necp_kernel_policy_result_parameter ultimate_result_parameter; 1936 memset(&ultimate_result_parameter, 0, sizeof(ultimate_result_parameter)); 1937 1938 if (policy == NULL) { 1939 return (FALSE); 1940 } 1941 1942 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 1943 1944 // Process conditions 1945 while (offset < policy->conditions_size) { 1946 size_t length = 0; 1947 u_int8_t *value = necp_buffer_get_tlv_value(policy->conditions, offset, &length); 1948 1949 u_int8_t condition_type = necp_policy_condition_get_type_from_buffer(value, length); 1950 u_int8_t condition_flags = necp_policy_condition_get_flags_from_buffer(value, length); 1951 bool condition_is_negative = condition_flags & NECP_POLICY_CONDITION_FLAGS_NEGATIVE; 1952 size_t condition_length = necp_policy_condition_get_value_length_from_buffer(value, length); 1953 u_int8_t *condition_value = necp_policy_condition_get_value_pointer_from_buffer(value, length); 1954 switch (condition_type) { 1955 case NECP_POLICY_CONDITION_DEFAULT: { 1956 socket_ip_conditions = TRUE; 1957 break; 1958 } 1959 case NECP_POLICY_CONDITION_ALL_INTERFACES: { 1960 master_condition_mask |= NECP_KERNEL_CONDITION_ALL_INTERFACES; 1961 socket_ip_conditions = TRUE; 1962 break; 1963 } 1964 case NECP_POLICY_CONDITION_ENTITLEMENT: { 1965 master_condition_mask |= NECP_KERNEL_CONDITION_ENTITLEMENT; 1966 socket_only_conditions = TRUE; 1967 break; 1968 } 1969 case NECP_POLICY_CONDITION_DOMAIN: { 1970 // Make sure there is only one such rule 1971 if (condition_length > 0 && cond_domain == NULL) { 1972 cond_domain = necp_create_trimmed_domain((char *)condition_value, condition_length); 1973 if (cond_domain != NULL) { 1974 master_condition_mask |= NECP_KERNEL_CONDITION_DOMAIN; 1975 if (condition_is_negative) { 1976 master_condition_negated_mask |= NECP_KERNEL_CONDITION_DOMAIN; 1977 } 1978 socket_only_conditions = TRUE; 1979 } 1980 } 1981 break; 1982 } 1983 case NECP_POLICY_CONDITION_ACCOUNT: { 1984 // Make sure there is only one such rule 1985 if (condition_length > 0 && cond_account_id == 0 && policy->applied_account == NULL) { 1986 char *string = NULL; 1987 MALLOC(string, char *, condition_length + 1, M_NECP, M_WAITOK); 1988 if (string != NULL) { 1989 memcpy(string, condition_value, condition_length); 1990 string[condition_length] = 0; 1991 cond_account_id = necp_create_string_to_id_mapping(&necp_account_id_list, string); 1992 if (cond_account_id != 0) { 1993 policy->applied_account = string; // Save the string in parent policy 1994 master_condition_mask |= NECP_KERNEL_CONDITION_ACCOUNT_ID; 1995 if (condition_is_negative) { 1996 master_condition_negated_mask |= NECP_KERNEL_CONDITION_ACCOUNT_ID; 1997 } 1998 socket_only_conditions = TRUE; 1999 } else { 2000 FREE(string, M_NECP); 2001 } 2002 } 2003 } 2004 break; 2005 } 2006 case NECP_POLICY_CONDITION_APPLICATION: { 2007 // Make sure there is only one such rule, because we save the uuid in the policy 2008 if (condition_length >= sizeof(uuid_t) && cond_app_id == 0) { 2009 bool allocated_mapping = FALSE; 2010 uuid_t application_uuid; 2011 memcpy(application_uuid, condition_value, sizeof(uuid_t)); 2012 cond_app_id = necp_create_uuid_app_id_mapping(application_uuid, &allocated_mapping, TRUE); 2013 if (cond_app_id != 0) { 2014 if (allocated_mapping) { 2015 necp_uuid_app_id_mappings_dirty = TRUE; 2016 necp_num_uuid_app_id_mappings++; 2017 } 2018 uuid_copy(policy->applied_app_uuid, application_uuid); 2019 master_condition_mask |= NECP_KERNEL_CONDITION_APP_ID; 2020 if (condition_is_negative) { 2021 master_condition_negated_mask |= NECP_KERNEL_CONDITION_APP_ID; 2022 } 2023 socket_only_conditions = TRUE; 2024 } 2025 } 2026 break; 2027 } 2028 case NECP_POLICY_CONDITION_REAL_APPLICATION: { 2029 // Make sure there is only one such rule, because we save the uuid in the policy 2030 if (condition_length >= sizeof(uuid_t) && cond_real_app_id == 0) { 2031 uuid_t real_application_uuid; 2032 memcpy(real_application_uuid, condition_value, sizeof(uuid_t)); 2033 cond_real_app_id = necp_create_uuid_app_id_mapping(real_application_uuid, NULL, FALSE); 2034 if (cond_real_app_id != 0) { 2035 uuid_copy(policy->applied_real_app_uuid, real_application_uuid); 2036 master_condition_mask |= NECP_KERNEL_CONDITION_REAL_APP_ID; 2037 if (condition_is_negative) { 2038 master_condition_negated_mask |= NECP_KERNEL_CONDITION_REAL_APP_ID; 2039 } 2040 socket_only_conditions = TRUE; 2041 } 2042 } 2043 break; 2044 } 2045 case NECP_POLICY_CONDITION_PID: { 2046 if (condition_length >= sizeof(pid_t)) { 2047 master_condition_mask |= NECP_KERNEL_CONDITION_PID; 2048 if (condition_is_negative) { 2049 master_condition_negated_mask |= NECP_KERNEL_CONDITION_PID; 2050 } 2051 memcpy(&cond_pid, condition_value, sizeof(cond_pid)); 2052 socket_only_conditions = TRUE; 2053 } 2054 break; 2055 } 2056 case NECP_POLICY_CONDITION_UID: { 2057 if (condition_length >= sizeof(uid_t)) { 2058 master_condition_mask |= NECP_KERNEL_CONDITION_UID; 2059 if (condition_is_negative) { 2060 master_condition_negated_mask |= NECP_KERNEL_CONDITION_UID; 2061 } 2062 memcpy(&cond_uid, condition_value, sizeof(cond_uid)); 2063 socket_only_conditions = TRUE; 2064 } 2065 break; 2066 } 2067 case NECP_POLICY_CONDITION_TRAFFIC_CLASS: { 2068 if (condition_length >= sizeof(struct necp_policy_condition_tc_range)) { 2069 master_condition_mask |= NECP_KERNEL_CONDITION_TRAFFIC_CLASS; 2070 if (condition_is_negative) { 2071 master_condition_negated_mask |= NECP_KERNEL_CONDITION_TRAFFIC_CLASS; 2072 } 2073 memcpy(&cond_traffic_class, condition_value, sizeof(cond_traffic_class)); 2074 socket_only_conditions = TRUE; 2075 } 2076 break; 2077 } 2078 case NECP_POLICY_CONDITION_BOUND_INTERFACE: { 2079 if (condition_length <= IFXNAMSIZ && condition_length > 0) { 2080 char interface_name[IFXNAMSIZ]; 2081 memcpy(interface_name, condition_value, condition_length); 2082 interface_name[condition_length - 1] = 0; // Make sure the string is NULL terminated 2083 if (ifnet_find_by_name(interface_name, &cond_bound_interface) == 0) { 2084 master_condition_mask |= NECP_KERNEL_CONDITION_BOUND_INTERFACE; 2085 if (condition_is_negative) { 2086 master_condition_negated_mask |= NECP_KERNEL_CONDITION_BOUND_INTERFACE; 2087 } 2088 } 2089 socket_ip_conditions = TRUE; 2090 } 2091 break; 2092 } 2093 case NECP_POLICY_CONDITION_IP_PROTOCOL: { 2094 if (condition_length >= sizeof(u_int16_t)) { 2095 master_condition_mask |= NECP_KERNEL_CONDITION_PROTOCOL; 2096 if (condition_is_negative) { 2097 master_condition_negated_mask |= NECP_KERNEL_CONDITION_PROTOCOL; 2098 } 2099 memcpy(&cond_protocol, condition_value, sizeof(cond_protocol)); 2100 socket_ip_conditions = TRUE; 2101 } 2102 break; 2103 } 2104 case NECP_POLICY_CONDITION_LOCAL_ADDR: { 2105 struct necp_policy_condition_addr *address_struct = (struct necp_policy_condition_addr *)(void *)condition_value; 2106 cond_local_prefix = address_struct->prefix; 2107 memcpy(&cond_local_start, &address_struct->address, sizeof(address_struct->address)); 2108 master_condition_mask |= NECP_KERNEL_CONDITION_LOCAL_START; 2109 master_condition_mask |= NECP_KERNEL_CONDITION_LOCAL_PREFIX; 2110 if (condition_is_negative) { 2111 master_condition_negated_mask |= NECP_KERNEL_CONDITION_LOCAL_START; 2112 master_condition_negated_mask |= NECP_KERNEL_CONDITION_LOCAL_PREFIX; 2113 } 2114 socket_ip_conditions = TRUE; 2115 break; 2116 } 2117 case NECP_POLICY_CONDITION_REMOTE_ADDR: { 2118 struct necp_policy_condition_addr *address_struct = (struct necp_policy_condition_addr *)(void *)condition_value; 2119 cond_remote_prefix = address_struct->prefix; 2120 memcpy(&cond_remote_start, &address_struct->address, sizeof(address_struct->address)); 2121 master_condition_mask |= NECP_KERNEL_CONDITION_REMOTE_START; 2122 master_condition_mask |= NECP_KERNEL_CONDITION_REMOTE_PREFIX; 2123 if (condition_is_negative) { 2124 master_condition_negated_mask |= NECP_KERNEL_CONDITION_REMOTE_START; 2125 master_condition_negated_mask |= NECP_KERNEL_CONDITION_REMOTE_PREFIX; 2126 } 2127 socket_ip_conditions = TRUE; 2128 break; 2129 } 2130 case NECP_POLICY_CONDITION_LOCAL_ADDR_RANGE: { 2131 struct necp_policy_condition_addr_range *address_struct = (struct necp_policy_condition_addr_range *)(void *)condition_value; 2132 memcpy(&cond_local_start, &address_struct->start_address, sizeof(address_struct->start_address)); 2133 memcpy(&cond_local_end, &address_struct->end_address, sizeof(address_struct->end_address)); 2134 master_condition_mask |= NECP_KERNEL_CONDITION_LOCAL_START; 2135 master_condition_mask |= NECP_KERNEL_CONDITION_LOCAL_END; 2136 if (condition_is_negative) { 2137 master_condition_negated_mask |= NECP_KERNEL_CONDITION_LOCAL_START; 2138 master_condition_negated_mask |= NECP_KERNEL_CONDITION_LOCAL_END; 2139 } 2140 socket_ip_conditions = TRUE; 2141 break; 2142 } 2143 case NECP_POLICY_CONDITION_REMOTE_ADDR_RANGE: { 2144 struct necp_policy_condition_addr_range *address_struct = (struct necp_policy_condition_addr_range *)(void *)condition_value; 2145 memcpy(&cond_remote_start, &address_struct->start_address, sizeof(address_struct->start_address)); 2146 memcpy(&cond_remote_end, &address_struct->end_address, sizeof(address_struct->end_address)); 2147 master_condition_mask |= NECP_KERNEL_CONDITION_REMOTE_START; 2148 master_condition_mask |= NECP_KERNEL_CONDITION_REMOTE_END; 2149 if (condition_is_negative) { 2150 master_condition_negated_mask |= NECP_KERNEL_CONDITION_REMOTE_START; 2151 master_condition_negated_mask |= NECP_KERNEL_CONDITION_REMOTE_END; 2152 } 2153 socket_ip_conditions = TRUE; 2154 break; 2155 } 2156 default: { 2157 break; 2158 } 2159 } 2160 2161 offset += sizeof(u_int8_t) + sizeof(size_t) + length; 2162 } 2163 2164 // Process result 2165 ultimate_result = necp_policy_get_result_type(policy); 2166 switch (ultimate_result) { 2167 case NECP_POLICY_RESULT_PASS: { 2168 if (socket_only_conditions) { // socket_ip_conditions can be TRUE or FALSE 2169 socket_layer_non_id_conditions = TRUE; 2170 ip_output_layer_id_condition = TRUE; 2171 } else if (socket_ip_conditions) { 2172 socket_layer_non_id_conditions = TRUE; 2173 ip_output_layer_id_condition = TRUE; 2174 ip_output_layer_non_id_conditions = TRUE; 2175 } 2176 break; 2177 } 2178 case NECP_POLICY_RESULT_DROP: { 2179 if (socket_only_conditions) { // socket_ip_conditions can be TRUE or FALSE 2180 socket_layer_non_id_conditions = TRUE; 2181 } else if (socket_ip_conditions) { 2182 socket_layer_non_id_conditions = TRUE; 2183 ip_output_layer_non_id_conditions = TRUE; 2184 } 2185 break; 2186 } 2187 case NECP_POLICY_RESULT_SKIP: { 2188 u_int32_t skip_policy_order = 0; 2189 if (necp_policy_get_result_parameter(policy, (u_int8_t *)&skip_policy_order, sizeof(skip_policy_order))) { 2190 ultimate_result_parameter.skip_policy_order = skip_policy_order; 2191 } 2192 2193 if (socket_only_conditions) { // socket_ip_conditions can be TRUE or FALSE 2194 socket_layer_non_id_conditions = TRUE; 2195 ip_output_layer_id_condition = TRUE; 2196 } else if (socket_ip_conditions) { 2197 socket_layer_non_id_conditions = TRUE; 2198 ip_output_layer_non_id_conditions = TRUE; 2199 } 2200 break; 2201 } 2202 case NECP_POLICY_RESULT_SOCKET_DIVERT: 2203 case NECP_POLICY_RESULT_SOCKET_FILTER: { 2204 u_int32_t control_unit = 0; 2205 if (necp_policy_get_result_parameter(policy, (u_int8_t *)&control_unit, sizeof(control_unit))) { 2206 ultimate_result_parameter.flow_divert_control_unit = control_unit; 2207 } 2208 socket_layer_non_id_conditions = TRUE; 2209 break; 2210 } 2211 case NECP_POLICY_RESULT_IP_TUNNEL: { 2212 struct necp_policy_result_ip_tunnel tunnel_parameters; 2213 size_t tunnel_parameters_length = necp_policy_get_result_parameter_length(policy); 2214 if (tunnel_parameters_length > sizeof(u_int32_t) && 2215 tunnel_parameters_length <= sizeof(struct necp_policy_result_ip_tunnel) && 2216 necp_policy_get_result_parameter(policy, (u_int8_t *)&tunnel_parameters, sizeof(tunnel_parameters))) { 2217 ifnet_t tunnel_interface = NULL; 2218 tunnel_parameters.interface_name[tunnel_parameters_length - sizeof(u_int32_t) - 1] = 0; // Make sure the string is NULL terminated 2219 if (ifnet_find_by_name(tunnel_parameters.interface_name, &tunnel_interface) == 0) { 2220 ultimate_result_parameter.tunnel_interface_index = tunnel_interface->if_index; 2221 } 2222 2223 secondary_result = tunnel_parameters.secondary_result; 2224 if (secondary_result) { 2225 cond_last_interface_index = ultimate_result_parameter.tunnel_interface_index; 2226 } 2227 } 2228 2229 if (socket_only_conditions) { // socket_ip_conditions can be TRUE or FALSE 2230 socket_layer_non_id_conditions = TRUE; 2231 ip_output_layer_id_condition = TRUE; 2232 if (secondary_result) { 2233 ip_output_layer_tunnel_condition_from_id = TRUE; 2234 } 2235 } else if (socket_ip_conditions) { 2236 socket_layer_non_id_conditions = TRUE; 2237 ip_output_layer_id_condition = TRUE; 2238 ip_output_layer_non_id_conditions = TRUE; 2239 if (secondary_result) { 2240 ip_output_layer_tunnel_condition_from_id = TRUE; 2241 ip_output_layer_tunnel_condition_from_non_id = TRUE; 2242 } 2243 } 2244 break; 2245 } 2246 case NECP_POLICY_RESULT_TRIGGER: 2247 case NECP_POLICY_RESULT_TRIGGER_IF_NEEDED: 2248 case NECP_POLICY_RESULT_TRIGGER_SCOPED: 2249 case NECP_POLICY_RESULT_NO_TRIGGER_SCOPED: { 2250 struct necp_policy_result_service service_parameters; 2251 size_t service_result_length = necp_policy_get_result_parameter_length(policy); 2252 bool has_extra_service_data = FALSE; 2253 if (service_result_length >= (sizeof(service_parameters))) { 2254 has_extra_service_data = TRUE; 2255 } 2256 if (necp_policy_get_result_parameter(policy, (u_int8_t *)&service_parameters, sizeof(service_parameters))) { 2257 ultimate_result_parameter.service.identifier = necp_create_uuid_service_id_mapping(service_parameters.identifier); 2258 if (ultimate_result_parameter.service.identifier != 0) { 2259 uuid_copy(policy->applied_service_uuid, service_parameters.identifier); 2260 socket_layer_non_id_conditions = TRUE; 2261 if (has_extra_service_data) { 2262 ultimate_result_parameter.service.data = service_parameters.data; 2263 } else { 2264 ultimate_result_parameter.service.data = 0; 2265 } 2266 } 2267 } 2268 break; 2269 } 2270 case NECP_POLICY_RESULT_SOCKET_SCOPED: { 2271 size_t interface_name_length = necp_policy_get_result_parameter_length(policy); 2272 if (interface_name_length <= IFXNAMSIZ && interface_name_length > 0) { 2273 char interface_name[IFXNAMSIZ]; 2274 ifnet_t scope_interface = NULL; 2275 necp_policy_get_result_parameter(policy, (u_int8_t *)interface_name, interface_name_length); 2276 interface_name[interface_name_length - 1] = 0; // Make sure the string is NULL terminated 2277 if (ifnet_find_by_name(interface_name, &scope_interface) == 0) { 2278 ultimate_result_parameter.scoped_interface_index = scope_interface->if_index; 2279 socket_layer_non_id_conditions = TRUE; 2280 } 2281 } 2282 } 2283 default: { 2284 break; 2285 } 2286 } 2287 2288 if (socket_layer_non_id_conditions) { 2289 necp_kernel_policy_id policy_id = necp_kernel_socket_policy_add(policy->id, policy->order, session->session_order, master_condition_mask, master_condition_negated_mask, cond_app_id, cond_real_app_id, cond_account_id, cond_domain, cond_pid, cond_uid, cond_bound_interface, cond_traffic_class, cond_protocol, &cond_local_start, &cond_local_end, cond_local_prefix, &cond_remote_start, &cond_remote_end, cond_remote_prefix, ultimate_result, ultimate_result_parameter); 2290 2291 if (policy_id == 0) { 2292 NECPLOG0(LOG_DEBUG, "Error applying socket kernel policy"); 2293 goto fail; 2294 } 2295 2296 cond_ip_output_layer_id = policy_id; 2297 policy->kernel_socket_policies[0] = policy_id; 2298 } 2299 2300 if (ip_output_layer_non_id_conditions) { 2301 necp_kernel_policy_id policy_id = necp_kernel_ip_output_policy_add(policy->id, policy->order, NECP_KERNEL_POLICY_SUBORDER_NON_ID_CONDITIONS, session->session_order, master_condition_mask, master_condition_negated_mask, NECP_KERNEL_POLICY_ID_NONE, cond_bound_interface, 0, cond_protocol, &cond_local_start, &cond_local_end, cond_local_prefix, &cond_remote_start, &cond_remote_end, cond_remote_prefix, ultimate_result, ultimate_result_parameter); 2302 2303 if (policy_id == 0) { 2304 NECPLOG0(LOG_DEBUG, "Error applying IP output kernel policy"); 2305 goto fail; 2306 } 2307 2308 policy->kernel_ip_output_policies[NECP_KERNEL_POLICY_SUBORDER_NON_ID_CONDITIONS] = policy_id; 2309 } 2310 2311 if (ip_output_layer_id_condition) { 2312 necp_kernel_policy_id policy_id = necp_kernel_ip_output_policy_add(policy->id, policy->order, NECP_KERNEL_POLICY_SUBORDER_ID_CONDITION, session->session_order, NECP_KERNEL_CONDITION_POLICY_ID | NECP_KERNEL_CONDITION_ALL_INTERFACES, 0, cond_ip_output_layer_id, NULL, 0, 0, NULL, NULL, 0, NULL, NULL, 0, ultimate_result, ultimate_result_parameter); 2313 2314 if (policy_id == 0) { 2315 NECPLOG0(LOG_DEBUG, "Error applying IP output kernel policy"); 2316 goto fail; 2317 } 2318 2319 policy->kernel_ip_output_policies[NECP_KERNEL_POLICY_SUBORDER_ID_CONDITION] = policy_id; 2320 } 2321 2322 // Extra policies for IP Output tunnels for when packets loop back 2323 if (ip_output_layer_tunnel_condition_from_id) { 2324 necp_kernel_policy_id policy_id = necp_kernel_ip_output_policy_add(policy->id, policy->order, NECP_KERNEL_POLICY_SUBORDER_NON_ID_TUNNEL_CONDITION, session->session_order, NECP_KERNEL_CONDITION_POLICY_ID | NECP_KERNEL_CONDITION_LAST_INTERFACE | NECP_KERNEL_CONDITION_ALL_INTERFACES, 0, policy->kernel_ip_output_policies[NECP_KERNEL_POLICY_SUBORDER_NON_ID_CONDITIONS], NULL, cond_last_interface_index, 0, NULL, NULL, 0, NULL, NULL, 0, secondary_result, secondary_result_parameter); 2325 2326 if (policy_id == 0) { 2327 NECPLOG0(LOG_DEBUG, "Error applying IP output kernel policy"); 2328 goto fail; 2329 } 2330 2331 policy->kernel_ip_output_policies[NECP_KERNEL_POLICY_SUBORDER_NON_ID_TUNNEL_CONDITION] = policy_id; 2332 } 2333 2334 if (ip_output_layer_tunnel_condition_from_id) { 2335 necp_kernel_policy_id policy_id = necp_kernel_ip_output_policy_add(policy->id, policy->order, NECP_KERNEL_POLICY_SUBORDER_ID_TUNNEL_CONDITION, session->session_order, NECP_KERNEL_CONDITION_POLICY_ID | NECP_KERNEL_CONDITION_LAST_INTERFACE | NECP_KERNEL_CONDITION_ALL_INTERFACES, 0, policy->kernel_ip_output_policies[NECP_KERNEL_POLICY_SUBORDER_ID_CONDITION], NULL, cond_last_interface_index, 0, NULL, NULL, 0, NULL, NULL, 0, secondary_result, secondary_result_parameter); 2336 2337 if (policy_id == 0) { 2338 NECPLOG0(LOG_DEBUG, "Error applying IP output kernel policy"); 2339 goto fail; 2340 } 2341 2342 policy->kernel_ip_output_policies[NECP_KERNEL_POLICY_SUBORDER_ID_TUNNEL_CONDITION] = policy_id; 2343 } 2344 2345 policy->applied = TRUE; 2346 policy->pending_update = FALSE; 2347 return (TRUE); 2348 2349fail: 2350 return (FALSE); 2351} 2352 2353static void 2354necp_policy_apply_all(struct necp_session *session) 2355{ 2356 struct necp_session_policy *policy = NULL; 2357 struct necp_session_policy *temp_policy = NULL; 2358 2359 lck_rw_lock_exclusive(&necp_kernel_policy_lock); 2360 2361 // Remove exisiting applied policies 2362 if (session->dirty) { 2363 LIST_FOREACH_SAFE(policy, &session->policies, chain, temp_policy) { 2364 if (policy->pending_deletion) { 2365 if (policy->applied) { 2366 necp_policy_unapply(policy); 2367 } 2368 // Delete the policy 2369 necp_policy_delete(session, policy); 2370 } else if (!policy->applied) { 2371 necp_policy_apply(session, policy); 2372 } else if (policy->pending_update) { 2373 // Must have been applied, but needs an update. Remove and re-add. 2374 necp_policy_unapply(policy); 2375 necp_policy_apply(session, policy); 2376 } 2377 } 2378 2379 necp_kernel_socket_policies_update_uuid_table(); 2380 necp_kernel_socket_policies_reprocess(); 2381 necp_kernel_ip_output_policies_reprocess(); 2382 2383 // Clear dirty bit flags 2384 session->dirty = FALSE; 2385 } 2386 2387 lck_rw_done(&necp_kernel_policy_lock); 2388 2389 if (necp_debug) { 2390 NECPLOG0(LOG_DEBUG, "Applied NECP policies"); 2391 } 2392} 2393 2394// Kernel Policy Management 2395// --------------------- 2396// Kernel policies are derived from session policies 2397static necp_kernel_policy_id 2398necp_kernel_policy_get_new_id(void) 2399{ 2400 necp_kernel_policy_id newid = NECP_KERNEL_POLICY_ID_NONE; 2401 2402 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 2403 2404 necp_last_kernel_policy_id++; 2405 if (necp_last_kernel_policy_id < NECP_KERNEL_POLICY_ID_FIRST_VALID) { 2406 necp_last_kernel_policy_id = NECP_KERNEL_POLICY_ID_FIRST_VALID; 2407 } 2408 2409 newid = necp_last_kernel_policy_id; 2410 if (newid == NECP_KERNEL_POLICY_ID_NONE) { 2411 NECPLOG0(LOG_DEBUG, "Allocate kernel policy id failed.\n"); 2412 return (0); 2413 } 2414 2415 return (newid); 2416} 2417 2418#define NECP_KERNEL_VALID_SOCKET_CONDITIONS (NECP_KERNEL_CONDITION_APP_ID | NECP_KERNEL_CONDITION_REAL_APP_ID | NECP_KERNEL_CONDITION_DOMAIN | NECP_KERNEL_CONDITION_ACCOUNT_ID | NECP_KERNEL_CONDITION_PID | NECP_KERNEL_CONDITION_UID | NECP_KERNEL_CONDITION_ALL_INTERFACES | NECP_KERNEL_CONDITION_BOUND_INTERFACE | NECP_KERNEL_CONDITION_TRAFFIC_CLASS | NECP_KERNEL_CONDITION_PROTOCOL | NECP_KERNEL_CONDITION_LOCAL_START | NECP_KERNEL_CONDITION_LOCAL_END | NECP_KERNEL_CONDITION_LOCAL_PREFIX | NECP_KERNEL_CONDITION_REMOTE_START | NECP_KERNEL_CONDITION_REMOTE_END | NECP_KERNEL_CONDITION_REMOTE_PREFIX | NECP_KERNEL_CONDITION_ENTITLEMENT) 2419static necp_kernel_policy_id 2420necp_kernel_socket_policy_add(necp_policy_id parent_policy_id, necp_policy_order order, u_int32_t session_order, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_app_id cond_app_id, necp_app_id cond_real_app_id, u_int32_t cond_account_id, char *cond_domain, pid_t cond_pid, uid_t cond_uid, ifnet_t cond_bound_interface, struct necp_policy_condition_tc_range cond_traffic_class, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter) 2421{ 2422 struct necp_kernel_socket_policy *new_kernel_policy = NULL; 2423 struct necp_kernel_socket_policy *tmp_kernel_policy = NULL; 2424 2425 MALLOC_ZONE(new_kernel_policy, struct necp_kernel_socket_policy *, sizeof(*new_kernel_policy), M_NECP_SOCKET_POLICY, M_WAITOK); 2426 if (new_kernel_policy == NULL) { 2427 goto done; 2428 } 2429 2430 memset(new_kernel_policy, 0, sizeof(*new_kernel_policy)); 2431 new_kernel_policy->parent_policy_id = parent_policy_id; 2432 new_kernel_policy->id = necp_kernel_policy_get_new_id(); 2433 new_kernel_policy->order = order; 2434 new_kernel_policy->session_order = session_order; 2435 2436 // Sanitize condition mask 2437 new_kernel_policy->condition_mask = (condition_mask & NECP_KERNEL_VALID_SOCKET_CONDITIONS); 2438 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES) && (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE)) { 2439 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_BOUND_INTERFACE; 2440 } 2441 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REAL_APP_ID) && !(new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_APP_ID)) { 2442 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_REAL_APP_ID; 2443 } 2444 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ENTITLEMENT) && !(new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_APP_ID)) { 2445 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_ENTITLEMENT; 2446 } 2447 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) && (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX)) { 2448 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_LOCAL_PREFIX; 2449 } 2450 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) && (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX)) { 2451 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_REMOTE_PREFIX; 2452 } 2453 new_kernel_policy->condition_negated_mask = condition_negated_mask & new_kernel_policy->condition_mask; 2454 2455 // Set condition values 2456 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_APP_ID) { 2457 new_kernel_policy->cond_app_id = cond_app_id; 2458 } 2459 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REAL_APP_ID) { 2460 new_kernel_policy->cond_real_app_id = cond_real_app_id; 2461 } 2462 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID) { 2463 new_kernel_policy->cond_account_id = cond_account_id; 2464 } 2465 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_DOMAIN) { 2466 new_kernel_policy->cond_domain = cond_domain; 2467 new_kernel_policy->cond_domain_dot_count = necp_count_dots(cond_domain, strlen(cond_domain)); 2468 } 2469 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_PID) { 2470 new_kernel_policy->cond_pid = cond_pid; 2471 } 2472 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_UID) { 2473 new_kernel_policy->cond_uid = cond_uid; 2474 } 2475 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE) { 2476 if (cond_bound_interface) { 2477 ifnet_reference(cond_bound_interface); 2478 } 2479 new_kernel_policy->cond_bound_interface = cond_bound_interface; 2480 } 2481 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_TRAFFIC_CLASS) { 2482 new_kernel_policy->cond_traffic_class = cond_traffic_class; 2483 } 2484 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_PROTOCOL) { 2485 new_kernel_policy->cond_protocol = cond_protocol; 2486 } 2487 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_START) { 2488 memcpy(&new_kernel_policy->cond_local_start, cond_local_start, cond_local_start->sa.sa_len); 2489 } 2490 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 2491 memcpy(&new_kernel_policy->cond_local_end, cond_local_end, cond_local_end->sa.sa_len); 2492 } 2493 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 2494 new_kernel_policy->cond_local_prefix = cond_local_prefix; 2495 } 2496 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_START) { 2497 memcpy(&new_kernel_policy->cond_remote_start, cond_remote_start, cond_remote_start->sa.sa_len); 2498 } 2499 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 2500 memcpy(&new_kernel_policy->cond_remote_end, cond_remote_end, cond_remote_end->sa.sa_len); 2501 } 2502 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 2503 new_kernel_policy->cond_remote_prefix = cond_remote_prefix; 2504 } 2505 2506 new_kernel_policy->result = result; 2507 memcpy(&new_kernel_policy->result_parameter, &result_parameter, sizeof(result_parameter)); 2508 2509 if (necp_debug) { 2510 NECPLOG(LOG_DEBUG, "Added kernel policy: socket, id=%d, mask=%x\n", new_kernel_policy->id, new_kernel_policy->condition_mask); 2511 } 2512 LIST_INSERT_SORTED_TWICE_ASCENDING(&necp_kernel_socket_policies, new_kernel_policy, chain, session_order, order, tmp_kernel_policy); 2513done: 2514 return (new_kernel_policy ? new_kernel_policy->id : 0); 2515} 2516 2517static struct necp_kernel_socket_policy * 2518necp_kernel_socket_policy_find(necp_kernel_policy_id policy_id) 2519{ 2520 struct necp_kernel_socket_policy *kernel_policy = NULL; 2521 struct necp_kernel_socket_policy *tmp_kernel_policy = NULL; 2522 2523 if (policy_id == 0) { 2524 return (NULL); 2525 } 2526 2527 LIST_FOREACH_SAFE(kernel_policy, &necp_kernel_socket_policies, chain, tmp_kernel_policy) { 2528 if (kernel_policy->id == policy_id) { 2529 return (kernel_policy); 2530 } 2531 } 2532 2533 return (NULL); 2534} 2535 2536static bool 2537necp_kernel_socket_policy_delete(necp_kernel_policy_id policy_id) 2538{ 2539 struct necp_kernel_socket_policy *policy = NULL; 2540 2541 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 2542 2543 policy = necp_kernel_socket_policy_find(policy_id); 2544 if (policy) { 2545 LIST_REMOVE(policy, chain); 2546 2547 if (policy->cond_bound_interface) { 2548 ifnet_release(policy->cond_bound_interface); 2549 policy->cond_bound_interface = NULL; 2550 } 2551 2552 if (policy->cond_domain) { 2553 FREE(policy->cond_domain, M_NECP); 2554 policy->cond_domain = NULL; 2555 } 2556 2557 FREE_ZONE(policy, sizeof(*policy), M_NECP_SOCKET_POLICY); 2558 return (TRUE); 2559 } 2560 2561 return (FALSE); 2562} 2563 2564static void 2565necp_kernel_socket_policies_dump_all(void) 2566{ 2567 struct necp_kernel_socket_policy *policy = NULL; 2568 int policy_i; 2569 int app_i; 2570 2571 if (necp_debug) { 2572 NECPLOG0(LOG_DEBUG, "NECP Application Policies:\n"); 2573 NECPLOG0(LOG_DEBUG, "-----------\n"); 2574 for (policy_i = 0; necp_kernel_socket_policies_app_layer_map != NULL && necp_kernel_socket_policies_app_layer_map[policy_i] != NULL; policy_i++) { 2575 policy = necp_kernel_socket_policies_app_layer_map[policy_i]; 2576 NECPLOG(LOG_DEBUG, "\t%d. Policy ID: %d, Order: %d.%d, Mask: %x, Result: %d, Parameter: %d\n", policy_i, policy->id, policy->session_order, policy->order, policy->condition_mask, policy->result, policy->result_parameter); 2577 } 2578 if (necp_kernel_socket_policies_app_layer_map[0] != NULL) { 2579 NECPLOG0(LOG_DEBUG, "-----------\n"); 2580 } 2581 2582 NECPLOG0(LOG_DEBUG, "NECP Socket Policies:\n"); 2583 NECPLOG0(LOG_DEBUG, "-----------\n"); 2584 for (app_i = 0; app_i < NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS; app_i++) { 2585 NECPLOG(LOG_DEBUG, "\tApp Bucket: %d\n", app_i); 2586 for (policy_i = 0; necp_kernel_socket_policies_map[app_i] != NULL && (necp_kernel_socket_policies_map[app_i])[policy_i] != NULL; policy_i++) { 2587 policy = (necp_kernel_socket_policies_map[app_i])[policy_i]; 2588 NECPLOG(LOG_DEBUG, "\t%d. Policy ID: %d, Order: %d.%d, Mask: %x, Result: %d, Parameter: %d\n", policy_i, policy->id, policy->session_order, policy->order, policy->condition_mask, policy->result, policy->result_parameter); 2589 } 2590 NECPLOG0(LOG_DEBUG, "-----------\n"); 2591 } 2592 } 2593} 2594 2595static inline bool 2596necp_kernel_socket_result_is_service_type(struct necp_kernel_socket_policy *kernel_policy) 2597{ 2598 return (kernel_policy->result >= NECP_KERNEL_POLICY_RESULT_TRIGGER && kernel_policy->result <= NECP_KERNEL_POLICY_RESULT_NO_TRIGGER_SCOPED); 2599} 2600 2601static inline bool 2602necp_kernel_socket_policy_results_overlap(struct necp_kernel_socket_policy *upper_policy, struct necp_kernel_socket_policy *lower_policy) 2603{ 2604 if (upper_policy->result == NECP_KERNEL_POLICY_RESULT_DROP) { 2605 // Drop always cancels out lower policies 2606 return (TRUE); 2607 } else if (upper_policy->result == NECP_KERNEL_POLICY_RESULT_SOCKET_FILTER) { 2608 // Filters never cancel out lower policies 2609 return (FALSE); 2610 } else if (necp_kernel_socket_result_is_service_type(upper_policy)) { 2611 // Trigger/Scoping policies can overlap one another, but not other results 2612 return (necp_kernel_socket_result_is_service_type(lower_policy)); 2613 } else if (upper_policy->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 2614 if (upper_policy->session_order != lower_policy->session_order) { 2615 // A skip cannot override a policy of a different session 2616 return (FALSE); 2617 } else { 2618 if (upper_policy->result_parameter.skip_policy_order == 0 || 2619 lower_policy->order >= upper_policy->result_parameter.skip_policy_order) { 2620 // This policy is beyond the skip 2621 return (FALSE); 2622 } else { 2623 // This policy is inside the skip 2624 return (TRUE); 2625 } 2626 } 2627 } 2628 2629 // A hard pass, flow divert, or tunnel will currently block out lower policies 2630 return (TRUE); 2631} 2632 2633static bool 2634necp_kernel_socket_policy_is_unnecessary(struct necp_kernel_socket_policy *policy, struct necp_kernel_socket_policy **policy_array, int valid_indices) 2635{ 2636 bool can_skip = FALSE; 2637 u_int32_t highest_skip_session_order = 0; 2638 u_int32_t highest_skip_order = 0; 2639 int i; 2640 for (i = 0; i < valid_indices; i++) { 2641 struct necp_kernel_socket_policy *compared_policy = policy_array[i]; 2642 2643 // For policies in a skip window, we can't mark conflicting policies as unnecessary 2644 if (can_skip) { 2645 if (highest_skip_session_order != compared_policy->session_order || 2646 (highest_skip_order != 0 && compared_policy->order >= highest_skip_order)) { 2647 // If we've moved on to the next session, or passed the skip window 2648 highest_skip_session_order = 0; 2649 highest_skip_order = 0; 2650 can_skip = FALSE; 2651 } else { 2652 // If this policy is also a skip, in can increase the skip window 2653 if (compared_policy->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 2654 if (compared_policy->result_parameter.skip_policy_order > highest_skip_order) { 2655 highest_skip_order = compared_policy->result_parameter.skip_policy_order; 2656 } 2657 } 2658 continue; 2659 } 2660 } 2661 2662 if (compared_policy->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 2663 // This policy is a skip. Set the skip window accordingly 2664 can_skip = TRUE; 2665 highest_skip_session_order = compared_policy->session_order; 2666 highest_skip_order = compared_policy->result_parameter.skip_policy_order; 2667 } 2668 2669 // The result of the compared policy must be able to block out this policy result 2670 if (!necp_kernel_socket_policy_results_overlap(compared_policy, policy)) { 2671 continue; 2672 } 2673 2674 // If new policy matches All Interfaces, compared policy must also 2675 if ((policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES) && !(compared_policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES)) { 2676 continue; 2677 } 2678 2679 // Default makes lower policies unecessary always 2680 if (compared_policy->condition_mask == 0) { 2681 return (TRUE); 2682 } 2683 2684 // Compared must be more general than policy, and include only conditions within policy 2685 if ((policy->condition_mask & compared_policy->condition_mask) != compared_policy->condition_mask) { 2686 continue; 2687 } 2688 2689 // Negative conditions must match for the overlapping conditions 2690 if ((policy->condition_negated_mask & compared_policy->condition_mask) != (compared_policy->condition_negated_mask & compared_policy->condition_mask)) { 2691 continue; 2692 } 2693 2694 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_DOMAIN && 2695 strcmp(compared_policy->cond_domain, policy->cond_domain) != 0) { 2696 continue; 2697 } 2698 2699 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID && 2700 compared_policy->cond_account_id != policy->cond_account_id) { 2701 continue; 2702 } 2703 2704 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_POLICY_ID && 2705 compared_policy->cond_policy_id != policy->cond_policy_id) { 2706 continue; 2707 } 2708 2709 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_APP_ID && 2710 compared_policy->cond_app_id != policy->cond_app_id) { 2711 continue; 2712 } 2713 2714 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_REAL_APP_ID && 2715 compared_policy->cond_real_app_id != policy->cond_real_app_id) { 2716 continue; 2717 } 2718 2719 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_PID && 2720 compared_policy->cond_pid != policy->cond_pid) { 2721 continue; 2722 } 2723 2724 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_UID && 2725 compared_policy->cond_uid != policy->cond_uid) { 2726 continue; 2727 } 2728 2729 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE && 2730 compared_policy->cond_bound_interface != policy->cond_bound_interface) { 2731 continue; 2732 } 2733 2734 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_PROTOCOL && 2735 compared_policy->cond_protocol != policy->cond_protocol) { 2736 continue; 2737 } 2738 2739 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_TRAFFIC_CLASS && 2740 !(compared_policy->cond_traffic_class.start_tc <= policy->cond_traffic_class.start_tc && 2741 compared_policy->cond_traffic_class.end_tc >= policy->cond_traffic_class.end_tc)) { 2742 continue; 2743 } 2744 2745 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_START) { 2746 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 2747 if (!necp_is_range_in_range((struct sockaddr *)&policy->cond_local_start, (struct sockaddr *)&policy->cond_local_end, (struct sockaddr *)&compared_policy->cond_local_start, (struct sockaddr *)&compared_policy->cond_local_end)) { 2748 continue; 2749 } 2750 } else if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 2751 if (compared_policy->cond_local_prefix > policy->cond_local_prefix || 2752 !necp_is_addr_in_subnet((struct sockaddr *)&policy->cond_local_start, (struct sockaddr *)&compared_policy->cond_local_start, compared_policy->cond_local_prefix)) { 2753 continue; 2754 } 2755 } 2756 } 2757 2758 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_START) { 2759 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 2760 if (!necp_is_range_in_range((struct sockaddr *)&policy->cond_remote_start, (struct sockaddr *)&policy->cond_remote_end, (struct sockaddr *)&compared_policy->cond_remote_start, (struct sockaddr *)&compared_policy->cond_remote_end)) { 2761 continue; 2762 } 2763 } else if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 2764 if (compared_policy->cond_remote_prefix > policy->cond_remote_prefix || 2765 !necp_is_addr_in_subnet((struct sockaddr *)&policy->cond_remote_start, (struct sockaddr *)&compared_policy->cond_remote_start, compared_policy->cond_remote_prefix)) { 2766 continue; 2767 } 2768 } 2769 } 2770 2771 return (TRUE); 2772 } 2773 2774 return (FALSE); 2775} 2776 2777static bool 2778necp_kernel_socket_policies_reprocess(void) 2779{ 2780 int app_i; 2781 int bucket_allocation_counts[NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS]; 2782 int bucket_current_free_index[NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS]; 2783 int app_layer_allocation_count = 0; 2784 int app_layer_current_free_index = 0; 2785 struct necp_kernel_socket_policy *kernel_policy = NULL; 2786 2787 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 2788 2789 // Reset mask to 0 2790 necp_kernel_application_policies_condition_mask = 0; 2791 necp_kernel_socket_policies_condition_mask = 0; 2792 necp_kernel_application_policies_count = 0; 2793 necp_kernel_socket_policies_count = 0; 2794 necp_kernel_socket_policies_non_app_count = 0; 2795 2796 // Reset all maps to NULL 2797 for (app_i = 0; app_i < NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS; app_i++) { 2798 if (necp_kernel_socket_policies_map[app_i] != NULL) { 2799 FREE(necp_kernel_socket_policies_map[app_i], M_NECP); 2800 necp_kernel_socket_policies_map[app_i] = NULL; 2801 } 2802 2803 // Init counts 2804 bucket_allocation_counts[app_i] = 0; 2805 } 2806 if (necp_kernel_socket_policies_app_layer_map != NULL) { 2807 FREE(necp_kernel_socket_policies_app_layer_map, M_NECP); 2808 necp_kernel_socket_policies_app_layer_map = NULL; 2809 } 2810 2811 // Create masks and counts 2812 LIST_FOREACH(kernel_policy, &necp_kernel_socket_policies, chain) { 2813 // App layer mask/count 2814 necp_kernel_application_policies_condition_mask |= kernel_policy->condition_mask; 2815 necp_kernel_application_policies_count++; 2816 app_layer_allocation_count++; 2817 2818 // Update socket layer bucket mask/counts 2819 necp_kernel_socket_policies_condition_mask |= kernel_policy->condition_mask; 2820 necp_kernel_socket_policies_count++; 2821 2822 if (!(kernel_policy->condition_mask & NECP_KERNEL_CONDITION_APP_ID) || 2823 kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_APP_ID) { 2824 necp_kernel_socket_policies_non_app_count++; 2825 for (app_i = 0; app_i < NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS; app_i++) { 2826 bucket_allocation_counts[app_i]++; 2827 } 2828 } else { 2829 bucket_allocation_counts[NECP_SOCKET_MAP_APP_ID_TO_BUCKET(kernel_policy->cond_app_id)]++; 2830 } 2831 } 2832 2833 // Allocate maps 2834 for (app_i = 0; app_i < NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS; app_i++) { 2835 if (bucket_allocation_counts[app_i] > 0) { 2836 // Allocate a NULL-terminated array of policy pointers for each bucket 2837 MALLOC(necp_kernel_socket_policies_map[app_i], struct necp_kernel_socket_policy **, sizeof(struct necp_kernel_socket_policy *) * (bucket_allocation_counts[app_i] + 1), M_NECP, M_WAITOK); 2838 if (necp_kernel_socket_policies_map[app_i] == NULL) { 2839 goto fail; 2840 } 2841 2842 // Initialize the first entry to NULL 2843 (necp_kernel_socket_policies_map[app_i])[0] = NULL; 2844 } 2845 bucket_current_free_index[app_i] = 0; 2846 } 2847 MALLOC(necp_kernel_socket_policies_app_layer_map, struct necp_kernel_socket_policy **, sizeof(struct necp_kernel_socket_policy *) * (app_layer_allocation_count + 1), M_NECP, M_WAITOK); 2848 if (necp_kernel_socket_policies_app_layer_map == NULL) { 2849 goto fail; 2850 } 2851 necp_kernel_socket_policies_app_layer_map[0] = NULL; 2852 2853 // Fill out maps 2854 LIST_FOREACH(kernel_policy, &necp_kernel_socket_policies, chain) { 2855 // Insert pointers into map 2856 if (!(kernel_policy->condition_mask & NECP_KERNEL_CONDITION_APP_ID) || 2857 kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_APP_ID) { 2858 for (app_i = 0; app_i < NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS; app_i++) { 2859 if (!necp_kernel_socket_policy_is_unnecessary(kernel_policy, necp_kernel_socket_policies_map[app_i], bucket_current_free_index[app_i])) { 2860 (necp_kernel_socket_policies_map[app_i])[(bucket_current_free_index[app_i])] = kernel_policy; 2861 bucket_current_free_index[app_i]++; 2862 (necp_kernel_socket_policies_map[app_i])[(bucket_current_free_index[app_i])] = NULL; 2863 } 2864 } 2865 } else { 2866 app_i = NECP_SOCKET_MAP_APP_ID_TO_BUCKET(kernel_policy->cond_app_id); 2867 if (!necp_kernel_socket_policy_is_unnecessary(kernel_policy, necp_kernel_socket_policies_map[app_i], bucket_current_free_index[app_i])) { 2868 (necp_kernel_socket_policies_map[app_i])[(bucket_current_free_index[app_i])] = kernel_policy; 2869 bucket_current_free_index[app_i]++; 2870 (necp_kernel_socket_policies_map[app_i])[(bucket_current_free_index[app_i])] = NULL; 2871 } 2872 } 2873 2874 if (!necp_kernel_socket_policy_is_unnecessary(kernel_policy, necp_kernel_socket_policies_app_layer_map, app_layer_current_free_index)) { 2875 necp_kernel_socket_policies_app_layer_map[app_layer_current_free_index] = kernel_policy; 2876 app_layer_current_free_index++; 2877 necp_kernel_socket_policies_app_layer_map[app_layer_current_free_index] = NULL; 2878 } 2879 } 2880 necp_kernel_socket_policies_dump_all(); 2881 BUMP_KERNEL_SOCKET_POLICIES_GENERATION_COUNT(); 2882 return (TRUE); 2883 2884fail: 2885 // Free memory, reset masks to 0 2886 necp_kernel_application_policies_condition_mask = 0; 2887 necp_kernel_socket_policies_condition_mask = 0; 2888 necp_kernel_application_policies_count = 0; 2889 necp_kernel_socket_policies_count = 0; 2890 necp_kernel_socket_policies_non_app_count = 0; 2891 for (app_i = 0; app_i < NECP_KERNEL_SOCKET_POLICIES_MAP_NUM_APP_ID_BUCKETS; app_i++) { 2892 if (necp_kernel_socket_policies_map[app_i] != NULL) { 2893 FREE(necp_kernel_socket_policies_map[app_i], M_NECP); 2894 necp_kernel_socket_policies_map[app_i] = NULL; 2895 } 2896 } 2897 if (necp_kernel_socket_policies_app_layer_map != NULL) { 2898 FREE(necp_kernel_socket_policies_app_layer_map, M_NECP); 2899 necp_kernel_socket_policies_app_layer_map = NULL; 2900 } 2901 return (FALSE); 2902} 2903 2904static u_int32_t 2905necp_get_new_string_id(void) 2906{ 2907 u_int32_t newid = 0; 2908 2909 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 2910 2911 necp_last_string_id++; 2912 if (necp_last_string_id < 1) { 2913 necp_last_string_id = 1; 2914 } 2915 2916 newid = necp_last_string_id; 2917 if (newid == 0) { 2918 NECPLOG0(LOG_DEBUG, "Allocate string id failed.\n"); 2919 return (0); 2920 } 2921 2922 return (newid); 2923} 2924 2925static struct necp_string_id_mapping * 2926necp_lookup_string_to_id_locked(struct necp_string_id_mapping_list *list, char *string) 2927{ 2928 struct necp_string_id_mapping *searchentry = NULL; 2929 struct necp_string_id_mapping *foundentry = NULL; 2930 2931 LIST_FOREACH(searchentry, list, chain) { 2932 if (strcmp(searchentry->string, string) == 0) { 2933 foundentry = searchentry; 2934 break; 2935 } 2936 } 2937 2938 return (foundentry); 2939} 2940 2941static u_int32_t 2942necp_create_string_to_id_mapping(struct necp_string_id_mapping_list *list, char *string) 2943{ 2944 u_int32_t string_id = 0; 2945 struct necp_string_id_mapping *existing_mapping = NULL; 2946 2947 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 2948 2949 existing_mapping = necp_lookup_string_to_id_locked(list, string); 2950 if (existing_mapping != NULL) { 2951 string_id = existing_mapping->id; 2952 existing_mapping->refcount++; 2953 } else { 2954 struct necp_string_id_mapping *new_mapping = NULL; 2955 MALLOC(new_mapping, struct necp_string_id_mapping *, sizeof(struct necp_string_id_mapping), M_NECP, M_WAITOK); 2956 if (new_mapping != NULL) { 2957 memset(new_mapping, 0, sizeof(struct necp_string_id_mapping)); 2958 2959 size_t length = strlen(string) + 1; 2960 MALLOC(new_mapping->string, char *, length, M_NECP, M_WAITOK); 2961 if (new_mapping->string != NULL) { 2962 memcpy(new_mapping->string, string, length); 2963 new_mapping->id = necp_get_new_string_id(); 2964 new_mapping->refcount = 1; 2965 LIST_INSERT_HEAD(list, new_mapping, chain); 2966 string_id = new_mapping->id; 2967 } else { 2968 FREE(new_mapping, M_NECP); 2969 new_mapping = NULL; 2970 } 2971 } 2972 } 2973 return (string_id); 2974} 2975 2976static bool 2977necp_remove_string_to_id_mapping(struct necp_string_id_mapping_list *list, char *string) 2978{ 2979 struct necp_string_id_mapping *existing_mapping = NULL; 2980 2981 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 2982 2983 existing_mapping = necp_lookup_string_to_id_locked(list, string); 2984 if (existing_mapping != NULL) { 2985 if (--existing_mapping->refcount == 0) { 2986 LIST_REMOVE(existing_mapping, chain); 2987 FREE(existing_mapping->string, M_NECP); 2988 FREE(existing_mapping, M_NECP); 2989 } 2990 return (TRUE); 2991 } 2992 2993 return (FALSE); 2994} 2995 2996#define NECP_NULL_SERVICE_ID 1 2997static u_int32_t 2998necp_get_new_uuid_id(void) 2999{ 3000 u_int32_t newid = 0; 3001 3002 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3003 3004 necp_last_uuid_id++; 3005 if (necp_last_uuid_id < (NECP_NULL_SERVICE_ID + 1)) { 3006 necp_last_uuid_id = (NECP_NULL_SERVICE_ID + 1); 3007 } 3008 3009 newid = necp_last_uuid_id; 3010 if (newid == 0) { 3011 NECPLOG0(LOG_DEBUG, "Allocate uuid id failed.\n"); 3012 return (0); 3013 } 3014 3015 return (newid); 3016} 3017 3018static struct necp_uuid_id_mapping * 3019necp_uuid_lookup_app_id_locked(uuid_t uuid) 3020{ 3021 struct necp_uuid_id_mapping *searchentry = NULL; 3022 struct necp_uuid_id_mapping *foundentry = NULL; 3023 3024 LIST_FOREACH(searchentry, APPUUIDHASH(uuid), chain) { 3025 if (uuid_compare(searchentry->uuid, uuid) == 0) { 3026 foundentry = searchentry; 3027 break; 3028 } 3029 } 3030 3031 return (foundentry); 3032} 3033 3034static u_int32_t 3035necp_create_uuid_app_id_mapping(uuid_t uuid, bool *allocated_mapping, bool uuid_policy_table) 3036{ 3037 u_int32_t local_id = 0; 3038 struct necp_uuid_id_mapping *existing_mapping = NULL; 3039 3040 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3041 3042 if (allocated_mapping) { 3043 *allocated_mapping = FALSE; 3044 } 3045 3046 existing_mapping = necp_uuid_lookup_app_id_locked(uuid); 3047 if (existing_mapping != NULL) { 3048 local_id = existing_mapping->id; 3049 existing_mapping->refcount++; 3050 if (uuid_policy_table) { 3051 existing_mapping->table_refcount++; 3052 } 3053 } else { 3054 struct necp_uuid_id_mapping *new_mapping = NULL; 3055 MALLOC(new_mapping, struct necp_uuid_id_mapping *, sizeof(*new_mapping), M_NECP, M_WAITOK); 3056 if (new_mapping != NULL) { 3057 uuid_copy(new_mapping->uuid, uuid); 3058 new_mapping->id = necp_get_new_uuid_id(); 3059 new_mapping->refcount = 1; 3060 if (uuid_policy_table) { 3061 new_mapping->table_refcount = 1; 3062 } else { 3063 new_mapping->table_refcount = 0; 3064 } 3065 3066 LIST_INSERT_HEAD(APPUUIDHASH(uuid), new_mapping, chain); 3067 3068 if (allocated_mapping) { 3069 *allocated_mapping = TRUE; 3070 } 3071 3072 local_id = new_mapping->id; 3073 } 3074 } 3075 3076 return (local_id); 3077} 3078 3079static bool 3080necp_remove_uuid_app_id_mapping(uuid_t uuid, bool *removed_mapping, bool uuid_policy_table) 3081{ 3082 struct necp_uuid_id_mapping *existing_mapping = NULL; 3083 3084 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3085 3086 if (removed_mapping) { 3087 *removed_mapping = FALSE; 3088 } 3089 3090 existing_mapping = necp_uuid_lookup_app_id_locked(uuid); 3091 if (existing_mapping != NULL) { 3092 if (uuid_policy_table) { 3093 existing_mapping->table_refcount--; 3094 } 3095 if (--existing_mapping->refcount == 0) { 3096 LIST_REMOVE(existing_mapping, chain); 3097 FREE(existing_mapping, M_NECP); 3098 if (removed_mapping) { 3099 *removed_mapping = TRUE; 3100 } 3101 } 3102 return (TRUE); 3103 } 3104 3105 return (FALSE); 3106} 3107 3108static struct necp_uuid_id_mapping * 3109necp_uuid_get_null_service_id_mapping(void) 3110{ 3111 static struct necp_uuid_id_mapping null_mapping; 3112 uuid_clear(null_mapping.uuid); 3113 null_mapping.id = NECP_NULL_SERVICE_ID; 3114 3115 return (&null_mapping); 3116} 3117 3118static struct necp_uuid_id_mapping * 3119necp_uuid_lookup_service_id_locked(uuid_t uuid) 3120{ 3121 struct necp_uuid_id_mapping *searchentry = NULL; 3122 struct necp_uuid_id_mapping *foundentry = NULL; 3123 3124 if (uuid_is_null(uuid)) { 3125 return necp_uuid_get_null_service_id_mapping(); 3126 } 3127 3128 LIST_FOREACH(searchentry, &necp_uuid_service_id_list, chain) { 3129 if (uuid_compare(searchentry->uuid, uuid) == 0) { 3130 foundentry = searchentry; 3131 break; 3132 } 3133 } 3134 3135 return (foundentry); 3136} 3137 3138static struct necp_uuid_id_mapping * 3139necp_uuid_lookup_uuid_with_service_id_locked(u_int32_t local_id) 3140{ 3141 struct necp_uuid_id_mapping *searchentry = NULL; 3142 struct necp_uuid_id_mapping *foundentry = NULL; 3143 3144 if (local_id == NECP_NULL_SERVICE_ID) { 3145 return necp_uuid_get_null_service_id_mapping(); 3146 } 3147 3148 LIST_FOREACH(searchentry, &necp_uuid_service_id_list, chain) { 3149 if (searchentry->id == local_id) { 3150 foundentry = searchentry; 3151 break; 3152 } 3153 } 3154 3155 return (foundentry); 3156} 3157 3158static u_int32_t 3159necp_create_uuid_service_id_mapping(uuid_t uuid) 3160{ 3161 u_int32_t local_id = 0; 3162 struct necp_uuid_id_mapping *existing_mapping = NULL; 3163 3164 if (uuid_is_null(uuid)) { 3165 return (NECP_NULL_SERVICE_ID); 3166 } 3167 3168 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3169 3170 existing_mapping = necp_uuid_lookup_service_id_locked(uuid); 3171 if (existing_mapping != NULL) { 3172 local_id = existing_mapping->id; 3173 existing_mapping->refcount++; 3174 } else { 3175 struct necp_uuid_id_mapping *new_mapping = NULL; 3176 MALLOC(new_mapping, struct necp_uuid_id_mapping *, sizeof(*new_mapping), M_NECP, M_WAITOK); 3177 if (new_mapping != NULL) { 3178 uuid_copy(new_mapping->uuid, uuid); 3179 new_mapping->id = necp_get_new_uuid_id(); 3180 new_mapping->refcount = 1; 3181 3182 LIST_INSERT_HEAD(&necp_uuid_service_id_list, new_mapping, chain); 3183 3184 local_id = new_mapping->id; 3185 } 3186 } 3187 3188 return (local_id); 3189} 3190 3191static bool 3192necp_remove_uuid_service_id_mapping(uuid_t uuid) 3193{ 3194 struct necp_uuid_id_mapping *existing_mapping = NULL; 3195 3196 if (uuid_is_null(uuid)) { 3197 return (TRUE); 3198 } 3199 3200 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3201 3202 existing_mapping = necp_uuid_lookup_app_id_locked(uuid); 3203 if (existing_mapping != NULL) { 3204 if (--existing_mapping->refcount == 0) { 3205 LIST_REMOVE(existing_mapping, chain); 3206 FREE(existing_mapping, M_NECP); 3207 } 3208 return (TRUE); 3209 } 3210 3211 return (FALSE); 3212} 3213 3214 3215static bool 3216necp_kernel_socket_policies_update_uuid_table(void) 3217{ 3218 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3219 3220 if (necp_uuid_app_id_mappings_dirty) { 3221 if (proc_uuid_policy_kernel(PROC_UUID_POLICY_OPERATION_CLEAR, NULL, PROC_UUID_NECP_APP_POLICY) < 0) { 3222 NECPLOG0(LOG_DEBUG, "Error clearing uuids from policy table\n"); 3223 return (FALSE); 3224 } 3225 3226 if (necp_num_uuid_app_id_mappings > 0) { 3227 struct necp_uuid_id_mapping_head *uuid_list_head = NULL; 3228 for (uuid_list_head = &necp_uuid_app_id_hashtbl[necp_uuid_app_id_hash_num_buckets - 1]; uuid_list_head >= necp_uuid_app_id_hashtbl; uuid_list_head--) { 3229 struct necp_uuid_id_mapping *mapping = NULL; 3230 LIST_FOREACH(mapping, uuid_list_head, chain) { 3231 if (mapping->table_refcount > 0 && 3232 proc_uuid_policy_kernel(PROC_UUID_POLICY_OPERATION_ADD, mapping->uuid, PROC_UUID_NECP_APP_POLICY) < 0) { 3233 NECPLOG0(LOG_DEBUG, "Error adding uuid to policy table\n"); 3234 } 3235 } 3236 } 3237 } 3238 3239 necp_uuid_app_id_mappings_dirty = FALSE; 3240 } 3241 3242 return (TRUE); 3243} 3244 3245#define NECP_KERNEL_VALID_IP_OUTPUT_CONDITIONS (NECP_KERNEL_CONDITION_ALL_INTERFACES | NECP_KERNEL_CONDITION_BOUND_INTERFACE | NECP_KERNEL_CONDITION_PROTOCOL | NECP_KERNEL_CONDITION_LOCAL_START | NECP_KERNEL_CONDITION_LOCAL_END | NECP_KERNEL_CONDITION_LOCAL_PREFIX | NECP_KERNEL_CONDITION_REMOTE_START | NECP_KERNEL_CONDITION_REMOTE_END | NECP_KERNEL_CONDITION_REMOTE_PREFIX | NECP_KERNEL_CONDITION_POLICY_ID | NECP_KERNEL_CONDITION_LAST_INTERFACE) 3246static necp_kernel_policy_id 3247necp_kernel_ip_output_policy_add(necp_policy_id parent_policy_id, necp_policy_order order, necp_policy_order suborder, u_int32_t session_order, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_kernel_policy_id cond_policy_id, ifnet_t cond_bound_interface, u_int32_t cond_last_interface_index, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter) 3248{ 3249 struct necp_kernel_ip_output_policy *new_kernel_policy = NULL; 3250 struct necp_kernel_ip_output_policy *tmp_kernel_policy = NULL; 3251 3252 MALLOC_ZONE(new_kernel_policy, struct necp_kernel_ip_output_policy *, sizeof(*new_kernel_policy), M_NECP_IP_POLICY, M_WAITOK); 3253 if (new_kernel_policy == NULL) { 3254 goto done; 3255 } 3256 3257 memset(new_kernel_policy, 0, sizeof(*new_kernel_policy)); 3258 new_kernel_policy->parent_policy_id = parent_policy_id; 3259 new_kernel_policy->id = necp_kernel_policy_get_new_id(); 3260 new_kernel_policy->suborder = suborder; 3261 new_kernel_policy->order = order; 3262 new_kernel_policy->session_order = session_order; 3263 3264 // Sanitize condition mask 3265 new_kernel_policy->condition_mask = (condition_mask & NECP_KERNEL_VALID_IP_OUTPUT_CONDITIONS); 3266 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES) && (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE)) { 3267 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_BOUND_INTERFACE; 3268 } 3269 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) && (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX)) { 3270 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_LOCAL_PREFIX; 3271 } 3272 if ((new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) && (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX)) { 3273 new_kernel_policy->condition_mask &= ~NECP_KERNEL_CONDITION_REMOTE_PREFIX; 3274 } 3275 new_kernel_policy->condition_negated_mask = condition_negated_mask & new_kernel_policy->condition_mask; 3276 3277 // Set condition values 3278 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_POLICY_ID) { 3279 new_kernel_policy->cond_policy_id = cond_policy_id; 3280 } 3281 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE) { 3282 if (cond_bound_interface) { 3283 ifnet_reference(cond_bound_interface); 3284 } 3285 new_kernel_policy->cond_bound_interface = cond_bound_interface; 3286 } 3287 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LAST_INTERFACE) { 3288 new_kernel_policy->cond_last_interface_index = cond_last_interface_index; 3289 } 3290 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_PROTOCOL) { 3291 new_kernel_policy->cond_protocol = cond_protocol; 3292 } 3293 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_START) { 3294 memcpy(&new_kernel_policy->cond_local_start, cond_local_start, cond_local_start->sa.sa_len); 3295 } 3296 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 3297 memcpy(&new_kernel_policy->cond_local_end, cond_local_end, cond_local_end->sa.sa_len); 3298 } 3299 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 3300 new_kernel_policy->cond_local_prefix = cond_local_prefix; 3301 } 3302 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_START) { 3303 memcpy(&new_kernel_policy->cond_remote_start, cond_remote_start, cond_remote_start->sa.sa_len); 3304 } 3305 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 3306 memcpy(&new_kernel_policy->cond_remote_end, cond_remote_end, cond_remote_end->sa.sa_len); 3307 } 3308 if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 3309 new_kernel_policy->cond_remote_prefix = cond_remote_prefix; 3310 } 3311 3312 new_kernel_policy->result = result; 3313 memcpy(&new_kernel_policy->result_parameter, &result_parameter, sizeof(result_parameter)); 3314 3315 if (necp_debug) { 3316 NECPLOG(LOG_DEBUG, "Added kernel policy: ip output, id=%d, mask=%x\n", new_kernel_policy->id, new_kernel_policy->condition_mask); 3317 } 3318 LIST_INSERT_SORTED_THRICE_ASCENDING(&necp_kernel_ip_output_policies, new_kernel_policy, chain, session_order, order, suborder, tmp_kernel_policy); 3319done: 3320 return (new_kernel_policy ? new_kernel_policy->id : 0); 3321} 3322 3323static struct necp_kernel_ip_output_policy * 3324necp_kernel_ip_output_policy_find(necp_kernel_policy_id policy_id) 3325{ 3326 struct necp_kernel_ip_output_policy *kernel_policy = NULL; 3327 struct necp_kernel_ip_output_policy *tmp_kernel_policy = NULL; 3328 3329 if (policy_id == 0) { 3330 return (NULL); 3331 } 3332 3333 LIST_FOREACH_SAFE(kernel_policy, &necp_kernel_ip_output_policies, chain, tmp_kernel_policy) { 3334 if (kernel_policy->id == policy_id) { 3335 return (kernel_policy); 3336 } 3337 } 3338 3339 return (NULL); 3340} 3341 3342static bool 3343necp_kernel_ip_output_policy_delete(necp_kernel_policy_id policy_id) 3344{ 3345 struct necp_kernel_ip_output_policy *policy = NULL; 3346 3347 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3348 3349 policy = necp_kernel_ip_output_policy_find(policy_id); 3350 if (policy) { 3351 LIST_REMOVE(policy, chain); 3352 3353 if (policy->cond_bound_interface) { 3354 ifnet_release(policy->cond_bound_interface); 3355 policy->cond_bound_interface = NULL; 3356 } 3357 3358 FREE_ZONE(policy, sizeof(*policy), M_NECP_IP_POLICY); 3359 return (TRUE); 3360 } 3361 3362 return (FALSE); 3363} 3364 3365static void 3366necp_kernel_ip_output_policies_dump_all(void) 3367{ 3368 struct necp_kernel_ip_output_policy *policy = NULL; 3369 int policy_i; 3370 int id_i; 3371 3372 if (necp_debug) { 3373 NECPLOG0(LOG_DEBUG, "NECP IP Output Policies:\n"); 3374 NECPLOG0(LOG_DEBUG, "-----------\n"); 3375 for (id_i = 0; id_i < NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS; id_i++) { 3376 NECPLOG(LOG_DEBUG, " ID Bucket: %d\n", id_i); 3377 for (policy_i = 0; necp_kernel_ip_output_policies_map[id_i] != NULL && (necp_kernel_ip_output_policies_map[id_i])[policy_i] != NULL; policy_i++) { 3378 policy = (necp_kernel_ip_output_policies_map[id_i])[policy_i]; 3379 NECPLOG(LOG_DEBUG, "\t%d. Policy ID: %d, Order: %d.%d.%d, Mask: %x, Result: %d, Parameter: %d\n", policy_i, policy->id, policy->session_order, policy->order, policy->suborder, policy->condition_mask, policy->result, policy->result_parameter); 3380 } 3381 NECPLOG0(LOG_DEBUG, "-----------\n"); 3382 } 3383 } 3384} 3385 3386static inline bool 3387necp_kernel_ip_output_policy_results_overlap(struct necp_kernel_ip_output_policy *upper_policy, struct necp_kernel_ip_output_policy *lower_policy) 3388{ 3389 if (upper_policy->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 3390 if (upper_policy->session_order != lower_policy->session_order) { 3391 // A skip cannot override a policy of a different session 3392 return (FALSE); 3393 } else { 3394 if (upper_policy->result_parameter.skip_policy_order == 0 || 3395 lower_policy->order >= upper_policy->result_parameter.skip_policy_order) { 3396 // This policy is beyond the skip 3397 return (FALSE); 3398 } else { 3399 // This policy is inside the skip 3400 return (TRUE); 3401 } 3402 } 3403 } 3404 3405 // All other IP Output policy results (drop, tunnel, hard pass) currently overlap 3406 return (TRUE); 3407} 3408 3409static bool 3410necp_kernel_ip_output_policy_is_unnecessary(struct necp_kernel_ip_output_policy *policy, struct necp_kernel_ip_output_policy **policy_array, int valid_indices) 3411{ 3412 bool can_skip = FALSE; 3413 u_int32_t highest_skip_session_order = 0; 3414 u_int32_t highest_skip_order = 0; 3415 int i; 3416 for (i = 0; i < valid_indices; i++) { 3417 struct necp_kernel_ip_output_policy *compared_policy = policy_array[i]; 3418 3419 // For policies in a skip window, we can't mark conflicting policies as unnecessary 3420 if (can_skip) { 3421 if (highest_skip_session_order != compared_policy->session_order || 3422 (highest_skip_order != 0 && compared_policy->order >= highest_skip_order)) { 3423 // If we've moved on to the next session, or passed the skip window 3424 highest_skip_session_order = 0; 3425 highest_skip_order = 0; 3426 can_skip = FALSE; 3427 } else { 3428 // If this policy is also a skip, in can increase the skip window 3429 if (compared_policy->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 3430 if (compared_policy->result_parameter.skip_policy_order > highest_skip_order) { 3431 highest_skip_order = compared_policy->result_parameter.skip_policy_order; 3432 } 3433 } 3434 continue; 3435 } 3436 } 3437 3438 if (compared_policy->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 3439 // This policy is a skip. Set the skip window accordingly 3440 can_skip = TRUE; 3441 highest_skip_session_order = compared_policy->session_order; 3442 highest_skip_order = compared_policy->result_parameter.skip_policy_order; 3443 } 3444 3445 // The result of the compared policy must be able to block out this policy result 3446 if (!necp_kernel_ip_output_policy_results_overlap(compared_policy, policy)) { 3447 continue; 3448 } 3449 3450 // If new policy matches All Interfaces, compared policy must also 3451 if ((policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES) && !(compared_policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES)) { 3452 continue; 3453 } 3454 3455 // Default makes lower policies unecessary always 3456 if (compared_policy->condition_mask == 0) { 3457 return (TRUE); 3458 } 3459 3460 // Compared must be more general than policy, and include only conditions within policy 3461 if ((policy->condition_mask & compared_policy->condition_mask) != compared_policy->condition_mask) { 3462 continue; 3463 } 3464 3465 // Negative conditions must match for the overlapping conditions 3466 if ((policy->condition_negated_mask & compared_policy->condition_mask) != (compared_policy->condition_negated_mask & compared_policy->condition_mask)) { 3467 continue; 3468 } 3469 3470 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_POLICY_ID && 3471 compared_policy->cond_policy_id != policy->cond_policy_id) { 3472 continue; 3473 } 3474 3475 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE && 3476 compared_policy->cond_bound_interface != policy->cond_bound_interface) { 3477 continue; 3478 } 3479 3480 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_PROTOCOL && 3481 compared_policy->cond_protocol != policy->cond_protocol) { 3482 continue; 3483 } 3484 3485 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_START) { 3486 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 3487 if (!necp_is_range_in_range((struct sockaddr *)&policy->cond_local_start, (struct sockaddr *)&policy->cond_local_end, (struct sockaddr *)&compared_policy->cond_local_start, (struct sockaddr *)&compared_policy->cond_local_end)) { 3488 continue; 3489 } 3490 } else if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 3491 if (compared_policy->cond_local_prefix > policy->cond_local_prefix || 3492 !necp_is_addr_in_subnet((struct sockaddr *)&policy->cond_local_start, (struct sockaddr *)&compared_policy->cond_local_start, compared_policy->cond_local_prefix)) { 3493 continue; 3494 } 3495 } 3496 } 3497 3498 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_START) { 3499 if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 3500 if (!necp_is_range_in_range((struct sockaddr *)&policy->cond_remote_start, (struct sockaddr *)&policy->cond_remote_end, (struct sockaddr *)&compared_policy->cond_remote_start, (struct sockaddr *)&compared_policy->cond_remote_end)) { 3501 continue; 3502 } 3503 } else if (compared_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 3504 if (compared_policy->cond_remote_prefix > policy->cond_remote_prefix || 3505 !necp_is_addr_in_subnet((struct sockaddr *)&policy->cond_remote_start, (struct sockaddr *)&compared_policy->cond_remote_start, compared_policy->cond_remote_prefix)) { 3506 continue; 3507 } 3508 } 3509 } 3510 3511 return (TRUE); 3512 } 3513 3514 return (FALSE); 3515} 3516 3517static bool 3518necp_kernel_ip_output_policies_reprocess(void) 3519{ 3520 int i; 3521 int bucket_allocation_counts[NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS]; 3522 int bucket_current_free_index[NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS]; 3523 struct necp_kernel_ip_output_policy *kernel_policy = NULL; 3524 3525 lck_rw_assert(&necp_kernel_policy_lock, LCK_RW_ASSERT_EXCLUSIVE); 3526 3527 // Reset mask to 0 3528 necp_kernel_ip_output_policies_condition_mask = 0; 3529 necp_kernel_ip_output_policies_count = 0; 3530 necp_kernel_ip_output_policies_non_id_count = 0; 3531 3532 for (i = 0; i < NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS; i++) { 3533 if (necp_kernel_ip_output_policies_map[i] != NULL) { 3534 FREE(necp_kernel_ip_output_policies_map[i], M_NECP); 3535 necp_kernel_ip_output_policies_map[i] = NULL; 3536 } 3537 3538 // Init counts 3539 bucket_allocation_counts[i] = 0; 3540 } 3541 3542 LIST_FOREACH(kernel_policy, &necp_kernel_ip_output_policies, chain) { 3543 // Update mask 3544 necp_kernel_ip_output_policies_condition_mask |= kernel_policy->condition_mask; 3545 necp_kernel_ip_output_policies_count++; 3546 3547 // Update bucket counts 3548 if (!(kernel_policy->condition_mask & NECP_KERNEL_CONDITION_POLICY_ID)) { 3549 necp_kernel_ip_output_policies_non_id_count++; 3550 for (i = 0; i < NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS; i++) { 3551 bucket_allocation_counts[i]++; 3552 } 3553 } else { 3554 bucket_allocation_counts[NECP_IP_OUTPUT_MAP_ID_TO_BUCKET(kernel_policy->cond_policy_id)]++; 3555 } 3556 } 3557 3558 for (i = 0; i < NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS; i++) { 3559 if (bucket_allocation_counts[i] > 0) { 3560 // Allocate a NULL-terminated array of policy pointers for each bucket 3561 MALLOC(necp_kernel_ip_output_policies_map[i], struct necp_kernel_ip_output_policy **, sizeof(struct necp_kernel_ip_output_policy *) * (bucket_allocation_counts[i] + 1), M_NECP, M_WAITOK); 3562 if (necp_kernel_ip_output_policies_map[i] == NULL) { 3563 goto fail; 3564 } 3565 3566 // Initialize the first entry to NULL 3567 (necp_kernel_ip_output_policies_map[i])[0] = NULL; 3568 } 3569 bucket_current_free_index[i] = 0; 3570 } 3571 3572 LIST_FOREACH(kernel_policy, &necp_kernel_ip_output_policies, chain) { 3573 // Insert pointers into map 3574 if (!(kernel_policy->condition_mask & NECP_KERNEL_CONDITION_POLICY_ID)) { 3575 for (i = 0; i < NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS; i++) { 3576 if (!necp_kernel_ip_output_policy_is_unnecessary(kernel_policy, necp_kernel_ip_output_policies_map[i], bucket_current_free_index[i])) { 3577 (necp_kernel_ip_output_policies_map[i])[(bucket_current_free_index[i])] = kernel_policy; 3578 bucket_current_free_index[i]++; 3579 (necp_kernel_ip_output_policies_map[i])[(bucket_current_free_index[i])] = NULL; 3580 } 3581 } 3582 } else { 3583 i = NECP_IP_OUTPUT_MAP_ID_TO_BUCKET(kernel_policy->cond_policy_id); 3584 if (!necp_kernel_ip_output_policy_is_unnecessary(kernel_policy, necp_kernel_ip_output_policies_map[i], bucket_current_free_index[i])) { 3585 (necp_kernel_ip_output_policies_map[i])[(bucket_current_free_index[i])] = kernel_policy; 3586 bucket_current_free_index[i]++; 3587 (necp_kernel_ip_output_policies_map[i])[(bucket_current_free_index[i])] = NULL; 3588 } 3589 } 3590 } 3591 necp_kernel_ip_output_policies_dump_all(); 3592 return (TRUE); 3593 3594fail: 3595 // Free memory, reset mask to 0 3596 necp_kernel_ip_output_policies_condition_mask = 0; 3597 necp_kernel_ip_output_policies_count = 0; 3598 necp_kernel_ip_output_policies_non_id_count = 0; 3599 for (i = 0; i < NECP_KERNEL_IP_OUTPUT_POLICIES_MAP_NUM_ID_BUCKETS; i++) { 3600 if (necp_kernel_ip_output_policies_map[i] != NULL) { 3601 FREE(necp_kernel_ip_output_policies_map[i], M_NECP); 3602 necp_kernel_ip_output_policies_map[i] = NULL; 3603 } 3604 } 3605 return (FALSE); 3606} 3607 3608// Outbound Policy Matching 3609// --------------------- 3610struct substring { 3611 char *string; 3612 size_t length; 3613}; 3614 3615static struct substring 3616necp_trim_dots_and_stars(char *string, size_t length) 3617{ 3618 struct substring sub; 3619 sub.string = string; 3620 sub.length = string ? length : 0; 3621 3622 while (sub.length && (sub.string[0] == '.' || sub.string[0] == '*')) { 3623 sub.string++; 3624 sub.length--; 3625 } 3626 3627 while (sub.length && (sub.string[sub.length - 1] == '.' || sub.string[sub.length - 1] == '*')) { 3628 sub.length--; 3629 } 3630 3631 return (sub); 3632} 3633 3634static char * 3635necp_create_trimmed_domain(char *string, size_t length) 3636{ 3637 char *trimmed_domain = NULL; 3638 struct substring sub = necp_trim_dots_and_stars(string, length); 3639 3640 MALLOC(trimmed_domain, char *, sub.length + 1, M_NECP, M_WAITOK); 3641 if (trimmed_domain == NULL) { 3642 return (NULL); 3643 } 3644 3645 memcpy(trimmed_domain, sub.string, sub.length); 3646 trimmed_domain[sub.length] = 0; 3647 3648 return (trimmed_domain); 3649} 3650 3651static inline int 3652necp_count_dots(char *string, size_t length) 3653{ 3654 int dot_count = 0; 3655 size_t i = 0; 3656 3657 for (i = 0; i < length; i++) { 3658 if (string[i] == '.') { 3659 dot_count++; 3660 } 3661 } 3662 3663 return (dot_count); 3664} 3665 3666static bool 3667necp_check_suffix(struct substring parent, struct substring suffix, bool require_dot_before_suffix) 3668{ 3669 if (parent.length <= suffix.length) { 3670 return (FALSE); 3671 } 3672 3673 size_t length_difference = (parent.length - suffix.length); 3674 3675 if (require_dot_before_suffix) { 3676 if (((char *)(parent.string + length_difference - 1))[0] != '.') { 3677 return (FALSE); 3678 } 3679 } 3680 3681 return (memcmp(parent.string + length_difference, suffix.string, suffix.length) == 0); 3682} 3683 3684static bool 3685necp_hostname_matches_domain(struct substring hostname_substring, u_int8_t hostname_dot_count, char *domain, u_int8_t domain_dot_count) 3686{ 3687 if (hostname_substring.string == NULL || domain == NULL) { 3688 return (hostname_substring.string == domain); 3689 } 3690 3691 struct substring domain_substring; 3692 domain_substring.string = domain; 3693 domain_substring.length = strlen(domain); 3694 3695 if (hostname_dot_count == domain_dot_count) { 3696 if (hostname_substring.length == domain_substring.length && 3697 memcmp(hostname_substring.string, domain_substring.string, hostname_substring.length) == 0) { 3698 return (TRUE); 3699 } 3700 } else if (domain_dot_count > 0 && domain_dot_count < hostname_dot_count) { 3701 if (necp_check_suffix(hostname_substring, domain_substring, TRUE)) { 3702 return (TRUE); 3703 } 3704 } 3705 3706 return (FALSE); 3707} 3708 3709static void 3710necp_application_fillout_info_locked(uuid_t application_uuid, uuid_t real_application_uuid, char *account, char *domain, pid_t pid, uid_t uid, u_int16_t protocol, u_int32_t bound_interface_index, u_int32_t traffic_class, struct necp_socket_info *info) 3711{ 3712 memset(info, 0, sizeof(struct necp_socket_info)); 3713 3714 info->pid = pid; 3715 info->uid = uid; 3716 info->protocol = protocol; 3717 info->bound_interface_index = bound_interface_index; 3718 info->traffic_class = traffic_class; 3719 info->cred_result = 0; // Don't check the entitlement here, only in the socket layer 3720 3721 if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_APP_ID && !uuid_is_null(application_uuid)) { 3722 struct necp_uuid_id_mapping *existing_mapping = necp_uuid_lookup_app_id_locked(application_uuid); 3723 if (existing_mapping) { 3724 info->application_id = existing_mapping->id; 3725 } 3726 } 3727 3728 if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_REAL_APP_ID && !uuid_is_null(real_application_uuid)) { 3729 if (uuid_compare(application_uuid, real_application_uuid) == 0) { 3730 info->real_application_id = info->application_id; 3731 } else { 3732 struct necp_uuid_id_mapping *existing_mapping = necp_uuid_lookup_app_id_locked(real_application_uuid); 3733 if (existing_mapping) { 3734 info->real_application_id = existing_mapping->id; 3735 } 3736 } 3737 } 3738 3739 if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID && account != NULL) { 3740 struct necp_string_id_mapping *existing_mapping = necp_lookup_string_to_id_locked(&necp_account_id_list, account); 3741 if (existing_mapping) { 3742 info->account_id = existing_mapping->id; 3743 } 3744 } 3745 3746 if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_DOMAIN) { 3747 info->domain = domain; 3748 } 3749} 3750 3751static int 3752necp_application_find_policy_match_internal(u_int8_t *parameters, size_t parameters_size, struct necp_aggregate_result *returned_result) 3753{ 3754 int error = 0; 3755 size_t offset = 0; 3756 3757 struct necp_kernel_socket_policy *matched_policy = NULL; 3758 struct necp_socket_info info; 3759 necp_kernel_policy_filter filter_control_unit = 0; 3760 necp_kernel_policy_result service_action = 0; 3761 necp_kernel_policy_service service = { 0, 0 }; 3762 3763 pid_t pid = 0; 3764 uid_t uid = 0; 3765 u_int16_t protocol = 0; 3766 u_int32_t bound_interface_index = 0; 3767 u_int32_t traffic_class = 0; 3768 3769 uuid_t application_uuid; 3770 uuid_clear(application_uuid); 3771 uuid_t real_application_uuid; 3772 uuid_clear(real_application_uuid); 3773 char *domain = NULL; 3774 char *account = NULL; 3775 3776 if (returned_result == NULL) { 3777 return (EINVAL); 3778 } 3779 3780 memset(returned_result, 0, sizeof(struct necp_aggregate_result)); 3781 3782 lck_rw_lock_shared(&necp_kernel_policy_lock); 3783 if (necp_kernel_application_policies_count == 0) { 3784 if (necp_drop_all_order > 0) { 3785 returned_result->routing_result = NECP_KERNEL_POLICY_RESULT_DROP; 3786 lck_rw_done(&necp_kernel_policy_lock); 3787 return (0); 3788 } 3789 } 3790 lck_rw_done(&necp_kernel_policy_lock); 3791 3792 while (offset < parameters_size) { 3793 u_int8_t type = necp_buffer_get_tlv_type(parameters, offset); 3794 size_t length = necp_buffer_get_tlv_length(parameters, offset); 3795 3796 if (length > 0 && (offset + sizeof(u_int8_t) + sizeof(size_t) + length) <= parameters_size) { 3797 u_int8_t *value = necp_buffer_get_tlv_value(parameters, offset, NULL); 3798 if (value != NULL) { 3799 switch (type) { 3800 case NECP_POLICY_CONDITION_APPLICATION: { 3801 if (length >= sizeof(uuid_t)) { 3802 uuid_copy(application_uuid, value); 3803 } 3804 break; 3805 } 3806 case NECP_POLICY_CONDITION_REAL_APPLICATION: { 3807 if (length >= sizeof(uuid_t)) { 3808 uuid_copy(real_application_uuid, value); 3809 } 3810 break; 3811 } 3812 case NECP_POLICY_CONDITION_DOMAIN: { 3813 domain = (char *)value; 3814 domain[length - 1] = 0; 3815 break; 3816 } 3817 case NECP_POLICY_CONDITION_ACCOUNT: { 3818 account = (char *)value; 3819 account[length - 1] = 0; 3820 break; 3821 } 3822 case NECP_POLICY_CONDITION_TRAFFIC_CLASS: { 3823 if (length >= sizeof(u_int32_t)) { 3824 memcpy(&traffic_class, value, sizeof(u_int32_t)); 3825 } 3826 break; 3827 } 3828 case NECP_POLICY_CONDITION_PID: { 3829 if (length >= sizeof(pid_t)) { 3830 memcpy(&pid, value, sizeof(pid_t)); 3831 } 3832 break; 3833 } 3834 case NECP_POLICY_CONDITION_UID: { 3835 if (length >= sizeof(uid_t)) { 3836 memcpy(&uid, value, sizeof(uid_t)); 3837 } 3838 break; 3839 } 3840 case NECP_POLICY_CONDITION_IP_PROTOCOL: { 3841 if (length >= sizeof(u_int16_t)) { 3842 memcpy(&protocol, value, sizeof(u_int16_t)); 3843 } 3844 break; 3845 } 3846 case NECP_POLICY_CONDITION_BOUND_INTERFACE: { 3847 if (length <= IFXNAMSIZ && length > 0) { 3848 ifnet_t bound_interface = NULL; 3849 char interface_name[IFXNAMSIZ]; 3850 memcpy(interface_name, value, length); 3851 interface_name[length - 1] = 0; // Make sure the string is NULL terminated 3852 if (ifnet_find_by_name(interface_name, &bound_interface) == 0) { 3853 bound_interface_index = bound_interface->if_index; 3854 } 3855 } 3856 break; 3857 } 3858 default: { 3859 break; 3860 } 3861 } 3862 } 3863 } 3864 3865 offset += sizeof(u_int8_t) + sizeof(size_t) + length; 3866 } 3867 3868 // Lock 3869 lck_rw_lock_shared(&necp_kernel_policy_lock); 3870 3871 necp_application_fillout_info_locked(application_uuid, real_application_uuid, account, domain, pid, uid, protocol, bound_interface_index, traffic_class, &info); 3872 matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_app_layer_map, &info, &filter_control_unit, &service_action, &service); 3873 if (matched_policy) { 3874 returned_result->routing_result = matched_policy->result; 3875 memcpy(&returned_result->routing_result_parameter, &matched_policy->result_parameter, sizeof(returned_result->routing_result_parameter)); 3876 } else { 3877 returned_result->routing_result = NECP_KERNEL_POLICY_RESULT_NONE; 3878 } 3879 returned_result->filter_control_unit = filter_control_unit; 3880 returned_result->service_action = service_action; 3881 3882 if (service.identifier != 0) { 3883 struct necp_uuid_id_mapping *mapping = necp_uuid_lookup_uuid_with_service_id_locked(service.identifier); 3884 if (mapping != NULL) { 3885 struct necp_service_registration *service_registration = NULL; 3886 uuid_copy(returned_result->service_uuid, mapping->uuid); 3887 returned_result->service_data = service.data; 3888 if (service.identifier == NECP_NULL_SERVICE_ID) { 3889 // NULL service is always 'registered' 3890 returned_result->service_flags |= NECP_SERVICE_FLAGS_REGISTERED; 3891 } else { 3892 LIST_FOREACH(service_registration, &necp_registered_service_list, kernel_chain) { 3893 if (service.identifier == service_registration->service_id) { 3894 returned_result->service_flags |= NECP_SERVICE_FLAGS_REGISTERED; 3895 break; 3896 } 3897 } 3898 } 3899 } 3900 } 3901 3902 // Unlock 3903 lck_rw_done(&necp_kernel_policy_lock); 3904 3905 return (error); 3906} 3907 3908#define NECP_MAX_MATCH_POLICY_PARAMETER_SIZE 1024 3909 3910int 3911necp_match_policy(struct proc *p, struct necp_match_policy_args *uap, int32_t *retval) 3912{ 3913#pragma unused(p, retval) 3914 u_int8_t *parameters = NULL; 3915 struct necp_aggregate_result returned_result; 3916 int error = 0; 3917 3918 if (uap == NULL) { 3919 error = EINVAL; 3920 goto done; 3921 } 3922 3923 if (uap->parameters == 0 || uap->parameters_size == 0 || uap->parameters_size > NECP_MAX_MATCH_POLICY_PARAMETER_SIZE || uap->returned_result == 0) { 3924 error = EINVAL; 3925 goto done; 3926 } 3927 3928 MALLOC(parameters, u_int8_t *, uap->parameters_size, M_NECP, M_WAITOK); 3929 if (parameters == NULL) { 3930 error = ENOMEM; 3931 goto done; 3932 } 3933 // Copy parameters in 3934 copyin(uap->parameters, parameters, uap->parameters_size); 3935 3936 error = necp_application_find_policy_match_internal(parameters, uap->parameters_size, &returned_result); 3937 if (error) { 3938 goto done; 3939 } 3940 3941 // Copy return value back 3942 copyout(&returned_result, uap->returned_result, sizeof(struct necp_aggregate_result)); 3943done: 3944 if (parameters != NULL) { 3945 FREE(parameters, M_NECP); 3946 } 3947 return (error); 3948} 3949 3950static bool 3951necp_socket_check_policy(struct necp_kernel_socket_policy *kernel_policy, necp_app_id app_id, necp_app_id real_app_id, errno_t cred_result, u_int32_t account_id, struct substring domain, u_int8_t domain_dot_count, pid_t pid, uid_t uid, u_int32_t bound_interface_index, u_int32_t traffic_class, u_int16_t protocol, union necp_sockaddr_union *local, union necp_sockaddr_union *remote) 3952{ 3953 if (!(kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES)) { 3954 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE) { 3955 u_int32_t cond_bound_interface_index = kernel_policy->cond_bound_interface ? kernel_policy->cond_bound_interface->if_index : 0; 3956 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE) { 3957 if (bound_interface_index == cond_bound_interface_index) { 3958 // No match, matches forbidden interface 3959 return (FALSE); 3960 } 3961 } else { 3962 if (bound_interface_index != cond_bound_interface_index) { 3963 // No match, does not match required interface 3964 return (FALSE); 3965 } 3966 } 3967 } else { 3968 if (bound_interface_index != 0) { 3969 // No match, requires a non-bound packet 3970 return (FALSE); 3971 } 3972 } 3973 } 3974 3975 if (kernel_policy->condition_mask == 0) { 3976 return (TRUE); 3977 } 3978 3979 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_APP_ID) { 3980 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_APP_ID) { 3981 if (app_id == kernel_policy->cond_app_id) { 3982 // No match, matches forbidden application 3983 return (FALSE); 3984 } 3985 } else { 3986 if (app_id != kernel_policy->cond_app_id) { 3987 // No match, does not match required application 3988 return (FALSE); 3989 } 3990 } 3991 } 3992 3993 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REAL_APP_ID) { 3994 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_REAL_APP_ID) { 3995 if (real_app_id == kernel_policy->cond_real_app_id) { 3996 // No match, matches forbidden application 3997 return (FALSE); 3998 } 3999 } else { 4000 if (real_app_id != kernel_policy->cond_real_app_id) { 4001 // No match, does not match required application 4002 return (FALSE); 4003 } 4004 } 4005 } 4006 4007 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ENTITLEMENT) { 4008 if (cred_result != 0) { 4009 // Process is missing entitlement 4010 return (FALSE); 4011 } 4012 } 4013 4014 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_DOMAIN) { 4015 bool domain_matches = necp_hostname_matches_domain(domain, domain_dot_count, kernel_policy->cond_domain, kernel_policy->cond_domain_dot_count); 4016 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_DOMAIN) { 4017 if (domain_matches) { 4018 // No match, matches forbidden domain 4019 return (FALSE); 4020 } 4021 } else { 4022 if (!domain_matches) { 4023 // No match, does not match required domain 4024 return (FALSE); 4025 } 4026 } 4027 } 4028 4029 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID) { 4030 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID) { 4031 if (account_id == kernel_policy->cond_account_id) { 4032 // No match, matches forbidden account 4033 return (FALSE); 4034 } 4035 } else { 4036 if (account_id != kernel_policy->cond_account_id) { 4037 // No match, does not match required account 4038 return (FALSE); 4039 } 4040 } 4041 } 4042 4043 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_PID) { 4044 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_PID) { 4045 if (pid == kernel_policy->cond_pid) { 4046 // No match, matches forbidden pid 4047 return (FALSE); 4048 } 4049 } else { 4050 if (pid != kernel_policy->cond_pid) { 4051 // No match, does not match required pid 4052 return (FALSE); 4053 } 4054 } 4055 } 4056 4057 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_UID) { 4058 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_UID) { 4059 if (uid == kernel_policy->cond_uid) { 4060 // No match, matches forbidden uid 4061 return (FALSE); 4062 } 4063 } else { 4064 if (uid != kernel_policy->cond_uid) { 4065 // No match, does not match required uid 4066 return (FALSE); 4067 } 4068 } 4069 } 4070 4071 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_TRAFFIC_CLASS) { 4072 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_TRAFFIC_CLASS) { 4073 if (traffic_class >= kernel_policy->cond_traffic_class.start_tc && 4074 traffic_class <= kernel_policy->cond_traffic_class.end_tc) { 4075 // No match, matches forbidden traffic class 4076 return (FALSE); 4077 } 4078 } else { 4079 if (traffic_class < kernel_policy->cond_traffic_class.start_tc || 4080 traffic_class > kernel_policy->cond_traffic_class.end_tc) { 4081 // No match, does not match required traffic class 4082 return (FALSE); 4083 } 4084 } 4085 } 4086 4087 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_PROTOCOL) { 4088 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_PROTOCOL) { 4089 if (protocol == kernel_policy->cond_protocol) { 4090 // No match, matches forbidden protocol 4091 return (FALSE); 4092 } 4093 } else { 4094 if (protocol != kernel_policy->cond_protocol) { 4095 // No match, does not match required protocol 4096 return (FALSE); 4097 } 4098 } 4099 } 4100 4101 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_START) { 4102 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 4103 bool inRange = necp_is_addr_in_range((struct sockaddr *)local, (struct sockaddr *)&kernel_policy->cond_local_start, (struct sockaddr *)&kernel_policy->cond_local_end); 4104 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 4105 if (inRange) { 4106 return (FALSE); 4107 } 4108 } else { 4109 if (!inRange) { 4110 return (FALSE); 4111 } 4112 } 4113 } else if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 4114 bool inSubnet = necp_is_addr_in_subnet((struct sockaddr *)local, (struct sockaddr *)&kernel_policy->cond_local_start, kernel_policy->cond_local_prefix); 4115 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 4116 if (inSubnet) { 4117 return (FALSE); 4118 } 4119 } else { 4120 if (!inSubnet) { 4121 return (FALSE); 4122 } 4123 } 4124 } 4125 } 4126 4127 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_START) { 4128 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 4129 bool inRange = necp_is_addr_in_range((struct sockaddr *)remote, (struct sockaddr *)&kernel_policy->cond_remote_start, (struct sockaddr *)&kernel_policy->cond_remote_end); 4130 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 4131 if (inRange) { 4132 return (FALSE); 4133 } 4134 } else { 4135 if (!inRange) { 4136 return (FALSE); 4137 } 4138 } 4139 } else if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 4140 bool inSubnet = necp_is_addr_in_subnet((struct sockaddr *)remote, (struct sockaddr *)&kernel_policy->cond_remote_start, kernel_policy->cond_remote_prefix); 4141 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 4142 if (inSubnet) { 4143 return (FALSE); 4144 } 4145 } else { 4146 if (!inSubnet) { 4147 return (FALSE); 4148 } 4149 } 4150 } 4151 } 4152 4153 return (TRUE); 4154} 4155 4156static inline u_int32_t 4157necp_socket_calc_flowhash_locked(struct necp_socket_info *info) 4158{ 4159 return (net_flowhash(info, sizeof(*info), necp_kernel_socket_policies_gencount)); 4160} 4161 4162#define NECP_KERNEL_ADDRESS_TYPE_CONDITIONS (NECP_KERNEL_CONDITION_LOCAL_START | NECP_KERNEL_CONDITION_LOCAL_END | NECP_KERNEL_CONDITION_LOCAL_PREFIX | NECP_KERNEL_CONDITION_REMOTE_START | NECP_KERNEL_CONDITION_REMOTE_END | NECP_KERNEL_CONDITION_REMOTE_PREFIX) 4163static void 4164necp_socket_fillout_info_locked(struct inpcb *inp, struct sockaddr *override_local_addr, struct sockaddr *override_remote_addr, u_int32_t override_bound_interface, struct necp_socket_info *info) 4165{ 4166 struct socket *so = NULL; 4167 4168 memset(info, 0, sizeof(struct necp_socket_info)); 4169 4170 so = inp->inp_socket; 4171 4172 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_PID) { 4173 info->pid = ((so->so_flags & SOF_DELEGATED) ? so->e_pid : so->last_pid); 4174 } 4175 4176 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_UID) { 4177 info->uid = kauth_cred_getuid(so->so_cred); 4178 } 4179 4180 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_TRAFFIC_CLASS) { 4181 info->traffic_class = so->so_traffic_class; 4182 } 4183 4184 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_PROTOCOL) { 4185 if (inp->inp_ip_p) { 4186 info->protocol = inp->inp_ip_p; 4187 } else { 4188 info->protocol = SOCK_PROTO(so); 4189 } 4190 } 4191 4192 if (inp->inp_flags2 & INP2_WANT_APP_POLICY && necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_APP_ID) { 4193 struct necp_uuid_id_mapping *existing_mapping = necp_uuid_lookup_app_id_locked(((so->so_flags & SOF_DELEGATED) ? so->e_uuid : so->last_uuid)); 4194 if (existing_mapping) { 4195 info->application_id = existing_mapping->id; 4196 } 4197 4198 if (!(so->so_flags & SOF_DELEGATED)) { 4199 info->real_application_id = info->application_id; 4200 } else if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_REAL_APP_ID) { 4201 struct necp_uuid_id_mapping *real_existing_mapping = necp_uuid_lookup_app_id_locked(so->last_uuid); 4202 if (real_existing_mapping) { 4203 info->real_application_id = real_existing_mapping->id; 4204 } 4205 } 4206 4207 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_ENTITLEMENT) { 4208 info->cred_result = priv_check_cred(so->so_cred, PRIV_NET_PRIVILEGED_NECP_MATCH, 0); 4209 } 4210 } 4211 4212 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID && inp->inp_necp_attributes.inp_account != NULL) { 4213 struct necp_string_id_mapping *existing_mapping = necp_lookup_string_to_id_locked(&necp_account_id_list, inp->inp_necp_attributes.inp_account); 4214 if (existing_mapping) { 4215 info->account_id = existing_mapping->id; 4216 } 4217 } 4218 4219 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_DOMAIN) { 4220 info->domain = inp->inp_necp_attributes.inp_domain; 4221 } 4222 4223 if (override_bound_interface) { 4224 info->bound_interface_index = override_bound_interface; 4225 } else { 4226 if ((inp->inp_flags & INP_BOUND_IF) && inp->inp_boundifp) { 4227 info->bound_interface_index = inp->inp_boundifp->if_index; 4228 } 4229 } 4230 4231 if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_ADDRESS_TYPE_CONDITIONS) { 4232 if (inp->inp_vflag & INP_IPV4) { 4233 if (override_local_addr) { 4234 memcpy(&info->local_addr, override_local_addr, override_local_addr->sa_len); 4235 } else { 4236 ((struct sockaddr_in *)&info->local_addr)->sin_family = AF_INET; 4237 ((struct sockaddr_in *)&info->local_addr)->sin_len = sizeof(struct sockaddr_in); 4238 ((struct sockaddr_in *)&info->local_addr)->sin_port = inp->inp_lport; 4239 memcpy(&((struct sockaddr_in *)&info->local_addr)->sin_addr, &inp->inp_laddr, sizeof(struct in_addr)); 4240 } 4241 4242 if (override_remote_addr) { 4243 memcpy(&info->remote_addr, override_remote_addr, override_remote_addr->sa_len); 4244 } else { 4245 ((struct sockaddr_in *)&info->remote_addr)->sin_family = AF_INET; 4246 ((struct sockaddr_in *)&info->remote_addr)->sin_len = sizeof(struct sockaddr_in); 4247 ((struct sockaddr_in *)&info->remote_addr)->sin_port = inp->inp_fport; 4248 memcpy(&((struct sockaddr_in *)&info->remote_addr)->sin_addr, &inp->inp_faddr, sizeof(struct in_addr)); 4249 } 4250 } else if (inp->inp_vflag & INP_IPV6) { 4251 if (override_local_addr) { 4252 memcpy(&info->local_addr, override_local_addr, override_local_addr->sa_len); 4253 } else { 4254 ((struct sockaddr_in6 *)&info->local_addr)->sin6_family = AF_INET6; 4255 ((struct sockaddr_in6 *)&info->local_addr)->sin6_len = sizeof(struct sockaddr_in6); 4256 ((struct sockaddr_in6 *)&info->local_addr)->sin6_port = inp->inp_lport; 4257 memcpy(&((struct sockaddr_in6 *)&info->local_addr)->sin6_addr, &inp->in6p_laddr, sizeof(struct in6_addr)); 4258 } 4259 4260 if (override_remote_addr) { 4261 memcpy(&info->remote_addr, override_remote_addr, override_remote_addr->sa_len); 4262 } else { 4263 ((struct sockaddr_in6 *)&info->remote_addr)->sin6_family = AF_INET6; 4264 ((struct sockaddr_in6 *)&info->remote_addr)->sin6_len = sizeof(struct sockaddr_in6); 4265 ((struct sockaddr_in6 *)&info->remote_addr)->sin6_port = inp->inp_fport; 4266 memcpy(&((struct sockaddr_in6 *)&info->remote_addr)->sin6_addr, &inp->in6p_faddr, sizeof(struct in6_addr)); 4267 } 4268 } 4269 } 4270} 4271 4272static inline struct necp_kernel_socket_policy * 4273necp_socket_find_policy_match_with_info_locked(struct necp_kernel_socket_policy **policy_search_array, struct necp_socket_info *info, necp_kernel_policy_filter *return_filter, necp_kernel_policy_result *return_service_action, necp_kernel_policy_service *return_service) 4274{ 4275 struct necp_kernel_socket_policy *matched_policy = NULL; 4276 u_int32_t skip_order = 0; 4277 u_int32_t skip_session_order = 0; 4278 int i; 4279 4280 // Pre-process domain for quick matching 4281 struct substring domain_substring = necp_trim_dots_and_stars(info->domain, info->domain ? strlen(info->domain) : 0); 4282 u_int8_t domain_dot_count = necp_count_dots(domain_substring.string, domain_substring.length); 4283 4284 if (return_filter) { 4285 *return_filter = 0; 4286 } 4287 4288 if (return_service_action) { 4289 *return_service_action = 0; 4290 } 4291 4292 if (return_service) { 4293 return_service->identifier = 0; 4294 return_service->data = 0; 4295 } 4296 4297 if (policy_search_array != NULL) { 4298 for (i = 0; policy_search_array[i] != NULL; i++) { 4299 if (necp_drop_all_order != 0 && policy_search_array[i]->session_order >= necp_drop_all_order) { 4300 // We've hit a drop all rule 4301 break; 4302 } 4303 if (skip_session_order && policy_search_array[i]->session_order >= skip_session_order) { 4304 // Done skipping 4305 skip_order = 0; 4306 skip_session_order = 0; 4307 } 4308 if (skip_order) { 4309 if (policy_search_array[i]->order < skip_order) { 4310 // Skip this policy 4311 continue; 4312 } else { 4313 // Done skipping 4314 skip_order = 0; 4315 skip_session_order = 0; 4316 } 4317 } else if (skip_session_order) { 4318 // Skip this policy 4319 continue; 4320 } 4321 if (necp_socket_check_policy(policy_search_array[i], info->application_id, info->real_application_id, info->cred_result, info->account_id, domain_substring, domain_dot_count, info->pid, info->uid, info->bound_interface_index, info->traffic_class, info->protocol, &info->local_addr, &info->remote_addr)) { 4322 if (policy_search_array[i]->result == NECP_KERNEL_POLICY_RESULT_SOCKET_FILTER) { 4323 if (return_filter && *return_filter == 0) { 4324 *return_filter = policy_search_array[i]->result_parameter.filter_control_unit; 4325 if (necp_debug > 1) { 4326 NECPLOG(LOG_DEBUG, "Socket Policy: (Application %d Real Application %d BoundInterface %d Proto %d) Filter %d", info->application_id, info->real_application_id, info->bound_interface_index, info->protocol, policy_search_array[i]->result_parameter.filter_control_unit); 4327 } 4328 } 4329 continue; 4330 } else if (necp_kernel_socket_result_is_service_type(policy_search_array[i])) { 4331 if (return_service_action && *return_service_action == 0) { 4332 *return_service_action = policy_search_array[i]->result; 4333 if (necp_debug > 1) { 4334 NECPLOG(LOG_DEBUG, "Socket Policy: (Application %d Real Application %d BoundInterface %d Proto %d) Service Action %d", info->application_id, info->real_application_id, info->bound_interface_index, info->protocol, policy_search_array[i]->result); 4335 } 4336 } 4337 if (return_service && return_service->identifier == 0) { 4338 return_service->identifier = policy_search_array[i]->result_parameter.service.identifier; 4339 return_service->data = policy_search_array[i]->result_parameter.service.data; 4340 if (necp_debug > 1) { 4341 NECPLOG(LOG_DEBUG, "Socket Policy: (Application %d Real Application %d BoundInterface %d Proto %d) Service ID %d Data %d", info->application_id, info->real_application_id, info->bound_interface_index, info->protocol, policy_search_array[i]->result_parameter.service.identifier, policy_search_array[i]->result_parameter.service.data); 4342 } 4343 } 4344 continue; 4345 } 4346 4347 // Passed all tests, found a match 4348 matched_policy = policy_search_array[i]; 4349 if (policy_search_array[i]->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 4350 skip_order = policy_search_array[i]->result_parameter.skip_policy_order; 4351 skip_session_order = policy_search_array[i]->session_order + 1; 4352 continue; 4353 } 4354 break; 4355 } 4356 } 4357 } 4358 4359 return (matched_policy); 4360} 4361 4362static bool 4363necp_socket_uses_interface(struct inpcb *inp, u_int32_t interface_index) 4364{ 4365 bool found_match = FALSE; 4366 errno_t result = 0; 4367 ifaddr_t *addresses = NULL; 4368 union necp_sockaddr_union address_storage; 4369 int i; 4370 int family = AF_INET; 4371 ifnet_t interface = ifindex2ifnet[interface_index]; 4372 4373 if (inp == NULL || interface == NULL) { 4374 return (FALSE); 4375 } 4376 4377 if (inp->inp_vflag & INP_IPV4) { 4378 family = AF_INET; 4379 } else if (inp->inp_vflag & INP_IPV6) { 4380 family = AF_INET6; 4381 } 4382 4383 result = ifnet_get_address_list_family(interface, &addresses, family); 4384 if (result != 0) { 4385 NECPLOG(LOG_ERR, "Failed to get address list for %s%d", ifnet_name(interface), ifnet_unit(interface)); 4386 return (FALSE); 4387 } 4388 4389 for (i = 0; addresses[i] != NULL; i++) { 4390 if (ifaddr_address(addresses[i], &address_storage.sa, sizeof(address_storage)) == 0) { 4391 if (family == AF_INET) { 4392 if (memcmp(&address_storage.sin.sin_addr, &inp->inp_laddr, sizeof(inp->inp_laddr)) == 0) { 4393 found_match = TRUE; 4394 goto done; 4395 } 4396 } else if (family == AF_INET6) { 4397 if (memcmp(&address_storage.sin6.sin6_addr, &inp->in6p_laddr, sizeof(inp->in6p_laddr)) == 0) { 4398 found_match = TRUE; 4399 goto done; 4400 } 4401 } 4402 } 4403 } 4404 4405done: 4406 ifnet_free_address_list(addresses); 4407 addresses = NULL; 4408 return (found_match); 4409} 4410 4411static inline bool 4412necp_socket_is_connected(struct inpcb *inp) 4413{ 4414 return (inp->inp_socket->so_state & (SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING)); 4415} 4416 4417necp_kernel_policy_id 4418necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local_addr, struct sockaddr *override_remote_addr, u_int32_t override_bound_interface) 4419{ 4420 struct socket *so = NULL; 4421 necp_kernel_policy_filter filter_control_unit = 0; 4422 struct necp_kernel_socket_policy *matched_policy = NULL; 4423 necp_kernel_policy_id matched_policy_id = NECP_KERNEL_POLICY_ID_NONE; 4424 necp_kernel_policy_result service_action = 0; 4425 necp_kernel_policy_service service = { 0, 0 }; 4426 4427 struct necp_socket_info info; 4428 4429 if (inp == NULL) { 4430 return (NECP_KERNEL_POLICY_ID_NONE); 4431 } 4432 4433 so = inp->inp_socket; 4434 4435 // Don't lock. Possible race condition, but we don't want the performance hit. 4436 if (necp_kernel_socket_policies_count == 0 || 4437 (!(inp->inp_flags2 & INP2_WANT_APP_POLICY) && necp_kernel_socket_policies_non_app_count == 0)) { 4438 if (necp_drop_all_order > 0) { 4439 inp->inp_policyresult.policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4440 inp->inp_policyresult.policy_gencount = 0; 4441 inp->inp_policyresult.flowhash = 0; 4442 inp->inp_policyresult.results.filter_control_unit = 0; 4443 if (necp_pass_loopback > 0 && 4444 necp_is_loopback(override_local_addr, override_remote_addr, inp, NULL)) { 4445 inp->inp_policyresult.results.result = NECP_KERNEL_POLICY_RESULT_PASS; 4446 } else { 4447 inp->inp_policyresult.results.result = NECP_KERNEL_POLICY_RESULT_DROP; 4448 } 4449 } 4450 return (NECP_KERNEL_POLICY_ID_NONE); 4451 } 4452 4453 // Check for loopback exception 4454 if (necp_pass_loopback > 0 && 4455 necp_is_loopback(override_local_addr, override_remote_addr, inp, NULL)) { 4456 // Mark socket as a pass 4457 inp->inp_policyresult.policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4458 inp->inp_policyresult.policy_gencount = 0; 4459 inp->inp_policyresult.flowhash = 0; 4460 inp->inp_policyresult.results.filter_control_unit = 0; 4461 inp->inp_policyresult.results.result = NECP_KERNEL_POLICY_RESULT_PASS; 4462 return (NECP_KERNEL_POLICY_ID_NONE); 4463 } 4464 4465 // Lock 4466 lck_rw_lock_shared(&necp_kernel_policy_lock); 4467 4468 necp_socket_fillout_info_locked(inp, override_local_addr, override_remote_addr, override_bound_interface, &info); 4469 4470 // Check info 4471 u_int32_t flowhash = necp_socket_calc_flowhash_locked(&info); 4472 if (inp->inp_policyresult.policy_id != NECP_KERNEL_POLICY_ID_NONE && 4473 inp->inp_policyresult.policy_gencount == necp_kernel_socket_policies_gencount && 4474 inp->inp_policyresult.flowhash == flowhash) { 4475 // If already matched this socket on this generation of table, skip 4476 4477 // Unlock 4478 lck_rw_done(&necp_kernel_policy_lock); 4479 4480 return (inp->inp_policyresult.policy_id); 4481 } 4482 4483 // Match socket to policy 4484 matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_map[NECP_SOCKET_MAP_APP_ID_TO_BUCKET(info.application_id)], &info, &filter_control_unit, &service_action, &service); 4485 // If the socket matched a scoped service policy, mark as Drop if not registered. 4486 // This covers the cases in which a service is required (on demand) but hasn't started yet. 4487 if ((service_action == NECP_KERNEL_POLICY_RESULT_TRIGGER_SCOPED || 4488 service_action == NECP_KERNEL_POLICY_RESULT_NO_TRIGGER_SCOPED) && 4489 service.identifier != 0 && 4490 service.identifier != NECP_NULL_SERVICE_ID) { 4491 bool service_is_registered = FALSE; 4492 struct necp_service_registration *service_registration = NULL; 4493 LIST_FOREACH(service_registration, &necp_registered_service_list, kernel_chain) { 4494 if (service.identifier == service_registration->service_id) { 4495 service_is_registered = TRUE; 4496 break; 4497 } 4498 } 4499 if (!service_is_registered) { 4500 // Mark socket as a drop if service is not registered 4501 inp->inp_policyresult.policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4502 inp->inp_policyresult.policy_gencount = necp_kernel_socket_policies_gencount; 4503 inp->inp_policyresult.flowhash = flowhash; 4504 inp->inp_policyresult.results.filter_control_unit = 0; 4505 inp->inp_policyresult.results.result = NECP_KERNEL_POLICY_RESULT_DROP; 4506 4507 if (necp_debug > 1) { 4508 NECPLOG(LOG_DEBUG, "Socket Policy: (BoundInterface %d Proto %d) Dropping packet because service is not registered", info.bound_interface_index, info.protocol); 4509 } 4510 4511 // Unlock 4512 lck_rw_done(&necp_kernel_policy_lock); 4513 return (NECP_KERNEL_POLICY_ID_NONE); 4514 } 4515 } 4516 if (matched_policy) { 4517 matched_policy_id = matched_policy->id; 4518 inp->inp_policyresult.policy_id = matched_policy->id; 4519 inp->inp_policyresult.policy_gencount = necp_kernel_socket_policies_gencount; 4520 inp->inp_policyresult.flowhash = flowhash; 4521 inp->inp_policyresult.results.filter_control_unit = filter_control_unit; 4522 inp->inp_policyresult.results.result = matched_policy->result; 4523 memcpy(&inp->inp_policyresult.results.result_parameter, &matched_policy->result_parameter, sizeof(matched_policy->result_parameter)); 4524 4525 if (necp_socket_is_connected(inp) && 4526 (matched_policy->result == NECP_KERNEL_POLICY_RESULT_DROP || 4527 (matched_policy->result == NECP_KERNEL_POLICY_RESULT_IP_TUNNEL && !necp_socket_uses_interface(inp, matched_policy->result_parameter.tunnel_interface_index)))) { 4528 if (necp_debug) { 4529 NECPLOG(LOG_DEBUG, "Marking socket in state %d as defunct", so->so_state); 4530 } 4531 sosetdefunct(current_proc(), so, SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL, TRUE); 4532 } 4533 4534 if (necp_debug > 1) { 4535 NECPLOG(LOG_DEBUG, "Socket Policy: (BoundInterface %d Proto %d) Policy %d Result %d Parameter %d", info.bound_interface_index, info.protocol, matched_policy->id, matched_policy->result, matched_policy->result_parameter.tunnel_interface_index); 4536 } 4537 } else if (necp_drop_all_order > 0) { 4538 // Mark socket as a drop if set 4539 inp->inp_policyresult.policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4540 inp->inp_policyresult.policy_gencount = necp_kernel_socket_policies_gencount; 4541 inp->inp_policyresult.flowhash = flowhash; 4542 inp->inp_policyresult.results.filter_control_unit = 0; 4543 inp->inp_policyresult.results.result = NECP_KERNEL_POLICY_RESULT_DROP; 4544 } else { 4545 // Mark non-matching socket so we don't re-check it 4546 inp->inp_policyresult.policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4547 inp->inp_policyresult.policy_gencount = necp_kernel_socket_policies_gencount; 4548 inp->inp_policyresult.flowhash = flowhash; 4549 inp->inp_policyresult.results.filter_control_unit = filter_control_unit; // We may have matched a filter, so mark it! 4550 inp->inp_policyresult.results.result = NECP_KERNEL_POLICY_RESULT_NONE; 4551 } 4552 4553 // Unlock 4554 lck_rw_done(&necp_kernel_policy_lock); 4555 4556 return (matched_policy_id); 4557} 4558 4559static bool 4560necp_ip_output_check_policy(struct necp_kernel_ip_output_policy *kernel_policy, necp_kernel_policy_id socket_policy_id, u_int32_t bound_interface_index, u_int32_t last_interface_index, u_int16_t protocol, union necp_sockaddr_union *local, union necp_sockaddr_union *remote) 4561{ 4562 if (!(kernel_policy->condition_mask & NECP_KERNEL_CONDITION_ALL_INTERFACES)) { 4563 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE) { 4564 u_int32_t cond_bound_interface_index = kernel_policy->cond_bound_interface ? kernel_policy->cond_bound_interface->if_index : 0; 4565 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_BOUND_INTERFACE) { 4566 if (bound_interface_index == cond_bound_interface_index) { 4567 // No match, matches forbidden interface 4568 return (FALSE); 4569 } 4570 } else { 4571 if (bound_interface_index != cond_bound_interface_index) { 4572 // No match, does not match required interface 4573 return (FALSE); 4574 } 4575 } 4576 } else { 4577 if (bound_interface_index != 0) { 4578 // No match, requires a non-bound packet 4579 return (FALSE); 4580 } 4581 } 4582 } 4583 4584 if (kernel_policy->condition_mask == 0) { 4585 return (TRUE); 4586 } 4587 4588 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_POLICY_ID) { 4589 if (socket_policy_id != kernel_policy->cond_policy_id) { 4590 // No match, does not match required id 4591 return (FALSE); 4592 } 4593 } 4594 4595 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LAST_INTERFACE) { 4596 if (last_interface_index != kernel_policy->cond_last_interface_index) { 4597 return (FALSE); 4598 } 4599 } 4600 4601 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_PROTOCOL) { 4602 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_PROTOCOL) { 4603 if (protocol == kernel_policy->cond_protocol) { 4604 // No match, matches forbidden protocol 4605 return (FALSE); 4606 } 4607 } else { 4608 if (protocol != kernel_policy->cond_protocol) { 4609 // No match, does not match required protocol 4610 return (FALSE); 4611 } 4612 } 4613 } 4614 4615 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_START) { 4616 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 4617 bool inRange = necp_is_addr_in_range((struct sockaddr *)local, (struct sockaddr *)&kernel_policy->cond_local_start, (struct sockaddr *)&kernel_policy->cond_local_end); 4618 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_LOCAL_END) { 4619 if (inRange) { 4620 return (FALSE); 4621 } 4622 } else { 4623 if (!inRange) { 4624 return (FALSE); 4625 } 4626 } 4627 } else if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 4628 bool inSubnet = necp_is_addr_in_subnet((struct sockaddr *)local, (struct sockaddr *)&kernel_policy->cond_local_start, kernel_policy->cond_local_prefix); 4629 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_LOCAL_PREFIX) { 4630 if (inSubnet) { 4631 return (FALSE); 4632 } 4633 } else { 4634 if (!inSubnet) { 4635 return (FALSE); 4636 } 4637 } 4638 } 4639 } 4640 4641 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_START) { 4642 if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 4643 bool inRange = necp_is_addr_in_range((struct sockaddr *)remote, (struct sockaddr *)&kernel_policy->cond_remote_start, (struct sockaddr *)&kernel_policy->cond_remote_end); 4644 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_REMOTE_END) { 4645 if (inRange) { 4646 return (FALSE); 4647 } 4648 } else { 4649 if (!inRange) { 4650 return (FALSE); 4651 } 4652 } 4653 } else if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 4654 bool inSubnet = necp_is_addr_in_subnet((struct sockaddr *)remote, (struct sockaddr *)&kernel_policy->cond_remote_start, kernel_policy->cond_remote_prefix); 4655 if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_REMOTE_PREFIX) { 4656 if (inSubnet) { 4657 return (FALSE); 4658 } 4659 } else { 4660 if (!inSubnet) { 4661 return (FALSE); 4662 } 4663 } 4664 } 4665 } 4666 4667 return (TRUE); 4668} 4669 4670static inline struct necp_kernel_ip_output_policy * 4671necp_ip_output_find_policy_match_locked(necp_kernel_policy_id socket_policy_id, u_int32_t bound_interface_index, u_int32_t last_interface_index, u_int16_t protocol, union necp_sockaddr_union *local_addr, union necp_sockaddr_union *remote_addr) 4672{ 4673 u_int32_t skip_order = 0; 4674 u_int32_t skip_session_order = 0; 4675 int i; 4676 struct necp_kernel_ip_output_policy *matched_policy = NULL; 4677 struct necp_kernel_ip_output_policy **policy_search_array = necp_kernel_ip_output_policies_map[NECP_IP_OUTPUT_MAP_ID_TO_BUCKET(socket_policy_id)]; 4678 if (policy_search_array != NULL) { 4679 for (i = 0; policy_search_array[i] != NULL; i++) { 4680 if (necp_drop_all_order != 0 && policy_search_array[i]->session_order >= necp_drop_all_order) { 4681 // We've hit a drop all rule 4682 break; 4683 } 4684 if (skip_session_order && policy_search_array[i]->session_order >= skip_session_order) { 4685 // Done skipping 4686 skip_order = 0; 4687 skip_session_order = 0; 4688 } 4689 if (skip_order) { 4690 if (policy_search_array[i]->order < skip_order) { 4691 // Skip this policy 4692 continue; 4693 } else { 4694 // Done skipping 4695 skip_order = 0; 4696 skip_session_order = 0; 4697 } 4698 } else if (skip_session_order) { 4699 // Skip this policy 4700 continue; 4701 } 4702 if (necp_ip_output_check_policy(policy_search_array[i], socket_policy_id, bound_interface_index, last_interface_index, protocol, local_addr, remote_addr)) { 4703 // Passed all tests, found a match 4704 matched_policy = policy_search_array[i]; 4705 4706 if (policy_search_array[i]->result == NECP_KERNEL_POLICY_RESULT_SKIP) { 4707 skip_order = policy_search_array[i]->result_parameter.skip_policy_order; 4708 skip_session_order = policy_search_array[i]->session_order + 1; 4709 continue; 4710 } 4711 4712 break; 4713 } 4714 } 4715 } 4716 4717 return (matched_policy); 4718} 4719 4720necp_kernel_policy_id 4721necp_ip_output_find_policy_match(struct mbuf *packet, int flags, struct ip_out_args *ipoa, necp_kernel_policy_result *result, necp_kernel_policy_result_parameter *result_parameter) 4722{ 4723 struct ip *ip = NULL; 4724 int hlen = sizeof(struct ip); 4725 necp_kernel_policy_id socket_policy_id = NECP_KERNEL_POLICY_ID_NONE; 4726 necp_kernel_policy_id matched_policy_id = NECP_KERNEL_POLICY_ID_NONE; 4727 struct necp_kernel_ip_output_policy *matched_policy = NULL; 4728 u_int16_t protocol = 0; 4729 u_int32_t bound_interface_index = 0; 4730 u_int32_t last_interface_index = 0; 4731 union necp_sockaddr_union local_addr; 4732 union necp_sockaddr_union remote_addr; 4733 4734 if (result) { 4735 *result = 0; 4736 } 4737 4738 if (result_parameter) { 4739 memset(result_parameter, 0, sizeof(*result_parameter)); 4740 } 4741 4742 if (packet == NULL) { 4743 return (NECP_KERNEL_POLICY_ID_NONE); 4744 } 4745 4746 socket_policy_id = necp_get_policy_id_from_packet(packet); 4747 4748 // Exit early for an empty list 4749 // Don't lock. Possible race condition, but we don't want the performance hit. 4750 if (necp_kernel_ip_output_policies_count == 0 || 4751 ((socket_policy_id == NECP_KERNEL_POLICY_ID_NONE) && necp_kernel_ip_output_policies_non_id_count == 0)) { 4752 if (necp_drop_all_order > 0) { 4753 matched_policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4754 if (result) { 4755 if ((necp_pass_loopback > 0 && 4756 necp_is_loopback(NULL, NULL, NULL, packet)) || 4757 (necp_pass_keepalives > 0 && 4758 necp_get_is_keepalive_from_packet(packet))) { 4759 *result = NECP_KERNEL_POLICY_RESULT_PASS; 4760 } else { 4761 *result = NECP_KERNEL_POLICY_RESULT_DROP; 4762 } 4763 } 4764 } 4765 4766 return (matched_policy_id); 4767 } 4768 4769 // Check for loopback exception 4770 if ((necp_pass_loopback > 0 && 4771 necp_is_loopback(NULL, NULL, NULL, packet)) || 4772 (necp_pass_keepalives > 0 && 4773 necp_get_is_keepalive_from_packet(packet))) { 4774 matched_policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4775 if (result) { 4776 *result = NECP_KERNEL_POLICY_RESULT_PASS; 4777 } 4778 return (matched_policy_id); 4779 } 4780 4781 last_interface_index = necp_get_last_interface_index_from_packet(packet); 4782 4783 // Process packet to get relevant fields 4784 ip = mtod(packet, struct ip *); 4785#ifdef _IP_VHL 4786 hlen = _IP_VHL_HL(ip->ip_vhl) << 2; 4787#else 4788 hlen = ip->ip_hl << 2; 4789#endif 4790 4791 protocol = ip->ip_p; 4792 4793 if ((flags & IP_OUTARGS) && (ipoa != NULL) && 4794 (ipoa->ipoa_flags & IPOAF_BOUND_IF) && 4795 ipoa->ipoa_boundif != IFSCOPE_NONE) { 4796 bound_interface_index = ipoa->ipoa_boundif; 4797 } 4798 4799 local_addr.sin.sin_family = AF_INET; 4800 local_addr.sin.sin_len = sizeof(struct sockaddr_in); 4801 memcpy(&local_addr.sin.sin_addr, &ip->ip_src, sizeof(ip->ip_src)); 4802 4803 remote_addr.sin.sin_family = AF_INET; 4804 remote_addr.sin.sin_len = sizeof(struct sockaddr_in); 4805 memcpy(&((struct sockaddr_in *)&remote_addr)->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)); 4806 4807 switch (protocol) { 4808 case IPPROTO_TCP: { 4809 struct tcphdr th; 4810 if ((int)(hlen + sizeof(th)) <= packet->m_pkthdr.len) { 4811 m_copydata(packet, hlen, sizeof(th), (u_int8_t *)&th); 4812 ((struct sockaddr_in *)&local_addr)->sin_port = th.th_sport; 4813 ((struct sockaddr_in *)&remote_addr)->sin_port = th.th_dport; 4814 } 4815 break; 4816 } 4817 case IPPROTO_UDP: { 4818 struct udphdr uh; 4819 if ((int)(hlen + sizeof(uh)) <= packet->m_pkthdr.len) { 4820 m_copydata(packet, hlen, sizeof(uh), (u_int8_t *)&uh); 4821 ((struct sockaddr_in *)&local_addr)->sin_port = uh.uh_sport; 4822 ((struct sockaddr_in *)&remote_addr)->sin_port = uh.uh_dport; 4823 } 4824 break; 4825 } 4826 default: { 4827 ((struct sockaddr_in *)&local_addr)->sin_port = 0; 4828 ((struct sockaddr_in *)&remote_addr)->sin_port = 0; 4829 break; 4830 } 4831 } 4832 4833 // Match packet to policy 4834 lck_rw_lock_shared(&necp_kernel_policy_lock); 4835 matched_policy = necp_ip_output_find_policy_match_locked(socket_policy_id, bound_interface_index, last_interface_index, protocol, &local_addr, &remote_addr); 4836 if (matched_policy) { 4837 matched_policy_id = matched_policy->id; 4838 if (result) { 4839 *result = matched_policy->result; 4840 } 4841 4842 if (result_parameter) { 4843 memcpy(result_parameter, &matched_policy->result_parameter, sizeof(matched_policy->result_parameter)); 4844 } 4845 4846 if (necp_debug > 1) { 4847 NECPLOG(LOG_DEBUG, "IP Output: (ID %d BoundInterface %d LastInterface %d Proto %d) Policy %d Result %d Parameter %d", socket_policy_id, bound_interface_index, last_interface_index, protocol, matched_policy->id, matched_policy->result, matched_policy->result_parameter.tunnel_interface_index); 4848 } 4849 } else if (necp_drop_all_order > 0) { 4850 matched_policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4851 if (result) { 4852 *result = NECP_KERNEL_POLICY_RESULT_DROP; 4853 } 4854 } 4855 4856 lck_rw_done(&necp_kernel_policy_lock); 4857 4858 return (matched_policy_id); 4859} 4860 4861necp_kernel_policy_id 4862necp_ip6_output_find_policy_match(struct mbuf *packet, int flags, struct ip6_out_args *ip6oa, necp_kernel_policy_result *result, necp_kernel_policy_result_parameter *result_parameter) 4863{ 4864 struct ip6_hdr *ip6 = NULL; 4865 int next = -1; 4866 int offset = 0; 4867 necp_kernel_policy_id socket_policy_id = NECP_KERNEL_POLICY_ID_NONE; 4868 necp_kernel_policy_id matched_policy_id = NECP_KERNEL_POLICY_ID_NONE; 4869 struct necp_kernel_ip_output_policy *matched_policy = NULL; 4870 u_int16_t protocol = 0; 4871 u_int32_t bound_interface_index = 0; 4872 u_int32_t last_interface_index = 0; 4873 union necp_sockaddr_union local_addr; 4874 union necp_sockaddr_union remote_addr; 4875 4876 if (result) { 4877 *result = 0; 4878 } 4879 4880 if (result_parameter) { 4881 memset(result_parameter, 0, sizeof(*result_parameter)); 4882 } 4883 4884 if (packet == NULL) { 4885 return (NECP_KERNEL_POLICY_ID_NONE); 4886 } 4887 4888 socket_policy_id = necp_get_policy_id_from_packet(packet); 4889 4890 // Exit early for an empty list 4891 // Don't lock. Possible race condition, but we don't want the performance hit. 4892 if (necp_kernel_ip_output_policies_count == 0 || 4893 ((socket_policy_id == NECP_KERNEL_POLICY_ID_NONE) && necp_kernel_ip_output_policies_non_id_count == 0)) { 4894 if (necp_drop_all_order > 0) { 4895 matched_policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4896 if (result) { 4897 if ((necp_pass_loopback > 0 && 4898 necp_is_loopback(NULL, NULL, NULL, packet)) || 4899 (necp_pass_keepalives > 0 && 4900 necp_get_is_keepalive_from_packet(packet))) { 4901 *result = NECP_KERNEL_POLICY_RESULT_PASS; 4902 } else { 4903 *result = NECP_KERNEL_POLICY_RESULT_DROP; 4904 } 4905 } 4906 } 4907 4908 return (matched_policy_id); 4909 } 4910 4911 // Check for loopback exception 4912 if ((necp_pass_loopback > 0 && 4913 necp_is_loopback(NULL, NULL, NULL, packet)) || 4914 (necp_pass_keepalives > 0 && 4915 necp_get_is_keepalive_from_packet(packet))) { 4916 matched_policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4917 if (result) { 4918 *result = NECP_KERNEL_POLICY_RESULT_PASS; 4919 } 4920 return (matched_policy_id); 4921 } 4922 4923 last_interface_index = necp_get_last_interface_index_from_packet(packet); 4924 4925 // Process packet to get relevant fields 4926 ip6 = mtod(packet, struct ip6_hdr *); 4927 4928 if ((flags & IPV6_OUTARGS) && (ip6oa != NULL) && 4929 (ip6oa->ip6oa_flags & IP6OAF_BOUND_IF) && 4930 ip6oa->ip6oa_boundif != IFSCOPE_NONE) { 4931 bound_interface_index = ip6oa->ip6oa_boundif; 4932 } 4933 4934 ((struct sockaddr_in6 *)&local_addr)->sin6_family = AF_INET6; 4935 ((struct sockaddr_in6 *)&local_addr)->sin6_len = sizeof(struct sockaddr_in6); 4936 memcpy(&((struct sockaddr_in6 *)&local_addr)->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)); 4937 4938 ((struct sockaddr_in6 *)&remote_addr)->sin6_family = AF_INET6; 4939 ((struct sockaddr_in6 *)&remote_addr)->sin6_len = sizeof(struct sockaddr_in6); 4940 memcpy(&((struct sockaddr_in6 *)&remote_addr)->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 4941 4942 offset = ip6_lasthdr(packet, 0, IPPROTO_IPV6, &next); 4943 if (offset >= 0 && packet->m_pkthdr.len >= offset) { 4944 protocol = next; 4945 switch (protocol) { 4946 case IPPROTO_TCP: { 4947 struct tcphdr th; 4948 if ((int)(offset + sizeof(th)) <= packet->m_pkthdr.len) { 4949 m_copydata(packet, offset, sizeof(th), (u_int8_t *)&th); 4950 ((struct sockaddr_in6 *)&local_addr)->sin6_port = th.th_sport; 4951 ((struct sockaddr_in6 *)&remote_addr)->sin6_port = th.th_dport; 4952 } 4953 break; 4954 } 4955 case IPPROTO_UDP: { 4956 struct udphdr uh; 4957 if ((int)(offset + sizeof(uh)) <= packet->m_pkthdr.len) { 4958 m_copydata(packet, offset, sizeof(uh), (u_int8_t *)&uh); 4959 ((struct sockaddr_in6 *)&local_addr)->sin6_port = uh.uh_sport; 4960 ((struct sockaddr_in6 *)&remote_addr)->sin6_port = uh.uh_dport; 4961 } 4962 break; 4963 } 4964 default: { 4965 ((struct sockaddr_in6 *)&local_addr)->sin6_port = 0; 4966 ((struct sockaddr_in6 *)&remote_addr)->sin6_port = 0; 4967 break; 4968 } 4969 } 4970 } 4971 4972 // Match packet to policy 4973 lck_rw_lock_shared(&necp_kernel_policy_lock); 4974 matched_policy = necp_ip_output_find_policy_match_locked(socket_policy_id, bound_interface_index, last_interface_index, protocol, &local_addr, &remote_addr); 4975 if (matched_policy) { 4976 matched_policy_id = matched_policy->id; 4977 if (result) { 4978 *result = matched_policy->result; 4979 } 4980 4981 if (result_parameter) { 4982 memcpy(result_parameter, &matched_policy->result_parameter, sizeof(matched_policy->result_parameter)); 4983 } 4984 4985 if (necp_debug > 1) { 4986 NECPLOG(LOG_DEBUG, "IP6 Output: (ID %d BoundInterface %d LastInterface %d Proto %d) Policy %d Result %d Parameter %d", socket_policy_id, bound_interface_index, last_interface_index, protocol, matched_policy->id, matched_policy->result, matched_policy->result_parameter.tunnel_interface_index); 4987 } 4988 } else if (necp_drop_all_order > 0) { 4989 matched_policy_id = NECP_KERNEL_POLICY_ID_NO_MATCH; 4990 if (result) { 4991 *result = NECP_KERNEL_POLICY_RESULT_DROP; 4992 } 4993 } 4994 4995 lck_rw_done(&necp_kernel_policy_lock); 4996 4997 return (matched_policy_id); 4998} 4999 5000// Utilities 5001static bool 5002necp_is_addr_in_range(struct sockaddr *addr, struct sockaddr *range_start, struct sockaddr *range_end) 5003{ 5004 int cmp = 0; 5005 5006 if (addr == NULL || range_start == NULL || range_end == NULL) { 5007 return (FALSE); 5008 } 5009 5010 /* Must be greater than or equal to start */ 5011 cmp = necp_addr_compare(addr, range_start, 1); 5012 if (cmp != 0 && cmp != 1) { 5013 return (FALSE); 5014 } 5015 5016 /* Must be less than or equal to end */ 5017 cmp = necp_addr_compare(addr, range_end, 1); 5018 if (cmp != 0 && cmp != -1) { 5019 return (FALSE); 5020 } 5021 5022 return (TRUE); 5023} 5024 5025static bool 5026necp_is_range_in_range(struct sockaddr *inner_range_start, struct sockaddr *inner_range_end, struct sockaddr *range_start, struct sockaddr *range_end) 5027{ 5028 int cmp = 0; 5029 5030 if (inner_range_start == NULL || inner_range_end == NULL || range_start == NULL || range_end == NULL) { 5031 return (FALSE); 5032 } 5033 5034 /* Must be greater than or equal to start */ 5035 cmp = necp_addr_compare(inner_range_start, range_start, 1); 5036 if (cmp != 0 && cmp != 1) { 5037 return (FALSE); 5038 } 5039 5040 /* Must be less than or equal to end */ 5041 cmp = necp_addr_compare(inner_range_end, range_end, 1); 5042 if (cmp != 0 && cmp != -1) { 5043 return (FALSE); 5044 } 5045 5046 return (TRUE); 5047} 5048 5049static bool 5050necp_is_addr_in_subnet(struct sockaddr *addr, struct sockaddr *subnet_addr, u_int8_t subnet_prefix) 5051{ 5052 if (addr == NULL || subnet_addr == NULL) { 5053 return (FALSE); 5054 } 5055 5056 if (addr->sa_family != subnet_addr->sa_family || addr->sa_len != subnet_addr->sa_len) { 5057 return (FALSE); 5058 } 5059 5060 switch (addr->sa_family) { 5061 case AF_INET: { 5062 if (satosin(subnet_addr)->sin_port != 0 && 5063 satosin(addr)->sin_port != satosin(subnet_addr)->sin_port) { 5064 return (FALSE); 5065 } 5066 return (necp_buffer_compare_with_bit_prefix((u_int8_t *)&satosin(addr)->sin_addr, (u_int8_t *)&satosin(subnet_addr)->sin_addr, subnet_prefix)); 5067 } 5068 case AF_INET6: { 5069 if (satosin6(subnet_addr)->sin6_port != 0 && 5070 satosin6(addr)->sin6_port != satosin6(subnet_addr)->sin6_port) { 5071 return (FALSE); 5072 } 5073 if (satosin6(addr)->sin6_scope_id && 5074 satosin6(subnet_addr)->sin6_scope_id && 5075 satosin6(addr)->sin6_scope_id != satosin6(subnet_addr)->sin6_scope_id) { 5076 return (FALSE); 5077 } 5078 return (necp_buffer_compare_with_bit_prefix((u_int8_t *)&satosin6(addr)->sin6_addr, (u_int8_t *)&satosin6(subnet_addr)->sin6_addr, subnet_prefix)); 5079 } 5080 default: { 5081 return (FALSE); 5082 } 5083 } 5084 5085 return (FALSE); 5086} 5087 5088/* 5089 * Return values: 5090 * -1: sa1 < sa2 5091 * 0: sa1 == sa2 5092 * 1: sa1 > sa2 5093 * 2: Not comparable or error 5094 */ 5095static int 5096necp_addr_compare(struct sockaddr *sa1, struct sockaddr *sa2, int check_port) 5097{ 5098 int result = 0; 5099 int port_result = 0; 5100 5101 if (sa1->sa_family != sa2->sa_family || sa1->sa_len != sa2->sa_len) { 5102 return (2); 5103 } 5104 5105 if (sa1->sa_len == 0) { 5106 return (0); 5107 } 5108 5109 switch (sa1->sa_family) { 5110 case AF_INET: { 5111 if (sa1->sa_len != sizeof(struct sockaddr_in)) { 5112 return (2); 5113 } 5114 5115 result = memcmp(&satosin(sa1)->sin_addr.s_addr, &satosin(sa2)->sin_addr.s_addr, sizeof(satosin(sa1)->sin_addr.s_addr)); 5116 5117 if (check_port) { 5118 if (satosin(sa1)->sin_port < satosin(sa2)->sin_port) { 5119 port_result = -1; 5120 } else if (satosin(sa1)->sin_port > satosin(sa2)->sin_port) { 5121 port_result = 1; 5122 } 5123 5124 if (result == 0) { 5125 result = port_result; 5126 } else if ((result > 0 && port_result < 0) || (result < 0 && port_result > 0)) { 5127 return (2); 5128 } 5129 } 5130 5131 break; 5132 } 5133 case AF_INET6: { 5134 if (sa1->sa_len != sizeof(struct sockaddr_in6)) { 5135 return (2); 5136 } 5137 5138 if (satosin6(sa1)->sin6_scope_id != satosin6(sa2)->sin6_scope_id) { 5139 return (2); 5140 } 5141 5142 result = memcmp(&satosin6(sa1)->sin6_addr.s6_addr[0], &satosin6(sa2)->sin6_addr.s6_addr[0], sizeof(struct in6_addr)); 5143 5144 if (check_port) { 5145 if (satosin6(sa1)->sin6_port < satosin6(sa2)->sin6_port) { 5146 port_result = -1; 5147 } else if (satosin6(sa1)->sin6_port > satosin6(sa2)->sin6_port) { 5148 port_result = 1; 5149 } 5150 5151 if (result == 0) { 5152 result = port_result; 5153 } else if ((result > 0 && port_result < 0) || (result < 0 && port_result > 0)) { 5154 return (2); 5155 } 5156 } 5157 5158 break; 5159 } 5160 default: { 5161 result = memcmp(sa1, sa2, sa1->sa_len); 5162 break; 5163 } 5164 } 5165 5166 if (result < 0) { 5167 result = (-1); 5168 } else if (result > 0) { 5169 result = (1); 5170 } 5171 5172 return (result); 5173} 5174 5175static bool 5176necp_buffer_compare_with_bit_prefix(u_int8_t *p1, u_int8_t *p2, u_int32_t bits) 5177{ 5178 u_int8_t mask; 5179 5180 /* Handle null pointers */ 5181 if (p1 == NULL || p2 == NULL) { 5182 return (p1 == p2); 5183 } 5184 5185 while (bits >= 8) { 5186 if (*p1++ != *p2++) { 5187 return (FALSE); 5188 } 5189 bits -= 8; 5190 } 5191 5192 if (bits > 0) { 5193 mask = ~((1<<(8-bits))-1); 5194 if ((*p1 & mask) != (*p2 & mask)) { 5195 return (FALSE); 5196 } 5197 } 5198 return (TRUE); 5199} 5200 5201// Socket operations 5202#define NECP_MAX_SOCKET_ATTRIBUTE_STRING_LENGTH 253 5203 5204static bool 5205necp_set_socket_attribute(u_int8_t *buffer, size_t buffer_length, u_int8_t type, char **buffer_p) 5206{ 5207 int error = 0; 5208 int cursor = 0; 5209 size_t string_size = 0; 5210 char *local_string = NULL; 5211 u_int8_t *value = NULL; 5212 5213 cursor = necp_buffer_find_tlv(buffer, buffer_length, 0, type, 0); 5214 if (cursor < 0) { 5215 // This will clear out the parameter 5216 goto done; 5217 } 5218 5219 string_size = necp_buffer_get_tlv_length(buffer, cursor); 5220 if (string_size == 0 || string_size > NECP_MAX_SOCKET_ATTRIBUTE_STRING_LENGTH) { 5221 // This will clear out the parameter 5222 goto done; 5223 } 5224 5225 MALLOC(local_string, char *, string_size + 1, M_NECP, M_WAITOK); 5226 if (local_string == NULL) { 5227 NECPLOG(LOG_ERR, "Failed to allocate a socket attribute buffer (size %d)", string_size); 5228 goto fail; 5229 } 5230 5231 value = necp_buffer_get_tlv_value(buffer, cursor, NULL); 5232 if (value == NULL) { 5233 NECPLOG0(LOG_ERR, "Failed to get socket attribute"); 5234 goto fail; 5235 } 5236 5237 memcpy(local_string, value, string_size); 5238 local_string[string_size] = 0; 5239 5240done: 5241 if (*buffer_p != NULL) { 5242 FREE(*buffer_p, M_NECP); 5243 *buffer_p = NULL; 5244 } 5245 5246 *buffer_p = local_string; 5247 return (0); 5248fail: 5249 if (local_string != NULL) { 5250 FREE(local_string, M_NECP); 5251 } 5252 return (error); 5253} 5254 5255errno_t 5256necp_set_socket_attributes(struct socket *so, struct sockopt *sopt) 5257{ 5258 int error = 0; 5259 u_int8_t *buffer = NULL; 5260 struct inpcb *inp = sotoinpcb(so); 5261 5262 size_t valsize = sopt->sopt_valsize; 5263 if (valsize == 0 || 5264 valsize > ((sizeof(u_int8_t) + sizeof(size_t) + NECP_MAX_SOCKET_ATTRIBUTE_STRING_LENGTH) * 2)) { 5265 goto done; 5266 } 5267 5268 MALLOC(buffer, u_int8_t *, valsize, M_NECP, M_WAITOK); 5269 if (buffer == NULL) { 5270 goto done; 5271 } 5272 5273 error = sooptcopyin(sopt, buffer, valsize, 0); 5274 if (error) { 5275 goto done; 5276 } 5277 5278 error = necp_set_socket_attribute(buffer, valsize, NECP_TLV_ATTRIBUTE_DOMAIN, &inp->inp_necp_attributes.inp_domain); 5279 if (error) { 5280 NECPLOG0(LOG_ERR, "Could not set domain TLV for socket attributes"); 5281 goto done; 5282 } 5283 5284 error = necp_set_socket_attribute(buffer, valsize, NECP_TLV_ATTRIBUTE_ACCOUNT, &inp->inp_necp_attributes.inp_account); 5285 if (error) { 5286 NECPLOG0(LOG_ERR, "Could not set account TLV for socket attributes"); 5287 goto done; 5288 } 5289 5290 if (necp_debug) { 5291 NECPLOG(LOG_DEBUG, "Set on socket: Domain %s, Account %s", inp->inp_necp_attributes.inp_domain, inp->inp_necp_attributes.inp_account); 5292 } 5293done: 5294 if (buffer != NULL) { 5295 FREE(buffer, M_NECP); 5296 } 5297 5298 return (error); 5299} 5300 5301errno_t 5302necp_get_socket_attributes(struct socket *so, struct sockopt *sopt) 5303{ 5304 int error = 0; 5305 u_int8_t *buffer = NULL; 5306 u_int8_t *cursor = NULL; 5307 size_t valsize = 0; 5308 struct inpcb *inp = sotoinpcb(so); 5309 5310 if (inp->inp_necp_attributes.inp_domain != NULL) { 5311 valsize += sizeof(u_int8_t) + sizeof(size_t) + strlen(inp->inp_necp_attributes.inp_domain); 5312 } 5313 if (inp->inp_necp_attributes.inp_account != NULL) { 5314 valsize += sizeof(u_int8_t) + sizeof(size_t) + strlen(inp->inp_necp_attributes.inp_account); 5315 } 5316 if (valsize == 0) { 5317 goto done; 5318 } 5319 5320 MALLOC(buffer, u_int8_t *, valsize, M_NECP, M_WAITOK); 5321 if (buffer == NULL) { 5322 goto done; 5323 } 5324 5325 cursor = buffer; 5326 if (inp->inp_necp_attributes.inp_domain != NULL) { 5327 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_ATTRIBUTE_DOMAIN, strlen(inp->inp_necp_attributes.inp_domain), inp->inp_necp_attributes.inp_domain); 5328 } 5329 5330 if (inp->inp_necp_attributes.inp_account != NULL) { 5331 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_ATTRIBUTE_ACCOUNT, strlen(inp->inp_necp_attributes.inp_account), inp->inp_necp_attributes.inp_account); 5332 } 5333 5334 error = sooptcopyout(sopt, buffer, valsize); 5335 if (error) { 5336 goto done; 5337 } 5338done: 5339 if (buffer != NULL) { 5340 FREE(buffer, M_NECP); 5341 } 5342 5343 return (error); 5344} 5345 5346static bool 5347necp_socket_is_allowed_to_send_recv_internal(struct inpcb *inp, struct sockaddr *override_local_addr, struct sockaddr *override_remote_addr, ifnet_t interface, necp_kernel_policy_id *return_policy_id) 5348{ 5349 u_int32_t verifyifindex = interface ? interface->if_index : 0; 5350 bool allowed_to_receive = TRUE; 5351 struct necp_socket_info info; 5352 u_int32_t flowhash = 0; 5353 necp_kernel_policy_result service_action = 0; 5354 necp_kernel_policy_service service = { 0, 0 }; 5355 5356 if (return_policy_id) { 5357 *return_policy_id = NECP_KERNEL_POLICY_ID_NONE; 5358 } 5359 5360 if (inp == NULL) { 5361 goto done; 5362 } 5363 5364 // Don't lock. Possible race condition, but we don't want the performance hit. 5365 if (necp_kernel_socket_policies_count == 0 || 5366 (!(inp->inp_flags2 & INP2_WANT_APP_POLICY) && necp_kernel_socket_policies_non_app_count == 0)) { 5367 if (necp_drop_all_order > 0) { 5368 if (necp_pass_loopback > 0 && 5369 necp_is_loopback(override_local_addr, override_remote_addr, inp, NULL)) { 5370 allowed_to_receive = TRUE; 5371 } else { 5372 allowed_to_receive = FALSE; 5373 } 5374 } 5375 goto done; 5376 } 5377 5378 // If this socket is connected, or we are not taking addresses into account, try to reuse last result 5379 if ((necp_socket_is_connected(inp) || (override_local_addr == NULL && override_remote_addr == NULL)) && inp->inp_policyresult.policy_id != NECP_KERNEL_POLICY_ID_NONE) { 5380 bool policies_have_changed = FALSE; 5381 lck_rw_lock_shared(&necp_kernel_policy_lock); 5382 if (inp->inp_policyresult.policy_gencount != necp_kernel_socket_policies_gencount) { 5383 policies_have_changed = TRUE; 5384 } 5385 lck_rw_done(&necp_kernel_policy_lock); 5386 5387 if (!policies_have_changed) { 5388 if (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_DROP || 5389 inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_SOCKET_DIVERT || 5390 (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_IP_TUNNEL && interface && 5391 inp->inp_policyresult.results.result_parameter.tunnel_interface_index != verifyifindex)) { 5392 allowed_to_receive = FALSE; 5393 } else if (return_policy_id) { 5394 *return_policy_id = inp->inp_policyresult.policy_id; 5395 } 5396 goto done; 5397 } 5398 } 5399 5400 // Check for loopback exception 5401 if (necp_pass_loopback > 0 && 5402 necp_is_loopback(override_local_addr, override_remote_addr, inp, NULL)) { 5403 allowed_to_receive = TRUE; 5404 goto done; 5405 } 5406 5407 // Actually calculate policy result 5408 lck_rw_lock_shared(&necp_kernel_policy_lock); 5409 necp_socket_fillout_info_locked(inp, override_local_addr, override_remote_addr, 0, &info); 5410 5411 flowhash = necp_socket_calc_flowhash_locked(&info); 5412 if (inp->inp_policyresult.policy_id != NECP_KERNEL_POLICY_ID_NONE && 5413 inp->inp_policyresult.policy_gencount == necp_kernel_socket_policies_gencount && 5414 inp->inp_policyresult.flowhash == flowhash) { 5415 if (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_DROP || 5416 inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_SOCKET_DIVERT || 5417 (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_IP_TUNNEL && interface && 5418 inp->inp_policyresult.results.result_parameter.tunnel_interface_index != verifyifindex)) { 5419 allowed_to_receive = FALSE; 5420 } else if (return_policy_id) { 5421 *return_policy_id = inp->inp_policyresult.policy_id; 5422 } 5423 lck_rw_done(&necp_kernel_policy_lock); 5424 goto done; 5425 } 5426 5427 struct necp_kernel_socket_policy *matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_map[NECP_SOCKET_MAP_APP_ID_TO_BUCKET(info.application_id)], &info, NULL, &service_action, &service); 5428 if (matched_policy != NULL) { 5429 if (matched_policy->result == NECP_KERNEL_POLICY_RESULT_DROP || 5430 matched_policy->result == NECP_KERNEL_POLICY_RESULT_SOCKET_DIVERT || 5431 (matched_policy->result == NECP_KERNEL_POLICY_RESULT_IP_TUNNEL && interface && 5432 matched_policy->result_parameter.tunnel_interface_index != verifyifindex) || 5433 ((service_action == NECP_KERNEL_POLICY_RESULT_TRIGGER_SCOPED || 5434 service_action == NECP_KERNEL_POLICY_RESULT_NO_TRIGGER_SCOPED) && 5435 service.identifier != 0 && service.identifier != NECP_NULL_SERVICE_ID)) { 5436 allowed_to_receive = FALSE; 5437 } else if (return_policy_id) { 5438 *return_policy_id = matched_policy->id; 5439 } 5440 lck_rw_done(&necp_kernel_policy_lock); 5441 5442 if (necp_debug > 1 && matched_policy->id != inp->inp_policyresult.policy_id) { 5443 NECPLOG(LOG_DEBUG, "Socket Send/Recv Policy: Policy %d Allowed %d", return_policy_id ? *return_policy_id : 0, allowed_to_receive); 5444 } 5445 goto done; 5446 } else if (necp_drop_all_order > 0) { 5447 allowed_to_receive = FALSE; 5448 } 5449 5450 lck_rw_done(&necp_kernel_policy_lock); 5451 5452done: 5453 return (allowed_to_receive); 5454} 5455 5456bool 5457necp_socket_is_allowed_to_send_recv_v4(struct inpcb *inp, u_int16_t local_port, u_int16_t remote_port, struct in_addr *local_addr, struct in_addr *remote_addr, ifnet_t interface, necp_kernel_policy_id *return_policy_id) 5458{ 5459 struct sockaddr_in local; 5460 struct sockaddr_in remote; 5461 local.sin_family = remote.sin_family = AF_INET; 5462 local.sin_len = remote.sin_len = sizeof(struct sockaddr_in); 5463 local.sin_port = local_port; 5464 remote.sin_port = remote_port; 5465 memcpy(&local.sin_addr, local_addr, sizeof(local.sin_addr)); 5466 memcpy(&remote.sin_addr, remote_addr, sizeof(remote.sin_addr)); 5467 5468 return (necp_socket_is_allowed_to_send_recv_internal(inp, (struct sockaddr *)&local, (struct sockaddr *)&remote, interface, return_policy_id)); 5469} 5470 5471bool 5472necp_socket_is_allowed_to_send_recv_v6(struct inpcb *inp, u_int16_t local_port, u_int16_t remote_port, struct in6_addr *local_addr, struct in6_addr *remote_addr, ifnet_t interface, necp_kernel_policy_id *return_policy_id) 5473{ 5474 struct sockaddr_in6 local; 5475 struct sockaddr_in6 remote; 5476 local.sin6_family = remote.sin6_family = AF_INET6; 5477 local.sin6_len = remote.sin6_len = sizeof(struct sockaddr_in6); 5478 local.sin6_port = local_port; 5479 remote.sin6_port = remote_port; 5480 memcpy(&local.sin6_addr, local_addr, sizeof(local.sin6_addr)); 5481 memcpy(&remote.sin6_addr, remote_addr, sizeof(remote.sin6_addr)); 5482 5483 return (necp_socket_is_allowed_to_send_recv_internal(inp, (struct sockaddr *)&local, (struct sockaddr *)&remote, interface, return_policy_id)); 5484} 5485 5486bool 5487necp_socket_is_allowed_to_send_recv(struct inpcb *inp, necp_kernel_policy_id *return_policy_id) 5488{ 5489 return (necp_socket_is_allowed_to_send_recv_internal(inp, NULL, NULL, NULL, return_policy_id)); 5490} 5491 5492int 5493necp_mark_packet_from_socket(struct mbuf *packet, struct inpcb *inp, necp_kernel_policy_id policy_id) 5494{ 5495 if (packet == NULL || inp == NULL) { 5496 return (EINVAL); 5497 } 5498 5499 // Mark ID for Pass and IP Tunnel 5500 if (policy_id != NECP_KERNEL_POLICY_ID_NONE) { 5501 packet->m_pkthdr.necp_mtag.necp_policy_id = policy_id; 5502 } else if (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_PASS || 5503 inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_IP_TUNNEL) { 5504 packet->m_pkthdr.necp_mtag.necp_policy_id = inp->inp_policyresult.policy_id; 5505 } else { 5506 packet->m_pkthdr.necp_mtag.necp_policy_id = NECP_KERNEL_POLICY_ID_NONE; 5507 } 5508 packet->m_pkthdr.necp_mtag.necp_last_interface_index = 0; 5509 5510 return (0); 5511} 5512 5513int 5514necp_mark_packet_from_ip(struct mbuf *packet, necp_kernel_policy_id policy_id) 5515{ 5516 if (packet == NULL) { 5517 return (EINVAL); 5518 } 5519 5520 // Mark ID for Pass and IP Tunnel 5521 if (policy_id != NECP_KERNEL_POLICY_ID_NONE) { 5522 packet->m_pkthdr.necp_mtag.necp_policy_id = policy_id; 5523 } else { 5524 packet->m_pkthdr.necp_mtag.necp_policy_id = NECP_KERNEL_POLICY_ID_NONE; 5525 } 5526 5527 return (0); 5528} 5529 5530int 5531necp_mark_packet_from_interface(struct mbuf *packet, ifnet_t interface) 5532{ 5533 if (packet == NULL) { 5534 return (EINVAL); 5535 } 5536 5537 // Mark ID for Pass and IP Tunnel 5538 if (interface != NULL) { 5539 packet->m_pkthdr.necp_mtag.necp_last_interface_index = interface->if_index; 5540 } 5541 5542 return (0); 5543} 5544 5545int 5546necp_mark_packet_as_keepalive(struct mbuf *packet, bool is_keepalive) 5547{ 5548 if (packet == NULL) { 5549 return (EINVAL); 5550 } 5551 5552 if (is_keepalive) { 5553 packet->m_pkthdr.pkt_flags |= PKTF_KEEPALIVE; 5554 } else { 5555 packet->m_pkthdr.pkt_flags &= ~PKTF_KEEPALIVE; 5556 } 5557 5558 return (0); 5559} 5560 5561necp_kernel_policy_id 5562necp_get_policy_id_from_packet(struct mbuf *packet) 5563{ 5564 if (packet == NULL) { 5565 return (NECP_KERNEL_POLICY_ID_NONE); 5566 } 5567 5568 return (packet->m_pkthdr.necp_mtag.necp_policy_id); 5569} 5570 5571u_int32_t 5572necp_get_last_interface_index_from_packet(struct mbuf *packet) 5573{ 5574 if (packet == NULL) { 5575 return (0); 5576 } 5577 5578 return (packet->m_pkthdr.necp_mtag.necp_last_interface_index); 5579} 5580 5581bool 5582necp_get_is_keepalive_from_packet(struct mbuf *packet) 5583{ 5584 if (packet == NULL) { 5585 return (FALSE); 5586 } 5587 5588 return (packet->m_pkthdr.pkt_flags & PKTF_KEEPALIVE); 5589} 5590 5591u_int32_t 5592necp_socket_get_content_filter_control_unit(struct socket *so) 5593{ 5594 struct inpcb *inp = sotoinpcb(so); 5595 5596 if (inp == NULL) { 5597 return (0); 5598 } 5599 return (inp->inp_policyresult.results.filter_control_unit); 5600} 5601 5602bool 5603necp_socket_should_use_flow_divert(struct inpcb *inp) 5604{ 5605 if (inp == NULL) { 5606 return (FALSE); 5607 } 5608 5609 return (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_SOCKET_DIVERT); 5610} 5611 5612u_int32_t 5613necp_socket_get_flow_divert_control_unit(struct inpcb *inp) 5614{ 5615 if (inp == NULL) { 5616 return (0); 5617 } 5618 5619 if (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_SOCKET_DIVERT) { 5620 return (inp->inp_policyresult.results.result_parameter.flow_divert_control_unit); 5621 } 5622 5623 return (0); 5624} 5625 5626bool 5627necp_socket_should_rescope(struct inpcb *inp) 5628{ 5629 if (inp == NULL) { 5630 return (FALSE); 5631 } 5632 5633 return (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_SOCKET_SCOPED); 5634} 5635 5636u_int 5637necp_socket_get_rescope_if_index(struct inpcb *inp) 5638{ 5639 if (inp == NULL) { 5640 return (0); 5641 } 5642 5643 if (inp->inp_policyresult.results.result == NECP_KERNEL_POLICY_RESULT_SOCKET_SCOPED) { 5644 return (inp->inp_policyresult.results.result_parameter.scoped_interface_index); 5645 } 5646 5647 return (0); 5648} 5649 5650ifnet_t 5651necp_get_ifnet_from_result_parameter(necp_kernel_policy_result_parameter *result_parameter) 5652{ 5653 if (result_parameter == NULL) { 5654 return (NULL); 5655 } 5656 5657 return (ifindex2ifnet[result_parameter->tunnel_interface_index]); 5658} 5659 5660bool 5661necp_packet_can_rebind_to_ifnet(struct mbuf *packet, struct ifnet *interface, struct route *new_route, int family) 5662{ 5663 bool found_match = FALSE; 5664 errno_t result = 0; 5665 ifaddr_t *addresses = NULL; 5666 union necp_sockaddr_union address_storage; 5667 int i; 5668 5669 if (packet == NULL || interface == NULL || new_route == NULL || (family != AF_INET && family != AF_INET6)) { 5670 return (FALSE); 5671 } 5672 5673 result = ifnet_get_address_list_family(interface, &addresses, family); 5674 if (result != 0) { 5675 NECPLOG(LOG_ERR, "Failed to get address list for %s%d", ifnet_name(interface), ifnet_unit(interface)); 5676 return (FALSE); 5677 } 5678 5679 for (i = 0; addresses[i] != NULL; i++) { 5680 ROUTE_RELEASE(new_route); 5681 if (ifaddr_address(addresses[i], &address_storage.sa, sizeof(address_storage)) == 0) { 5682 if (family == AF_INET) { 5683 struct ip *ip = mtod(packet, struct ip *); 5684 if (memcmp(&address_storage.sin.sin_addr, &ip->ip_src, sizeof(ip->ip_src)) == 0) { 5685 struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)&new_route->ro_dst; 5686 dst4->sin_family = AF_INET; 5687 dst4->sin_len = sizeof(struct sockaddr_in); 5688 dst4->sin_addr = ip->ip_dst; 5689 rtalloc_scoped(new_route, interface->if_index); 5690 if (!ROUTE_UNUSABLE(new_route)) { 5691 found_match = TRUE; 5692 goto done; 5693 } 5694 } 5695 } else if (family == AF_INET6) { 5696 struct ip6_hdr *ip6 = mtod(packet, struct ip6_hdr *); 5697 if (memcmp(&address_storage.sin6.sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)) == 0) { 5698 struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)&new_route->ro_dst; 5699 dst6->sin6_family = AF_INET6; 5700 dst6->sin6_len = sizeof(struct sockaddr_in6); 5701 dst6->sin6_addr = ip6->ip6_dst; 5702 rtalloc_scoped(new_route, interface->if_index); 5703 if (!ROUTE_UNUSABLE(new_route)) { 5704 found_match = TRUE; 5705 goto done; 5706 } 5707 } 5708 } 5709 } 5710 } 5711 5712done: 5713 ifnet_free_address_list(addresses); 5714 addresses = NULL; 5715 return (found_match); 5716} 5717 5718static bool 5719necp_addr_is_loopback(struct sockaddr *address) 5720{ 5721 if (address == NULL) { 5722 return (FALSE); 5723 } 5724 5725 if (address->sa_family == AF_INET) { 5726 return (ntohl(((struct sockaddr_in *)(void *)address)->sin_addr.s_addr) == INADDR_LOOPBACK); 5727 } else if (address->sa_family == AF_INET6) { 5728 return IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6 *)(void *)address)->sin6_addr); 5729 } 5730 5731 return (FALSE); 5732} 5733 5734static bool 5735necp_is_loopback(struct sockaddr *local_addr, struct sockaddr *remote_addr, struct inpcb *inp, struct mbuf *packet) 5736{ 5737 // Note: This function only checks for the loopback addresses. 5738 // In the future, we may want to expand to also allow any traffic 5739 // going through the loopback interface, but until then, this 5740 // check is cheaper. 5741 5742 if (local_addr != NULL && necp_addr_is_loopback(local_addr)) { 5743 return (TRUE); 5744 } 5745 5746 if (remote_addr != NULL && necp_addr_is_loopback(remote_addr)) { 5747 return (TRUE); 5748 } 5749 5750 if (inp != NULL) { 5751 if ((inp->inp_flags & INP_BOUND_IF) && inp->inp_boundifp && (inp->inp_boundifp->if_flags & IFF_LOOPBACK)) { 5752 return (TRUE); 5753 } 5754 if (inp->inp_vflag & INP_IPV4) { 5755 if (ntohl(inp->inp_laddr.s_addr) == INADDR_LOOPBACK || 5756 ntohl(inp->inp_faddr.s_addr) == INADDR_LOOPBACK) { 5757 return (TRUE); 5758 } 5759 } else if (inp->inp_vflag & INP_IPV6) { 5760 if (IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr) || 5761 IN6_IS_ADDR_LOOPBACK(&inp->in6p_faddr)) { 5762 return (TRUE); 5763 } 5764 } 5765 } 5766 5767 if (packet != NULL) { 5768 struct ip *ip = mtod(packet, struct ip *); 5769 if (ip->ip_v == 4) { 5770 if (ntohl(ip->ip_src.s_addr) == INADDR_LOOPBACK) { 5771 return (TRUE); 5772 } 5773 if (ntohl(ip->ip_dst.s_addr) == INADDR_LOOPBACK) { 5774 return (TRUE); 5775 } 5776 } else if (ip->ip_v == 6) { 5777 struct ip6_hdr *ip6 = mtod(packet, struct ip6_hdr *); 5778 if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src)) { 5779 return (TRUE); 5780 } 5781 if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) { 5782 return (TRUE); 5783 } 5784 } 5785 } 5786 5787 return (FALSE); 5788} 5789