Giving status.cgi Access to Resource File.

Support forum for Nagios Core, Nagios Plugins, NCPA, NRPE, NSCA, NDOUtils and more. Engage with the community of users including those using the open source solutions.
Locked
mmartin
Posts: 45
Joined: Fri Jul 15, 2011 12:45 pm

Giving status.cgi Access to Resource File.

Post by mmartin »

Hello All,

Nagios Core Version 3.5.1

So I have done some modifying of the status.c file in the past and some other small stuff recently. For example, I included the LONGSERVICEOUTPUT macro in the Status Information column of Nagios' Services page of the Web GUI. I did this because I had a few service checks that I wanted to have their 2nd+ lines included as well... Now I wanted to try something different and was hoping someone could give me a hand.

What I want to do now is see if I can get access to the User-defined macros stored in the resource.cfg file inside the status.c code. We do NOT use any passwords or any sensitive data inside this file so I wouldn't be worried about a password getting out there or anything like that. Would this be something that would be possible without a great deal of work? I have done C++ programming in the past and have kind of just finagled my way through using C to modify the .c/.cgi files.

I was wondering if there is a way to simply include access to this file so I could capture the $USER#$ macros.
Looking through the other .c files I can see these files below using the macros in resource.cfg, but I couldn't figure out how to include it in status.c and USE it within the code:

*I found this stuff below inside the other .c files, but I'm not sure how I could utilize it in status.c?
### FROM: include/nagios.h

Code: Select all

############################# Line 434 #############################
int read_resource_file(char *);					/* processes macros in resource file */
### FROM: base/config.c

Code: Select all

############################# Starting at Line 328 #############################
		if(!strcmp(variable, "resource_file")) {

			/* save the macro */
			my_free(mac->x[MACRO_RESOURCEFILE]);
			mac->x[MACRO_RESOURCEFILE] = (char *)strdup(value);

			/* process the resource file */
			read_resource_file(value);
			}

################################ Lines 1418 to 1503 ################################
/* processes macros in resource file */
int read_resource_file(char *resource_file) {
	char *input = NULL;
	char *variable = NULL;
	char *value = NULL;
	char *temp_ptr = NULL;
	mmapfile *thefile = NULL;
	int current_line = 1;
	int error = FALSE;
	int user_index = 0;

	if((thefile = mmap_fopen(resource_file)) == NULL) {
		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open resource file '%s' for reading!", resource_file);
		return ERROR;
		}

	/* process all lines in the resource file */
	while(1) {

		/* free memory */
		my_free(input);
		my_free(variable);
		my_free(value);

		/* read the next line */
		if((input = mmap_fgets_multiline(thefile)) == NULL)
			break;

		current_line = thefile->current_line;

		/* skip blank lines and comments */
		if(input[0] == '#' || input[0] == '\x0' || input[0] == '\n' || input[0] == '\r')
			continue;

		strip(input);

		/* get the variable name */
		if((temp_ptr = my_strtok(input, "=")) == NULL) {
			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable - Line %d of resource file '%s'", current_line, resource_file);
			error = TRUE;
			break;
			}
		if((variable = (char *)strdup(temp_ptr)) == NULL) {
			error = TRUE;
			break;
			}

		/* get the value */
		if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable value - Line %d of resource file '%s'", current_line, resource_file);
			error = TRUE;
			break;
			}
		if((value = (char *)strdup(temp_ptr)) == NULL) {
			error = TRUE;
			break;
			}

		/* what should we do with the variable/value pair? */

		/* check for macro declarations */
		if(variable[0] == '$' && variable[strlen(variable) - 1] == '$') {

			/* $USERx$ macro declarations */
			if(strstr(variable, "$USER") == variable  && strlen(variable) > 5) {
				user_index = atoi(variable + 5) - 1;
				if(user_index >= 0 && user_index < MAX_USER_MACROS) {
					my_free(macro_user[user_index]);
					macro_user[user_index] = (char *)strdup(value);
					}
				}
			}
		}

	/* free leftover memory and close the file */
	my_free(input);
	mmap_fclose(thefile);

	/* free memory */
	my_free(variable);
	my_free(value);

	if(error == TRUE)
		return ERROR;

	return OK;
	}
If anyone can point me in the right direction or give me a few pointers, that would be awesome!
Any thoughts or suggestions at all would be greatly appreciated!


Thanks in Advance,
Matt
tmcdonald
Posts: 9117
Joined: Mon Sep 23, 2013 8:40 am

Re: Giving status.cgi Access to Resource File.

Post by tmcdonald »

We would almost certainly need to have a core dev weigh in on this as this goes quite beyond standard support. This might be best posted on the Nagios Core github, since our core devs spend most of their time there.

https://github.com/NagiosEnterprises/nagioscore
Former Nagios employee
mmartin
Posts: 45
Joined: Fri Jul 15, 2011 12:45 pm

Re: Giving status.cgi Access to Resource File.

Post by mmartin »

Hey tmcdonald, thanks for the reply! Yup, you're right about that....

But, I think I may have gotten it to work after tooling around with it for a bit.

