Back to index

nagios-nrpe  2.13
Classes | Typedefs | Functions
nrpe.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  command_struct

Typedefs

typedef struct command_struct command

Functions

int process_arguments (int, char **)
void wait_for_connections (void)
void handle_connection (int)
int read_config_file (char *)
int read_config_dir (char *)
int get_log_facility (char *)
int add_command (char *, char *)
commandfind_command (char *)
void sighandler (int)
int drop_privileges (char *, char *)
int check_privileges (void)
int write_pid_file (void)
int remove_pid_file (void)
void free_memory (void)
int validate_request (packet *)
int contains_nasty_metachars (char *)
int process_macros (char *, char *, int)
int my_system (char *, int, int *, char *, int)
void my_system_sighandler (int)
void my_connection_sighandler (int)
void child_sighandler (int)

Class Documentation

struct command_struct

Definition at line 33 of file nrpe.h.

Collaboration diagram for command_struct:
Class Members
char * command_line
char * command_name
struct command_struct * next

Typedef Documentation

typedef struct command_struct command

Function Documentation

int add_command ( char *  ,
char *   
)

Definition at line 654 of file nrpe.c.

                                                       {
       command *new_command;

       if(command_name==NULL || command_line==NULL)
              return ERROR;

       /* allocate memory for the new command */
       new_command=(command *)malloc(sizeof(command));
       if(new_command==NULL)
              return ERROR;

       new_command->command_name=strdup(command_name);
       if(new_command->command_name==NULL){
              free(new_command);
              return ERROR;
               }
       new_command->command_line=strdup(command_line);
       if(new_command->command_line==NULL){
              free(new_command->command_name);
              free(new_command);
              return ERROR;
               }

       /* add new command to head of list in memory */
       new_command->next=command_list;
       command_list=new_command;

       if(debug==TRUE)
              syslog(LOG_DEBUG,"Added command[%s]=%s\n",command_name,command_line);

       return OK;
        }

Here is the caller graph for this function:

int check_privileges ( void  )

Definition at line 1595 of file nrpe.c.

                          {
       uid_t uid=-1;
       gid_t gid=-1;

       uid=geteuid();
       gid=getegid();

       if(uid==0 || gid==0){
              syslog(LOG_ERR,"Error: NRPE daemon cannot be run as user/group root!");
              exit(STATE_CRITICAL);
               }

       return OK;
        }

Here is the caller graph for this function:

void child_sighandler ( int  )

Definition at line 1650 of file nrpe.c.

                              {

       /* free all memory we allocated */
       free_memory();

       /* terminate */
       exit(0);
       
       /* so the compiler doesn't complain... */
       return;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

int contains_nasty_metachars ( char *  )

Definition at line 1759 of file nrpe.c.

                                       {
       int result;

       if(str==NULL)
              return FALSE;
       
       result=strcspn(str,NASTY_METACHARS);
       if(result!=strlen(str))
              return TRUE;

       return FALSE;
        }

Here is the caller graph for this function:

int drop_privileges ( char *  ,
char *   
)

Definition at line 1448 of file nrpe.c.

                                            {
       uid_t uid=-1;
       gid_t gid=-1;
       struct group *grp;
       struct passwd *pw;

       /* set effective group ID */
       if(group!=NULL){
              
              /* see if this is a group name */
              if(strspn(group,"0123456789")<strlen(group)){
                     grp=(struct group *)getgrnam(group);
                     if(grp!=NULL)
                            gid=(gid_t)(grp->gr_gid);
                     else
                            syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group);
                     endgrent();
                      }

              /* else we were passed the GID */
              else
                     gid=(gid_t)atoi(group);

              /* set effective group ID if other than current EGID */
              if(gid!=getegid()){

                     if(setgid(gid)==-1)
                            syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid);
                      }
               }


       /* set effective user ID */
       if(user!=NULL){
              
              /* see if this is a user name */
              if(strspn(user,"0123456789")<strlen(user)){
                     pw=(struct passwd *)getpwnam(user);
                     if(pw!=NULL)
                            uid=(uid_t)(pw->pw_uid);
                     else
                            syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user);
                     endpwent();
                      }

              /* else we were passed the UID */
              else
                     uid=(uid_t)atoi(user);
                     
              /* set effective user ID if other than current EUID */
              if(uid!=geteuid()){

#ifdef HAVE_INITGROUPS
                     /* initialize supplementary groups */
                     if(initgroups(user,gid)==-1){
                            if(errno==EPERM)
                                   syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()");
                            else{
                                   syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()");
                                   return ERROR;
                                     }
                               }
#endif

                     if(setuid(uid)==-1)
                            syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid);
                      }
               }

       return OK;
        }

Here is the caller graph for this function:

command* find_command ( char *  )

Definition at line 690 of file nrpe.c.

                                         {
       command *temp_command;

       for(temp_command=command_list;temp_command!=NULL;temp_command=temp_command->next)
              if(!strcmp(command_name,temp_command->command_name))
                     return temp_command;

       return NULL;
        }

Here is the caller graph for this function:

void free_memory ( void  )

Definition at line 1239 of file nrpe.c.

                      {
       command *this_command;
       command *next_command;
       
       /* free memory for the command list */
       this_command=command_list;
       while(this_command!=NULL){
              next_command=this_command->next;
              if(this_command->command_name)
                     free(this_command->command_name);
              if(this_command->command_line)
                     free(this_command->command_line);
              free(this_command);
              this_command=next_command;
               }

       command_list=NULL;

       return;
        }

Here is the caller graph for this function:

int get_log_facility ( char *  )

