]> git.saurik.com Git - apple/syslog.git/blame - syslogd.tproj/dbserver.c
syslog-217.1.4.tar.gz
[apple/syslog.git] / syslogd.tproj / dbserver.c
CommitLineData
57b0aad2 1/*
81582353 2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
57b0aad2
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
81582353
A
24#include <TargetConditionals.h>
25
5dd30d76
A
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <sys/socket.h>
32#include <sys/un.h>
33#include <sys/ipc.h>
34#include <sys/mman.h>
35#include <sys/fcntl.h>
36#include <sys/signal.h>
57b0aad2 37#include <sys/errno.h>
5dd30d76
A
38#include <mach/mach.h>
39#include <mach/mach_error.h>
c4fdb7d1 40#include <bsm/libbsm.h>
5dd30d76
A
41#include <errno.h>
42#include <netinet/in.h>
a83ff38a 43#include <netinet/tcp.h>
5dd30d76
A
44#include <sys/event.h>
45#include <servers/bootstrap.h>
46#include <pthread.h>
47#include <notify.h>
48#include <sys/time.h>
81582353
A
49#include <xpc/xpc.h>
50#include <xpc/private.h>
51#include <libproc.h>
52#include <uuid/uuid.h>
db78b1bd 53#include "daemon.h"
a83ff38a
A
54#include "asl_ipc.h"
55#include "asl_ipcServer.h"
5dd30d76
A
56
57#define forever for(;;)
58
59#define LIST_SIZE_DELTA 256
5dd30d76
A
60
61#define SEND_NOTIFICATION 0xfadefade
62
63#define QUERY_FLAG_SEARCH_REVERSE 0x00000001
64#define SEARCH_FORWARD 1
65#define SEARCH_BACKWARD -1
66
db78b1bd
A
67#define MAX_AGAIN 100
68
81582353
A
69#define ASL_ENTITLEMENT_KEY "com.apple.asl.access_as_root"
70#define ASL_ENTITLEMENT_UID_KEY "com.apple.asl.access_as_uid"
71#define ASL_ENTITLEMENT_GID_KEY "com.apple.asl.access_as_gid"
72
db78b1bd 73static dispatch_queue_t asl_server_queue;
81582353
A
74static dispatch_queue_t watch_queue;
75static dispatch_once_t watch_init_once;
5dd30d76
A
76
77extern char *asl_list_to_string(asl_search_result_t *list, uint32_t *outlen);
78extern asl_search_result_t *asl_list_from_string(const char *buf);
57b0aad2 79extern boolean_t asl_ipc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
c4fdb7d1 80extern uint32_t bb_convert(const char *name);
5dd30d76 81
c4fdb7d1
A
82static task_name_t *client_tasks = NULL;
83static uint32_t client_tasks_count = 0;
5dd30d76 84
a83ff38a
A
85static int *direct_watch = NULL;
86/* N.B. ports are in network byte order */
87static uint16_t *direct_watch_port = NULL;
88static uint32_t direct_watch_count = 0;
89
5dd30d76
A
90typedef union
91{
92 mach_msg_header_t head;
93 union __RequestUnion__asl_ipc_subsystem request;
94} asl_request_msg;
95
96typedef union
97{
98 mach_msg_header_t head;
99 union __ReplyUnion__asl_ipc_subsystem reply;
100} asl_reply_msg;
101
db78b1bd
A
102static void
103db_asl_open(uint32_t dbtype)
57b0aad2
A
104{
105 uint32_t status;
106 struct stat sb;
107
db78b1bd 108 if ((dbtype & DB_TYPE_FILE) && (global.file_db == NULL))
57b0aad2
A
109 {
110 memset(&sb, 0, sizeof(struct stat));
111 if (stat(PATH_ASL_STORE, &sb) == 0)
112 {
113 /* must be a directory */
a83ff38a 114 if (!S_ISDIR(sb.st_mode))
57b0aad2
A
115 {
116 asldebug("error: %s is not a directory", PATH_ASL_STORE);
117 return;
118 }
119 }
120 else
121 {
122 if (errno == ENOENT)
123 {
124 /* /var/log/asl doesn't exist - create it */
125 if (mkdir(PATH_ASL_STORE, 0755) != 0)
126 {
127 asldebug("error: can't create data store %s: %s\n", PATH_ASL_STORE, strerror(errno));
128 return;
c4fdb7d1 129 }
57b0aad2
A
130 }
131 else
132 {
133 /* stat failed for some other reason */
134 asldebug("error: can't stat data store %s: %s\n", PATH_ASL_STORE, strerror(errno));
135 return;
136 }
137 }
138
c4fdb7d1
A
139 /*
140 * One-time store conversion from the old "LongTTL" style to the new "Best Before" style.
141 * bb_convert returns quickly if the store has already been converted.
142 */
143 status = bb_convert(PATH_ASL_STORE);
144 if (status != ASL_STATUS_OK)
145 {
146 asldebug("ASL data store conversion failed!: %s\n", asl_core_error(status));
147 }
148
57b0aad2
A
149 status = asl_store_open_write(NULL, &(global.file_db));
150 if (status != ASL_STATUS_OK)
151 {
152 asldebug("asl_store_open_write: %s\n", asl_core_error(status));
153 }
154 else
155 {
156 if (global.db_file_max != 0) asl_store_max_file_size(global.file_db, global.db_file_max);
81582353 157 asl_trigger_aslmanager();
57b0aad2
A
158 }
159 }
160
db78b1bd 161 if ((dbtype & DB_TYPE_MEMORY) && (global.memory_db == NULL))
57b0aad2
A
162 {
163 status = asl_memory_open(global.db_memory_max, &(global.memory_db));
164 if (status != ASL_STATUS_OK)
165 {
166 asldebug("asl_memory_open: %s\n", asl_core_error(status));
167 }
168 }
169
db78b1bd 170 if ((dbtype & DB_TYPE_MINI) && (global.mini_db == NULL))
57b0aad2
A
171 {
172 status = asl_mini_memory_open(global.db_mini_max, &(global.mini_db));
173 if (status != ASL_STATUS_OK)
174 {
175 asldebug("asl_mini_memory_open: %s\n", asl_core_error(status));
176 }
177 }
178}
179
5dd30d76 180void
81582353
A
181add_lockdown_session(int fd)
182{
183 dispatch_once(&watch_init_once, ^{
184 watch_queue = dispatch_queue_create("Direct Watch Queue", NULL);
185 });
186
187 dispatch_async(watch_queue, ^{
188 if (global.lockdown_session_count == 0) global.lockdown_session_fds = NULL;
189
190 global.lockdown_session_fds = reallocf(global.lockdown_session_fds, global.lockdown_session_count + 1 * sizeof(int));
191
192 if (global.lockdown_session_fds == NULL)
193 {
194 asldebug("add_lockdown_session: realloc failed\n");
195 global.lockdown_session_count = 0;
196 }
197 else
198 {
199 global.lockdown_session_fds[global.lockdown_session_count++] = fd;
200 }
201
202 global.watchers_active = direct_watch_count + global.lockdown_session_count;
203 });
204}
205
206void
207remove_lockdown_session(int fd)
208{
209 dispatch_once(&watch_init_once, ^{
210 watch_queue = dispatch_queue_create("Direct Watch Queue", NULL);
211 });
212
213 dispatch_async(watch_queue, ^{
214 int i, n;
215
216 for (i = 0, n = 0; i < global.lockdown_session_count; i++)
217 {
218 if (global.lockdown_session_fds[i] == fd)
219 {
220 }
221 else
222 {
223 if (i != n) global.lockdown_session_fds[n] = global.lockdown_session_fds[i];
224 n++;
225 }
226 }
227
228 if (n == 0)
229 {
230 free(global.lockdown_session_fds);
231 global.lockdown_session_fds = NULL;
232 global.lockdown_session_count = 0;
233 }
234 else
235 {
236 global.lockdown_session_fds = reallocf(global.lockdown_session_fds, n * sizeof(int));
237 if (global.lockdown_session_fds == NULL)
238 {
239 asldebug("remove_lockdown_session: realloc failed\n");
240 global.lockdown_session_count = 0;
241 }
242 else
243 {
244 global.lockdown_session_count = n;
245 }
246 }
247
248 global.watchers_active = direct_watch_count + global.lockdown_session_count;
249 });
250}
251
252#ifdef LOCKDOWN
253static void
254sweep_lockdown_session_fds()
255{
256 int i, n;
257
258 for (i = 0, n = 0; i < global.lockdown_session_count; i++)
259 {
260 if (global.lockdown_session_fds[i] >= 0)
261 {
262 if (i != n) global.lockdown_session_fds[n] = global.lockdown_session_fds[i];
263 n++;
264 }
265 }
266
267 if (n == 0)
268 {
269 free(global.lockdown_session_fds);
270 global.lockdown_session_fds = NULL;
271 global.lockdown_session_count = 0;
272 }
273 else
274 {
275 global.lockdown_session_fds = reallocf(global.lockdown_session_fds, n * sizeof(int));
276 if (global.lockdown_session_fds == NULL)
277 {
278 asldebug("sweep_lockdown_session_fds: realloc failed\n");
279 global.lockdown_session_count = 0;
280 }
281 else
282 {
283 global.lockdown_session_count = n;
284 }
285 }
286
287 global.watchers_active = direct_watch_count + global.lockdown_session_count;
288}
289#endif
290
291static void
292_internal_send_to_direct_watchers(asl_msg_t *msg)
5dd30d76 293{
db78b1bd
A
294 uint32_t i, j, nlen, outlen, cleanup, total_sent, again;
295 ssize_t sent;
296 char *out;
5dd30d76 297
db78b1bd
A
298#ifdef LOCKDOWN
299 static struct timeval last_time;
5dd30d76 300
81582353
A
301 cleanup = 0;
302
303 if (global.lockdown_session_count > 0)
5dd30d76 304 {
db78b1bd 305 if (global.remote_delay_time > 0)
c4fdb7d1 306 {
db78b1bd
A
307 struct timeval now;
308 uint64_t delta;
81582353 309
db78b1bd 310 if (gettimeofday(&now, NULL) == 0)
c4fdb7d1 311 {
db78b1bd
A
312 if (last_time.tv_sec != 0)
313 {
314 if (now.tv_sec > last_time.tv_sec)
315 {
316 now.tv_sec -= 1;
317 now.tv_usec += 1000000;
318 }
81582353 319
db78b1bd
A
320 delta = now.tv_sec - last_time.tv_sec;
321 delta *= 1000000;
322 delta += (now.tv_usec - last_time.tv_usec);
323 if (delta < global.remote_delay_time)
324 {
325 usleep(delta);
326 }
327 }
5dd30d76 328
db78b1bd
A
329 if (now.tv_usec >= 1000000)
330 {
331 now.tv_sec += 1;
332 now.tv_usec -= 1000000;
333 }
c4fdb7d1 334
db78b1bd
A
335 last_time = now;
336 }
c4fdb7d1
A
337 }
338
a83ff38a 339 out = asl_format_message(msg, ASL_MSG_FMT_STD, ASL_TIME_FMT_LCL, ASL_ENCODE_SAFE, &outlen);
81582353
A
340
341 for (i = 0; i < global.lockdown_session_count; i++)
a83ff38a 342 {
81582353
A
343 if (write(global.lockdown_session_fds[i], out, outlen) < 0)
344 {
345 asldebug("send_to_direct_watchers: lockdown %d write error: %d %s\n", global.lockdown_session_fds[i], errno, strerror(errno));
346 close(global.lockdown_session_fds[i]);
347 global.lockdown_session_fds[i] = -1;
348 cleanup = 1;
349 }
a83ff38a
A
350 }
351
352 free(out);
353 }
81582353
A
354
355 if (cleanup != 0) sweep_lockdown_session_fds();
a83ff38a
A
356#endif
357
db78b1bd
A
358 if (direct_watch_count == 0)
359 {
360 direct_watch = NULL;
361 return;
362 }
363
364 if (direct_watch == NULL)
365 {
366 direct_watch_count = 0;
367 return;
368 }
a83ff38a
A
369
370 cleanup = 0;
371 out = asl_msg_to_string(msg, &outlen);
372
373 if (out == NULL) return;
374
375 nlen = htonl(outlen);
376 for (i = 0; i < direct_watch_count; i++)
377 {
378 sent = send(direct_watch[i], &nlen, sizeof(nlen), 0);
379 if (sent < sizeof(nlen))
380 {
381 /* bail out if we can't send 4 bytes */
382 close(direct_watch[i]);
383 direct_watch[i] = -1;
384 cleanup = 1;
385 }
386 else
387 {
388 total_sent = 0;
db78b1bd
A
389 again = 0;
390
a83ff38a
A
391 while (total_sent < outlen)
392 {
db78b1bd 393 errno = 0;
a83ff38a 394 sent = send(direct_watch[i], out + total_sent, outlen - total_sent, 0);
db78b1bd 395 if (sent <= 0)
a83ff38a 396 {
db78b1bd
A
397 asldebug("send_to_direct_watchers: send returned %d (errno %d)\n", sent, errno);
398 if (errno == EAGAIN)
399 {
400 if (again > MAX_AGAIN)
401 {
402 asldebug("send_to_direct_watchers: exceeded EAGAIN limit - closing connection\n");
403 break;
404 }
405 else
406 {
407 again++;
408 errno = 0;
409 continue;
410 }
411 }
412
a83ff38a
A
413 close(direct_watch[i]);
414 direct_watch[i] = -1;
415 cleanup = 1;
416 break;
417 }
418
419 total_sent += sent;
420 }
421 }
422 }
423
424 free(out);
425
426 if (cleanup == 0) return;
427
428 j = 0;
429 for (i = 0; i < direct_watch_count; i++)
430 {
431 if (direct_watch[i] >= 0)
432 {
433 if (j != i)
434 {
435 direct_watch[j] = direct_watch[i];
436 direct_watch_port[j] = direct_watch_port[i];
437 j++;
438 }
439 }
440 }
441
442 direct_watch_count = j;
443 if (direct_watch_count == 0)
444 {
445 free(direct_watch);
446 direct_watch = NULL;
447
448 free(direct_watch_port);
449 direct_watch_port = NULL;
450 }
451 else
452 {
453 direct_watch = reallocf(direct_watch, direct_watch_count * sizeof(int));
454 direct_watch_port = reallocf(direct_watch_port, direct_watch_count * sizeof(uint16_t));
455 if ((direct_watch == NULL) || (direct_watch_port == NULL))
456 {
457 free(direct_watch);
458 direct_watch = NULL;
459
460 free(direct_watch_port);
461 direct_watch_port = NULL;
462
463 direct_watch_count = 0;
464 }
c4fdb7d1
A
465 }
466}
467
81582353
A
468void
469send_to_direct_watchers(asl_msg_t *msg)
470{
471 dispatch_once(&watch_init_once, ^{
472 watch_queue = dispatch_queue_create("Direct Watch Queue", NULL);
473 });
474
475 asl_msg_retain(msg);
476
477 dispatch_async(watch_queue, ^{
478 _internal_send_to_direct_watchers(msg);
479 asl_msg_release(msg);
480 });
481}
482
c4fdb7d1
A
483/*
484 * Called from asl_action.c to save messgaes to the ASL data store
485 */
486void
a83ff38a 487db_save_message(aslmsg msg)
c4fdb7d1
A
488{
489 uint64_t msgid;
db78b1bd
A
490 uint32_t status, dbtype;
491 static int armed;
492 static dispatch_source_t timer_src;
493 static dispatch_once_t once;
494
495 dispatch_once(&once, ^{
496 timer_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
497 dispatch_source_set_event_handler(timer_src, ^{
498 notify_post(kNotifyASLDBUpdate);
499 dispatch_suspend(timer_src);
500 armed = 0;
501 });
502 armed = 0;
503 });
c4fdb7d1 504
a83ff38a
A
505 send_to_direct_watchers((asl_msg_t *)msg);
506
db78b1bd
A
507 dbtype = global.dbtype;
508
509 if (asl_check_option(msg, ASL_OPT_DB_FILE)) dbtype |= DB_TYPE_FILE;
510 if (asl_check_option(msg, ASL_OPT_DB_MINI)) dbtype |= DB_TYPE_MINI;
511 if (asl_check_option(msg, ASL_OPT_DB_MEMORY)) dbtype |= DB_TYPE_MEMORY;
c4fdb7d1 512
db78b1bd 513 db_asl_open(dbtype);
5dd30d76 514
db78b1bd 515 if (dbtype & DB_TYPE_FILE)
c4fdb7d1
A
516 {
517 status = asl_store_save(global.file_db, msg);
518 if (status != ASL_STATUS_OK)
519 {
520 /* write failed - reopen & retry */
521 asldebug("asl_store_save: %s\n", asl_core_error(status));
522 asl_store_close(global.file_db);
523 global.file_db = NULL;
524
db78b1bd 525 db_asl_open(dbtype);
c4fdb7d1
A
526 status = asl_store_save(global.file_db, msg);
527 if (status != ASL_STATUS_OK)
5dd30d76 528 {
c4fdb7d1
A
529 asldebug("(retry) asl_store_save: %s\n", asl_core_error(status));
530 asl_store_close(global.file_db);
531 global.file_db = NULL;
532
533 global.dbtype |= DB_TYPE_MEMORY;
db78b1bd 534 dbtype |= DB_TYPE_MEMORY;
c4fdb7d1 535 if (global.memory_db == NULL)
5dd30d76 536 {
c4fdb7d1 537 status = asl_memory_open(global.db_memory_max, &(global.memory_db));
57b0aad2
A
538 if (status != ASL_STATUS_OK)
539 {
c4fdb7d1 540 asldebug("asl_memory_open: %s\n", asl_core_error(status));
57b0aad2 541 }
5dd30d76 542 }
57b0aad2 543 }
c4fdb7d1
A
544 }
545 }
5dd30d76 546
db78b1bd 547 if (dbtype & DB_TYPE_MEMORY)
c4fdb7d1
A
548 {
549 msgid = 0;
550 status = asl_memory_save(global.memory_db, msg, &msgid);
551 if (status != ASL_STATUS_OK)
552 {
553 /* save failed - reopen & retry*/
554 asldebug("asl_memory_save: %s\n", asl_core_error(status));
555 asl_memory_close(global.memory_db);
556 global.memory_db = NULL;
557
db78b1bd 558 db_asl_open(dbtype);
c4fdb7d1
A
559 msgid = 0;
560 status = asl_memory_save(global.memory_db, msg, &msgid);
561 if (status != ASL_STATUS_OK)
57b0aad2 562 {
c4fdb7d1
A
563 asldebug("(retry) asl_memory_save: %s\n", asl_core_error(status));
564 asl_memory_close(global.memory_db);
565 global.memory_db = NULL;
5dd30d76 566 }
c4fdb7d1
A
567 }
568 }
5dd30d76 569
db78b1bd 570 if (dbtype & DB_TYPE_MINI)
c4fdb7d1
A
571 {
572 status = asl_mini_memory_save(global.mini_db, msg, &msgid);
573 if (status != ASL_STATUS_OK)
574 {
575 /* save failed - reopen & retry*/
576 asldebug("asl_mini_memory_save: %s\n", asl_core_error(status));
577 asl_mini_memory_close(global.mini_db);
578 global.mini_db = NULL;
579
db78b1bd 580 db_asl_open(dbtype);
c4fdb7d1
A
581 status = asl_mini_memory_save(global.mini_db, msg, &msgid);
582 if (status != ASL_STATUS_OK)
5dd30d76 583 {
c4fdb7d1
A
584 asldebug("(retry) asl_memory_save: %s\n", asl_core_error(status));
585 asl_mini_memory_close(global.mini_db);
586 global.mini_db = NULL;
5dd30d76
A
587 }
588 }
c4fdb7d1 589 }
5dd30d76 590
db78b1bd
A
591 if (armed == 0)
592 {
593 armed = 1;
81582353 594 dispatch_source_set_timer(timer_src, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2), DISPATCH_TIME_FOREVER, 0);
db78b1bd
A
595 dispatch_resume(timer_src);
596 }
5dd30d76
A
597}
598
57b0aad2 599void
a83ff38a 600disaster_message(aslmsg msg)
5dd30d76 601{
57b0aad2
A
602 uint64_t msgid;
603 uint32_t status;
5dd30d76 604
57b0aad2 605 msgid = 0;
5dd30d76 606
57b0aad2 607 if ((global.dbtype & DB_TYPE_MINI) == 0)
5dd30d76 608 {
57b0aad2 609 if (global.mini_db == NULL)
5dd30d76 610 {
57b0aad2
A
611 status = asl_mini_memory_open(global.db_mini_max, &(global.mini_db));
612 if (status != ASL_STATUS_OK) asldebug("asl_mini_memory_open: %s\n", asl_core_error(status));
613 else asl_mini_memory_save(global.mini_db, msg, &msgid);
5dd30d76 614 }
5dd30d76 615 }
5dd30d76
A
616}
617
618/*
619 * Do a database search.
620 */
621uint32_t
81582353 622db_query(aslresponse query, aslresponse *res, uint64_t startid, int count, int flags, uint64_t *lastid, int32_t ruid, int32_t rgid, int raccess)
5dd30d76
A
623{
624 uint32_t status, ucount;
625 int32_t dir;
81582353
A
626 uuid_string_t ustr;
627 struct proc_uniqidentifierinfo pinfo;
628 const char *str = NULL;
5dd30d76 629
e125da38
A
630 /*
631 * Special case: if count is -1, we return ASL_STATUS_OK to indicate that the store is
632 * in memory, and ASL_STATUS_INVALID_STORE to indicate that the file store is in use.
633 */
634 if (count == -1)
635 {
81582353
A
636 if (global.dbtype & DB_TYPE_FILE) return ASL_STATUS_INVALID_STORE;
637 return ASL_STATUS_OK;
638 }
639
640 if (raccess != 0)
641 {
642 str = "NO ACCESS";
643 uuid_clear(pinfo.p_uuid);
644 if (proc_pidinfo(raccess, PROC_PIDUNIQIDENTIFIERINFO, 1, &pinfo, sizeof(pinfo)) == sizeof(pinfo))
645 {
646 uuid_unparse(pinfo.p_uuid, ustr);
647 str = (const char *)ustr;
648 }
e125da38
A
649 }
650
5dd30d76
A
651 ucount = count;
652 dir = SEARCH_FORWARD;
653 if (flags & QUERY_FLAG_SEARCH_REVERSE) dir = SEARCH_BACKWARD;
654
57b0aad2 655 status = ASL_STATUS_FAILED;
5dd30d76 656
e125da38
A
657 if (global.dbtype & DB_TYPE_MEMORY)
658 {
81582353 659 status = asl_memory_match_restricted_uuid(global.memory_db, query, res, lastid, startid, ucount, dir, ruid, rgid, str);
e125da38
A
660 }
661 else if (global.dbtype & DB_TYPE_MINI)
662 {
81582353 663 status = asl_mini_memory_match_restricted_uuid(global.mini_db, query, res, lastid, startid, ucount, dir, ruid, rgid, str);
e125da38
A
664 }
665 else if (global.disaster_occurred != 0)
666 {
667 /* KernelEventAgent calls us to get the kernel disaster messages. */
81582353 668 status = asl_mini_memory_match_restricted_uuid(global.mini_db, query, res, lastid, startid, ucount, dir, ruid, rgid, str);
e125da38 669 }
5dd30d76 670
5dd30d76
A
671 return status;
672}
673
c4fdb7d1
A
674static void
675register_session(task_name_t task_name, pid_t pid)
676{
677 mach_port_t previous;
678 uint32_t i;
679
680 if (task_name == MACH_PORT_NULL) return;
c4fdb7d1 681
a83ff38a
A
682 if (global.dead_session_port == MACH_PORT_NULL)
683 {
684 mach_port_deallocate(mach_task_self(), task_name);
685 return;
686 }
687
688 for (i = 0; i < client_tasks_count; i++) if (task_name == client_tasks[i])
689 {
690 mach_port_deallocate(mach_task_self(), task_name);
691 return;
692 }
c4fdb7d1
A
693
694 if (client_tasks_count == 0) client_tasks = (task_name_t *)calloc(1, sizeof(task_name_t));
695 else client_tasks = (task_name_t *)reallocf(client_tasks, (client_tasks_count + 1) * sizeof(task_name_t));
696
a83ff38a
A
697 if (client_tasks == NULL)
698 {
699 mach_port_deallocate(mach_task_self(), task_name);
700 return;
701 }
702
c4fdb7d1
A
703 client_tasks[client_tasks_count] = task_name;
704 client_tasks_count++;
705
706 asldebug("register_session: %u PID %d\n", (unsigned int)task_name, (int)pid);
707
708 /* register for port death notification */
709 mach_port_request_notification(mach_task_self(), task_name, MACH_NOTIFY_DEAD_NAME, 0, global.dead_session_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
710 mach_port_deallocate(mach_task_self(), previous);
711
712 asl_client_count_increment();
713}
714
715static void
716cancel_session(task_name_t task_name)
717{
718 uint32_t i;
719
720 for (i = 0; (i < client_tasks_count) && (task_name != client_tasks[i]); i++);
721
722 if (i >= client_tasks_count) return;
723
724 if (client_tasks_count == 1)
725 {
726 free(client_tasks);
727 client_tasks = NULL;
728 client_tasks_count = 0;
729 }
730 else
731 {
732 for (i++; i < client_tasks_count; i++) client_tasks[i-1] = client_tasks[i];
733 client_tasks_count--;
734 client_tasks = (task_name_t *)reallocf(client_tasks, client_tasks_count * sizeof(task_name_t));
735 }
736
737 asldebug("cancel_session: %u\n", (unsigned int)task_name);
a83ff38a
A
738
739 /* we hold a send right or dead name right for the task name port */
740 mach_port_deallocate(mach_task_self(), task_name);
c4fdb7d1
A
741 asl_client_count_decrement();
742}
743
a83ff38a
A
744static uint32_t
745register_direct_watch(uint16_t port)
746{
81582353 747#if TARGET_OS_EMBEDDED
a83ff38a
A
748 uint32_t i;
749 int sock, flags;
750 struct sockaddr_in address;
751
752 if (port == 0) return ASL_STATUS_FAILED;
753
754 sock = socket(AF_INET, SOCK_STREAM, 0);
755 if (sock < 0) return ASL_STATUS_FAILED;
756
757 address.sin_family = AF_INET;
758 /* port must be sent in network byte order */
759 address.sin_port = port;
760 address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
761
762 if (connect(sock, (struct sockaddr*)&address, sizeof(address)) != 0) return ASL_STATUS_FAILED;
763
764 i = 1;
765 setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof(i));
766
767 i = 1;
768 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(i));
769
770 /* make socket non-blocking */
771 flags = fcntl(sock, F_GETFL, 0);
772 if (flags == -1) flags = 0;
773 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
774
775 if (direct_watch_count == 0)
776 {
777 direct_watch = (int *)calloc(1, sizeof(int));
778 direct_watch_port = (uint16_t *)calloc(1, sizeof(uint16_t));
779 }
780 else
781 {
782 direct_watch = (int *)reallocf(direct_watch, (direct_watch_count + 1) * sizeof(int));
783 direct_watch_port = (uint16_t *)reallocf(direct_watch_port, (direct_watch_count + 1) * sizeof(uint16_t));
784 }
785
786 if ((direct_watch == NULL) || (direct_watch_port == NULL))
787 {
788 close(sock);
789
790 free(direct_watch);
791 direct_watch = NULL;
792
793 free(direct_watch_port);
794 direct_watch_port = NULL;
795
796 direct_watch_count = 0;
797 global.watchers_active = 0;
81582353 798 if (global.lockdown_session_count > 0) global.watchers_active = 1;
a83ff38a
A
799
800 return ASL_STATUS_FAILED;
801 }
802
803 direct_watch[direct_watch_count] = sock;
804 direct_watch_port[direct_watch_count] = port;
805 direct_watch_count++;
81582353 806 global.watchers_active = direct_watch_count + global.lockdown_session_count;
a83ff38a
A
807
808 return ASL_STATUS_OK;
db78b1bd
A
809#else
810 return ASL_STATUS_FAILED;
811#endif
a83ff38a
A
812}
813
814static void
815cancel_direct_watch(uint16_t port)
816{
81582353 817#if TARGET_OS_EMBEDDED
a83ff38a
A
818 uint32_t i;
819
820 for (i = 0; (i < direct_watch_count) && (port != direct_watch_port[i]); i++);
821
822 if (i >= direct_watch_count) return;
823
824 if (direct_watch_count == 1)
825 {
826 free(direct_watch);
827 direct_watch = NULL;
828
829 free(direct_watch_port);
830 direct_watch_port = NULL;
831
832 direct_watch_count = 0;
833 global.watchers_active = 0;
81582353 834 if (global.lockdown_session_count > 0) global.watchers_active = 1;
a83ff38a
A
835 }
836 else
837 {
838 for (i++; i < direct_watch_count; i++)
839 {
840 direct_watch[i-1] = direct_watch[i];
841 direct_watch_port[i-1] = direct_watch_port[i];
842 }
843
844 direct_watch_count--;
81582353 845 global.watchers_active = direct_watch_count + global.lockdown_session_count;
a83ff38a
A
846
847 direct_watch = (int *)reallocf(direct_watch, direct_watch_count * sizeof(int));
848 direct_watch_port = (uint16_t *)reallocf(direct_watch_port, direct_watch_count * sizeof(uint16_t));
849
850 if ((direct_watch == NULL) || (direct_watch_port == NULL))
851 {
852 free(direct_watch);
853 direct_watch = NULL;
854
855 free(direct_watch_port);
856 direct_watch_port = NULL;
857
858 direct_watch_count = 0;
859 global.watchers_active = 0;
81582353
A
860 if (global.lockdown_session_count > 0) global.watchers_active = 1;
861 }
862 }
863#endif
864}
865
866static int
867syslogd_state_query(asl_msg_t *q, aslresponse *res, uid_t uid)
868{
869 asl_search_result_t *out;
870 uint32_t i, n;
871 bool all = false;
872 aslmsg m;
873 char val[256];
874 const char *mval;
875 asl_out_module_t *om;
876
877 if (res == NULL) return ASL_STATUS_INVALID_ARG;
878 *res = NULL;
879
880 out = (asl_search_result_t *)calloc(1, sizeof(asl_search_result_t));
881 if (out == NULL) return ASL_STATUS_NO_MEMORY;
882
883 m = asl_new(ASL_TYPE_MSG);
884 if (m == NULL)
885 {
886 free(out);
887 return ASL_STATUS_NO_MEMORY;
888 }
889
890 out->count = 1;
891 out->msg = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
892 if (out->msg == NULL)
893 {
894 free(out);
895 asl_free(m);
896 return ASL_STATUS_NO_MEMORY;
897 }
898
899 out->msg[0] = (asl_msg_t *)m;
900
901 /* q must have [ASLOption control], so a "null" query really has count == 1 */
902 if (asl_msg_count(q) == 1) all = true;
903
904 if (all || (0 == asl_msg_lookup(q, "debug", NULL, NULL)))
905 {
906 if (global.debug == 0) snprintf(val, sizeof(val), "0");
907 else snprintf(val, sizeof(val), "1 %s", global.debug_file);
908 asl_set(m, "debug", val);
909 }
910
911 if (all || (0 == asl_msg_lookup(q, "dbtype", NULL, NULL)))
912 {
913 n = 0;
914 if (global.dbtype & DB_TYPE_FILE) n++;
915 if (global.dbtype & DB_TYPE_MEMORY) n++;
916 if (global.dbtype & DB_TYPE_MINI) n++;
917
918 if (n == 0)
919 {
920 asl_set(m, "dbtype", "unknown");
921 }
922 else
923 {
924 i = 0;
925 memset(val, 0, sizeof(val));
926
927 if (global.dbtype & DB_TYPE_FILE)
928 {
929 i++;
930 strncat(val, "file", 4);
931 if (i < n) strncat(val, " ", 1);
932 }
933
934 if (global.dbtype & DB_TYPE_MEMORY)
935 {
936 i++;
937 strncat(val, "memory", 6);
938 if (i < n) strncat(val, " ", 1);
939 }
940
941 if (global.dbtype & DB_TYPE_MINI)
942 {
943 strncat(val, "mini-memory", 11);
944 }
945
946 asl_set(m, "dbtype", val);
a83ff38a
A
947 }
948 }
81582353
A
949
950 if (all || (0 == asl_msg_lookup(q, "db_file_max", NULL, NULL)))
951 {
952 snprintf(val, sizeof(val), "%u", global.db_file_max);
953 asl_set(m, "db_file_max", val);
954 }
955
956 if (all || (0 == asl_msg_lookup(q, "db_memory_max", NULL, NULL)))
957 {
958 snprintf(val, sizeof(val), "%u", global.db_memory_max);
959 asl_set(m, "db_memory_max", val);
960 }
961
962 if (all || (0 == asl_msg_lookup(q, "db_mini_max", NULL, NULL)))
963 {
964 snprintf(val, sizeof(val), "%u", global.db_mini_max);
965 asl_set(m, "db_mini_max", val);
966 }
967
968 if (all || (0 == asl_msg_lookup(q, "mps_limit", NULL, NULL)))
969 {
970 snprintf(val, sizeof(val), "%u", global.mps_limit);
971 asl_set(m, "mps_limit", val);
972 }
973
974 if (all || (0 == asl_msg_lookup(q, "bsd_max_dup_time", NULL, NULL)))
975 {
976 snprintf(val, sizeof(val), "%llu", global.bsd_max_dup_time);
977 asl_set(m, "bsd_max_dup_time", val);
978 }
979
980 if (all || (0 == asl_msg_lookup(q, "mark_time", NULL, NULL)))
981 {
982 snprintf(val, sizeof(val), "%llu", global.mark_time);
983 asl_set(m, "mark_time", val);
984 }
985
986 if (all || (0 == asl_msg_lookup(q, "utmp_ttl", NULL, NULL)))
987 {
988 snprintf(val, sizeof(val), "%lu", global.utmp_ttl);
989 asl_set(m, "utmp_ttl", val);
990 }
991
992 if (all || (0 == asl_msg_lookup(q, "work_queue_count", NULL, NULL)))
993 {
994 snprintf(val, sizeof(val), "%d", global.work_queue_count);
995 asl_set(m, "work_queue_count", val);
996 }
997
998 if (all || (0 == asl_msg_lookup(q, "asl_queue_count", NULL, NULL)))
999 {
1000 snprintf(val, sizeof(val), "%d", global.asl_queue_count);
1001 asl_set(m, "asl_queue_count", val);
1002 }
1003
1004 if (all || (0 == asl_msg_lookup(q, "bsd_queue_count", NULL, NULL)))
1005 {
1006 snprintf(val, sizeof(val), "%d", global.bsd_queue_count);
1007 asl_set(m, "bsd_queue_count", val);
1008 }
1009
1010 if (all || (0 == asl_msg_lookup(q, "client_count", NULL, NULL)))
1011 {
1012 snprintf(val, sizeof(val), "%d", global.client_count);
1013 asl_set(m, "client_count", val);
1014 }
1015
1016 if (all || (0 == asl_msg_lookup(q, "disaster_occurred", NULL, NULL)))
1017 {
1018 snprintf(val, sizeof(val), "%d", global.disaster_occurred);
1019 asl_set(m, "disaster_occurred", val);
1020 }
1021
1022#ifdef LOCKDOWN
1023 if (all || (0 == asl_msg_lookup(q, "lockdown_session_count", NULL, NULL)))
1024 {
1025 snprintf(val, sizeof(val), "%d", global.lockdown_session_count);
1026 asl_set(m, "lockdown_session_count", val);
1027 }
1028
1029 if (all || (0 == asl_msg_lookup(q, "remote_delay_time", NULL, NULL)))
1030 {
1031 snprintf(val, sizeof(val), "%u", global.remote_delay_time);
1032 asl_set(m, "remote_delay_time", val);
1033 }
1034
db78b1bd 1035#endif
81582353
A
1036
1037 if (all || (0 == asl_msg_lookup(q, "watchers_active", NULL, NULL)))
1038 {
1039 snprintf(val, sizeof(val), "%d", global.watchers_active);
1040 asl_set(m, "watchers_active", val);
1041 }
1042
1043 for (i = 0; i < global.module_count; i++)
1044 {
1045 if (all || (0 == asl_msg_lookup(q, global.module[i]->name, NULL, NULL)))
1046 {
1047 snprintf(val, sizeof(val), "%s", global.module[i]->enabled ? "enabled" : "disabled");
1048 asl_set(m, global.module[i]->name, val);
1049 }
1050 }
1051
1052 for (om = global.asl_out_module; om != NULL; om = om->next)
1053 {
1054 if (all || (0 == asl_msg_lookup(q, om->name, NULL, NULL)))
1055 {
1056 snprintf(val, sizeof(val), "%s", om->flags & MODULE_FLAG_ENABLED ? "enabled" : "disabled");
1057 if (om->name == NULL) asl_set(m, "asl.conf", val);
1058 else asl_set(m, om->name, val);
1059 }
1060 }
1061
1062 /* synchronous actions use queries, since messages are simpleroutines */
1063 if (0 == asl_msg_lookup(q, "action", &mval, NULL))
1064 {
1065 int res = -1;
1066 if (uid == 0) res = asl_action_control_set_param(mval);
1067 snprintf(val, sizeof(val), "%d", res);
1068 asl_set(m, "action", val);
1069 }
1070
1071 *res = out;
1072 return ASL_STATUS_OK;
a83ff38a
A
1073}
1074
5dd30d76
A
1075/*
1076 * Receives messages on the "com.apple.system.logger" mach port.
57b0aad2 1077 * Services database search requests.
5dd30d76
A
1078 * Runs in it's own thread.
1079 */
1080void
1081database_server()
1082{
5dd30d76 1083 asl_request_msg *request;
db78b1bd 1084 uint32_t rqs;
5dd30d76 1085 uint32_t rbits, sbits;
db78b1bd 1086 uint32_t flags;
5dd30d76 1087 struct timeval now, send_time;
c4fdb7d1 1088 mach_dead_name_notification_t *deadname;
5dd30d76
A
1089
1090 send_time.tv_sec = 0;
1091 send_time.tv_usec = 0;
1092
1093 rqs = sizeof(asl_request_msg) + MAX_TRAILER_SIZE;
5dd30d76 1094
c4fdb7d1 1095 rbits = MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
5dd30d76
A
1096 sbits = MACH_SEND_MSG | MACH_SEND_TIMEOUT;
1097
db78b1bd
A
1098 asl_server_queue = dispatch_queue_create("ASL Server Queue", NULL);
1099
5dd30d76
A
1100 forever
1101 {
5dd30d76
A
1102 now.tv_sec = 0;
1103 now.tv_usec = 0;
1104
5dd30d76
A
1105 request = (asl_request_msg *)calloc(1, rqs);
1106 if (request == NULL) continue;
1107
57b0aad2 1108 request->head.msgh_local_port = global.server_port;
5dd30d76
A
1109 request->head.msgh_size = rqs;
1110
5dd30d76 1111 flags = rbits;
5dd30d76 1112
db78b1bd 1113 (void)mach_msg(&(request->head), flags, 0, rqs, global.listen_set, 0, MACH_PORT_NULL);
5dd30d76 1114
c4fdb7d1
A
1115 if (request->head.msgh_id == MACH_NOTIFY_DEAD_NAME)
1116 {
1117 deadname = (mach_dead_name_notification_t *)request;
db78b1bd
A
1118 dispatch_async(asl_server_queue, ^{
1119 cancel_session(deadname->not_port);
1120 /* dead name notification includes a dead name right */
1121 mach_port_deallocate(mach_task_self(), deadname->not_port);
1122 free(request);
1123 });
a83ff38a 1124
c4fdb7d1
A
1125 continue;
1126 }
1127
db78b1bd
A
1128 dispatch_async(asl_server_queue, ^{
1129 kern_return_t ks;
1130 asl_reply_msg *reply = calloc(1, sizeof(asl_reply_msg) + MAX_TRAILER_SIZE);
81582353 1131
db78b1bd
A
1132 asl_ipc_server(&(request->head), &(reply->head));
1133 ks = mach_msg(&(reply->head), sbits, reply->head.msgh_size, 0, MACH_PORT_NULL, 10, MACH_PORT_NULL);
1134 free(reply);
1135 if ((ks == MACH_SEND_INVALID_DEST) || (ks == MACH_SEND_TIMED_OUT))
1136 {
1137 /* clean up */
1138 mach_msg_destroy(&(reply->head));
1139 }
5dd30d76 1140
db78b1bd
A
1141 free(request);
1142 });
5dd30d76
A
1143 }
1144}
1145
81582353
A
1146static void
1147caller_get_read_entitlement(pid_t pid, uid_t *uid, gid_t *gid)
1148{
1149#if TARGET_OS_EMBEDDED
1150 xpc_object_t edata, entitlements, val;
1151 bool bval = false;
1152 int64_t ival = -2;
1153 size_t len;
1154 const void *ptr;
1155
1156 edata = xpc_copy_entitlements_for_pid(pid);
1157 if (edata == NULL) return;
1158
1159 ptr = xpc_data_get_bytes_ptr(edata);
1160 len = xpc_data_get_length(edata);
1161
1162 entitlements = xpc_create_from_plist(ptr, len);
1163 xpc_release(edata);
1164 if (entitlements == NULL) return;
1165
1166 if (xpc_get_type(entitlements) != XPC_TYPE_DICTIONARY)
1167 {
1168 asldebug("xpc_copy_entitlements_for_pid has non-dictionary data for pid %d\n", pid);
1169 return;
1170 }
1171
1172 bval = xpc_dictionary_get_bool(entitlements, ASL_ENTITLEMENT_KEY);
1173 if (bval && (uid != NULL))
1174 {
1175 *uid = 0;
1176 xpc_release(entitlements);
1177 return;
1178 }
1179
1180 val = xpc_dictionary_get_value(entitlements, ASL_ENTITLEMENT_UID_KEY);
1181 if (val != NULL)
1182 {
1183 if ((xpc_get_type(val) == XPC_TYPE_INT64) && (uid != NULL))
1184 {
1185 ival = xpc_int64_get_value(val);
1186 *uid = ival;
1187 }
1188 }
1189
1190 val = xpc_dictionary_get_value(entitlements, ASL_ENTITLEMENT_GID_KEY);
1191 if (val != NULL)
1192 {
1193 if ((xpc_get_type(val) == XPC_TYPE_INT64) && (gid != NULL))
1194 {
1195 ival = xpc_int64_get_value(val);
1196 *gid = ival;
1197 }
1198 }
1199
1200 xpc_release(entitlements);
1201#endif
1202}
1203
1204static kern_return_t
1205__asl_server_query_internal
5dd30d76 1206(
c4fdb7d1
A
1207 mach_port_t server,
1208 caddr_t request,
1209 mach_msg_type_number_t requestCnt,
1210 uint64_t startid,
1211 int count,
1212 int flags,
1213 caddr_t *reply,
1214 mach_msg_type_number_t *replyCnt,
1215 uint64_t *lastid,
1216 int *status,
81582353
A
1217 uid_t uid,
1218 gid_t gid,
1219 pid_t pid
5dd30d76
A
1220)
1221{
1222 aslresponse query;
1223 aslresponse res;
1224 char *out, *vmbuffer;
1225 uint32_t outlen;
1226 kern_return_t kstatus;
1227
1228 *status = ASL_STATUS_OK;
a83ff38a
A
1229
1230 if ((request != NULL) && (request[requestCnt - 1] != '\0'))
1231 {
1232 *status = ASL_STATUS_INVALID_ARG;
1233 vm_deallocate(mach_task_self(), (vm_address_t)request, requestCnt);
1234 return KERN_SUCCESS;
1235 }
1236
5dd30d76 1237 query = asl_list_from_string(request);
a83ff38a 1238 if (request != NULL) vm_deallocate(mach_task_self(), (vm_address_t)request, requestCnt);
5dd30d76
A
1239 res = NULL;
1240
81582353
A
1241 /* A query list containing a single query, which itself contains
1242 * [ASLOption control] is an internal state query */
1243 if ((query != NULL) && (query->count == 1) && asl_check_option((aslmsg)query->msg[0], ASL_OPT_CONTROL))
1244 {
1245 *status = syslogd_state_query(query->msg[0], &res, uid);
1246 }
1247 else
1248 {
1249 int x = 0;
1250#if TARGET_OS_EMBEDDED
1251 x = pid;
1252#endif
1253
1254 if (pid > 0)
1255 {
1256 caller_get_read_entitlement(pid, &uid, &gid);
1257 if (uid == 0) x = 0;
1258 }
1259
1260 *status = db_query(query, &res, startid, count, flags, lastid, uid, gid, x);
1261 }
57b0aad2
A
1262
1263 aslresponse_free(query);
e125da38
A
1264 if (*status != ASL_STATUS_INVALID_STORE)
1265 {
1266 /* ignore */
1267 }
1268 else if (*status != ASL_STATUS_OK)
5dd30d76 1269 {
57b0aad2
A
1270 if (res != NULL) aslresponse_free(res);
1271 return KERN_SUCCESS;
5dd30d76 1272 }
5dd30d76 1273
57b0aad2
A
1274 out = NULL;
1275 outlen = 0;
1276 out = asl_list_to_string((asl_search_result_t *)res, &outlen);
1277 aslresponse_free(res);
5dd30d76
A
1278
1279 if ((out == NULL) || (outlen == 0)) return KERN_SUCCESS;
1280
1281 kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&vmbuffer, outlen, TRUE);
1282 if (kstatus != KERN_SUCCESS)
1283 {
1284 free(out);
1285 return kstatus;
1286 }
1287
1288 memmove(vmbuffer, out, outlen);
1289 free(out);
1290
1291 *reply = vmbuffer;
1292 *replyCnt = outlen;
1293
1294 return KERN_SUCCESS;
1295}
1296
81582353
A
1297kern_return_t
1298__asl_server_query_2
1299(
1300 mach_port_t server,
1301 caddr_t request,
1302 mach_msg_type_number_t requestCnt,
1303 uint64_t startid,
1304 int count,
1305 int flags,
1306 caddr_t *reply,
1307 mach_msg_type_number_t *replyCnt,
1308 uint64_t *lastid,
1309 int *status,
1310 audit_token_t token
1311)
1312{
1313 uid_t uid = (uid_t)-1;
1314 gid_t gid = (gid_t)-1;
1315 pid_t pid = (pid_t)-1;
1316
1317 audit_token_to_au32(token, NULL, &uid, &gid, NULL, NULL, &pid, NULL, NULL);
1318
1319 return __asl_server_query_internal(server, request, requestCnt, startid, count, flags, reply, replyCnt, lastid, status, uid, gid, pid);
1320}
1321kern_return_t
1322__asl_server_query
1323(
1324 mach_port_t server,
1325 caddr_t request,
1326 mach_msg_type_number_t requestCnt,
1327 uint64_t startid,
1328 int count,
1329 int flags,
1330 caddr_t *reply,
1331 mach_msg_type_number_t *replyCnt,
1332 uint64_t *lastid,
1333 int *status,
1334 security_token_t *token
1335)
1336{
1337 return __asl_server_query_internal(server, request, requestCnt, startid, count, flags, reply, replyCnt, lastid, status, (uid_t)token->val[0], (gid_t)token->val[1], (pid_t)-1);
1338}
1339
5dd30d76
A
1340
1341kern_return_t
1342__asl_server_query_timeout
1343(
c4fdb7d1
A
1344 mach_port_t server,
1345 caddr_t request,
1346 mach_msg_type_number_t requestCnt,
1347 uint64_t startid,
1348 int count,
1349 int flags,
1350 caddr_t *reply,
1351 mach_msg_type_number_t *replyCnt,
1352 uint64_t *lastid,
1353 int *status,
1354 security_token_t *token
81582353 1355)
5dd30d76 1356{
81582353 1357 return __asl_server_query_internal(server, request, requestCnt, startid, count, flags, reply, replyCnt, lastid, status, (uid_t)token->val[0], (gid_t)token->val[1], (pid_t)-1);
5dd30d76
A
1358}
1359
1360kern_return_t
1361__asl_server_prune
1362(
1363 mach_port_t server,
1364 caddr_t request,
1365 mach_msg_type_number_t requestCnt,
1366 int *status,
1367 security_token_t *token
1368)
1369{
5dd30d76
A
1370 return KERN_SUCCESS;
1371}
c4fdb7d1
A
1372
1373kern_return_t
1374__asl_server_message
1375(
1376 mach_port_t server,
1377 caddr_t message,
1378 mach_msg_type_number_t messageCnt,
1379 audit_token_t token
1380)
1381{
a83ff38a 1382 aslmsg msg;
c4fdb7d1
A
1383 char tmp[64];
1384 uid_t uid;
1385 gid_t gid;
1386 pid_t pid;
1387 kern_return_t kstatus;
1388 mach_port_name_t client;
1389
a83ff38a
A
1390 if (message == NULL)
1391 {
1392 return KERN_SUCCESS;
1393 }
1394
1395 if (message[messageCnt - 1] != '\0')
1396 {
1397 vm_deallocate(mach_task_self(), (vm_address_t)message, messageCnt);
1398 return KERN_SUCCESS;
1399 }
1400
c4fdb7d1
A
1401 asldebug("__asl_server_message: %s\n", (message == NULL) ? "NULL" : message);
1402
a83ff38a 1403 msg = (aslmsg)asl_msg_from_string(message);
c4fdb7d1
A
1404 vm_deallocate(mach_task_self(), (vm_address_t)message, messageCnt);
1405
a83ff38a
A
1406 if (msg == NULL) return KERN_SUCCESS;
1407
c4fdb7d1
A
1408 uid = (uid_t)-1;
1409 gid = (gid_t)-1;
db78b1bd 1410 pid = (pid_t)-1;
c4fdb7d1
A
1411 audit_token_to_au32(token, NULL, &uid, &gid, NULL, NULL, &pid, NULL, NULL);
1412
1413 client = MACH_PORT_NULL;
1414 kstatus = task_name_for_pid(mach_task_self(), pid, &client);
1415 if (kstatus == KERN_SUCCESS) register_session(client, pid);
1416
c4fdb7d1 1417 snprintf(tmp, sizeof(tmp), "%d", uid);
a83ff38a 1418 asl_set(msg, ASL_KEY_UID, tmp);
c4fdb7d1
A
1419
1420 snprintf(tmp, sizeof(tmp), "%d", gid);
a83ff38a 1421 asl_set(msg, ASL_KEY_GID, tmp);
c4fdb7d1
A
1422
1423 snprintf(tmp, sizeof(tmp), "%d", pid);
a83ff38a 1424 asl_set(msg, ASL_KEY_PID, tmp);
c4fdb7d1 1425
81582353 1426 process_message(msg, SOURCE_ASL_MESSAGE);
a83ff38a
A
1427
1428 return KERN_SUCCESS;
1429}
1430
1431kern_return_t
1432__asl_server_create_aux_link
1433(
1434 mach_port_t server,
1435 caddr_t message,
1436 mach_msg_type_number_t messageCnt,
1437 mach_port_t *fileport,
1438 caddr_t *newurl,
1439 mach_msg_type_number_t *newurlCnt,
1440 int *status,
1441 audit_token_t token
1442)
1443{
1444 aslmsg msg;
1445 char tmp[64];
1446 uid_t uid;
1447 gid_t gid;
1448 pid_t pid;
1449 kern_return_t kstatus;
1450 mach_port_name_t client;
1451 char *url, *vmbuffer;
1452 int fd;
1453
1454 *status = ASL_STATUS_OK;
1455
1456 if (message == NULL)
1457 {
1458 *status = ASL_STATUS_INVALID_ARG;
1459 return KERN_SUCCESS;
1460 }
1461
1462 if (message[messageCnt - 1] != '\0')
1463 {
1464 *status = ASL_STATUS_INVALID_ARG;
1465 vm_deallocate(mach_task_self(), (vm_address_t)message, messageCnt);
1466 return KERN_SUCCESS;
1467 }
1468
1469 asldebug("__asl_server_create_aux_link: %s\n", (message == NULL) ? "NULL" : message);
1470
1471 if ((global.dbtype & DB_TYPE_FILE) == 0)
1472 {
1473 *status = ASL_STATUS_INVALID_STORE;
1474 return KERN_SUCCESS;
1475 }
1476
1477 *fileport = MACH_PORT_NULL;
1478
1479 msg = (aslmsg)asl_msg_from_string(message);
1480 vm_deallocate(mach_task_self(), (vm_address_t)message, messageCnt);
1481
1482 if (msg == NULL) return KERN_SUCCESS;
1483
1484 uid = (uid_t)-1;
1485 gid = (gid_t)-1;
db78b1bd 1486 pid = (pid_t)-1;
a83ff38a
A
1487 audit_token_to_au32(token, NULL, &uid, &gid, NULL, NULL, &pid, NULL, NULL);
1488
1489 client = MACH_PORT_NULL;
1490 kstatus = task_name_for_pid(mach_task_self(), pid, &client);
1491 if (kstatus == KERN_SUCCESS) register_session(client, pid);
1492
1493 snprintf(tmp, sizeof(tmp), "%d", uid);
1494 asl_set(msg, ASL_KEY_UID, tmp);
1495
1496 snprintf(tmp, sizeof(tmp), "%d", gid);
1497 asl_set(msg, ASL_KEY_GID, tmp);
1498
1499 snprintf(tmp, sizeof(tmp), "%d", pid);
1500 asl_set(msg, ASL_KEY_PID, tmp);
1501
1502 /* create a file for the client */
1503 *status = asl_store_open_aux(global.file_db, msg, &fd, &url);
1504 asl_free(msg);
1505 if (*status != ASL_STATUS_OK) return KERN_SUCCESS;
1506 if (url == NULL)
1507 {
1508 if (fd >= 0) close(fd);
1509 *status = ASL_STATUS_FAILED;
1510 return KERN_SUCCESS;
1511 }
1512
1513 if (fileport_makeport(fd, (fileport_t *)fileport) < 0)
1514 {
1515 close(fd);
1516 free(url);
1517 *status = ASL_STATUS_FAILED;
1518 return KERN_SUCCESS;
1519 }
1520
1521 close(fd);
1522
1523 *newurlCnt = strlen(url) + 1;
1524
1525 kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&vmbuffer, *newurlCnt, TRUE);
1526 if (kstatus != KERN_SUCCESS)
1527 {
1528 free(url);
1529 return kstatus;
1530 }
1531
1532 memmove(vmbuffer, url, *newurlCnt);
1533 free(url);
81582353
A
1534
1535 *newurl = vmbuffer;
1536
a83ff38a
A
1537 return KERN_SUCCESS;
1538}
1539
1540kern_return_t
1541__asl_server_register_direct_watch
1542(
1543 mach_port_t server,
1544 int port,
1545 audit_token_t token
1546)
1547{
1548 uint16_t p16 = port;
db78b1bd
A
1549 pid_t pid = (pid_t)-1;
1550
1551 audit_token_to_au32(token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
a83ff38a 1552
db78b1bd 1553 asldebug("__asl_server_register_direct_watch: pid %u port %hu\n", pid, ntohs(p16));
a83ff38a 1554
81582353
A
1555 dispatch_once(&watch_init_once, ^{
1556 watch_queue = dispatch_queue_create("Direct Watch Queue", NULL);
1557 });
1558
1559 dispatch_async(watch_queue, ^{ register_direct_watch(p16); });
a83ff38a
A
1560
1561 return KERN_SUCCESS;
1562}
1563
1564kern_return_t
1565__asl_server_cancel_direct_watch
1566(
1567 mach_port_t server,
1568 int port,
1569 audit_token_t token
1570)
1571{
1572 uint16_t p16 = port;
1573
1574 asldebug("__asl_server_cancel_direct_watch: %hu\n", ntohs(p16));
1575
81582353
A
1576 dispatch_once(&watch_init_once, ^{
1577 watch_queue = dispatch_queue_create("Direct Watch Queue", NULL);
1578 });
1579
1580 dispatch_async(watch_queue, ^{ cancel_direct_watch(p16); });
c4fdb7d1
A
1581
1582 return KERN_SUCCESS;
1583}