source: trunk/src/sh_log_parse_pacct.c @ 452

Last change on this file since 452 was 384, checked in by katerina, 10 years ago

Fix for ticket #282 (compile issues on FreeBSD).

File size: 7.7 KB
Line 
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#ifdef ACORE
119  BIT(ACORE, 'D');
120#endif
121#ifdef AXSIG
122  BIT(AXSIG, 'X');
123#endif
124
125  out[i] = '\0';
126  return;
127}
128
129static char * uid_name (int uid)
130{
131  static int  userid   = 0;
132  static char user[16] = "";
133
134  if (uid == userid && user[0] != '\0')
135    {
136      return user;
137    }
138  else
139    {
140      struct passwd *thispw = getpwuid (uid);
141      if (thispw)
142        sl_strlcpy (user, thispw->pw_name, sizeof(user));
143      else
144        sl_snprintf(user, sizeof(user), "%d", uid);
145      user[sizeof(user)-1] = '\0';
146      userid = uid;
147    }
148  return user;
149}
150
151struct dev_struct {
152  char * device;
153  long   dev_id;
154  struct dev_struct * next;
155};
156static struct dev_struct * devicelist = NULL;
157
158static void add_devices(const char * dir)
159{
160  DIR *  mdir;
161  char   dirl[256];
162
163  sl_strlcpy(dirl, dir, sizeof(dirl));
164  dirl[sizeof(dirl)-1] = '\0';
165
166  mdir = opendir(dir);
167 
168  if (mdir)
169    {
170      char * path;
171      size_t len;
172      struct dirent * dent;
173      struct stat buf;
174
175      while (NULL != (dent = readdir(mdir)))
176        {
177          if (0 == strcmp(dent->d_name, "."))
178            continue;
179          if (0 == strcmp(dent->d_name, ".."))
180            continue;
181          len = strlen(dir) + strlen(dent->d_name) + 2;
182          path = SH_ALLOC(len);
183          snprintf(path, len, "%s/%s", dir, dent->d_name);
184          if (0 == lstat(path, &buf) && S_ISCHR(buf.st_mode))
185            {
186              struct dev_struct * dstruct;
187              dstruct = SH_ALLOC(sizeof(struct dev_struct));
188              /* eliminate leading '/dev/' */
189              memmove(path, &path[5], strlen(path)-4); 
190              dstruct->device = path;
191              dstruct->dev_id = buf.st_rdev;
192              dstruct->next   = devicelist;
193              devicelist      = dstruct;
194            }
195          else
196            {
197              SH_FREE(path);
198            }
199        }
200      closedir(mdir);
201    }
202  return;
203}
204
205static char * dev_name(long tty)
206{
207  struct dev_struct * dstruct;
208
209  if (!devicelist)
210    {
211      add_devices("/dev");
212      add_devices("/dev/pts");
213      add_devices("/dev/pty");
214      add_devices("/dev/ptym");
215    }
216
217  dstruct = devicelist;
218  while (dstruct)
219    {
220      if (dstruct->dev_id == tty)
221        return dstruct->device;
222      dstruct = dstruct->next;
223    }
224  return "??";
225}
226
227#if defined(__linux__) && defined(HAVE_ACCT_V3)
228#  define STRUCT_ACCT struct acct_v3
229#elif defined(__FreeBSD__) && defined(HAVE_ACCTV2)
230#  define STRUCT_ACCT struct acctv2
231#else
232#  define STRUCT_ACCT struct acct
233#endif
234
235/* This looks strange, but it's real ANSI C. */
236extern STRUCT_ACCT pacct_rd_never_used;
237#define COMM_LEN ((int) sizeof (pacct_rd_never_used.ac_comm))
238
239sh_string * sh_read_pacct (sh_string * record, struct sh_logfile * logfile)
240{
241  STRUCT_ACCT rec;
242
243  if (NULL != sh_binary_reader ((void*) &rec, sizeof(STRUCT_ACCT), logfile))
244    {
245      time_t btime = (time_t) rec.ac_btime;
246      double ut    = ACUTIME_2_DOUBLE (rec.ac_utime);
247      double st    = ACSTIME_2_DOUBLE (rec.ac_stime);
248      char   fl[6];
249      char   comm[COMM_LEN+1];
250      int    i;
251      char   out[64+COMM_LEN+1+5+8+8+32+4+19+7]; /* see printf format below */
252     
253#if defined(ac_flagx)
254      expand_flags(rec.ac_flagx, fl);
255#else
256      expand_flags(rec.ac_flag,  fl);
257#endif
258     
259      /* ac_comm may not be null terminated
260       */
261      for (i = 0; i < COMM_LEN; i++)
262        {
263          if (rec.ac_comm[i] == '\0')
264            {
265              comm[i] = '\0';
266              break;
267            }
268          if (! isprint (rec.ac_comm[i]))
269            comm[i] = '?';
270          else
271            comm[i] = rec.ac_comm[i];
272        }
273      comm[COMM_LEN] = '\0';
274
275      sl_snprintf (out, sizeof(out),
276                   "%ld:%-*.*s %5.5s %-8.8s %-8.8s %6.2f secs %-19.19s",
277                   btime,
278                   COMM_LEN, COMM_LEN, comm, fl, 
279                   uid_name(rec.ac_uid), 
280                   dev_name((long)rec.ac_tty),
281                   ((ut + st) / (double) AHZ),
282                   ctime (&btime));
283
284
285      sh_string_set_from_char(record, out);
286      return record;
287    }
288
289  if (record)
290    sh_string_destroy(&record);
291  return NULL;
292}
293
294static void * sh_dummy_record = NULL;
295
296struct sh_logrecord * sh_parse_pacct (sh_string * logline, void * fileinfo)
297{
298  char * p;
299  char * endptr;
300  unsigned long ltime;
301  struct sh_logrecord * record = NULL;
302
303  (void) fileinfo;
304
305  sh_dummy_record = (void *) &record;
306
307  if (sh_string_len(logline) > 0 && flag_err_debug == SL_TRUE)
308    {
309      SH_MUTEX_LOCK(mutex_thread_nolog);
310      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
311                      sh_string_str(logline),
312                      _("sh_parse_pacct"));
313      SH_MUTEX_UNLOCK(mutex_thread_nolog);
314    }
315
316  p = strchr(sh_string_str(logline), ':');
317
318  if (!p || p == sh_string_str(logline))
319    return NULL;
320
321  ltime = strtoul(sh_string_str(logline), &endptr, 10);
322  if (p != endptr)
323    return NULL;
324                 
325  ++p; /* points to first char of pacct record */
326 
327  if (*p != '\0')
328    {
329      size_t lengths[7];
330      unsigned int  fields = 7;
331      char ** array;
332      sh_string * message = sh_string_new_from_lchar(p, strlen(p));
333      array = split_array_ws(p, &fields, lengths);
334
335      if (fields == 7)
336        {
337          record = SH_ALLOC(sizeof(struct sh_logrecord));
338
339          record->timestamp = ltime;
340          record->timestr   = sh_string_new_from_lchar(array[6], lengths[6]);
341          record->message   = message;
342          record->pid       = 0;
343          record->host      = sh_string_new_from_lchar(sh.host.name, strlen(sh.host.name));
344        }
345      else
346        {
347          sh_string_destroy(&message);
348        }
349      SH_FREE(array);
350    }
351  return record;
352}
353/* USE_LOGFILE_MONITOR */
354#endif
Note: See TracBrowser for help on using the repository browser.