Definition at line 601 of file nrpe.c.

                                    {

       if(!strcmp(varvalue,"kern"))
              log_facility=LOG_KERN;
       else if(!strcmp(varvalue,"user"))
              log_facility=LOG_USER;
       else if(!strcmp(varvalue,"mail"))
              log_facility=LOG_MAIL;
       else if(!strcmp(varvalue,"daemon"))
              log_facility=LOG_DAEMON;
       else if(!strcmp(varvalue,"auth"))
              log_facility=LOG_AUTH;
       else if(!strcmp(varvalue,"syslog"))
              log_facility=LOG_SYSLOG;
       else if(!strcmp(varvalue,"lrp"))
              log_facility=LOG_LPR;
       else if(!strcmp(varvalue,"news"))
              log_facility=LOG_NEWS;
       else if(!strcmp(varvalue,"uucp"))
              log_facility=LOG_UUCP;
       else if(!strcmp(varvalue,"cron"))
              log_facility=LOG_CRON;
       else if(!strcmp(varvalue,"authpriv"))
              log_facility=LOG_AUTHPRIV;
       else if(!strcmp(varvalue,"ftp"))
              log_facility=LOG_FTP;
       else if(!strcmp(varvalue,"local0"))
              log_facility=LOG_LOCAL0;
       else if(!strcmp(varvalue,"local1"))
              log_facility=LOG_LOCAL1;
       else if(!strcmp(varvalue,"local2"))
              log_facility=LOG_LOCAL2;
       else if(!strcmp(varvalue,"local3"))
              log_facility=LOG_LOCAL3;
       else if(!strcmp(varvalue,"local4"))
              log_facility=LOG_LOCAL4;
       else if(!strcmp(varvalue,"local5"))
              log_facility=LOG_LOCAL5;
       else if(!strcmp(varvalue,"local6"))
              log_facility=LOG_LOCAL6;
       else if(!strcmp(varvalue,"local7"))
              log_facility=LOG_LOCAL7;
       else{
              log_facility=LOG_DAEMON;
              return ERROR;
              }

       return OK;
       }

Here is the caller graph for this function:

void handle_connection ( int  )

Definition at line 963 of file nrpe.c.

                                {
        u_int32_t calculated_crc32;
       command *temp_command;
       packet receive_packet;
       packet send_packet;
       int bytes_to_send;
       int bytes_to_recv;
       char buffer[MAX_INPUT_BUFFER];
       char raw_command[MAX_INPUT_BUFFER];
       char processed_command[MAX_INPUT_BUFFER];
       int result=STATE_OK;
       int early_timeout=FALSE;
       int rc;
       int x;
#ifdef DEBUG
       FILE *errfp;
#endif
#ifdef HAVE_SSL
       SSL *ssl=NULL;
#endif


       /* log info to syslog facility */
       if(debug==TRUE)
              syslog(LOG_DEBUG,"Handling the connection...");

#ifdef OLDSTUFF
       /* socket should be non-blocking */
       fcntl(sock,F_SETFL,O_NONBLOCK);
#endif

       /* set connection handler */
       signal(SIGALRM,my_connection_sighandler);
       alarm(connection_timeout);

#ifdef HAVE_SSL
       /* do SSL handshake */
       if(result==STATE_OK && use_ssl==TRUE){
              if((ssl=SSL_new(ctx))!=NULL){
                     SSL_set_fd(ssl,sock);

                     /* keep attempting the request if needed */
                        while(((rc=SSL_accept(ssl))!=1) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ));

                     if(rc!=1){
                            syslog(LOG_ERR,"Error: Could not complete SSL handshake. %d\n",SSL_get_error(ssl,rc));
#ifdef DEBUG
                            errfp=fopen("/tmp/err.log","w");
                            ERR_print_errors_fp(errfp);
                            fclose(errfp);
#endif
                            return;
                             }
                      }
              else{
                     syslog(LOG_ERR,"Error: Could not create SSL connection structure.\n");
#ifdef DEBUG
                     errfp=fopen("/tmp/err.log","w");
                     ERR_print_errors_fp(errfp);
                     fclose(errfp);
#endif
                     return;
                      }
               }
#endif

       bytes_to_recv=sizeof(receive_packet);
       if(use_ssl==FALSE)
              rc=recvall(sock,(char *)&receive_packet,&bytes_to_recv,socket_timeout);
#ifdef HAVE_SSL
       else{
                while(((rc=SSL_read(ssl,&receive_packet,bytes_to_recv))<=0) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ));
              }
#endif

       /* recv() error or client disconnect */
       if(rc<=0){

              /* log error to syslog facility */
              syslog(LOG_ERR,"Could not read request from client, bailing out...");

#ifdef HAVE_SSL
              if(ssl){
                     SSL_shutdown(ssl);
                     SSL_free(ssl);
                     syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n");
                     }
#endif

              return;
                }

       /* we couldn't read the correct amount of data, so bail out */
       else if(bytes_to_recv!=sizeof(receive_packet)){

              /* log error to syslog facility */
              syslog(LOG_ERR,"Data packet from client was too short, bailing out...");

#ifdef HAVE_SSL
              if(ssl){
                     SSL_shutdown(ssl);
                     SSL_free(ssl);
                     }
#endif

              return;
               }

#ifdef DEBUG
       fp=fopen("/tmp/packet","w");
       if(fp){
              fwrite(&receive_packet,1,sizeof(receive_packet),fp);
              fclose(fp);
               }
#endif

       /* make sure the request is valid */
       if(validate_request(&receive_packet)==ERROR){

              /* log an error */
              syslog(LOG_ERR,"Client request was invalid, bailing out...");

              /* free memory */
              free(command_name);
              command_name=NULL;
              for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
                     free(macro_argv[x]);
                     macro_argv[x]=NULL;
                       }

#ifdef HAVE_SSL
              if(ssl){
                     SSL_shutdown(ssl);
                     SSL_free(ssl);
                     }
