]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/content_filter.h
xnu-6153.81.5.tar.gz
[apple/xnu.git] / bsd / net / content_filter.h
CommitLineData
fe8ab488 1/*
cb323159 2 * Copyright (c) 2013-2019 Apple Inc. All rights reserved.
fe8ab488
A
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#ifndef __CONTENT_FILTER_H__
0a7de745 25#define __CONTENT_FILTER_H__
fe8ab488
A
26
27#include <sys/param.h>
28#include <sys/types.h>
3e170ce0 29#include <sys/_types/_timeval64.h>
fe8ab488
A
30#include <sys/socket.h>
31#include <sys/syslog.h>
32#include <netinet/in.h>
33#include <stdint.h>
cb323159 34#include <corecrypto/ccsha2.h>
fe8ab488
A
35
36#ifdef BSD_KERNEL_PRIVATE
37#include <sys/mbuf.h>
38#include <sys/socketvar.h>
39#endif /* BSD_KERNEL_PRIVATE */
40
41__BEGIN_DECLS
42
43#ifdef PRIVATE
44
45/*
46 * Kernel control name for an instance of a Content Filter
47 * Use CTLIOCGINFO to find out the corresponding kernel control id
48 * to be set in the sc_id field of sockaddr_ctl for connect(2)
49 * Note: the sc_unit is ephemeral
50 */
0a7de745 51#define CONTENT_FILTER_CONTROL_NAME "com.apple.content-filter"
fe8ab488 52
5ba3f43e
A
53/*
54 * Opaque socket identifier
55 */
56typedef uint64_t cfil_sock_id_t;
57
0a7de745 58#define CFIL_SOCK_ID_NONE UINT64_MAX
5ba3f43e
A
59
60
fe8ab488
A
61/*
62 * CFIL_OPT_NECP_CONTROL_UNIT
63 * To set or get the NECP filter control unit for the kernel control socket
64 * The option level is SYSPROTO_CONTROL
65 */
0a7de745 66#define CFIL_OPT_NECP_CONTROL_UNIT 1 /* uint32_t */
fe8ab488 67
5ba3f43e
A
68/*
69 * CFIL_OPT_GET_SOCKET_INFO
0a7de745 70 * To get information about a given socket that is being filtered.
5ba3f43e 71 */
0a7de745 72#define CFIL_OPT_GET_SOCKET_INFO 2 /* uint32_t */
5ba3f43e
A
73
74/*
75 * struct cfil_opt_sock_info
76 *
0a7de745 77 * Contains information about a socket that is being filtered.
5ba3f43e
A
78 */
79struct cfil_opt_sock_info {
0a7de745
A
80 cfil_sock_id_t cfs_sock_id;
81 int cfs_sock_family; /* e.g. PF_INET */
82 int cfs_sock_type; /* e.g. SOCK_STREAM */
83 int cfs_sock_protocol; /* e.g. IPPROTO_TCP */
84 union sockaddr_in_4_6 cfs_local;
85 union sockaddr_in_4_6 cfs_remote;
86 pid_t cfs_pid;
87 pid_t cfs_e_pid;
88 uuid_t cfs_uuid;
89 uuid_t cfs_e_uuid;
5ba3f43e
A
90};
91
fe8ab488
A
92/*
93 * How many filter may be active simultaneously
94 */
cb323159 95#if !TARGET_OS_OSX && !defined(XNU_TARGET_OS_OSX)
0a7de745 96#define CFIL_MAX_FILTER_COUNT 2
cb323159
A
97#else
98#define CFIL_MAX_FILTER_COUNT 8
99#endif
100
101
102/*
103 * Crypto Support
104 */
105#define CFIL_CRYPTO 1
106#define CFIL_CRYPTO_SIGNATURE_SIZE 32
107#define CFIL_CRYPTO_DATA_EVENT 1
108
109typedef uint8_t cfil_crypto_key[CCSHA256_OUTPUT_SIZE];
110typedef uint8_t cfil_crypto_signature[CFIL_CRYPTO_SIGNATURE_SIZE];
111
112typedef struct cfil_crypto_state {
113 const struct ccdigest_info *digest_info;
114 cfil_crypto_key key;
115} *cfil_crypto_state_t;
116
117typedef struct cfil_crypto_data {
118 uuid_t flow_id;
119 u_int64_t sock_id;
120 u_int32_t direction;
121 union sockaddr_in_4_6 remote;
122 union sockaddr_in_4_6 local;
123 u_int32_t socketProtocol;
124 pid_t pid;
125 pid_t effective_pid;
126 uuid_t uuid;
127 uuid_t effective_uuid;
128 u_int64_t byte_count_in;
129 u_int64_t byte_count_out;
130} *cfil_crypto_data_t;
fe8ab488
A
131
132/*
133 * Types of messages
134 *
135 * Event messages flow from kernel to user space while action
136 * messages flow in the reverse direction.
137 * A message in entirely represented by a packet sent or received
138 * on a Content Filter kernel control socket.
139 */
0a7de745
A
140#define CFM_TYPE_EVENT 1 /* message from kernel */
141#define CFM_TYPE_ACTION 2 /* message to kernel */
fe8ab488
A
142
143/*
144 * Operations associated with events from kernel
145 */
0a7de745
A
146#define CFM_OP_SOCKET_ATTACHED 1 /* a socket has been attached */
147#define CFM_OP_SOCKET_CLOSED 2 /* a socket is being closed */
148#define CFM_OP_DATA_OUT 3 /* data being sent */
149#define CFM_OP_DATA_IN 4 /* data being received */
150#define CFM_OP_DISCONNECT_OUT 5 /* no more outgoing data */
151#define CFM_OP_DISCONNECT_IN 6 /* no more incoming data */
fe8ab488
A
152
153/*
154 * Operations associated with action from filter to kernel
155 */
0a7de745
A
156#define CFM_OP_DATA_UPDATE 16 /* update pass or peek offsets */
157#define CFM_OP_DROP 17 /* shutdown socket, no more data */
158#define CFM_OP_BLESS_CLIENT 18 /* mark a client flow as already filtered, passes a uuid */
cb323159 159#define CFM_OP_SET_CRYPTO_KEY 19 /* assign client crypto key for message signing */
fe8ab488 160
fe8ab488
A
161/*
162 * struct cfil_msg_hdr
163 *
164 * Header common to all messages
165 */
166struct cfil_msg_hdr {
0a7de745
A
167 uint32_t cfm_len; /* total length */
168 uint32_t cfm_version;
169 uint32_t cfm_type;
170 uint32_t cfm_op;
171 cfil_sock_id_t cfm_sock_id;
fe8ab488
A
172};
173
0a7de745 174#define CFM_VERSION_CURRENT 1
fe8ab488 175
cb323159
A
176/*
177 * Connection Direction
178 */
179#define CFS_CONNECTION_DIR_IN 0
180#define CFS_CONNECTION_DIR_OUT 1
181
182#define CFS_AUDIT_TOKEN 1
183
fe8ab488
A
184/*
185 * struct cfil_msg_sock_attached
186 *
187 * Information about a new socket being attached to the content filter
188 *
189 * Action: No reply is expected as this does not block the creation of the
190 * TCP/IP but timely action must be taken to avoid user noticeable delays.
191 *
192 * Valid Types: CFM_TYPE_EVENT
193 *
194 * Valid Op: CFM_OP_SOCKET_ATTACHED
195 */
196struct cfil_msg_sock_attached {
0a7de745
A
197 struct cfil_msg_hdr cfs_msghdr;
198 int cfs_sock_family; /* e.g. PF_INET */
199 int cfs_sock_type; /* e.g. SOCK_STREAM */
200 int cfs_sock_protocol; /* e.g. IPPROTO_TCP */
201 int cfs_unused; /* padding */
202 pid_t cfs_pid;
203 pid_t cfs_e_pid;
204 uuid_t cfs_uuid;
205 uuid_t cfs_e_uuid;
cb323159
A
206 union sockaddr_in_4_6 cfs_src;
207 union sockaddr_in_4_6 cfs_dst;
208 int cfs_conn_dir;
209 unsigned int cfs_audit_token[8]; /* Must match audit_token_t */
210 cfil_crypto_signature cfs_signature;
211 uint32_t cfs_signature_length;
fe8ab488
A
212};
213
214/*
215 * struct cfil_msg_data_event
216 *
217 * Event for the content fiter to act on a span of data
218 * A data span is described by a pair of offsets over the cumulative
219 * number of bytes sent or received on the socket.
220 *
221 * Action: The event must be acted upon but the filter may buffer
222 * data spans until it has enough content to make a decision.
223 * The action must be timely to avoid user noticeable delays.
224 *
225 * Valid Type: CFM_TYPE_EVENT
226 *
227 * Valid Ops: CFM_OP_DATA_OUT, CFM_OP_DATA_IN
228 */
229struct cfil_msg_data_event {
0a7de745
A
230 struct cfil_msg_hdr cfd_msghdr;
231 union sockaddr_in_4_6 cfc_src;
232 union sockaddr_in_4_6 cfc_dst;
233 uint64_t cfd_start_offset;
234 uint64_t cfd_end_offset;
cb323159
A
235 cfil_crypto_signature cfd_signature;
236 uint32_t cfd_signature_length;
fe8ab488
A
237 /* Actual content data immediatly follows */
238};
239
5ba3f43e
A
240#define CFI_MAX_TIME_LOG_ENTRY 6
241/*
242 * struct cfil_msg_sock_closed
243 *
244 * Information about a socket being closed to the content filter
245 *
246 * Action: No reply is expected as this does not block the closing of the
247 * TCP/IP.
248 *
249 * Valid Types: CFM_TYPE_EVENT
250 *
251 * Valid Op: CFM_OP_SOCKET_CLOSED
252 */
253struct cfil_msg_sock_closed {
0a7de745
A
254 struct cfil_msg_hdr cfc_msghdr;
255 struct timeval64 cfc_first_event;
256 uint32_t cfc_op_list_ctr;
257 uint32_t cfc_op_time[CFI_MAX_TIME_LOG_ENTRY]; /* time interval in microseconds since first event */
258 unsigned char cfc_op_list[CFI_MAX_TIME_LOG_ENTRY];
cb323159
A
259 uint64_t cfc_byte_inbound_count;
260 uint64_t cfc_byte_outbound_count;
261 cfil_crypto_signature cfc_signature;
262 uint32_t cfc_signature_length;
5ba3f43e
A
263} __attribute__((aligned(8)));
264
fe8ab488
A
265/*
266 * struct cfil_msg_action
267 *
268 * Valid Type: CFM_TYPE_ACTION
269 *
270 * Valid Ops: CFM_OP_DATA_UPDATE, CFM_OP_DROP
271 *
272 * For CFM_OP_DATA_UPDATE:
273 *
274 * cfa_in_pass_offset and cfa_out_pass_offset indicates how much data is
275 * allowed to pass. A zero value does not modify the corresponding pass offset.
276 *
277 * cfa_in_peek_offset and cfa_out_peek_offset lets the filter specify how much
278 * data it needs to make a decision: the kernel will deliver data up to that
279 * offset (if less than cfa_pass_offset it is ignored). Use CFM_MAX_OFFSET
280 * if you don't value the corresponding peek offset to be updated.
281 */
282struct cfil_msg_action {
0a7de745
A
283 struct cfil_msg_hdr cfa_msghdr;
284 uint64_t cfa_in_pass_offset;
285 uint64_t cfa_in_peek_offset;
286 uint64_t cfa_out_pass_offset;
287 uint64_t cfa_out_peek_offset;
fe8ab488
A
288};
289
5ba3f43e
A
290/*
291 * struct cfil_msg_bless_client
292 *
293 * Marks a client UUID as already filtered at a higher level.
294 *
295 * Valid Type: CFM_TYPE_ACTION
296 *
297 * Valid Ops: CFM_OP_BLESS_CLIENT
298 */
299struct cfil_msg_bless_client {
0a7de745 300 struct cfil_msg_hdr cfb_msghdr;
5ba3f43e
A
301 uuid_t cfb_client_uuid;
302};
303
cb323159
A
304/*
305 * struct cfil_msg_set_crypto_key
306 *
307 * Filter assigning client crypto key to CFIL for message signing
308 *
309 * Valid Type: CFM_TYPE_ACTION
310 *
311 * Valid Ops: CFM_OP_SET_CRYPTO_KEY
312 */
313struct cfil_msg_set_crypto_key {
314 struct cfil_msg_hdr cfb_msghdr;
315 cfil_crypto_key crypto_key;
316};
317
0a7de745 318#define CFM_MAX_OFFSET UINT64_MAX
fe8ab488
A
319
320/*
321 * Statistics retrieved via sysctl(3)
322 */
323struct cfil_filter_stat {
0a7de745
A
324 uint32_t cfs_len;
325 uint32_t cfs_filter_id;
326 uint32_t cfs_flags;
327 uint32_t cfs_sock_count;
328 uint32_t cfs_necp_control_unit;
fe8ab488
A
329};
330
331struct cfil_entry_stat {
0a7de745
A
332 uint32_t ces_len;
333 uint32_t ces_filter_id;
334 uint32_t ces_flags;
335 uint32_t ces_necp_control_unit;
336 struct timeval64 ces_last_event;
337 struct timeval64 ces_last_action;
fe8ab488 338 struct cfe_buf_stat {
0a7de745
A
339 uint64_t cbs_pending_first;
340 uint64_t cbs_pending_last;
341 uint64_t cbs_ctl_first;
342 uint64_t cbs_ctl_last;
343 uint64_t cbs_pass_offset;
344 uint64_t cbs_peek_offset;
345 uint64_t cbs_peeked;
fe8ab488
A
346 } ces_snd, ces_rcv;
347};
348
349struct cfil_sock_stat {
0a7de745
A
350 uint32_t cfs_len;
351 int cfs_sock_family;
352 int cfs_sock_type;
353 int cfs_sock_protocol;
354 cfil_sock_id_t cfs_sock_id;
355 uint64_t cfs_flags;
356 pid_t cfs_pid;
357 pid_t cfs_e_pid;
358 uuid_t cfs_uuid;
359 uuid_t cfs_e_uuid;
fe8ab488 360 struct cfi_buf_stat {
0a7de745
A
361 uint64_t cbs_pending_first;
362 uint64_t cbs_pending_last;
363 uint64_t cbs_pass_offset;
364 uint64_t cbs_inject_q_len;
fe8ab488 365 } cfs_snd, cfs_rcv;
0a7de745 366 struct cfil_entry_stat ces_entries[CFIL_MAX_FILTER_COUNT];
fe8ab488
A
367};
368
369/*
370 * Global statistics
371 */
372struct cfil_stats {
0a7de745
A
373 int32_t cfs_ctl_connect_ok;
374 int32_t cfs_ctl_connect_fail;
375 int32_t cfs_ctl_disconnect_ok;
376 int32_t cfs_ctl_disconnect_fail;
377 int32_t cfs_ctl_send_ok;
378 int32_t cfs_ctl_send_bad;
379 int32_t cfs_ctl_rcvd_ok;
380 int32_t cfs_ctl_rcvd_bad;
381 int32_t cfs_ctl_rcvd_flow_lift;
382 int32_t cfs_ctl_action_data_update;
383 int32_t cfs_ctl_action_drop;
384 int32_t cfs_ctl_action_bad_op;
385 int32_t cfs_ctl_action_bad_len;
386
387 int32_t cfs_sock_id_not_found;
388
389 int32_t cfs_cfi_alloc_ok;
390 int32_t cfs_cfi_alloc_fail;
391
392 int32_t cfs_sock_userspace_only;
393 int32_t cfs_sock_attach_in_vain;
394 int32_t cfs_sock_attach_already;
395 int32_t cfs_sock_attach_no_mem;
396 int32_t cfs_sock_attach_failed;
397 int32_t cfs_sock_attached;
398 int32_t cfs_sock_detached;
399
400 int32_t cfs_attach_event_ok;
401 int32_t cfs_attach_event_flow_control;
402 int32_t cfs_attach_event_fail;
403
404 int32_t cfs_closed_event_ok;
405 int32_t cfs_closed_event_flow_control;
406 int32_t cfs_closed_event_fail;
407
408 int32_t cfs_data_event_ok;
409 int32_t cfs_data_event_flow_control;
410 int32_t cfs_data_event_fail;
411
412 int32_t cfs_disconnect_in_event_ok;
413 int32_t cfs_disconnect_out_event_ok;
414 int32_t cfs_disconnect_event_flow_control;
415 int32_t cfs_disconnect_event_fail;
416
417 int32_t cfs_ctl_q_not_started;
fe8ab488
A
418
419 int32_t cfs_close_wait;
420 int32_t cfs_close_wait_timeout;
421
422 int32_t cfs_flush_in_drop;
423 int32_t cfs_flush_out_drop;
424 int32_t cfs_flush_in_close;
425 int32_t cfs_flush_out_close;
426 int32_t cfs_flush_in_free;
427 int32_t cfs_flush_out_free;
428
0a7de745
A
429 int32_t cfs_inject_q_nomem;
430 int32_t cfs_inject_q_nobufs;
431 int32_t cfs_inject_q_detached;
432 int32_t cfs_inject_q_in_fail;
433 int32_t cfs_inject_q_out_fail;
fe8ab488 434
0a7de745
A
435 int32_t cfs_inject_q_in_retry;
436 int32_t cfs_inject_q_out_retry;
fe8ab488
A
437
438 int32_t cfs_data_in_control;
439 int32_t cfs_data_in_oob;
440 int32_t cfs_data_out_control;
441 int32_t cfs_data_out_oob;
442
0a7de745
A
443 int64_t cfs_ctl_q_in_enqueued __attribute__((aligned(8)));
444 int64_t cfs_ctl_q_out_enqueued __attribute__((aligned(8)));
445 int64_t cfs_ctl_q_in_peeked __attribute__((aligned(8)));
446 int64_t cfs_ctl_q_out_peeked __attribute__((aligned(8)));
fe8ab488 447
0a7de745
A
448 int64_t cfs_pending_q_in_enqueued __attribute__((aligned(8)));
449 int64_t cfs_pending_q_out_enqueued __attribute__((aligned(8)));
fe8ab488 450
0a7de745
A
451 int64_t cfs_inject_q_in_enqueued __attribute__((aligned(8)));
452 int64_t cfs_inject_q_out_enqueued __attribute__((aligned(8)));
453 int64_t cfs_inject_q_in_passed __attribute__((aligned(8)));
454 int64_t cfs_inject_q_out_passed __attribute__((aligned(8)));
fe8ab488
A
455};
456#endif /* PRIVATE */
457
458#ifdef BSD_KERNEL_PRIVATE
459
0a7de745 460#define M_SKIPCFIL M_PROTO5
fe8ab488
A
461
462extern int cfil_log_level;
463
0a7de745 464#define CFIL_LOG(level, fmt, ...) \
fe8ab488
A
465do { \
466 if (cfil_log_level >= level) \
0a7de745
A
467 printf("%s:%d " fmt "\n",\
468 __FUNCTION__, __LINE__, ##__VA_ARGS__); \
fe8ab488
A
469} while (0)
470
471
472extern void cfil_init(void);
473
cb323159
A
474extern boolean_t cfil_filter_present(void);
475extern boolean_t cfil_sock_connected_pending_verdict(struct socket *so);
476extern errno_t cfil_sock_attach(struct socket *so,
477 struct sockaddr *local, struct sockaddr *remote, int dir);
fe8ab488
A
478extern errno_t cfil_sock_detach(struct socket *so);
479
480extern int cfil_sock_data_out(struct socket *so, struct sockaddr *to,
0a7de745
A
481 struct mbuf *data, struct mbuf *control,
482 uint32_t flags);
fe8ab488 483extern int cfil_sock_data_in(struct socket *so, struct sockaddr *from,
0a7de745
A
484 struct mbuf *data, struct mbuf *control,
485 uint32_t flags);
fe8ab488
A
486
487extern int cfil_sock_shutdown(struct socket *so, int *how);
488extern void cfil_sock_is_closed(struct socket *so);
489extern void cfil_sock_notify_shutdown(struct socket *so, int how);
490extern void cfil_sock_close_wait(struct socket *so);
491
492extern boolean_t cfil_sock_data_pending(struct sockbuf *sb);
493extern int cfil_sock_data_space(struct sockbuf *sb);
494extern void cfil_sock_buf_update(struct sockbuf *sb);
495
496extern cfil_sock_id_t cfil_sock_id_from_socket(struct socket *so);
497
d9a64523 498extern struct m_tag *cfil_udp_get_socket_state(struct mbuf *m, uint32_t *state_change_cnt,
0a7de745 499 short *options, struct sockaddr **faddr);
fe8ab488
A
500#endif /* BSD_KERNEL_PRIVATE */
501
5ba3f43e
A
502__END_DECLS
503
fe8ab488 504#endif /* __CONTENT_FILTER_H__ */