source: trunk/src/sh_log_parse_pacct.c@ 184

Last change on this file since 184 was 183, checked in by katerina, 16 years ago

Support for logfile monitoring (ticket #122). Also improved some configure error messages.

File size: 7.5 KB
RevLine 
[183]1/**************************************
2 **
3 ** PARSER RULES
4 **
5 ** (a) must set record->host
6 ** (eventually to dummy value)
7 **
8 ** (b) must set record->prefix
9 ** (command)
10 **
11 **
12 **************************************/
13
14/* Based on the GNU Accounting Utilities, which is distributed with the
15 * following copyright:
16 */
17
18/* Copyright (C) 1993, 1996, 1997, 2003, 2005 Free Software Foundation, Inc.
19 *
20 * This file is part of the GNU Accounting Utilities
21 *
22 * The GNU Accounting Utilities are free software; you can redistribute
23 * them and/or modify them under the terms of the GNU General Public
24 * License as published by the Free Software Foundation; either version
25 * 2, or (at your option) any later version.
26 *
27 * The GNU Accounting Utilities are distributed in the hope that they will
28 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 * General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with the GNU Accounting Utilities; see the file COPYING. If
34 * not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
35 * MA 02139, USA. */
36
37#include "config_xor.h"
38
39#include <ctype.h>
40#include <string.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <unistd.h>
46#include <pwd.h>
47#include <dirent.h>
48
49#if defined(USE_LOGFILE_MONITOR) && defined(HAVE_SYS_ACCT_H)
50
51#include <sys/acct.h>
52
53#include "samhain.h"
54#include "sh_pthread.h"
55#include "sh_log_check.h"
56#include "sh_utils.h"
57#include "sh_string.h"
58
59#undef FIL__
60#define FIL__ _("sh_log_parse_pacct.c")
61
62extern int flag_err_debug;
63
64#ifndef ACCT_COMM
65#define ACCT_COMM 16
66#endif
67#ifndef AHZ
68#define AHZ 100
69#endif
70
71#if defined(ACUTIME_COMPT) || defined(ACSTIME_COMPT) || defined(ACETIME_COMPT)
72static double comp_t_2_double (comp_t ct)
73{
74 unsigned long out = 0;
75
76 out = ct & 017777;
77 ct >>= 13;
78
79 while (ct) {
80 ct--;
81 out <<= 3;
82 }
83
84 return (double) out;
85}
86#endif
87
88#ifdef ACUTIME_COMPT
89# define ACUTIME_2_DOUBLE(x) (comp_t_2_double(x))
90#else
91# define ACUTIME_2_DOUBLE(x) ((double)(x))
92#endif
93
94#ifdef ACSTIME_COMPT
95# define ACSTIME_2_DOUBLE(x) (comp_t_2_double(x))
96#else
97# define ACSTIME_2_DOUBLE(x) ((double)(x))
98#endif
99
100#ifdef ACETIME_COMPT
101# define ACETIME_2_DOUBLE(x) (comp_t_2_double(x))
102#else
103# define ACETIME_2_DOUBLE(x) ((double)(x))
104#endif
105
106
107static void expand_flags(char flag, char * out)
108{
109 int i = 0;
110
111#define BIT(flg, ch) if (flag & flg) out[i] = ch; else out[i] = ' '; ++i
112
113 BIT(ASU, 'S');
114 BIT(AFORK, 'F');
115#ifdef ACOMPAT
116 BIT(ACOMPAT, 'C');
117#endif
118 BIT(ACORE, 'D');
119 BIT(AXSIG, 'X');
120
121 out[i] = '\0';
122 return;
123}
124
125static char * uid_name (int uid)
126{
127 static int userid = 0;
128 static char user[16] = "";
129
130 if (uid == userid && user[0] != '\0')
131 {
132 return user;
133 }
134 else
135 {
136 struct passwd *thispw = getpwuid (uid);
137 if (thispw)
138 sl_strlcpy (user, thispw->pw_name, sizeof(user));
139 else
140 sl_snprintf(user, sizeof(user), "%d", uid);
141 user[sizeof(user)-1] = '\0';
142 userid = uid;
143 }
144 return user;
145}
146
147struct dev_struct {
148 char * device;
149 long dev_id;
150 struct dev_struct * next;
151};
152static struct dev_struct * devicelist = NULL;
153
154static void add_devices(const char * dir)
155{
156 DIR * mdir;
157 char dirl[256];
158
159 sl_strlcpy(dirl, dir, sizeof(dirl));
160 dirl[sizeof(dirl)-1] = '\0';
161
162 mdir = opendir(dir);
163
164 if (mdir)
165 {
166 char * path;
167 size_t len;
168 struct dirent * dent;
169 struct stat buf;
170
171 while (NULL != (dent = readdir(mdir)))
172 {
173 if (0 == strcmp(dent->d_name, "."))
174 continue;
175 if (0 == strcmp(dent->d_name, ".."))
176 continue;
177 len = strlen(dir) + strlen(dent->d_name) + 2;
178 path = SH_ALLOC(len);
179 snprintf(path, len, "%s/%s", dir, dent->d_name);
180 if (0 == lstat(path, &buf) && S_ISCHR(buf.st_mode))
181 {
182 struct dev_struct * dstruct;
183 dstruct = SH_ALLOC(sizeof(struct dev_struct));
184 /* eliminate leading '/dev/' */
185 memmove(path, &path[5], strlen(path)-4);
186 dstruct->device = path;
187 dstruct->dev_id = buf.st_rdev;
188 dstruct->next = devicelist;
189 devicelist = dstruct;
190 }
191 else
192 {
193 SH_FREE(path);
194 }
195 }
196 closedir(mdir);
197 }
198 return;
199}
200
201static char * dev_name(long tty)
202{
203 struct dev_struct * dstruct;
204
205 if (!devicelist)
206 {
207 add_devices("/dev");
208 add_devices("/dev/pts");
209 add_devices("/dev/pty");
210 add_devices("/dev/ptym");
211 }
212
213 dstruct = devicelist;
214 while (dstruct)
215 {
216 if (dstruct->dev_id == tty)
217 return dstruct->device;
218 dstruct = dstruct->next;
219 }
220 return "??";
221}
222
223/* This looks strange, but it's real ANSI C. */
224extern struct acct pacct_rd_never_used;
225#define COMM_LEN ((int) sizeof (pacct_rd_never_used.ac_comm))
226
227sh_string * sh_read_pacct (sh_string * record, struct sh_logfile * logfile)
228{
229#if defined(__linux__)
230# define STRUCT_ACCT struct acct_v3
231#else
232# define STRUCT_ACCT struct acct
233#endif
234
235 STRUCT_ACCT rec;
236
237 if (NULL != sh_binary_reader ((void*) &rec, sizeof(STRUCT_ACCT), logfile))
238 {
239 time_t btime = (time_t) rec.ac_btime;
240 double ut = ACUTIME_2_DOUBLE (rec.ac_utime);
241 double st = ACSTIME_2_DOUBLE (rec.ac_stime);
242 char fl[6];
243 char comm[COMM_LEN+1];
244 int i;
245 char out[64+COMM_LEN+1+5+8+8+32+4+19+7]; /* see printf format below */
246
247 expand_flags(rec.ac_flag, fl);
248
249 /* ac_comm may not be null terminated
250 */
251 for (i = 0; i < COMM_LEN; i++)
252 {
253 if (rec.ac_comm[i] == '\0')
254 {
255 comm[i] = '\0';
256 break;
257 }
258 if (! isprint (rec.ac_comm[i]))
259 comm[i] = '?';
260 else
261 comm[i] = rec.ac_comm[i];
262 }
263 comm[COMM_LEN] = '\0';
264
265 sl_snprintf (out, sizeof(out),
266 "%ld:%-*.*s %5.5s %-8.8s %-8.8s %6.2f secs %-19.19s",
267 btime,
268 COMM_LEN, COMM_LEN, comm, fl,
269 uid_name(rec.ac_uid),
270 dev_name((long)rec.ac_tty),
271 ((ut + st) / (double) AHZ),
272 ctime (&btime));
273
274
275 sh_string_set_from_char(record, out);
276 return record;
277 }
278
279 return NULL;
280}
281
282struct sh_logrecord * sh_parse_pacct (sh_string * logline, void * fileinfo)
283{
284 char * p;
285 char * endptr;
286 unsigned long ltime;
287 struct sh_logrecord * record = NULL;
288
289 (void) fileinfo;
290
291 if (sh_string_len(logline) > 0 && flag_err_debug == SL_TRUE)
292 {
293 SH_MUTEX_LOCK(mutex_thread_nolog);
294 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
295 sh_string_str(logline),
296 _("sh_parse_pacct"));
297 SH_MUTEX_UNLOCK(mutex_thread_nolog);
298 }
299
300 p = strchr(sh_string_str(logline), ':');
301
302 if (!p || p == sh_string_str(logline))
303 return NULL;
304
305 ltime = strtoul(sh_string_str(logline), &endptr, 10);
306 if (p != endptr)
307 return NULL;
308
309 ++p; /* points to first char of pacct record */
310
311 if (*p != '\0')
312 {
313 size_t lengths[7];
314 unsigned int fields = 7;
315 char ** array;
316 sh_string * message = sh_string_new_from_lchar(p, strlen(p));
317 array = split_array_ws(p, &fields, lengths);
318
319 if (fields == 7)
320 {
321 record = SH_ALLOC(sizeof(struct sh_logrecord));
322
323 record->timestamp = ltime;
324 record->timestr = sh_string_new_from_lchar(array[6], lengths[6]);
325 record->prefix = sh_string_new_from_lchar(array[0], lengths[0]);
326 record->message = message;
327 record->pid = 0;
328 record->host = sh_string_new_from_lchar(sh.host.name, strlen(sh.host.name));
329 }
330 else
331 {
332 sh_string_destroy(&message);
333 }
334 SH_FREE(array);
335 }
336 return record;
337}
338/* USE_LOGFILE_MONITOR */
339#endif
Note: See TracBrowser for help on using the repository browser.