#endif

              return;
               }

       /* log info to syslog facility */
       if(debug==TRUE)
              syslog(LOG_DEBUG,"Host is asking for command '%s' to be run...",receive_packet.buffer);

       /* disable connection alarm - a new alarm will be setup during my_system */
       alarm(0);

       /* if this is the version check command, just spew it out */
       if(!strcmp(command_name,NRPE_HELLO_COMMAND)){

              snprintf(buffer,sizeof(buffer),"NRPE v%s",PROGRAM_VERSION);
              buffer[sizeof(buffer)-1]='\x0';

              /* log info to syslog facility */
              if(debug==TRUE)
                     syslog(LOG_DEBUG,"Response: %s",buffer);

              result=STATE_OK;
               }

       /* find the command we're supposed to run */
       else{
              temp_command=find_command(command_name);
              if(temp_command==NULL){

                     snprintf(buffer,sizeof(buffer),"NRPE: Command '%s' not defined",command_name);
                     buffer[sizeof(buffer)-1]='\x0';

                     /* log error to syslog facility */
                     if(debug==TRUE)
                            syslog(LOG_DEBUG,"%s",buffer);

                     result=STATE_CRITICAL;
                       }

              else{

                     /* process command line */
                     if(command_prefix==NULL)
                            strncpy(raw_command,temp_command->command_line,sizeof(raw_command)-1);
                     else
                            snprintf(raw_command,sizeof(raw_command)-1,"%s %s",command_prefix,temp_command->command_line);
                     raw_command[sizeof(raw_command)-1]='\x0';
                     process_macros(raw_command,processed_command,sizeof(processed_command));

                     /* log info to syslog facility */
                     if(debug==TRUE)
                            syslog(LOG_DEBUG,"Running command: %s",processed_command);

                     /* run the command */
                     strcpy(buffer,"");
                     result=my_system(processed_command,command_timeout,&early_timeout,buffer,sizeof(buffer));

                     /* log debug info */
                     if(debug==TRUE)
                            syslog(LOG_DEBUG,"Command completed with return code %d and output: %s",result,buffer);

                     /* see if the command timed out */
                     if(early_timeout==TRUE)
                            snprintf(buffer,sizeof(buffer)-1,"NRPE: Command timed out after %d seconds\n",command_timeout);
                     else if(!strcmp(buffer,""))
                            snprintf(buffer,sizeof(buffer)-1,"NRPE: Unable to read output\n");

                     buffer[sizeof(buffer)-1]='\x0';

                     /* check return code bounds */
                     if((result<0) || (result>3)){

                            /* log error to syslog facility */
                            syslog(LOG_ERR,"Bad return code for [%s]: %d", buffer,result);

                            result=STATE_UNKNOWN;
                             }
                      }
               }

       /* free memory */
       free(command_name);
       command_name=NULL;
       for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
              free(macro_argv[x]);
              macro_argv[x]=NULL;
               }

       /* strip newline character from end of output buffer */
       if(buffer[strlen(buffer)-1]=='\n')
              buffer[strlen(buffer)-1]='\x0';

       /* clear the response packet buffer */
       bzero(&send_packet,sizeof(send_packet));

       /* fill the packet with semi-random data */
       randomize_buffer((char *)&send_packet,sizeof(send_packet));

       /* initialize response packet data */
       send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2);
       send_packet.packet_type=(int16_t)htons(RESPONSE_PACKET);
       send_packet.result_code=(int16_t)htons(result);
       strncpy(&send_packet.buffer[0],buffer,MAX_PACKETBUFFER_LENGTH);
       send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
       
       /* calculate the crc 32 value of the packet */
       send_packet.crc32_value=(u_int32_t)0L;
       calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet));
       send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32);


       /***** ENCRYPT RESPONSE *****/


       /* send the response back to the client */
       bytes_to_send=sizeof(send_packet);
       if(use_ssl==FALSE)
              sendall(sock,(char *)&send_packet,&bytes_to_send);
#ifdef HAVE_SSL
       else
              SSL_write(ssl,&send_packet,bytes_to_send);
#endif

#ifdef HAVE_SSL
       if(ssl){
              SSL_shutdown(ssl);
              SSL_free(ssl);
              }
#endif

       /* log info to syslog facility */
       if(debug==TRUE)
              syslog(LOG_DEBUG,"Return Code: %d, Output: %s",result,buffer);

       return;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

void my_connection_sighandler ( int  )

Definition at line 1439 of file nrpe.c.

                                       {

       syslog(LOG_ERR,"Connection has taken too long to establish. Exiting...");

       exit(STATE_CRITICAL);
       }

Here is the caller graph for this function:

int my_system ( char *  ,
int  ,
int *  ,
char *  ,
int   
)

