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