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(&current_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, &current_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(&current_time);
153 	get_time_string(&current_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(&current_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("&nbsp;&nbsp;&nbsp;");
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