Definition at line 1263 of file nrpe.c.

                                                                                          {
        pid_t pid;
       int status;
       int result;
       extern int errno;
       char buffer[MAX_INPUT_BUFFER];
       int fd[2];
       FILE *fp;
       int bytes_read=0;
       time_t start_time,end_time;

       /* initialize return variables */
       if(output!=NULL)
              strcpy(output,"");
       *early_timeout=FALSE;

       /* if no command was passed, return with no error */
       if(command==NULL)
               return STATE_OK;

       /* create a pipe */
       pipe(fd);

       /* make the pipe non-blocking */
       fcntl(fd[0],F_SETFL,O_NONBLOCK);
       fcntl(fd[1],F_SETFL,O_NONBLOCK);

       /* get the command start time */
       time(&start_time);

       /* fork */
       pid=fork();

       /* return an error if we couldn't fork */
       if(pid==-1){

              snprintf(buffer,sizeof(buffer)-1,"NRPE: Call to fork() failed\n");
              buffer[sizeof(buffer)-1]='\x0';

              if(output!=NULL){
                     strncpy(output,buffer,output_length-1);
                     output[output_length-1]='\x0';
                      }

              /* close both ends of the pipe */
              close(fd[0]);
              close(fd[1]);
              
               return STATE_UNKNOWN;  
               }

       /* execute the command in the child process */
        if(pid==0){

              /* close pipe for reading */
              close(fd[0]);

              /* become process group leader */
              setpgid(0,0);

              /* trap commands that timeout */
              signal(SIGALRM,my_system_sighandler);
              alarm(timeout);

              /* run the command */
              fp=popen(command,"r");
              
              /* report an error if we couldn't run the command */
              if(fp==NULL){

                     strncpy(buffer,"NRPE: Call to popen() failed\n",sizeof(buffer)-1);
                     buffer[sizeof(buffer)-1]='\x0';

                     /* write the error back to the parent process */
                     write(fd[1],buffer,strlen(buffer)+1);

                     result=STATE_CRITICAL;
                      }
              else{

                     /* read all lines of output - supports Nagios 3.x multiline output */
                     while((bytes_read=fread(buffer,1,sizeof(buffer)-1,fp))>0){

                            /* write the output back to the parent process */
                            write(fd[1],buffer,bytes_read);
                            }

                     /* close the command and get termination status */
                     status=pclose(fp);

                     /* report an error if we couldn't close the command */
                     if(status==-1)
                            result=STATE_CRITICAL;
                     /* report an error if child died due to signal (Klas Lindfors) */
                     else if(!WIFEXITED(status))
                            result=STATE_CRITICAL;
                     else
                            result=WEXITSTATUS(status);
                      }

              /* close pipe for writing */
              close(fd[1]);

              /* reset the alarm */
              alarm(0);

              /* return plugin exit code to parent process */
              exit(result);
               }

       /* parent waits for child to finish executing command */
       else{
              
              /* close pipe for writing */
              close(fd[1]);

              /* wait for child to exit */
              waitpid(pid,&status,0);

              /* get the end time for running the command */
              time(&end_time);

              /* get the exit code returned from the program */
              result=WEXITSTATUS(status);

              /* because of my idiotic idea of having UNKNOWN states be equivalent to -1, I must hack things a bit... */
              if(result==255)
                     result=STATE_UNKNOWN;

              /* check bounds on the return value */
              if(result<0 || result>3)
                     result=STATE_UNKNOWN;

              /* try and read the results from the command output (retry if we encountered a signal) */
              if(output!=NULL){
                     do{
                            bytes_read=read(fd[0], output, output_length-1);
                     }while (bytes_read==-1 && errno==EINTR);

                     if(bytes_read==-1)
                            *output='\0';
                     else
                            output[bytes_read]='\0';
                     }

              /* if there was a critical return code and no output AND the command time exceeded the timeout thresholds, assume a timeout */
              if(result==STATE_CRITICAL && bytes_read==-1 && (end_time-start_time)>=timeout){
                     *early_timeout=TRUE;

                     /* send termination signal to child process group */
                     kill((pid_t)(-pid),SIGTERM);
                     kill((pid_t)(-pid),SIGKILL);
                      }

              /* close the pipe for reading */
              close(fd[0]);
               }

#ifdef DEBUG
       printf("my_system() end\n");
#endif

       return result;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

void my_system_sighandler ( int  )

Definition at line 1431 of file nrpe.c.

                                  {

       /* force the child process to exit... */
       exit(STATE_CRITICAL);
        }

Here is the caller graph for this function:

int process_arguments ( int  argc,
char **  argv 
)

Definition at line 313 of file check_nrpe.c.

                                            {
       char optchars[MAX_INPUT_BUFFER];
       int argindex=0;
       int c=1;
       int i=1;

#ifdef HAVE_GETOPT_LONG
       int option_index=0;
       static struct option long_options[]={
              {"host", required_argument, 0, 'H'},
              {"command", required_argument, 0, 'c'},
              {"args", required_argument, 0, 'a'},
              {"no-ssl", no_argument, 0, 'n'},
              {"unknown-timeout", no_argument, 0, 'u'},
              {"timeout", required_argument, 0, 't'},
              {"port", required_argument, 0, 'p'},
              {"help", no_argument, 0, 'h'},
              {"license", no_argument, 0, 'l'},
              {0, 0, 0, 0}
                };
#endif

       /* no options were supplied */
       if(argc<2)
              return ERROR;

       snprintf(optchars,MAX_INPUT_BUFFER,"H:c:a:t:p:nuhl");

       while(1){
#ifdef HAVE_GETOPT_LONG
              c=getopt_long(argc,argv,optchars,long_options,&option_index);
#else
              c=getopt(argc,argv,optchars);
#endif
              if(c==-1 || c==EOF)
                     break;

              /* process all arguments */
              switch(c){

              case '?':
              case 'h':
                     show_help=TRUE;
                     break;
              case 'V':
                     show_version=TRUE;
                     break;
              case 'l':
                     show_license=TRUE;
                     break;
              case 't':
                     socket_timeout=atoi(optarg);
                     if(socket_timeout<=0)
                            return ERROR;
                     break;
              case 'p':
                     server_port=atoi(optarg);
                     if(server_port<=0)
                            return ERROR;
                     break;
              case 'H':
                     server_name=strdup(optarg);
                     break;
              case 'c':
                     command_name=strdup(optarg);
                     break;
              case 'a':
                     argindex=optind;
                     break;
              case 'n':
                     use_ssl=FALSE;
                     break;
              case 'u':
                     timeout_return_code=STATE_UNKNOWN;
                     break;
              default:
                     return ERROR;
                     break;
                      }
               }

       /* determine (base) command query */
       snprintf(query,sizeof(query),"%s",(command_name==NULL)?DEFAULT_NRPE_COMMAND:command_name);
       query[sizeof(query)-1]='\x0';

       /* get the command args */
       if(argindex>0){

              for(c=argindex-1;c<argc;c++){

                     i=sizeof(query)-strlen(query)-2;
                     if(i<=0)
                            break;

                     strcat(query,"!");
                     strncat(query,argv[c],i);
                     query[sizeof(query)-1]='\x0';
                      }
               }

       /* make sure required args were supplied */
       if(server_name==NULL && show_help==FALSE && show_version==FALSE  && show_license==FALSE)
              return ERROR;


       return OK;
        }

Here is the caller graph for this function:

int process_macros ( char *  ,
char *  ,
int   
)

Definition at line 1775 of file nrpe.c.

                                                                            {
       char *temp_buffer;
       int in_macro;
       int arg_index=0;
       char *selected_macro=NULL;

       strcpy(output_buffer,"");

       in_macro=FALSE;

       for(temp_buffer=my_strsep(&input_buffer,"$");temp_buffer!=NULL;temp_buffer=my_strsep(&input_buffer,"$")){

              selected_macro=NULL;

              if(in_macro==FALSE){
                     if(strlen(output_buffer)+strlen(temp_buffer)<buffer_length-1){
                            strncat(output_buffer,temp_buffer,buffer_length-strlen(output_buffer)-1);
                            output_buffer[buffer_length-1]='\x0';
                             }
                     in_macro=TRUE;
                     }
              else{

                     if(strlen(output_buffer)+strlen(temp_buffer)<buffer_length-1){

                            /* argument macro */
                            if(strstr(temp_buffer,"ARG")==temp_buffer){
                                   arg_index=atoi(temp_buffer+3);
                                   if(arg_index>=1 && arg_index<=MAX_COMMAND_ARGUMENTS)
                                          selected_macro=macro_argv[arg_index-1];
                                    }

                            /* an escaped $ is done by specifying two $$ next to each other */
                            else if(!strcmp(temp_buffer,"")){
                                   strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
                                    }
                            
                            /* a non-macro, just some user-defined string between two $s */
                            else{
                                   strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
                                   output_buffer[buffer_length-1]='\x0';
                                   strncat(output_buffer,temp_buffer,buffer_length-strlen(output_buffer)-1);
                                   output_buffer[buffer_length-1]='\x0';
                                   strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
                                    }

                            
                            /* insert macro */
                            if(selected_macro!=NULL)
                                   strncat(output_buffer,(selected_macro==NULL)?"":selected_macro,buffer_length-strlen(output_buffer)-1);

                            output_buffer[buffer_length-1]='\x0';
                            }

                     in_macro=FALSE;
                     }
              }

       return OK;
       }

Here is the call graph for this function:

Here is the caller graph for this function:

int read_config_dir ( char *  )

Definition at line 538 of file nrpe.c.

                                  {
       char config_file[MAX_FILENAME_LENGTH];
       DIR *dirp;
       struct dirent *dirfile;
       struct stat buf;
       int result=OK;
       int x;

       /* open the directory for reading */
       dirp=opendir(dirname);
        if(dirp==NULL){
              syslog(LOG_ERR,"Could not open config directory '%s' for reading.\n",dirname);
              return ERROR;
               }

       /* process all files in the directory... */
       while((dirfile=readdir(dirp))!=NULL){

              /* create the full path to the config file or subdirectory */
              snprintf(config_file,sizeof(config_file)-1,"%s/%s",dirname,dirfile->d_name);
              config_file[sizeof(config_file)-1]='\x0';
              stat(config_file, &buf);

              /* process this if it's a config file... */
              x=strlen(dirfile->d_name);
              if(x>4 && !strcmp(dirfile->d_name+(x-4),".cfg")){

                     /* only process normal files */
                     if(!S_ISREG(buf.st_mode))
                            continue;

                     /* process the config file */
                     result=read_config_file(config_file);

                     /* break out if we encountered an error */
                     if(result==ERROR)
                            break;
                      }

              /* recurse into subdirectories... */
              if(S_ISDIR(buf.st_mode)){

                     /* ignore current, parent and hidden directory entries */
                     if(dirfile->d_name[0]=='.')
                            continue;

                     /* process the config directory */
                     result=read_config_dir(config_file);

                     /* break out if we encountered an error */
                     if(result==ERROR)
                            break;
                      }
              }

       closedir(dirp);

       return result;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

int read_config_file ( char *  )

Definition at line 360 of file nrpe.c.

                                    {
       FILE *fp;
       char config_file[MAX_FILENAME_LENGTH];
       char input_buffer[MAX_INPUT_BUFFER];
       char *input_line;
       char *temp_buffer;
       char *varname;
       char *varvalue;
       int line=0;
       int len=0;
       int x=0;


       /* open the config file for reading */
       fp=fopen(filename,"r");

       /* exit if we couldn't open the config file */
       if(fp==NULL){
              syslog(LOG_ERR,"Unable to open config file '%s' for reading\n",filename);
              return ERROR;
               }

       while(fgets(input_buffer,MAX_INPUT_BUFFER-1,fp)){

              line++;
              input_line=input_buffer;

              /* skip leading whitespace */
              while(isspace(*input_line))
                     ++input_line;

              /* trim trailing whitespace */
              len=strlen(input_line);
              for(x=len-1;x>=0;x--){
                     if(isspace(input_line[x]))
                            input_line[x]='\x0';
                     else
                            break;
                      }

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

              /* get the variable name */
              varname=strtok(input_line,"=");
              if(varname==NULL){
                     syslog(LOG_ERR,"No variable name specified in config file '%s' - Line %d\n",filename,line);
                     return ERROR;
                      }

              /* get the variable value */
              varvalue=strtok(NULL,"\n");
              if(varvalue==NULL){
                     syslog(LOG_ERR,"No variable value specified in config file '%s' - Line %d\n",filename,line);
                     return ERROR;
                      }

              /* allow users to specify directories to recurse into for config files */
              else if(!strcmp(varname,"include_dir")){

                     strncpy(config_file,varvalue,sizeof(config_file)-1);
                     config_file[sizeof(config_file)-1]='\x0';

                     /* strip trailing / if necessary */
                     if(config_file[strlen(config_file)-1]=='/')
                            config_file[strlen(config_file)-1]='\x0';

                     /* process the config directory... */
                     if(read_config_dir(config_file)==ERROR)
                            syslog(LOG_ERR,"Continuing with errors...");
                     }

              /* allow users to specify individual config files to include */
              else if(!strcmp(varname,"include") || !strcmp(varname,"include_file")){

                     /* process the config file... */
                     if(read_config_file(varvalue)==ERROR)
                            syslog(LOG_ERR,"Continuing with errors...");
                      }

              else if(!strcmp(varname,"server_port")){
                     server_port=atoi(varvalue);
                     if(server_port<1024){
                            syslog(LOG_ERR,"Invalid port number specified in config file '%s' - Line %d\n",filename,line);
                            return ERROR;
                             }
                      }
              else if(!strcmp(varname,"command_prefix"))
                     command_prefix=strdup(varvalue);

              else if(!strcmp(varname,"server_address")){
                        strncpy(server_address,varvalue,sizeof(server_address) - 1);
                        server_address[sizeof(server_address)-1]='\0';
                        }
              else if(!strcmp(varname,"allowed_hosts")) {
                            allowed_hosts=strdup(varvalue);
                            parse_allowed_hosts(allowed_hosts);
              }
              else if(strstr(input_line,"command[")){
                     temp_buffer=strtok(varname,"[");
                     temp_buffer=strtok(NULL,"]");
                     if(temp_buffer==NULL){
                            syslog(LOG_ERR,"Invalid command specified in config file '%s' - Line %d\n",filename,line);
                            return ERROR;
                             }
                     add_command(temp_buffer,varvalue);
                      }

              else if(strstr(input_buffer,"debug")){
                     debug=atoi(varvalue);
                     if(debug>0)
                            debug=TRUE;
                     else 
                            debug=FALSE;
                      }

                else if(!strcmp(varname,"nrpe_user"))
                     nrpe_user=strdup(varvalue);

                else if(!strcmp(varname,"nrpe_group"))
                     nrpe_group=strdup(varvalue);
              
              else if(!strcmp(varname,"dont_blame_nrpe"))
                     allow_arguments=(atoi(varvalue)==1)?TRUE:FALSE;

              else if(!strcmp(varname,"command_timeout")){
                     command_timeout=atoi(varvalue);
                     if(command_timeout<1){
                            syslog(LOG_ERR,"Invalid command_timeout specified in config file '%s' - Line %d\n",filename,line);
                            return ERROR;
                             }
                      }

              else if(!strcmp(varname,"connection_timeout")){
                     connection_timeout=atoi(varvalue);
                     if(connection_timeout<1){
                            syslog(LOG_ERR,"Invalid connection_timeout specified in config file '%s' - Line %d\n",filename,line);
                            return ERROR;
                             }
                      }

              else if(!strcmp(varname,"allow_weak_random_seed"))
                     allow_weak_random_seed=(atoi(varvalue)==1)?TRUE:FALSE;

              else if(!strcmp(varname,"pid_file"))
                     pid_file=strdup(varvalue);

              else if(!strcmp(varname,"log_facility")){
                     if((get_log_facility(varvalue))==OK){
                            /* re-open log using new facility */
                            closelog();
                            openlog("nrpe",LOG_PID,log_facility); 
                            }
                     else
                            syslog(LOG_WARNING,"Invalid log_facility specified in config file '%s' - Line %d\n",filename,line);
                     }

              else{
                     syslog(LOG_WARNING,"Unknown option specified in config file '%s' - Line %d\n",filename,line);
                     continue;
                      }

               }


       /* close the config file */
       fclose(fp);

       return OK;
       }

Here is the call graph for this function:

Here is the caller graph for this function:

int remove_pid_file ( void  )

Definition at line 1573 of file nrpe.c.

                         {

       /* no pid file was specified */
       if(pid_file==NULL)
              return OK;

       /* pid file was not written */
       if(wrote_pid_file==FALSE)
              return OK;

       /* remove existing pid file */
       if(unlink(pid_file)==-1){
              syslog(LOG_ERR,"Cannot remove pidfile '%s' - check your privileges.",pid_file);
              return ERROR;
               }

       return OK;
        }

Here is the caller graph for this function:

void sighandler ( int  )

Definition at line 1613 of file nrpe.c.

                        {
       static char *sigs[]={"EXIT","HUP","INT","QUIT","ILL","TRAP","ABRT","BUS","FPE","KILL","USR1","SEGV","USR2","PIPE","ALRM","TERM","STKFLT","CHLD","CONT","STOP","TSTP","TTIN","TTOU","URG","XCPU","XFSZ","VTALRM","PROF","WINCH","IO","PWR","UNUSED","ZERR","DEBUG",(char *)NULL};
       int i;

       if(sig<0)
              sig=-sig;

       for(i=0;sigs[i]!=(char *)NULL;i++);

       sig%=i;

       /* we received a SIGHUP, so restart... */
       if(sig==SIGHUP){

              sigrestart=TRUE;

              syslog(LOG_NOTICE,"Caught SIGHUP - restarting...\n");
               }

       /* else begin shutting down... */
       if(sig==SIGTERM){

              /* if shutdown is already true, we're in a signal trap loop! */
              if(sigshutdown==TRUE)
                     exit(STATE_CRITICAL);

              sigshutdown=TRUE;

              syslog(LOG_NOTICE,"Caught SIG%s - shutting down...\n",sigs[sig]);
               }

       return;
        }

Here is the caller graph for this function:

int validate_request ( packet )

Definition at line 1665 of file nrpe.c.

                                 {
        u_int32_t packet_crc32;
        u_int32_t calculated_crc32;
       char *ptr;
#ifdef ENABLE_COMMAND_ARGUMENTS
       int x;
#endif


       /***** DECRYPT REQUEST ******/


        /* check the crc 32 value */
        packet_crc32=ntohl(pkt->crc32_value);
        pkt->crc32_value=0L;
        calculated_crc32=calculate_crc32((char *)pkt,sizeof(packet));
        if(packet_crc32!=calculated_crc32){
                syslog(LOG_ERR,"Error: Request packet had invalid CRC32.");
                return ERROR;
                }

       /* make sure this is the right type of packet */
       if(ntohs(pkt->packet_type)!=QUERY_PACKET || ntohs(pkt->packet_version)!=NRPE_PACKET_VERSION_2){
              syslog(LOG_ERR,"Error: Request packet type/version was invalid!");
              return ERROR;
               }

       /* make sure buffer is terminated */
       pkt->buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';

       /* client must send some kind of request */
       if(!strcmp(pkt->buffer,"")){
              syslog(LOG_ERR,"Error: Request contained no query!");
              return ERROR;
               }

       /* make sure request doesn't contain nasties */
       if(contains_nasty_metachars(pkt->buffer)==TRUE){
              syslog(LOG_ERR,"Error: Request contained illegal metachars!");
              return ERROR;
               }

       /* make sure the request doesn't contain arguments */
       if(strchr(pkt->buffer,'!')){
#ifdef ENABLE_COMMAND_ARGUMENTS
              if(allow_arguments==FALSE){
                     syslog(LOG_ERR,"Error: Request contained command arguments, but argument option is not enabled!");
                     return ERROR;
                       }
#else
              syslog(LOG_ERR,"Error: Request contained command arguments!");
              return ERROR;
#endif
               }

       /* get command name */
#ifdef ENABLE_COMMAND_ARGUMENTS
       ptr=strtok(pkt->buffer,"!");
#else
       ptr=pkt->buffer;
#endif 
       command_name=strdup(ptr);
       if(command_name==NULL){
              syslog(LOG_ERR,"Error: Memory allocation failed");
              return ERROR;
               }

#ifdef ENABLE_COMMAND_ARGUMENTS
       /* get command arguments */
       if(allow_arguments==TRUE){

              for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
                     ptr=strtok(NULL,"!");
                     if(ptr==NULL)
                            break;
                     macro_argv[x]=strdup(ptr);
                     if(macro_argv[x]==NULL){
                            syslog(LOG_ERR,"Error: Memory allocation failed");
                            return ERROR;
                             }
                     if(!strcmp(macro_argv[x],"")){
                            syslog(LOG_ERR,"Error: Request contained an empty command argument");
                            return ERROR;
                              }
                      }
               }
#endif

       return OK;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

void wait_for_connections ( void  )

Definition at line 703 of file nrpe.c.

                               {
       struct sockaddr_in myname;
       struct sockaddr_in *nptr;
       struct sockaddr addr;
       int rc;
       int sock, new_sd;
       socklen_t addrlen;
       pid_t pid;
       int flag=1;
       fd_set fdread;
       struct timeval timeout;
       int retval;
#ifdef HAVE_LIBWRAP
       struct request_info req;
#endif

       /* create a socket for listening */
       sock=socket(AF_INET,SOCK_STREAM,0);

       /* exit if we couldn't create the socket */
       if(sock<0){
               syslog(LOG_ERR,"Network server socket failure (%d: %s)",errno,strerror(errno));
               exit(STATE_CRITICAL);
              }

       /* socket should be non-blocking */
       fcntl(sock,F_SETFL,O_NONBLOCK);

        /* set the reuse address flag so we don't get errors when restarting */
        flag=1;
        if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){
              syslog(LOG_ERR,"Could not set reuse address option on socket!\n");
              exit(STATE_UNKNOWN);
               }

       myname.sin_family=AF_INET;
       myname.sin_port=htons(server_port);
       bzero(&myname.sin_zero,8);

       /* what address should we bind to? */
        if(!strlen(server_address))
              myname.sin_addr.s_addr=INADDR_ANY;

       else if(!my_inet_aton(server_address,&myname.sin_addr)){
              syslog(LOG_ERR,"Server address is not a valid IP address\n");
              exit(STATE_CRITICAL);
                }

       /* bind the address to the Internet socket */
       if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){
              syslog(LOG_ERR,"Network server bind failure (%d: %s)\n",errno,strerror(errno));
               exit(STATE_CRITICAL);
               }

       /* open the socket for listening */
       if(listen(sock,5)<0){
              syslog(LOG_ERR,"Network server listen failure (%d: %s)\n",errno,strerror(errno));
               exit(STATE_CRITICAL);
              }

       /* log warning about command arguments */
#ifdef ENABLE_COMMAND_ARGUMENTS
       if(allow_arguments==TRUE)
              syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments from clients!");
#endif

       syslog(LOG_INFO,"Listening for connections on port %d\n",htons(myname.sin_port));

       if(allowed_hosts)
              syslog(LOG_INFO,"Allowing connections from: %s\n",allowed_hosts);

       /* listen for connection requests - fork() if we get one */
       while(1){

              /* wait for a connection request */
               while(1){

                     /* wait until there's something to do */
                     FD_ZERO(&fdread);
                     FD_SET(sock,&fdread);
                     timeout.tv_sec=0;
                     timeout.tv_usec=500000;
                     retval=select(sock+1,&fdread,NULL,&fdread,&timeout);

                     /* bail out if necessary */
                     if(sigrestart==TRUE || sigshutdown==TRUE)
                            break;

                     /* error */
                     if(retval<0)
                            continue;

                     /* accept a new connection request */
                     new_sd=accept(sock,0,0);

                     /* some kind of error occurred... */
                     if(new_sd<0){

                            /* bail out if necessary */
                            if(sigrestart==TRUE || sigshutdown==TRUE)
                                   break;

                            /* retry */
                            if(errno==EWOULDBLOCK || errno==EINTR)
                                   continue;

                            /* socket is nonblocking and we don't have a connection yet */
                            if(errno==EAGAIN)
                                   continue;

                            /* fix for HP-UX 11.0 - just retry */
                            if(errno==ENOBUFS)
                                   continue;

                            /* else handle the error later */
                            break;
                             }

                     /* connection was good */
                     break;
                      }

              /* bail out if necessary */
              if(sigrestart==TRUE || sigshutdown==TRUE)
                     break;

              /* child process should handle the connection */
              pid=fork();
              if(pid==0){

                     /* fork again so we don't create zombies */
                     pid=fork();
                     if(pid==0){

                            /* hey, there was an error... */
                            if(new_sd<0){

                                   /* log error to syslog facility */
                                   syslog(LOG_ERR,"Network server accept failure (%d: %s)",errno,strerror(errno));

                                   /* close socket prioer to exiting */
                                   close(sock);
                     
                                   return;
                                    }

                            /* handle signals */
                            signal(SIGQUIT,child_sighandler);
                            signal(SIGTERM,child_sighandler);
                            signal(SIGHUP,child_sighandler);

                            /* grandchild does not need to listen for connections, so close the socket */
                            close(sock);  

                            /* find out who just connected... */
                            addrlen=sizeof(addr);
                            rc=getpeername(new_sd,&addr,&addrlen);

                            if(rc<0){

                                    /* log error to syslog facility */
                                   syslog(LOG_ERR,"Error: Network server getpeername() failure (%d: %s)",errno,strerror(errno));

                                    /* close socket prior to exiting */
                                   close(new_sd);

                                   return;
                                      }

                            nptr=(struct sockaddr_in *)&addr;

                            /* log info to syslog facility */
                            if(debug==TRUE)
                                   syslog(LOG_DEBUG,"Connection from %s port %d",inet_ntoa(nptr->sin_addr),nptr->sin_port);

                            /* is this is a blessed machine? */
                            if(allowed_hosts){
                     switch(nptr->sin_family) {
                     case AF_INET:
                            if(!is_an_allowed_host(nptr->sin_addr)) {
                                   /* log error to syslog facility */
                                   syslog(LOG_ERR,"Host %s is not allowed to talk to us!",inet_ntoa(nptr->sin_addr));

                                                        /* log info to syslog facility */
                                                        if ( debug==TRUE )
                                   syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr));

                                                        /* close socket prior to exiting */
                                                        close(new_sd);
                                                        exit(STATE_OK);
                                                        } else {
                                                               /* log info to syslog facility */
                                                               if(debug==TRUE)
                                                                      syslog(LOG_DEBUG,"Host address is in allowed_hosts");

                                                        }
                                                 break;
                           
                                          case AF_INET6:
                                                 syslog(LOG_DEBUG,"Connection from %s closed. We don't support AF_INET6 addreess family in ACL\n", inet_ntoa(nptr->sin_addr));
                                                 break;
                                   }
                            }

#ifdef HAVE_LIBWRAP

                            /* Check whether or not connections are allowed from this host */
                            request_init(&req,RQ_DAEMON,"nrpe",RQ_FILE,new_sd,0);
                            fromhost(&req);

                            if(!hosts_access(&req)){

                                   syslog(LOG_DEBUG,"Connection refused by TCP wrapper");

                                   /* refuse the connection */
                                   refuse(&req);
                                   close(new_sd);

                                   /* should not be reached */
                                   syslog(LOG_ERR,"libwrap refuse() returns!");
                                   exit(STATE_CRITICAL);
                                   }
#endif

                            /* handle the client connection */
                            handle_connection(new_sd);

                            /* log info to syslog facility */
                            if(debug==TRUE)
                                   syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr));

                            /* close socket prior to exiting */
                            close(new_sd);

                            exit(STATE_OK);
                             }

                     /* first child returns immediately, grandchild is inherited by INIT process -> no zombies... */
                     else
                            exit(STATE_OK);
                      }
              
              /* parent ... */
              else{
                     /* parent doesn't need the new connection */
                     close(new_sd);

                     /* parent waits for first child to exit */
                     waitpid(pid,NULL,0);
                      }
              }

       /* close the socket we're listening on */
       close(sock);

       return;
       }