I created a copy of the Nagios source from our production installation onto another server I use for testing things. Then, I copied over the entire/current Nagios installation (*directory structure and all) which we are currently running. I then setup Apache and all that good stuff to get the Nagios web portal to be able to display in a browser so I could test. This test server won't be running the nagios command at all, so basically it will just display the current status of all the service checks at the point I copied everything over, which is just fine for testing this...

In trying to find an example of where the resource file's macros get read and used, I opened the ./base/config.c file and found out where/how that source code captures the macros...

I believe in the base/config.c code it first loops through the entire nagios main config file and when it finds the line containing "resource_file" it passes the value assigned to resource_file="..." to the function read_resource_file(). Then, that function loops through the resource file and if a line is NOT a comment or NOT a blank line (*as well as a few other cases, like: NOT a null macro assignment and things like that), basically it makes sure the line begins with "$USERn$"...

It then captures the value of that assignment to the Array macro_user[user_index], where user_index is the number you assigned to 'n' -1, for --> $USERn$.

So what I did was I copied over the read_resource_file() function to status.c near the top of the code, and then where I wanted to use a Macro, I call the function using the same line they use in config.c, which is "read_resource_file("/opt/nagios/etc/resource.cfg");"... But, since config.c gets the resource file's name by checking the config file and passes it a variable name, I'm simply hardcoding in the absolute path to resource.cfg.

Code taken from "./base/config.c" and copied into "./cgi/status.c":

Code: Select all

int read_resource_file(char *resource_file) {
	char *input = NULL;
	char *variable = NULL;
	char *value = NULL;
	char *temp_ptr = NULL;
	mmapfile *thefile = NULL;
	int current_line = 1;
	int error = FALSE;
	int user_index = 0;

	if((thefile = mmap_fopen(resource_file)) == NULL) {
		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open resource file '%s' for reading!", resource_file);
		return ERROR;
		}

	/* process all lines in the resource file */
	while(1) {

		/* free memory */
		my_free(input);
		my_free(variable);
		my_free(value);

		/* read the next line */
		if((input = mmap_fgets_multiline(thefile)) == NULL)
			break;

		current_line = thefile->current_line;

		/* skip blank lines and comments */
		if(input[0] == '#' || input[0] == '\x0' || input[0] == '\n' || input[0] == '\r')
			continue;

		strip(input);

		/* get the variable name */
		if((temp_ptr = my_strtok(input, "=")) == NULL) {
			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable - Line %d of resource file '%s'", current_line, resource_file);
			error = TRUE;
			break;
			}
		if((variable = (char *)strdup(temp_ptr)) == NULL) {
			error = TRUE;
			break;
			}

		/* get the value */
		if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable value - Line %d of resource file '%s'", current_line, resource_file);
			error = TRUE;
			break;
			}
		if((value = (char *)strdup(temp_ptr)) == NULL) {
			error = TRUE;
			break;
			}

		/* what should we do with the variable/value pair? */

		/* check for macro declarations */
		if(variable[0] == '$' && variable[strlen(variable) - 1] == '$') {

			/* $USERx$ macro declarations */
			if(strstr(variable, "$USER") == variable  && strlen(variable) > 5) {
				user_index = atoi(variable + 5) - 1;
				if(user_index >= 0 && user_index < MAX_USER_MACROS) {
					my_free(macro_user[user_index]);
					macro_user[user_index] = (char *)strdup(value);
					}
				}
			}
		}

	/* free leftover memory and close the file */
	my_free(input);
	mmap_fclose(thefile);

	/* free memory */
	my_free(variable);
	my_free(value);

	if(error == TRUE)
		return ERROR;

	return OK;
}
:
:....................
:................................................................................................................:
:.......................................... CODE SNIPPED ..........................................:
:................................................................................................................:
:....................
:
/* Then when I want a Macro, I use: */
read_resource_file("/opt/nagios/etc/resource.cfg");

/* Then to use the Macro I want, I would use: 
 *     The Array is zero-based, so $USER7$ would be element [6] in the array
 */
printf("USER7 == '%s'", macro_user[6]);
This seems to do what I wanted. I was able to get access to the resource file's User-defined Macros, which is really all I wanted to do.
Thanks again for your reply, much apprecited!

ThanksAgain,
Matt
ssax
Dreams In Code
Posts: 7682
Joined: Wed Feb 11, 2015 12:54 pm

Re: Giving status.cgi Access to Resource File.

Post by ssax »

Is it ok if we mark this as resolved and lock the topic?
tmcdonald
Posts: 9117
Joined: Mon Sep 23, 2013 8:40 am

Re: Giving status.cgi Access to Resource File.

Post by tmcdonald »

And sorry for not being much help. Normally I would dive into the code but we got hit pretty hard today support-wise.
Former Nagios employee
mmartin
Posts: 45
Joined: Fri Jul 15, 2011 12:45 pm

Re: Giving status.cgi Access to Resource File.

Post by mmartin »

Yup, you can mark solved.

No worries, I assumed I'd be able to eventually figure it out, it's just ALOT of code and a little overwhelming when you first start looking into it. But I appreciate the replies, thanks.

Thanks Again,
Matt
Locked