]> git.saurik.com Git - apple/syslog.git/blob - syslogd.tproj/asl_action.c
syslog-69.0.3.tar.gz
[apple/syslog.git] / syslogd.tproj / asl_action.c
1 /*
2 * Copyright (c) 2004-2008 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 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <sys/uio.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <netdb.h>
36 #include <notify.h>
37 #include "daemon.h"
38
39 #define _PATH_ASL_CONF "/etc/asl.conf"
40 #define MY_ID "asl_action"
41
42 #define ASL_KEY_FACILITY "Facility"
43 #define IndexNull ((uint32_t)-1)
44 #define forever for(;;)
45
46 static asl_msg_t *query = NULL;
47 static int reset = 0;
48
49 struct action_rule
50 {
51 asl_msg_t *query;
52 char *action;
53 char *options;
54 void *data;
55 TAILQ_ENTRY(action_rule) entries;
56 };
57
58 static TAILQ_HEAD(cr, action_rule) asl_action_rule;
59
60 int asl_action_close();
61 static int _parse_notify_file(const char *);
62
63 static void
64 _do_reset(void)
65 {
66 asl_action_close();
67 _parse_notify_file(_PATH_ASL_CONF);
68 }
69
70 /*
71 * Config File format:
72 * Q [k v] [k v] ... action args...
73 */
74
75 /* Skip over query */
76 static char *
77 _find_action(char *s)
78 {
79 char *p;
80
81 p = s;
82 if (p == NULL) return NULL;
83 if (*p != 'Q') return NULL;
84
85 p++;
86
87 forever
88 {
89 /* Find next [ */
90 while ((*p == ' ') || (*p == '\t')) p++;
91
92 if (*p == '\0') return NULL;
93 if (*p != '[') return p;
94
95 /* skip to closing ] */
96 while (*p != ']')
97 {
98 p++;
99 if (*p == '\\')
100 {
101 p++;
102 if (*p == ']') p++;
103 }
104 }
105
106 if (*p == ']') p++;
107 }
108
109 return NULL;
110 }
111
112 static int
113 _parse_line(char *s)
114 {
115 char *act, *p;
116 struct action_rule *out;
117
118 if (s == NULL) return -1;
119 while ((*s == ' ') || (*s == '\t')) s++;
120 if (*s == '#') return -1;
121
122 act = _find_action(s);
123
124 if (act == NULL) return -1;
125 out = (struct action_rule *)calloc(1, sizeof(struct action_rule));
126 if (out == NULL) return -1;
127
128 p = strchr(act, ' ');
129 if (p != NULL) *p = '\0';
130 out->action = strdup(act);
131
132 if (out->action == NULL)
133 {
134 free(out);
135 return -1;
136 }
137
138 if (p != NULL)
139 {
140 out->options = strdup(p+1);
141
142 if (out->options == NULL)
143 {
144 free(out->action);
145 free(out);
146 return -1;
147 }
148 }
149
150 p = act - 1;
151
152 *p = '\0';
153 out->query = asl_msg_from_string(s);
154
155 if (out->query == NULL)
156 {
157 free(out->action);
158 if (out->options != NULL) free(out->options);
159 free(out);
160 return -1;
161 }
162
163 TAILQ_INSERT_TAIL(&asl_action_rule, out, entries);
164
165 return 0;
166 }
167
168 #ifdef NOTDEF
169 static char *
170 _next_word(char **s)
171 {
172 char *a, *p, *e, *out;
173 int quote, len;
174
175 if (s == NULL) return NULL;
176 if (*s == NULL) return NULL;
177
178 quote = 0;
179
180 p = *s;
181 a = p;
182 e = p;
183
184 while (*p != '\0')
185 {
186 if (*p == '\\')
187 {
188 p++;
189 e = p;
190
191 if (*p == '\0')
192 {
193 p--;
194 break;
195 }
196
197 p++;
198 e = p;
199 continue;
200 }
201
202 if (*p == '"')
203 {
204 if (quote == 0) quote = 1;
205 else quote = 0;
206 }
207
208 if (((*p == ' ') || (*p == '\t')) && (quote == 0))
209 {
210 e = p + 1;
211 break;
212 }
213
214 p++;
215 e = p;
216 }
217
218 *s = e;
219
220 len = p - a;
221 if (len == 0) return NULL;
222
223 out = malloc(len + 1);
224 if (out == NULL) return NULL;
225
226 memcpy(out, a, len);
227 out[len] = '\0';
228 return out;
229 }
230 #endif
231
232 static void
233 _act_notify(struct action_rule *r)
234 {
235 if (r == NULL) return;
236 if (r->options == NULL) return;
237 notify_post(r->options);
238 }
239
240 static void
241 _act_access_control(struct action_rule *r, asl_msg_t *msg)
242 {
243 int32_t ruid, rgid;
244 char *p;
245
246 ruid = atoi(r->options);
247 rgid = -1;
248 p = strchr(r->options, ' ');
249 if (p == NULL) p = strchr(r->options, '\t');
250 if (p != NULL)
251 {
252 *p = '\0';
253 p++;
254 rgid = atoi(p);
255 }
256
257 if (ruid != -1) asl_set((aslmsg)msg, ASL_KEY_READ_UID, r->options);
258 if (p != NULL)
259 {
260 if (rgid != -1) asl_set((aslmsg)msg, ASL_KEY_READ_GID, p);
261 p--;
262 *p = ' ';
263 }
264 }
265
266
267 int
268 asl_action_sendmsg(asl_msg_t *msg, const char *outid)
269 {
270 struct action_rule *r;
271
272 if (reset != 0)
273 {
274 _do_reset();
275 reset = 0;
276 }
277
278 if (msg == NULL) return -1;
279
280 for (r = asl_action_rule.tqh_first; r != NULL; r = r->entries.tqe_next)
281 {
282 if (asl_msg_cmp(r->query, msg) == 1)
283 {
284 if (r->action == NULL) continue;
285 else if (!strcmp(r->action, "access")) _act_access_control(r, msg);
286 else if (!strcmp(r->action, "notify")) _act_notify(r);
287 }
288 }
289
290 return 0;
291 }
292
293 static int
294 _parse_notify_file(const char *name)
295 {
296 FILE *cf;
297 char *line;
298
299 cf = fopen(name, "r");
300 if (cf == NULL) return 1;
301
302 while (NULL != (line = get_line_from_file(cf)))
303 {
304 _parse_line(line);
305 free(line);
306 }
307
308 fclose(cf);
309
310 return 0;
311 }
312
313 int
314 asl_action_init(void)
315 {
316 asldebug("%s: init\n", MY_ID);
317
318 TAILQ_INIT(&asl_action_rule);
319
320 query = asl_new(ASL_TYPE_QUERY);
321 aslevent_addmatch(query, MY_ID);
322 aslevent_addoutput(asl_action_sendmsg, MY_ID);
323
324 _parse_notify_file(_PATH_ASL_CONF);
325 return 0;
326 }
327
328 int
329 asl_action_reset(void)
330 {
331 reset = 1;
332 return 0;
333 }
334
335 int
336 asl_action_close(void)
337 {
338 struct action_rule *r, *n;
339
340 n = NULL;
341 for (r = asl_action_rule.tqh_first; r != NULL; r = n)
342 {
343 n = r->entries.tqe_next;
344
345 if (r->query != NULL) asl_free(r->query);
346 if (r->action != NULL) free(r->action);
347 if (r->options != NULL) free(r->options);
348
349 TAILQ_REMOVE(&asl_action_rule, r, entries);
350 free(r);
351 }
352
353 return 0;
354 }