Here is the call graph for this function:

Here is the caller graph for this function:

int write_pid_file ( void  )

Definition at line 1522 of file nrpe.c.

                        {
       int fd;
       int result=0;
       pid_t pid=0;
       char pbuf[16];

       /* no pid file was specified */
       if(pid_file==NULL)
              return OK;

       /* read existing pid file */
       if((fd=open(pid_file,O_RDONLY))>=0){

              result=read(fd,pbuf,(sizeof pbuf)-1);

              close(fd);

              if(result>0){

                     pbuf[result]='\x0';
                     pid=(pid_t)atoi(pbuf);

                     /* if previous process is no longer running running, remove the old pid file */
                     if(pid && (pid==getpid() || kill(pid,0)<0))
                            unlink(pid_file);

                     /* previous process is still running */
                     else{
                            syslog(LOG_ERR,"There's already an NRPE server running (PID %lu).  Bailing out...",(unsigned long)pid);
                            return ERROR;
                             }
                      }
               } 

       /* write new pid file */
       if((fd=open(pid_file,O_WRONLY | O_CREAT,0644))>=0){
              sprintf(pbuf,"%d\n",(int)getpid());
              write(fd,pbuf,strlen(pbuf));
              close(fd);
              wrote_pid_file=TRUE;
               }
       else{
              syslog(LOG_ERR,"Cannot write to pidfile '%s' - check your privileges.",pid_file);
               }

       return OK;
        }

Here is the caller graph for this function: