1 /***********************************************************************
2 *
3 * SHOWLOG.C - Nagios Log File CGI
4 *
5 *
6 * This CGI program will display the contents of the Nagios
7 * log file.
8 *
9 * License:
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 ***********************************************************************/
24
25 #include "../include/config.h"
26 #include "../include/common.h"
27 #include "../include/objects.h"
28
29 #include "../include/getcgi.h"
30 #include "../include/cgiutils.h"
31 #include "../include/cgiauth.h"
32
33 extern char main_config_file[MAX_FILENAME_LENGTH];
34 extern char url_html_path[MAX_FILENAME_LENGTH];
35 extern char url_images_path[MAX_FILENAME_LENGTH];
36 extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
37
38 extern int enable_splunk_integration;
39
40 void document_header(int);
41 void document_footer(void);
42 int process_cgivars(void);
43
44 authdata current_authdata;
45
46 int display_log(void);
47
48 char log_file_to_use[MAX_FILENAME_LENGTH] = "";
49 int log_archive = 0;
50
51 int use_lifo = TRUE;
52
53 int embedded = FALSE;
54 int display_header = TRUE;
55 int display_frills = TRUE;
56 int display_timebreaks = TRUE;
57
58
main(void)59 int main(void) {
60 char temp_buffer[MAX_INPUT_BUFFER];
61
62
63 /* get the CGI variables passed in the URL */
64 process_cgivars();
65
66 /* reset internal variables */
67 reset_cgi_vars();
68
69 cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0);
70
71 document_header(TRUE);
72
73 /* get authentication information */
74 get_authentication_information(¤t_authdata);
75
76 /* determine what log file we should be using */
77 get_log_archive_to_use(log_archive, log_file_to_use, (int)sizeof(log_file_to_use));
78
79 if(display_header == TRUE) {
80
81 /* begin top table */
82 printf("<table border=0 width=100%% cellpadding=0 cellspacing=0>\n");
83 printf("<tr>\n");
84
85 /* left column of top table - info box */
86 printf("<td align=left valign=top width=33%%>\n");
87 display_info_table((log_rotation_method == LOG_ROTATION_NONE || log_archive == 0) ? "Current Event Log" : "Archived Event Log", FALSE, ¤t_authdata);
88 printf("</td>\n");
89
90 /* middle column of top table - log file navigation options */
91 printf("<td align=center valign=top width=33%%>\n");
92 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s?%s", SHOWLOG_CGI, (use_lifo == FALSE) ? "oldestfirst&" : "");
93 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
94 display_nav_table(temp_buffer, log_archive);
95 printf("</td>\n");
96
97 /* right hand column of top row */
98 printf("<td align=right valign=top width=33%%>\n");
99
100 printf("<form method='GET' action='%s'>\n", SHOWLOG_CGI);
101 printf("<input type='hidden' name='archive' value='%d'>\n", log_archive);
102 printf("<table border=0 cellspacing=0 cellpadding=0 CLASS='optBox'>\n");
103 printf("<tr>");
104 printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='oldestfirst' %s> Older Entries First:</td>", (use_lifo == FALSE) ? "checked" : "");
105 printf("</tr>\n");
106 printf("<tr>");
107 printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='submit' value='Update'></td>\n");
108 printf("</tr>\n");
109
110 /* display context-sensitive help */
111 printf("<tr>\n");
112 printf("<td align=right>\n");
113 display_context_help(CONTEXTHELP_LOG);
114 printf("</td>\n");
115 printf("</tr>\n");
116
117 printf("</table>\n");
118 printf("</form>\n");
119
120 printf("</td>\n");
121
122 /* end of top table */
123 printf("</tr>\n");
124 printf("</table>\n");
125 printf("</p>\n");
126
127 }
128
129
130 /* display the contents of the log file */
131 display_log();
132
133 document_footer();
134
135 /* free allocated memory */
136 free_memory();
137
138 return OK;
139 }
140
141
142
143
document_header(int use_stylesheet)144 void document_header(int use_stylesheet) {
145 char date_time[MAX_DATETIME_LENGTH];
146 time_t current_time;
147 time_t expire_time;
148
149 printf("Cache-Control: no-store\r\n");
150 printf("Pragma: no-cache\r\n");
151
152 time(¤t_time);
153 get_time_string(¤t_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
154 printf("Last-Modified: %s\r\n", date_time);
155
156 expire_time = (time_t)0L;
157 get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
158 printf("Expires: %s\r\n", date_time);
159
160 printf("Content-type: text/html; charset=utf-8\r\n\r\n");
161
162 if(embedded == TRUE)
163 return;
164
165 printf("<HTML>\n");
166 printf("<HEAD>\n");
167 printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
168 printf("<TITLE>\n");
169 printf("Nagios Log File\n");
170 printf("</TITLE>\n");
171
172 if(use_stylesheet == TRUE) {
173 printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
174 printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, SHOWLOG_CSS);
175 }
176
177 printf("</HEAD>\n");
178 printf("<BODY CLASS='showlog'>\n");
179
180 /* include user SSI header */
181 include_ssi_files(SHOWLOG_CGI, SSI_HEADER);
182
183 return;
184 }
185
186
document_footer(void)187 void document_footer(void) {
188
189 if(embedded == TRUE)
190 return;
191
192 /* include user SSI footer */
193 include_ssi_files(SHOWLOG_CGI, SSI_FOOTER);
194
195 printf("</BODY>\n");
196 printf("</HTML>\n");
197
198 return;
199 }
200
201
process_cgivars(void)202 int process_cgivars(void) {
203 char **variables;
204 int error = FALSE;
205 int x;
206
207 variables = getcgivars();
208
209 for(x = 0; variables[x]; x++) {
210
211 /* do some basic length checking on the variable identifier to prevent buffer overflows */
212 if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
213 continue;
214 }
215
216 /* we found the archive argument */
217 else if(!strcmp(variables[x], "archive")) {
218 x++;
219 if(variables[x] == NULL) {
220 error = TRUE;
221 break;
222 }
223
224 log_archive = atoi(variables[x]);
225 if(log_archive < 0)
226 log_archive = 0;
227 }
228
229 /* we found the order argument */
230 else if(!strcmp(variables[x], "oldestfirst")) {
231 use_lifo = FALSE;
232 }
233
234 /* we found the embed option */
235 else if(!strcmp(variables[x], "embedded"))
236 embedded = TRUE;
237
238 /* we found the noheader option */
239 else if(!strcmp(variables[x], "noheader"))
240 display_header = FALSE;
241
242 /* we found the nofrills option */
243 else if(!strcmp(variables[x], "nofrills"))
244 display_frills = FALSE;
245
246 /* we found the notimebreaks option */
247 else if(!strcmp(variables[x], "notimebreaks"))
248 display_timebreaks = FALSE;
249
250 /* we received an invalid argument */
251 else
252 error = TRUE;
253
254 }
255
256 /* free memory allocated to the CGI variables */
257 free_cgivars(variables);
258
259 return error;
260 }
261
262
263
264 /* display the contents of the log file */
display_log(void)265 int display_log(void) {
266 char *input = NULL;
267 char image[MAX_INPUT_BUFFER];
268 char image_alt[MAX_INPUT_BUFFER];
269 time_t t;
270 char *temp_buffer = NULL;
271 char date_time[MAX_DATETIME_LENGTH];
272 int error = FALSE;
273 mmapfile *thefile = NULL;
274 char last_message_date[MAX_INPUT_BUFFER] = "";
275 char current_message_date[MAX_INPUT_BUFFER] = "";
276 struct tm *time_ptr = NULL;
277
278
279 /* check to see if the user is authorized to view the log file */
280 if(is_authorized_for_system_information(¤t_authdata) == FALSE) {
281 printf("<HR>\n");
282 printf("<DIV CLASS='errorMessage'>It appears as though you do not have permission to view the log file...</DIV><br><br>\n");
283 printf("<DIV CLASS='errorDescription'>If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI<br>and check the authorization options in your CGI configuration file.</DIV>\n");
284 printf("<HR>\n");
285 return ERROR;
286 }
287
288 error = FALSE;
289
290 if(use_lifo == TRUE) {
291 error = read_file_into_lifo(log_file_to_use);
292 if(error != LIFO_OK) {
293 if(error == LIFO_ERROR_MEMORY) {
294 printf("<P><DIV CLASS='warningMessage'>Not enough memory to reverse log file - displaying log in natural order...</DIV></P>");
295 error = FALSE;
296 }
297 else
298 error = TRUE;
299 use_lifo = FALSE;
300 }
301 else
302 error = FALSE;
303 }
304
305 if(use_lifo == FALSE) {
306
307 if((thefile = mmap_fopen(log_file_to_use)) == NULL) {
308 printf("<HR>\n");
309 printf("<P><DIV CLASS='errorMessage'>Error: Could not open log file '%s' for reading!</DIV></P>", log_file_to_use);
310 printf("<HR>\n");
311 error = TRUE;
312 }
313 }
314
315 if(error == FALSE) {
316
317 printf("<P><DIV CLASS='logEntries'>\n");
318
319 while(1) {
320
321 free(input);
322
323 if(use_lifo == TRUE) {
324 if((input = pop_lifo()) == NULL)
325 break;
326 }
327 else if((input = mmap_fgets(thefile)) == NULL)
328 break;
329
330 strip(input);
331
332 if(strstr(input, " starting...")) {
333 strcpy(image, START_ICON);
334 strcpy(image_alt, START_ICON_ALT);
335 }
336 else if(strstr(input, " shutting down...")) {
337 strcpy(image, STOP_ICON);
338 strcpy(image_alt, STOP_ICON_ALT);
339 }
340 else if(strstr(input, "Bailing out")) {
341 strcpy(image, STOP_ICON);
342 strcpy(image_alt, STOP_ICON_ALT);
343 }
344 else if(strstr(input, " restarting...")) {
345 strcpy(image, RESTART_ICON);
346 strcpy(image_alt, RESTART_ICON_ALT);
347 }
348 else if(strstr(input, "HOST ALERT:") && strstr(input, ";DOWN;")) {
349 strcpy(image, HOST_DOWN_ICON);
350 strcpy(image_alt, HOST_DOWN_ICON_ALT);
351 }
352 else if(strstr(input, "HOST ALERT:") && strstr(input, ";UNREACHABLE;")) {
353 strcpy(image, HOST_UNREACHABLE_ICON);
354 strcpy(image_alt, HOST_UNREACHABLE_ICON_ALT);
355 }
356 else if(strstr(input, "HOST ALERT:") && (strstr(input, ";RECOVERY;") || strstr(input, ";UP;"))) {
357 strcpy(image, HOST_UP_ICON);
358 strcpy(image_alt, HOST_UP_ICON_ALT);
359 }
360 else if(strstr(input, "HOST NOTIFICATION:")) {
361 strcpy(image, HOST_NOTIFICATION_ICON);
362 strcpy(image_alt, HOST_NOTIFICATION_ICON_ALT);
363 }
364 else if(strstr(input, "SERVICE ALERT:") && strstr(input, ";CRITICAL;")) {
365 strcpy(image, CRITICAL_ICON);
366 strcpy(image_alt, CRITICAL_ICON_ALT);
367 }
368 else if(strstr(input, "SERVICE ALERT:") && strstr(input, ";WARNING;")) {
369 strcpy(image, WARNING_ICON);
370 strcpy(image_alt, WARNING_ICON_ALT);
371 }
372 else if(strstr(input, "SERVICE ALERT:") && strstr(input, ";UNKNOWN;")) {
373 strcpy(image, UNKNOWN_ICON);
374 strcpy(image_alt, UNKNOWN_ICON_ALT);
375 }
376 else if(strstr(input, "SERVICE ALERT:") && (strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))) {
377 strcpy(image, OK_ICON);
378 strcpy(image_alt, OK_ICON_ALT);
379 }
380 else if(strstr(input, "SERVICE NOTIFICATION:")) {
381 strcpy(image, NOTIFICATION_ICON);
382 strcpy(image_alt, NOTIFICATION_ICON_ALT);
383 }
384 else if(strstr(input, "SERVICE EVENT HANDLER:")) {
385 strcpy(image, SERVICE_EVENT_ICON);
386 strcpy(image_alt, SERVICE_EVENT_ICON_ALT);
387 }
388 else if(strstr(input, "HOST EVENT HANDLER:")) {
389 strcpy(image, HOST_EVENT_ICON);
390 strcpy(image_alt, HOST_EVENT_ICON_ALT);
391 }
392 else if(strstr(input, "EXTERNAL COMMAND:")) {
393 strcpy(image, EXTERNAL_COMMAND_ICON);
394 strcpy(image_alt, EXTERNAL_COMMAND_ICON_ALT);
395 }
396 else if(strstr(input, "PASSIVE SERVICE CHECK:")) {
397 strcpy(image, PASSIVE_ICON);
398 strcpy(image_alt, "Passive Service Check");
399 }
400 else if(strstr(input, "PASSIVE HOST CHECK:")) {
401 strcpy(image, PASSIVE_ICON);
402 strcpy(image_alt, "Passive Host Check");
403 }
404 else if(strstr(input, "LOG ROTATION:")) {
405 strcpy(image, LOG_ROTATION_ICON);
406 strcpy(image_alt, LOG_ROTATION_ICON_ALT);
407 }
408 else if(strstr(input, "active mode...")) {
409 strcpy(image, ACTIVE_ICON);
410 strcpy(image_alt, ACTIVE_ICON_ALT);
411 }
412 else if(strstr(input, "standby mode...")) {
413 strcpy(image, STANDBY_ICON);
414 strcpy(image_alt, STANDBY_ICON_ALT);
415 }
416 else if(strstr(input, "SERVICE FLAPPING ALERT:") && strstr(input, ";STARTED;")) {
417 strcpy(image, FLAPPING_ICON);
418 strcpy(image_alt, "Service started flapping");
419 }
420 else if(strstr(input, "SERVICE FLAPPING ALERT:") && strstr(input, ";STOPPED;")) {
421 strcpy(image, FLAPPING_ICON);
422 strcpy(image_alt, "Service stopped flapping");
423 }
424 else if(strstr(input, "SERVICE FLAPPING ALERT:") && strstr(input, ";DISABLED;")) {
425 strcpy(image, FLAPPING_ICON);
426 strcpy(image_alt, "Service flap detection disabled");
427 }
428 else if(strstr(input, "HOST FLAPPING ALERT:") && strstr(input, ";STARTED;")) {
429 strcpy(image, FLAPPING_ICON);
430 strcpy(image_alt, "Host started flapping");
431 }
432 else if(strstr(input, "HOST FLAPPING ALERT:") && strstr(input, ";STOPPED;")) {
433 strcpy(image, FLAPPING_ICON);
434 strcpy(image_alt, "Host stopped flapping");
435 }
436 else if(strstr(input, "HOST FLAPPING ALERT:") && strstr(input, ";DISABLED;")) {
437 strcpy(image, FLAPPING_ICON);
438 strcpy(image_alt, "Host flap detection disabled");
439 }
440 else if(strstr(input, "SERVICE DOWNTIME ALERT:") && strstr(input, ";STARTED;")) {
441 strcpy(image, SCHEDULED_DOWNTIME_ICON);
442 strcpy(image_alt, "Service entered a period of scheduled downtime");
443 }
444 else if(strstr(input, "SERVICE DOWNTIME ALERT:") && strstr(input, ";STOPPED;")) {
445 strcpy(image, SCHEDULED_DOWNTIME_ICON);
446 strcpy(image_alt, "Service exited a period of scheduled downtime");
447 }
448 else if(strstr(input, "SERVICE DOWNTIME ALERT:") && strstr(input, ";CANCELLED;")) {
449 strcpy(image, SCHEDULED_DOWNTIME_ICON);
450 strcpy(image_alt, "Service scheduled downtime has been cancelled");
451 }
452 else if(strstr(input, "HOST DOWNTIME ALERT:") && strstr(input, ";STARTED;")) {
453 strcpy(image, SCHEDULED_DOWNTIME_ICON);
454 strcpy(image_alt, "Host entered a period of scheduled downtime");
455 }
456 else if(strstr(input, "HOST DOWNTIME ALERT:") && strstr(input, ";STOPPED;")) {
457 strcpy(image, SCHEDULED_DOWNTIME_ICON);
458 strcpy(image_alt, "Host exited a period of scheduled downtime");
459 }
460 else if(strstr(input, "HOST DOWNTIME ALERT:") && strstr(input, ";CANCELLED;")) {
461 strcpy(image, SCHEDULED_DOWNTIME_ICON);
462 strcpy(image_alt, "Host scheduled downtime has been cancelled");
463 }
464 else {
465 strcpy(image, INFO_ICON);
466 strcpy(image_alt, INFO_ICON_ALT);
467 }
468
469 temp_buffer = strtok(input, "]");
470 t = (temp_buffer == NULL) ? 0L : strtoul(temp_buffer + 1, NULL, 10);
471
472 time_ptr = localtime(&t);
473 strftime(current_message_date, sizeof(current_message_date), "%B %d, %Y %H:00\n", time_ptr);
474 current_message_date[sizeof(current_message_date) - 1] = '\x0';
475
476 if(strcmp(last_message_date, current_message_date) != 0 && display_timebreaks == TRUE) {
477 printf("<BR CLEAR='all'>\n");
478 printf("<DIV CLASS='dateTimeBreak'>\n");
479 printf("<table border=0 width=95%%><tr>");
480 printf("<td width=40%%><hr width=100%%></td>");
481 printf("<td align=center CLASS='dateTimeBreak'>%s</td>", current_message_date);
482 printf("<td width=40%%><hr width=100%%></td>");
483 printf("</tr></table>\n");
484 printf("</DIV>\n");
485 printf("<BR CLEAR='all'><DIV CLASS='logEntries'>\n");
486 strncpy(last_message_date, current_message_date, sizeof(last_message_date));
487 last_message_date[sizeof(last_message_date) - 1] = '\x0';
488 }
489
490 get_time_string(&t, date_time, (int)sizeof(date_time), SHORT_DATE_TIME);
491 strip(date_time);
492
493 temp_buffer = strtok(NULL, "\n");
494
495 if(display_frills == TRUE)
496 printf("<img align='left' src='%s%s' alt='%s' title='%s'>", url_images_path, image, image_alt, image_alt);
497 printf("[%s] %s", date_time, (temp_buffer == NULL) ? "" : html_encode(temp_buffer, FALSE));
498 if(enable_splunk_integration == TRUE) {
499 printf(" ");
500 display_splunk_generic_url(temp_buffer, 2);
501 }
502 printf("<br clear='all'>\n");
503 }
504
505 printf("</DIV></P>\n");
506 printf("<HR>\n");
507
508 free(input);
509
510 if(use_lifo == FALSE)
511 mmap_fclose(thefile);
512 }
513
514 if(use_lifo == TRUE)
515 free_lifo_memory();
516
517 return OK;
518 }
519