1/*
2 * Copyright (c) 2006-2013 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 OR NON-INFRINGEMENT.  Please see the
18 * License for the specific language governing rights and limitations
19 * under the License."
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <string.h>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/un.h>
28#include <fcntl.h>
29#include <stdint.h>
30#include <stdlib.h>
31#include <errno.h>
32#include <unistd.h>
33#include <Block.h>
34#include <dispatch/dispatch.h>
35#include <os/assumes.h>
36#include <xpc/xpc.h>
37#include <syslog.h>
38#include <asl_private.h>
39
40static uint8_t *b64charset = (uint8_t *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
41
42static int
43asl_is_utf8_char(const unsigned char *p, int *state, int *ctype)
44{
45	switch (*state)
46	{
47		case 0:
48		{
49			*ctype = 0;
50
51			if (*p >= 0x80)
52			{
53				*state = 1;
54				if ((*p >= 0xc2) && (*p <= 0xdf)) *ctype = 1;
55				else if (*p == 0xe0) *ctype = 2;
56				else if ((*p >= 0xe1) && (*p <= 0xef)) *ctype = 3;
57				else if (*p == 0xf0) *ctype = 4;
58				else if ((*p >= 0xf1) && (*p <= 0xf3)) *ctype = 5;
59				else if (*p == 0xf4) *ctype = 6;
60				else return 0;
61			}
62
63			break;
64		}
65
66		case 1:
67		{
68			switch (*ctype)
69			{
70				case 1:
71				{
72					if ((*p >= 0x80) && (*p <= 0xbf)) *state = 0;
73					else return 0;
74					break;
75				}
76
77				case 2:
78				{
79					if ((*p >= 0xa0) && (*p <= 0xbf)) *state = 2;
80					else return 0;
81					break;
82				}
83
84				case 3:
85				{
86					if ((*p >= 0x80) && (*p <= 0xbf)) *state = 2;
87					else return 0;
88					break;
89				}
90
91				case 4:
92				{
93					if ((*p >= 0x90) && (*p <= 0xbf)) *state = 2;
94					else return 0;
95					break;
96				}
97
98				case 5:
99				{
100					if ((*p >= 0x80) && (*p <= 0xbf)) *state = 2;
101					else return 0;
102					break;
103				}
104
105				case 6:
106				{
107					if ((*p >= 0x80) && (*p <= 0x8f)) *state = 2;
108					else return 0;
109					break;
110				}
111
112				default: return 0;
113			}
114
115			break;
116		}
117
118		case 2:
119		{
120			if ((*ctype >= 2) && (*ctype <= 3))
121			{
122				if ((*p >= 0x80) && (*p <= 0xbf)) *state = 0;
123				else return 0;
124			}
125			else if ((*ctype >= 4) && (*ctype <= 6))
126			{
127				if ((*p >= 0x80) && (*p <= 0xbf)) *state = 3;
128				else return 0;
129			}
130			else
131			{
132				return 0;
133			}
134
135			break;
136		}
137
138		case 3:
139		{
140			if ((*ctype >= 4) && (*ctype <= 6))
141			{
142				if ((*p >= 0x80) && (*p <= 0xbf)) *state = 0;
143				else return 0;
144			}
145			else
146			{
147				return 0;
148			}
149
150			break;
151		}
152
153		default: return 0;
154	}
155
156	return 1;
157}
158
159__private_extern__ int
160asl_is_utf8(const char *str)
161{
162	const unsigned char *p;
163	int flag = 1;
164	int state = 0;
165	int ctype = 0;
166
167	if (str == NULL) return flag;
168
169	for (p = (const unsigned char *)str; (*p != '\0') && (flag == 1); p++)
170	{
171		flag = asl_is_utf8_char(p, &state, &ctype);
172	}
173
174	return flag;
175}
176
177__private_extern__ uint8_t *
178asl_b64_encode(const uint8_t *buf, size_t len)
179{
180	uint8_t *out;
181	uint8_t b;
182	size_t i0, i1, i2, j, outlen;
183
184	if (buf == NULL) return NULL;
185	if (len == 0) return NULL;
186
187	outlen = ((len + 2) / 3) * 4;
188	out = (uint8_t *)malloc(outlen + 1);
189	if (out == NULL)
190	{
191		errno = ENOMEM;
192		return NULL;
193	}
194
195	out[outlen] = 0;
196
197	i0 = 0;
198	i1 = 1;
199	i2 = 2;
200	j = 0;
201
202	while (i2 < len)
203	{
204		b = buf[i0] >> 2;
205		out[j++] = b64charset[b];
206
207		b = ((buf[i0] & 0x03) << 4) | (buf[i1] >> 4);
208		out[j++] = b64charset[b];
209
210		b = ((buf[i1] & 0x0f) << 2) | ((buf[i2] & 0xc0) >> 6);
211		out[j++] = b64charset[b];
212
213		b = buf[i2] & 0x3f;
214		out[j++] = b64charset[b];
215
216		i0 += 3;
217		i1 = i0 + 1;
218		i2 = i1 + 1;
219	}
220
221	if (i0 < len)
222	{
223		b = buf[i0] >> 2;
224		out[j++] = b64charset[b];
225
226		b = (buf[i0] & 0x03) << 4;
227
228		if (i1 < len) b |= (buf[i1] >> 4);
229		out[j++] = b64charset[b];
230
231		if (i1 >= len)
232		{
233			out[j++] = '=';
234			out[j++] = '=';
235			return out;
236		}
237
238		b = (buf[i1] & 0x0f) << 2;
239		out[j++] = b64charset[b];
240		out[j++] = '=';
241	}
242
243	return out;
244}
245
246int
247asl_syslog_faciliy_name_to_num(const char *name)
248{
249	if (name == NULL) return -1;
250
251	if (strcaseeq(name, "auth")) return LOG_AUTH;
252	if (strcaseeq(name, "authpriv")) return LOG_AUTHPRIV;
253	if (strcaseeq(name, "cron")) return LOG_CRON;
254	if (strcaseeq(name, "daemon")) return LOG_DAEMON;
255	if (strcaseeq(name, "ftp")) return LOG_FTP;
256	if (strcaseeq(name, "install")) return LOG_INSTALL;
257	if (strcaseeq(name, "kern")) return LOG_KERN;
258	if (strcaseeq(name, "lpr")) return LOG_LPR;
259	if (strcaseeq(name, "mail")) return LOG_MAIL;
260	if (strcaseeq(name, "netinfo")) return LOG_NETINFO;
261	if (strcaseeq(name, "remoteauth")) return LOG_REMOTEAUTH;
262	if (strcaseeq(name, "news")) return LOG_NEWS;
263	if (strcaseeq(name, "security")) return LOG_AUTH;
264	if (strcaseeq(name, "syslog")) return LOG_SYSLOG;
265	if (strcaseeq(name, "user")) return LOG_USER;
266	if (strcaseeq(name, "uucp")) return LOG_UUCP;
267	if (strcaseeq(name, "local0")) return LOG_LOCAL0;
268	if (strcaseeq(name, "local1")) return LOG_LOCAL1;
269	if (strcaseeq(name, "local2")) return LOG_LOCAL2;
270	if (strcaseeq(name, "local3")) return LOG_LOCAL3;
271	if (strcaseeq(name, "local4")) return LOG_LOCAL4;
272	if (strcaseeq(name, "local5")) return LOG_LOCAL5;
273	if (strcaseeq(name, "local6")) return LOG_LOCAL6;
274	if (strcaseeq(name, "local7")) return LOG_LOCAL7;
275	if (strcaseeq(name, "launchd")) return LOG_LAUNCHD;
276
277	return -1;
278}
279
280const char *
281asl_syslog_faciliy_num_to_name(int n)
282{
283	if (n < 0) return NULL;
284
285	if (n == LOG_AUTH) return "auth";
286	if (n == LOG_AUTHPRIV) return "authpriv";
287	if (n == LOG_CRON) return "cron";
288	if (n == LOG_DAEMON) return "daemon";
289	if (n == LOG_FTP) return "ftp";
290	if (n == LOG_INSTALL) return "install";
291	if (n == LOG_KERN) return "kern";
292	if (n == LOG_LPR) return "lpr";
293	if (n == LOG_MAIL) return "mail";
294	if (n == LOG_NETINFO) return "netinfo";
295	if (n == LOG_REMOTEAUTH) return "remoteauth";
296	if (n == LOG_NEWS) return "news";
297	if (n == LOG_AUTH) return "security";
298	if (n == LOG_SYSLOG) return "syslog";
299	if (n == LOG_USER) return "user";
300	if (n == LOG_UUCP) return "uucp";
301	if (n == LOG_LOCAL0) return "local0";
302	if (n == LOG_LOCAL1) return "local1";
303	if (n == LOG_LOCAL2) return "local2";
304	if (n == LOG_LOCAL3) return "local3";
305	if (n == LOG_LOCAL4) return "local4";
306	if (n == LOG_LOCAL5) return "local5";
307	if (n == LOG_LOCAL6) return "local6";
308	if (n == LOG_LOCAL7) return "local7";
309	if (n == LOG_LAUNCHD) return "launchd";
310
311	return NULL;
312}
313
314static xpc_connection_t
315_create_aslmanager_connection(void)
316{
317	xpc_connection_t connection;
318
319	connection = xpc_connection_create_mach_service(ASLMANAGER_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
320	xpc_connection_set_event_handler(connection, ^(xpc_object_t xobj) { if (xobj != NULL) {}; });
321	xpc_connection_resume(connection);
322
323	return connection;
324}
325
326int
327asl_trigger_aslmanager(void)
328{
329	xpc_connection_t connection = _create_aslmanager_connection();
330	if (connection == NULL) return -1;
331
332	xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
333	if (request == NULL) return -1;
334
335	xpc_object_t reply = xpc_connection_send_message_with_reply_sync(connection, request);
336
337	if (reply != NULL) xpc_release(reply);
338	xpc_release(request);
339	xpc_release(connection);
340	return 0;
341}
342