1 /* Copyright (C) 2009 Trend Micro Inc.
2 * All rights reserved.
3 *
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
7 * Foundation.
8 */
9
10 /* Read DJB multilog */
11
12 #include "shared.h"
13 #include "logcollector.h"
14
15
16 /* To translate between month (int) to month (char) */
17 static const char *(djb_month[]) = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
18 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
19 };
20 static char djb_host[512 + 1];
21
22
23 /* Initialize multilog */
init_djbmultilog(int pos)24 int init_djbmultilog(int pos)
25 {
26 char *djbp_name = NULL;
27 char *tmp_str = NULL;
28
29 logff[pos].djb_program_name = NULL;
30
31 /* Initialize hostname */
32 memset(djb_host, '\0', 512 + 1);
33
34 #ifndef WIN32
35 if (gethostname(djb_host, 512 - 1) != 0) {
36 strncpy(djb_host, "unknown", 512 - 1);
37 } else {
38 char *_ltmp;
39
40 /* Remove domain part if available */
41 _ltmp = strchr(djb_host, '.');
42 if (_ltmp) {
43 *_ltmp = '\0';
44 }
45 }
46 #else
47 strncpy(djb_host, "win32", 512 - 1);
48 #endif
49
50 /* Multilog must be in the following format: /path/program_name/current */
51 tmp_str = strrchr(logff[pos].file, '/');
52 if (!tmp_str) {
53 return (0);
54 }
55
56 /* Must end with /current and must not be in the beginning of the string */
57 if ((strcmp(tmp_str, "/current") != 0) || (tmp_str == logff[pos].file)) {
58 return (0);
59 }
60
61 tmp_str[0] = '\0';
62
63 /* Get final name */
64 djbp_name = strrchr(logff[pos].file, '/');
65 if (djbp_name == logff[pos].file) {
66 tmp_str[0] = '/';
67 return (0);
68 }
69
70 os_strdup(djbp_name + 1, logff[pos].djb_program_name);
71 tmp_str[0] = '/';
72
73 verbose("%s: INFO: Using program name '%s' for DJB multilog file: '%s'.",
74 ARGV0, logff[pos].djb_program_name, logff[pos].file);
75
76 return (1);
77 }
78
read_djbmultilog(int pos,int * rc,int drop_it)79 void *read_djbmultilog(int pos, int *rc, int drop_it)
80 {
81 size_t str_len = 0;
82 int need_clear = 0;
83 char *p;
84 char str[OS_MAXSTR + 1];
85 char buffer[OS_MAXSTR + 1];
86
87 str[OS_MAXSTR] = '\0';
88 *rc = 0;
89
90 /* Must have a valid program name */
91 if (!logff[pos].djb_program_name) {
92 return (NULL);
93 }
94
95 /* Get new entry */
96 while (fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) {
97 /* Get buffer size */
98 str_len = strlen(str);
99
100 /* Getting the last occurrence of \n */
101 if ((p = strrchr(str, '\n')) != NULL) {
102 *p = '\0';
103
104 /* If need_clear is set, we just get the line and ignore it */
105 if (need_clear) {
106 need_clear = 0;
107 continue;
108 }
109 } else {
110 need_clear = 1;
111 }
112
113 /* Multilog messages have the following format:
114 * @40000000463246020c2ca16c xx...
115 */
116 if ((str_len > 26) &&
117 (str[0] == '@') &&
118 isalnum((int)str[1]) &&
119 isalnum((int)str[2]) &&
120 isalnum((int)str[3]) &&
121 isalnum((int)str[24]) &&
122 (str[25] == ' ')) {
123 /* Remove spaces and tabs */
124 p = str + 26;
125 while (*p == ' ' || *p == '\t') {
126 p++;
127 }
128
129 /* If message has a valid syslog header, send as is */
130 if ((str_len > 44) &&
131 (p[3] == ' ') &&
132 (p[6] == ' ') &&
133 (p[9] == ':') &&
134 (p[12] == ':') &&
135 (p[15] == ' ')) {
136 p += 16;
137 strncpy(buffer, p, OS_MAXSTR);
138 } else {
139 /* We will add a proper syslog header */
140 time_t djbtime;
141 struct tm *pt;
142
143 djbtime = time(NULL);
144 pt = localtime(&djbtime);
145
146 /* Syslog time: Apr 27 14:50:32 */
147 snprintf(buffer, OS_MAXSTR, "%s %02d %02d:%02d:%02d %s %s: %s",
148 djb_month[pt->tm_mon],
149 pt->tm_mday,
150 pt->tm_hour,
151 pt->tm_min,
152 pt->tm_sec,
153 djb_host,
154 logff[pos].djb_program_name,
155 p);
156 }
157 }
158
159 else {
160 debug2("%s: DEBUG: Invalid DJB log: '%s'", ARGV0, str);
161 continue;
162 }
163
164 debug2("%s: DEBUG: Reading DJB multilog message: '%s'", ARGV0, buffer);
165
166 /* Send message to queue */
167 if (drop_it == 0) {
168 if (SendMSG(logr_queue, buffer, logff[pos].file, MYSQL_MQ) < 0) {
169 merror(QUEUE_SEND, ARGV0);
170 if ((logr_queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
171 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
172 }
173 }
174 }
175
176 continue;
177 }
178
179 return (NULL);
180 }
181
182