1 /*******************************************************************************
2 *
3 * NSCA.C - Nagios Service Check Acceptor
4 * Copyright (c) 2000-2007 Ethan Galstad (nagios@nagios.org)
5 * License: GPL v2
6 *
7 * Last Modified: 07-03-2007
8 *
9 * Command line: NSCA -c <config_file> [mode]
10 *
11 * Description:
12 *
13 * This program is designed to run as a daemon on the main Nagios machine
14 * and accept service check results from remote hosts.
15 *
16 ******************************************************************************/
17
18 #include "../include/common.h"
19 #include "../include/config.h"
20 #include "../include/netutils.h"
21 #include "../include/utils.h"
22 #include "../include/nsca.h"
23
24
25 static int server_port=DEFAULT_SERVER_PORT;
26 static char server_address[16]="0.0.0.0";
27 static int socket_timeout=DEFAULT_SOCKET_TIMEOUT;
28
29 static char config_file[MAX_INPUT_BUFFER]="nsca.cfg";
30 static char alternate_dump_file[MAX_INPUT_BUFFER]="/dev/null";
31 static char command_file[MAX_INPUT_BUFFER]="";
32 static char password[MAX_INPUT_BUFFER]="";
33
34 static enum { OPTIONS_ERROR, SINGLE_PROCESS_DAEMON, MULTI_PROCESS_DAEMON, INETD } mode=SINGLE_PROCESS_DAEMON;
35 static int debug=FALSE;
36 static int aggregate_writes=FALSE;
37 static int decryption_method=ENCRYPT_XOR;
38 static int append_to_file=FALSE;
39 static unsigned long max_packet_age=30;
40
41 char *nsca_user=NULL;
42 char *nsca_group=NULL;
43
44 char *nsca_chroot=NULL;
45
46 char *pid_file=NULL;
47 int wrote_pid_file=FALSE;
48
49 int show_help=FALSE;
50 int show_license=FALSE;
51 int show_version=FALSE;
52
53 int sigrestart=FALSE;
54 int sigshutdown=FALSE;
55
56 static FILE *command_file_fp=NULL;
57
58 struct handler_entry *rhand=NULL;
59 struct handler_entry *whand=NULL;
60 struct pollfd *pfds=NULL;
61 int maxrhand=0;
62 int maxwhand=0;
63 int maxpfds=0;
64 int nrhand=0;
65 int nwhand=0;
66 int npfds=0;
67
68 #ifdef HAVE_LIBWRAP
69 int allow_severity=LOG_INFO;
70 int deny_severity=LOG_WARNING;
71 #endif
72
73
74
main(int argc,char ** argv)75 int main(int argc, char **argv){
76 char buffer[MAX_INPUT_BUFFER];
77 int result;
78 uid_t uid=-1;
79 gid_t gid=-1;
80
81
82 /* process command-line arguments */
83 result=process_arguments(argc,argv);
84
85 if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){
86
87 if(result!=OK)
88 printf("Incorrect command line arguments supplied\n");
89 printf("\n");
90 printf("NSCA - Nagios Service Check Acceptor\n");
91 printf("Copyright (c) 2000-2007 Ethan Galstad (www.nagios.org)\n");
92 printf("Version: %s\n",PROGRAM_VERSION);
93 printf("Last Modified: %s\n",MODIFICATION_DATE);
94 printf("License: GPL v2\n");
95 printf("Encryption Routines: ");
96 #ifdef HAVE_LIBMCRYPT
97 printf("AVAILABLE");
98 #else
99 printf("NOT AVAILABLE");
100 #endif
101 printf("\n");
102 #ifdef HAVE_LIBWRAP
103 printf("TCP Wrappers Available\n");
104 #endif
105 printf("\n");
106 }
107
108 if(result!=OK || show_help==TRUE){
109 printf("Usage: %s -c <config_file> [mode]\n",argv[0]);
110 printf("\n");
111 printf("Options:\n");
112 printf(" <config_file> = Name of config file to use\n");
113 printf(" [mode] = Determines how NSCA should run. Valid modes:\n");
114 printf(" --inetd = Run as a service under inetd or xinetd\n");
115 printf(" --daemon = Run as a standalone multi-process daemon\n");
116 printf(" --single = Run as a standalone single-process daemon (default)\n");
117 printf("\n");
118 printf("Notes:\n");
119 printf("This program is designed to accept passive check results from\n");
120 printf("remote hosts that use the send_nsca utility. Can run as a service\n");
121 printf("under inetd or xinetd (read the docs for info on this), or as a\n");
122 printf("standalone daemon.\n");
123 printf("\n");
124 }
125
126 if(show_license==TRUE)
127 display_license();
128
129 if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
130 do_exit(STATE_UNKNOWN);
131
132
133 /* open a connection to the syslog facility */
134 openlog("nsca",LOG_PID|LOG_NDELAY,LOG_DAEMON);
135
136 /* make sure the config file uses an absolute path */
137 if(config_file[0]!='/'){
138
139 /* save the name of the config file */
140 strncpy(buffer,config_file,sizeof(buffer));
141 buffer[sizeof(buffer)-1]='\0';
142
143 /* get absolute path of current working directory */
144 strcpy(config_file,"");
145 getcwd(config_file,sizeof(config_file));
146
147 /* append a forward slash */
148 strncat(config_file,"/",sizeof(config_file)-2);
149 config_file[sizeof(config_file)-1]='\0';
150
151 /* append the config file to the path */
152 strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1);
153 config_file[sizeof(config_file)-1]='\0';
154 }
155
156 /* read the config file */
157 result=read_config_file(config_file);
158
159 /* exit if there are errors... */
160 if(result==ERROR)
161 do_exit(STATE_CRITICAL);
162
163 /* generate the CRC 32 table */
164 generate_crc32_table();
165
166
167 /* how should we handle client connections? */
168 switch(mode){
169
170 case INETD:
171 /* chroot if configured */
172 do_chroot();
173
174 /* if we're running under inetd, handle one connection and get out */
175 handle_connection(0,NULL);
176 break;
177
178 case MULTI_PROCESS_DAEMON:
179
180 /* older style, mult-process daemon */
181 /* execution cascades below... */
182 install_child_handler();
183
184 /* |
185 |
186 | */
187 case SINGLE_PROCESS_DAEMON:
188 /* |
189 |
190 V */
191
192 /* daemonize and start listening for requests... */
193 if(fork()==0){
194
195 /* we're a daemon - set up a new process group */
196 setsid();
197
198 /* handle signals */
199 signal(SIGQUIT,sighandler);
200 signal(SIGTERM,sighandler);
201 signal(SIGHUP,sighandler);
202
203 /* close standard file descriptors */
204 close(0);
205 close(1);
206 close(2);
207
208 /* redirect standard descriptors to /dev/null */
209 open("/dev/null",O_RDONLY);
210 open("/dev/null",O_WRONLY);
211 open("/dev/null",O_WRONLY);
212
213 /* get group information before chrooting */
214 get_user_info(nsca_user,&uid);
215 get_group_info(nsca_group,&gid);
216
217 /* write pid file */
218 if(write_pid_file(uid,gid)==ERROR)
219 return STATE_CRITICAL;
220
221 /* chroot if configured */
222 do_chroot();
223
224 /* drop privileges */
225 if(drop_privileges(nsca_user,uid,gid)==ERROR)
226 do_exit(STATE_CRITICAL);
227
228 do{
229
230 /* reset flags */
231 sigrestart=FALSE;
232 sigshutdown=FALSE;
233
234 /* wait for connections */
235 wait_for_connections();
236
237 if(sigrestart==TRUE){
238
239 /* re-read the config file */
240 result=read_config_file(config_file);
241
242 /* exit if there are errors... */
243 if(result==ERROR){
244 syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file);
245 break;
246 }
247 }
248
249 }while(sigrestart==TRUE && sigshutdown==FALSE);
250
251 /* remove pid file */
252 remove_pid_file();
253
254 syslog(LOG_NOTICE,"Daemon shutdown\n");
255 }
256 break;
257
258 default:
259 break;
260 }
261
262 /* we are now running in daemon mode, or the connection handed over by inetd has been completed, so the parent process exits */
263 do_exit(STATE_OK);
264
265 /* keep the compilers happy... */
266 return STATE_OK;
267 }
268
269
270 /* cleanup */
do_cleanup(void)271 static void do_cleanup(void){
272
273 /* close the command file if its still open */
274 if(command_file_fp!=NULL)
275 close_command_file();
276
277 /*** CLEAR SENSITIVE INFO FROM MEMORY ***/
278
279 /* overwrite password */
280 clear_buffer(password,sizeof(password));
281
282 /* disguise decryption method */
283 decryption_method=-1;
284
285 return;
286 }
287
288
289 /* exit cleanly */
do_exit(int return_code)290 static void do_exit(int return_code){
291
292 do_cleanup();
293
294 exit(return_code);
295 }
296
297
298
299 /* read in the configuration file */
read_config_file(char * filename)300 static int read_config_file(char *filename){
301 FILE *fp;
302 char input_buffer[MAX_INPUT_BUFFER];
303 char *varname;
304 char *varvalue;
305 int line;
306
307 /* open the config file for reading */
308 fp=fopen(filename,"r");
309
310 /* exit if we couldn't open the config file */
311 if(fp==NULL){
312 syslog(LOG_ERR,"Could not open config file '%s' for reading\n",filename);
313 return ERROR;
314 }
315
316 line=0;
317 while(fgets(input_buffer,MAX_INPUT_BUFFER-1,fp)){
318
319 line++;
320
321 /* skip comments and blank lines */
322 if(input_buffer[0]=='#')
323 continue;
324 if(input_buffer[0]=='\0')
325 continue;
326 if(input_buffer[0]=='\n')
327 continue;
328
329 /* get the variable name */
330 varname=strtok(input_buffer,"=");
331 if(varname==NULL){
332 syslog(LOG_ERR,"No variable name specified in config file '%s' - Line %d\n",filename,line);
333 return ERROR;
334 }
335
336 /* get the variable value */
337 varvalue=strtok(NULL,"\n");
338 if(varvalue==NULL){
339 syslog(LOG_ERR,"No variable value specified in config file '%s' - Line %d\n",filename,line);
340 return ERROR;
341 }
342
343 if(!strcmp(varname,"server_port")){
344 server_port=atoi(varvalue);
345 if((server_port<1024 && (geteuid()!=0)) || server_port<0){
346 syslog(LOG_ERR,"Invalid port number specified in config file '%s' - Line %d\n",filename,line);
347 return ERROR;
348 }
349 }
350 else if(!strcmp(varname,"server_address")){
351 strncpy(server_address,varvalue,sizeof(server_address) - 1);
352 server_address[sizeof(server_address)-1]='\0';
353 }
354 else if(strstr(input_buffer,"command_file")){
355 if(strlen(varvalue)>sizeof(command_file)-1){
356 syslog(LOG_ERR,"Command file name is too long in config file '%s' - Line %d\n",filename,line);
357 return ERROR;
358 }
359 strncpy(command_file,varvalue,sizeof(command_file)-1);
360 command_file[sizeof(command_file)-1]='\0';
361 }
362 else if(strstr(input_buffer,"alternate_dump_file")){
363 if(strlen(varvalue)>sizeof(alternate_dump_file)-1){
364 syslog(LOG_ERR,"Alternate dump file name is too long in config file '%s' - Line %d\n",filename,line);
365 return ERROR;
366 }
367 strncpy(alternate_dump_file,varvalue,sizeof(alternate_dump_file)-1);
368 alternate_dump_file[sizeof(alternate_dump_file)-1]='\0';
369 }
370 else if(strstr(input_buffer,"password")){
371 if(strlen(varvalue)>sizeof(password)-1){
372 syslog(LOG_ERR,"Password is too long in config file '%s' - Line %d\n",filename,line);
373 return ERROR;
374 }
375 strncpy(password,varvalue,sizeof(password)-1);
376 password[sizeof(password)-1]='\0';
377 }
378 else if(strstr(input_buffer,"decryption_method")){
379
380 decryption_method=atoi(varvalue);
381
382 switch(decryption_method){
383 case ENCRYPT_NONE:
384 case ENCRYPT_XOR:
385 break;
386 #ifdef HAVE_LIBMCRYPT
387 case ENCRYPT_DES:
388 case ENCRYPT_3DES:
389 case ENCRYPT_CAST128:
390 case ENCRYPT_CAST256:
391 case ENCRYPT_XTEA:
392 case ENCRYPT_3WAY:
393 case ENCRYPT_BLOWFISH:
394 case ENCRYPT_TWOFISH:
395 case ENCRYPT_LOKI97:
396 case ENCRYPT_RC2:
397 case ENCRYPT_ARCFOUR:
398 case ENCRYPT_RIJNDAEL128:
399 case ENCRYPT_RIJNDAEL192:
400 case ENCRYPT_RIJNDAEL256:
401 case ENCRYPT_WAKE:
402 case ENCRYPT_SERPENT:
403 case ENCRYPT_ENIGMA:
404 case ENCRYPT_GOST:
405 case ENCRYPT_SAFER64:
406 case ENCRYPT_SAFER128:
407 case ENCRYPT_SAFERPLUS:
408 break;
409 #endif
410 default:
411 syslog(LOG_ERR,"Invalid decryption method (%d) in config file '%s' - Line %d\n",decryption_method,filename,line);
412 #ifndef HAVE_LIBMCRYPT
413 if(decryption_method>=2)
414 syslog(LOG_ERR,"Daemon was not compiled with mcrypt library, so decryption is unavailable.\n");
415 #endif
416 return ERROR;
417 }
418 }
419 else if(strstr(input_buffer,"debug")){
420 if(atoi(varvalue)>0)
421 debug=TRUE;
422 else
423 debug=FALSE;
424 }
425 else if(strstr(input_buffer,"aggregate_writes")){
426 if(atoi(varvalue)>0)
427 aggregate_writes=TRUE;
428 else
429 aggregate_writes=FALSE;
430 }
431 else if(strstr(input_buffer,"append_to_file")){
432 if(atoi(varvalue)>0)
433 append_to_file=TRUE;
434 else
435 append_to_file=FALSE;
436 }
437 else if(!strcmp(varname,"max_packet_age")){
438 max_packet_age=strtoul(varvalue,NULL,10);
439 if(max_packet_age>900){
440 syslog(LOG_ERR,"Max packet age cannot be greater than 15 minutes (900 seconds).\n");
441 return ERROR;
442 }
443 }
444
445 else if(!strcmp(varname,"nsca_user"))
446 nsca_user=strdup(varvalue);
447
448 else if(!strcmp(varname,"nsca_group"))
449 nsca_group=strdup(varvalue);
450
451 else if(!strcmp(varname,"nsca_chroot"))
452 nsca_chroot=strdup(varvalue);
453
454 else if(!strcmp(varname,"pid_file"))
455 pid_file=strdup(varvalue);
456
457 else{
458 syslog(LOG_ERR,"Unknown option specified in config file '%s' - Line %d\n",filename,line);
459
460 return ERROR;
461 }
462 }
463
464 /* close the config file */
465 fclose(fp);
466
467 return OK;
468 }
469
470
471
472 /* get rid of all the children we can... */
reap_children(int sig)473 static void reap_children(int sig){
474
475 while(waitpid(-1,NULL,WNOHANG)>0);
476
477 return;
478 }
479
480
481
482 /* install reap_children() signal handler */
install_child_handler(void)483 static void install_child_handler(void){
484 struct sigaction sa;
485
486 sa.sa_handler=reap_children;
487 sa.sa_flags=SA_NOCLDSTOP;
488 sigaction(SIGCHLD,&sa,NULL);
489
490 return;
491 }
492
493
494
495 /* register a file descriptor to be polled for an event set */
register_poll(short events,int fd)496 static void register_poll(short events, int fd){
497 int i;
498
499 /* if it's already in the list, just flag the events */
500 for(i=0;i<npfds;i++){
501 if(pfds[i].fd==fd){
502 pfds[i].events|=events;
503 return;
504 }
505 }
506
507 /* else add it to the list */
508 if(maxpfds==0){
509 maxpfds++;
510 pfds=malloc(sizeof(struct pollfd));
511 }
512 else if(npfds+1 > maxpfds){
513 maxpfds++;
514 pfds=realloc(pfds, sizeof(struct pollfd) * maxpfds);
515 }
516
517 pfds[npfds].fd=fd;
518 pfds[npfds].events=events;
519 npfds++;
520 }
521
522
523
524 /* register a read handler */
register_read_handler(int fd,void (* fp)(int,void *),void * data)525 static void register_read_handler(int fd, void (*fp)(int, void *), void *data){
526 int i;
527
528 /* register our interest in this descriptor */
529 register_poll(POLLIN,fd);
530
531 /* if it's already in the list, just update the handler */
532 for(i=0;i<nrhand;i++){
533 if(rhand[i].fd==fd){
534 rhand[i].handler=fp;
535 rhand[i].data=data;
536 return;
537 }
538 }
539
540 /* else add it to the list */
541 if(maxrhand==0){
542 maxrhand++;
543 rhand=malloc(sizeof(struct handler_entry));
544 }
545 else if(nrhand+1 > maxrhand){
546 maxrhand++;
547 rhand=realloc(rhand, sizeof(struct handler_entry) * maxrhand);
548 }
549
550 rhand[nrhand].fd=fd;
551 rhand[nrhand].handler=fp;
552 rhand[nrhand].data=data;
553 nrhand++;
554 }
555
556
557
558 /* register a write handler */
register_write_handler(int fd,void (* fp)(int,void *),void * data)559 static void register_write_handler(int fd, void (*fp)(int, void *), void *data){
560 int i;
561
562 /* register our interest in this descriptor */
563 register_poll(POLLOUT,fd);
564
565 /* if it's already in the list, just update the handler */
566 for(i=0;i<nwhand;i++){
567 if(whand[i].fd==fd){
568 whand[i].handler=fp;
569 whand[i].data=data;
570 return;
571 }
572 }
573
574 /* else add it to the list */
575 if(maxwhand==0){
576 maxwhand++;
577 whand=malloc(sizeof(struct handler_entry));
578 }
579 else if(nwhand+1 > maxwhand){
580 maxwhand++;
581 whand=realloc(whand, sizeof(struct handler_entry) * maxwhand);
582 }
583
584 whand[nwhand].fd=fd;
585 whand[nwhand].handler=fp;
586 whand[nwhand].data=data;
587 nwhand++;
588 }
589
590
591
592 /* find read handler */
find_rhand(int fd)593 static int find_rhand(int fd){
594 int i;
595
596 for(i=0;i<nrhand;i++){
597 if(rhand[i].fd==fd)
598 return i;
599 }
600
601 /* we couldn't find the read handler */
602 syslog(LOG_ERR, "Handler stack corrupt - aborting");
603 do_exit(STATE_CRITICAL);
604 }
605
606
607
608 /* find write handler */
find_whand(int fd)609 static int find_whand(int fd){
610 int i;
611
612 for(i=0;i<nwhand;i++){
613 if(whand[i].fd==fd)
614 return i;
615 }
616
617 /* we couldn't find the write handler */
618 syslog(LOG_ERR, "Handler stack corrupt - aborting");
619 do_exit(STATE_CRITICAL);
620 }
621
622
623 /* handle pending events */
handle_events(void)624 static void handle_events(void){
625 void (*handler)(int, void *);
626 void *data;
627 int i, hand;
628
629 /* bail out if necessary */
630 if(sigrestart==TRUE || sigshutdown==TRUE)
631 return;
632
633 poll(pfds,npfds,-1);
634 for(i=0;i<npfds;i++){
635 if((pfds[i].events&POLLIN) && (pfds[i].revents&(POLLIN|POLLERR|POLLHUP|POLLNVAL))){
636 pfds[i].events&=~POLLIN;
637 hand=find_rhand(pfds[i].fd);
638 handler=rhand[hand].handler;
639 data=rhand[hand].data;
640 rhand[hand].handler=NULL;
641 rhand[hand].data=NULL;
642 handler(pfds[i].fd,data);
643 }
644 if((pfds[i].events&POLLOUT) && (pfds[i].revents&(POLLOUT|POLLERR|POLLHUP|POLLNVAL))){
645 pfds[i].events&=~POLLOUT;
646 hand=find_whand(pfds[i].fd);
647 handler=whand[hand].handler;
648 data=whand[hand].data;
649 whand[hand].handler=NULL;
650 whand[hand].data=NULL;
651 handler(pfds[i].fd,data);
652 }
653 }
654
655 for(i=0;i<npfds;i++){
656 if(pfds[i].events==0){
657 npfds--;
658 pfds[i].fd=pfds[npfds].fd;
659 pfds[i].events=pfds[npfds].events;
660 }
661 }
662
663 return;
664 }
665
666
667
668 /* wait for incoming connection requests */
wait_for_connections(void)669 static void wait_for_connections(void) {
670 struct sockaddr_in myname;
671 int sock=0;
672 int flag=1;
673
674 /* create a socket for listening */
675 sock=socket(AF_INET,SOCK_STREAM,0);
676
677 /* exit if we couldn't create the socket */
678 if(sock<0){
679 syslog(LOG_ERR,"Network server socket failure (%d: %s)",errno,strerror(errno));
680 do_exit(STATE_CRITICAL);
681 }
682
683 /* set the reuse address flag so we don't get errors when restarting */
684 flag=1;
685 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){
686 syslog(LOG_ERR,"Could not set reuse address option on socket!\n");
687 do_exit(STATE_CRITICAL);
688 }
689
690 myname.sin_family=AF_INET;
691 myname.sin_port=htons(server_port);
692 bzero(&myname.sin_zero,8);
693
694 /* what address should we bind to? */
695 if(!strlen(server_address))
696 myname.sin_addr.s_addr=INADDR_ANY;
697 else if(!my_inet_aton(server_address,&myname.sin_addr)){
698 syslog(LOG_ERR,"Server address is not a valid IP address\n");
699 do_exit(STATE_CRITICAL);
700 }
701
702
703 /* bind the address to the Internet socket */
704 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){
705 syslog(LOG_ERR,"Network server bind failure (%d: %s)\n",errno,strerror(errno));
706 do_exit(STATE_CRITICAL);
707 }
708
709 /* open the socket for listening */
710 if(listen(sock,SOMAXCONN)<0){
711 syslog(LOG_ERR,"Network server listen failure (%d: %s)\n",errno,strerror(errno));
712 do_exit(STATE_CRITICAL);
713 }
714
715 /* log info to syslog facility */
716 syslog(LOG_NOTICE,"Starting up daemon");
717
718 if(debug==TRUE){
719 syslog(LOG_DEBUG,"Listening for connections on port %d\n",htons(myname.sin_port));
720 }
721
722 /* socket should be non-blocking for mult-process daemon */
723 if(mode==MULTI_PROCESS_DAEMON)
724 fcntl(sock,F_SETFL,O_NONBLOCK);
725
726 /* listen for connection requests */
727 if(mode==SINGLE_PROCESS_DAEMON)
728 register_read_handler(sock,accept_connection,NULL);
729 while(1){
730
731 /* bail out if necessary */
732 if(sigrestart==TRUE || sigshutdown==TRUE){
733 /* close the socket we're listening on */
734 close(sock);
735 break;
736 }
737
738 /* accept a new connection */
739 if(mode==MULTI_PROCESS_DAEMON)
740 accept_connection(sock,NULL);
741
742 /* handle the new connection (if any) */
743 else
744 handle_events();
745 }
746
747 return;
748 }
749
750
751
accept_connection(int sock,void * unused)752 static void accept_connection(int sock, void *unused){
753 int new_sd;
754 pid_t pid;
755 struct sockaddr addr;
756 struct sockaddr_in *nptr;
757 socklen_t addrlen;
758 int rc;
759 #ifdef HAVE_LIBWRAP
760 struct request_info req;
761 #endif
762
763 /* DO NOT REMOVE! 01/29/2007 single process daemon will fail if this is removed */
764 if(mode==SINGLE_PROCESS_DAEMON)
765 register_read_handler(sock,accept_connection,NULL);
766
767 /* wait for a connection request */
768 while(1){
769
770 /* we got a live one... */
771 if((new_sd=accept(sock,0,0))>=0)
772 break;
773
774 /* handle the error */
775 else{
776
777 /* bail out if necessary */
778 if(sigrestart==TRUE || sigshutdown==TRUE)
779 return;
780
781 /* try and handle temporary errors */
782 if(errno==EWOULDBLOCK || errno==EINTR || errno==ECHILD){
783 if(mode==MULTI_PROCESS_DAEMON)
784 sleep(1);
785 else
786 return;
787 }
788 else
789 break;
790 }
791 }
792
793 /* hey, there was an error... */
794 if(new_sd<0){
795
796 /* log error to syslog facility */
797 syslog(LOG_ERR,"Network server accept failure (%d: %s)",errno,strerror(errno));
798
799 /* close socket prior to exiting */
800 close(sock);
801 if(mode==MULTI_PROCESS_DAEMON)
802 do_exit(STATE_CRITICAL);
803 return;
804 }
805
806 #ifdef HAVE_LIBWRAP
807
808 /* Check whether or not connections are allowed from this host */
809 request_init(&req,RQ_DAEMON,"nsca",RQ_FILE,new_sd,0);
810 fromhost(&req);
811
812 if(!hosts_access(&req)){
813 /* refuse the connection */
814 syslog(LOG_ERR, "refused connect from %s", eval_client(&req));
815 close(new_sd);
816 return;
817 }
818 #endif
819
820
821 /* fork() if we have to... */
822 if(mode==MULTI_PROCESS_DAEMON){
823
824 pid=fork();
825 if(pid){
826 /* parent doesn't need the new connection */
827 close(new_sd);
828 return;
829 }
830 else{
831 /* child does not need to listen for connections */
832 close(sock);
833 }
834 }
835
836 /* find out who just connected... */
837 addrlen=sizeof(addr);
838 rc=getpeername(new_sd,&addr,&addrlen);
839
840 if(rc<0){
841 /* log error to syslog facility */
842 syslog(LOG_ERR,"Error: Network server getpeername() failure (%d: %s)",errno,strerror(errno));
843
844 /* close socket prior to exiting */
845 close(new_sd);
846 if(mode==MULTI_PROCESS_DAEMON)
847 do_exit(STATE_CRITICAL);
848 return;
849 }
850
851 nptr=(struct sockaddr_in *)&addr;
852
853 /* log info to syslog facility */
854 if(debug==TRUE)
855 syslog(LOG_DEBUG,"Connection from %s port %d",inet_ntoa(nptr->sin_addr),nptr->sin_port);
856
857 /* handle the connection */
858 if(mode==SINGLE_PROCESS_DAEMON)
859 /* mark the connection as ready to be handled */
860 register_write_handler(new_sd, handle_connection, NULL);
861 else
862 /* handle the client connection */
863 handle_connection(new_sd, NULL);
864
865 return;
866 }
867
868
869
870 /* handle a client connection */
handle_connection(int sock,void * data)871 static void handle_connection(int sock, void *data){
872 init_packet send_packet;
873 int bytes_to_send;
874 int rc;
875 int flags;
876 time_t packet_send_time;
877 struct crypt_instance *CI;
878
879
880 /* log info to syslog facility */
881 if(debug==TRUE)
882 syslog(LOG_INFO,"Handling the connection...");
883
884 /* socket should be non-blocking */
885 fcntl(sock,F_GETFL,&flags);
886 fcntl(sock,F_SETFL,flags|O_NONBLOCK);
887
888 /* initialize encryption/decryption routines (server generates the IV to use and send to the client) */
889 if(encrypt_init(password,decryption_method,NULL,&CI)!=OK){
890 close(sock);
891 if(mode==MULTI_PROCESS_DAEMON)
892 do_exit(STATE_CRITICAL);
893 return;
894 }
895
896 /* create initial packet to send to client (contains random IV and timestamp) */
897 memcpy(&send_packet.iv[0],CI->transmitted_iv,TRANSMITTED_IV_SIZE);
898 time(&packet_send_time);
899 send_packet.timestamp=(u_int32_t)htonl(packet_send_time);
900
901 /* send client the initial packet */
902 bytes_to_send=sizeof(send_packet);
903 rc=sendall(sock,(char *)&send_packet,&bytes_to_send);
904
905 /* there was an error sending the packet */
906 if(rc==-1){
907 syslog(LOG_ERR,"Could not send init packet to client\n");
908 encrypt_cleanup(decryption_method,CI);
909 close(sock);
910 if(mode==MULTI_PROCESS_DAEMON)
911 do_exit(STATE_CRITICAL);
912 return;
913 }
914
915 /* for some reason we didn't send all the bytes we were supposed to */
916 else if(bytes_to_send<sizeof(send_packet)){
917 syslog(LOG_ERR,"Only able to send %d of %d bytes of init packet to client\n",rc,sizeof(send_packet));
918 encrypt_cleanup(decryption_method,CI);
919 close(sock);
920 if(mode==MULTI_PROCESS_DAEMON)
921 do_exit(STATE_CRITICAL);
922 return;
923 }
924
925 /* open the command file if we're aggregating writes */
926 if(aggregate_writes==TRUE && !command_file_fp){
927 if(open_command_file()==ERROR){
928 close(sock);
929 if(mode==MULTI_PROCESS_DAEMON)
930 do_exit(STATE_CRITICAL);
931 return;
932 }
933 }
934
935 if(mode==SINGLE_PROCESS_DAEMON)
936 register_read_handler(sock, handle_connection_read, (void *)CI);
937 else{
938 while(1)
939 handle_connection_read(sock,(void *)CI);
940 }
941
942 return;
943 }
944
945
946
947 /* handle reading from a client connection */
handle_connection_read(int sock,void * data)948 static void handle_connection_read(int sock, void *data){
949 data_packet receive_packet;
950 u_int32_t packet_crc32;
951 u_int32_t calculated_crc32;
952 struct crypt_instance *CI;
953 time_t packet_time;
954 time_t current_time;
955 int16_t return_code;
956 unsigned long packet_age=0L;
957 int bytes_to_recv;
958 int rc;
959 char host_name[MAX_HOSTNAME_LENGTH];
960 char svc_description[MAX_DESCRIPTION_LENGTH];
961 char plugin_output[MAX_PLUGINOUTPUT_LENGTH];
962
963 CI=data;
964
965 /* process all data we get from the client... */
966
967 /* read the packet from the client */
968 bytes_to_recv=sizeof(receive_packet);
969 rc=recvall(sock,(char *)&receive_packet,&bytes_to_recv,socket_timeout);
970
971 /* recv() error or client disconnect */
972 if(rc<=0){
973 if(debug==TRUE)
974 syslog(LOG_ERR,"End of connection...");
975 encrypt_cleanup(decryption_method, CI);
976 close(sock);
977 if(mode==SINGLE_PROCESS_DAEMON)
978 return;
979 else
980 do_exit(STATE_OK);
981 }
982
983 /* we couldn't read the correct amount of data, so bail out */
984 if(bytes_to_recv!=sizeof(receive_packet)){
985 syslog(LOG_ERR,"Data sent from client was too short (%d < %d), aborting...",bytes_to_recv,sizeof(receive_packet));
986 encrypt_cleanup(decryption_method, CI);
987 close(sock);
988 return;
989 if(mode==SINGLE_PROCESS_DAEMON)
990 return;
991 else
992 do_exit(STATE_CRITICAL);
993 }
994
995 /* if we're single-process, we need to set things up so we handle the next packet after this one... */
996 if(mode==SINGLE_PROCESS_DAEMON)
997 register_read_handler(sock, handle_connection_read, (void *)CI);
998
999 /* decrypt the packet */
1000 decrypt_buffer((char *)&receive_packet,sizeof(receive_packet),password,decryption_method,CI);
1001
1002 /* make sure this is the right type of packet */
1003 if(ntohs(receive_packet.packet_version)!=NSCA_PACKET_VERSION_3){
1004 syslog(LOG_ERR,"Received invalid packet type/version from client - possibly due to client using wrong password or crypto algorithm?");
1005 /*return;*/
1006 close(sock);
1007 if(mode==SINGLE_PROCESS_DAEMON)
1008 return;
1009 else
1010 do_exit(STATE_OK);
1011 }
1012
1013 /* check the crc 32 value */
1014 packet_crc32=ntohl(receive_packet.crc32_value);
1015 receive_packet.crc32_value=0L;
1016 calculated_crc32=calculate_crc32((char *)&receive_packet,sizeof(receive_packet));
1017 if(packet_crc32!=calculated_crc32){
1018 syslog(LOG_ERR,"Dropping packet with invalid CRC32 - possibly due to client using wrong password or crypto algorithm?");
1019 /*return;*/
1020 close(sock);
1021 if(mode==SINGLE_PROCESS_DAEMON)
1022 return;
1023 else
1024 do_exit(STATE_OK);
1025 }
1026
1027 /* check the timestamp in the packet */
1028 packet_time=(time_t)ntohl(receive_packet.timestamp);
1029 time(¤t_time);
1030 if(packet_time>current_time){
1031 syslog(LOG_ERR,"Dropping packet with future timestamp.");
1032 /*return;*/
1033 close(sock);
1034 if(mode==SINGLE_PROCESS_DAEMON)
1035 return;
1036 else
1037 do_exit(STATE_OK);
1038 }
1039 else{
1040 packet_age=(unsigned long)(current_time-packet_time);
1041 if(max_packet_age>0 && (packet_age>max_packet_age)){
1042 syslog(LOG_ERR,"Dropping packet with stale timestamp - packet was %lu seconds old.",packet_age);
1043 /*return;*/
1044 close(sock);
1045 if(mode==SINGLE_PROCESS_DAEMON)
1046 return;
1047 else
1048 do_exit(STATE_OK);
1049 }
1050 }
1051
1052 /**** GET THE SERVICE CHECK INFORMATION ****/
1053
1054 /* plugin return code */
1055 return_code=ntohs(receive_packet.return_code);
1056
1057 /* host name */
1058 strncpy(host_name,receive_packet.host_name,sizeof(host_name)-1);
1059 host_name[sizeof(host_name)-1]='\0';
1060
1061 /* service description */
1062 strncpy(svc_description,receive_packet.svc_description,sizeof(svc_description)-1);
1063 svc_description[sizeof(svc_description)-1]='\0';
1064
1065 /* plugin output */
1066 strncpy(plugin_output,receive_packet.plugin_output,sizeof(plugin_output)-1);
1067 plugin_output[sizeof(plugin_output)-1]='\0';
1068
1069 /* log info to syslog facility */
1070 if(debug==TRUE){
1071 if(!strcmp(svc_description,""))
1072 syslog(LOG_NOTICE,"HOST CHECK -> Host Name: '%s', Return Code: '%d', Output: '%s'",host_name,return_code,plugin_output);
1073 else
1074 syslog(LOG_NOTICE,"SERVICE CHECK -> Host Name: '%s', Service Description: '%s', Return Code: '%d', Output: '%s'",host_name,svc_description,return_code,plugin_output);
1075 }
1076
1077 /* write the check result to the external command file.
1078 * Note: it's OK to hang at this point if the write doesn't succeed, as there's
1079 * no way we could handle any other connection properly anyway. so we don't
1080 * use poll() - which fails on a pipe with any data, so it would cause us to
1081 * only ever write one command at a time into the pipe.
1082 */
1083 write_check_result(host_name,svc_description,return_code,plugin_output,time(NULL));
1084
1085 return;
1086 }
1087
1088
1089
1090 /* writes service/host check results to the Nagios command file */
write_check_result(char * host_name,char * svc_description,int return_code,char * plugin_output,time_t check_time)1091 static int write_check_result(char *host_name, char *svc_description, int return_code, char *plugin_output, time_t check_time){
1092
1093 if(aggregate_writes==FALSE){
1094 if(open_command_file()==ERROR)
1095 return ERROR;
1096 }
1097
1098 if(!strcmp(svc_description,""))
1099 fprintf(command_file_fp,"[%lu] PROCESS_HOST_CHECK_RESULT;%s;%d;%s\n",(unsigned long)check_time,host_name,return_code,plugin_output);
1100 else
1101 fprintf(command_file_fp,"[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",(unsigned long)check_time,host_name,svc_description,return_code,plugin_output);
1102
1103 if(aggregate_writes==FALSE)
1104 close_command_file();
1105 else
1106 /* if we don't fflush() then we're writing in 4k non-CR-terminated blocks, and
1107 * anything else (eg. pscwatch) which writes to the file will be writing into
1108 * the middle of our commands.
1109 */
1110 fflush(command_file_fp);
1111
1112 return OK;
1113 }
1114
1115
1116
1117 /* opens the command file for writing */
open_command_file(void)1118 static int open_command_file(void){
1119 struct stat statbuf;
1120
1121 /* file is already open */
1122 if(command_file_fp!=NULL)
1123 return OK;
1124
1125 /* command file doesn't exist - monitoring app probably isn't running... */
1126 if(stat(command_file,&statbuf)){
1127
1128 if(debug==TRUE)
1129 syslog(LOG_ERR,"Command file '%s' does not exist, attempting to use alternate dump file '%s' for output",command_file,alternate_dump_file);
1130
1131 /* try and write checks to alternate dump file */
1132 command_file_fp=fopen(alternate_dump_file,"a");
1133 if(command_file_fp==NULL){
1134 if(debug==TRUE)
1135 syslog(LOG_ERR,"Could not open alternate dump file '%s' for appending",alternate_dump_file);
1136 return ERROR;
1137 }
1138
1139 return OK;
1140 }
1141
1142 /* open the command file for writing or appending */
1143 command_file_fp=fopen(command_file,(append_to_file==TRUE)?"a":"w");
1144 if(command_file_fp==NULL){
1145 if(debug==TRUE)
1146 syslog(LOG_ERR,"Could not open command file '%s' for %s",command_file,(append_to_file==TRUE)?"appending":"writing");
1147 return ERROR;
1148 }
1149
1150 return OK;
1151 }
1152
1153
1154
1155 /* closes the command file */
close_command_file(void)1156 static void close_command_file(void){
1157
1158 fclose(command_file_fp);
1159 command_file_fp=NULL;
1160
1161 return;
1162 }
1163
1164
1165
1166 /* process command line arguments */
process_arguments(int argc,char ** argv)1167 int process_arguments(int argc, char **argv){
1168 int x;
1169
1170 if(argc<2){
1171 show_help=TRUE;
1172 return OK;
1173 }
1174
1175 /* process arguments */
1176 for(x=2;x<=argc;x++){
1177
1178 /* show usage */
1179 if(!strcmp(argv[x-1],"-h") || !strcmp(argv[x-1],"--help"))
1180 show_help=TRUE;
1181
1182 /* show license */
1183 else if(!strcmp(argv[x-1],"-l") || !strcmp(argv[x-1],"--license"))
1184 show_license=TRUE;
1185
1186 /* show version */
1187 else if(!strcmp(argv[x-1],"-V") || !strcmp(argv[x-1],"--version"))
1188 show_version=TRUE;
1189
1190 else if(!strcmp(argv[x-1],"-d") || !strcmp(argv[x-1],"--daemon"))
1191 mode=MULTI_PROCESS_DAEMON;
1192
1193 else if(!strcmp(argv[x-1],"-s") || !strcmp(argv[x-1],"--single"))
1194 mode=SINGLE_PROCESS_DAEMON;
1195
1196 else if(!strcmp(argv[x-1],"-i") || !strcmp(argv[x-1],"--inetd"))
1197 mode=INETD;
1198
1199 /* config file */
1200 else if(!strcmp(argv[x-1],"-c")){
1201
1202 if(x<argc){
1203 /* grab the config file */
1204 strncpy(config_file,argv[x],sizeof(config_file)-1);
1205 config_file[sizeof(config_file)-1]='\0';
1206 x++;
1207 }
1208 else
1209 return ERROR;
1210 }
1211
1212 else
1213 return ERROR;
1214 }
1215
1216 return OK;
1217 }
1218
1219
1220
1221 /* write an optional pid file */
write_pid_file(uid_t usr,gid_t grp)1222 static int write_pid_file(uid_t usr, gid_t grp){
1223 int fd;
1224 int result=0;
1225 pid_t pid=0;
1226 char pbuf[16];
1227
1228 /* no pid file was specified */
1229 if(pid_file==NULL)
1230 return OK;
1231
1232 /* read existing pid file */
1233 if((fd=open(pid_file,O_RDONLY))>=0){
1234
1235 result=read(fd,pbuf,(sizeof pbuf)-1);
1236
1237 close(fd);
1238
1239 if(result>0){
1240
1241 pbuf[result]='\x0';
1242 pid=(pid_t)atoi(pbuf);
1243
1244 /* if previous process is no longer running running, remove the old pid file */
1245 if(pid && (pid==getpid() || kill(pid,0)<0))
1246 unlink(pid_file);
1247
1248 /* previous process is still running */
1249 else{
1250 syslog(LOG_ERR,"There's already an NSCA server running (PID %lu). Bailing out...",(unsigned long)pid);
1251 return ERROR;
1252 }
1253 }
1254 }
1255
1256 /* write new pid file */
1257 if((fd=open(pid_file,O_WRONLY | O_CREAT,0644))>=0){
1258 sprintf(pbuf,"%d\n",(int)getpid());
1259 write(fd,pbuf,strlen(pbuf));
1260 fchown(fd,usr,grp);
1261 close(fd);
1262 wrote_pid_file=TRUE;
1263 }
1264 else{
1265 syslog(LOG_ERR,"Cannot write to pidfile '%s' - check your privileges.",pid_file);
1266 }
1267
1268 return OK;
1269 }
1270
1271
1272
1273 /* remove pid file */
remove_pid_file(void)1274 static int remove_pid_file(void){
1275
1276 /* no pid file was specified */
1277 if(pid_file==NULL)
1278 return OK;
1279
1280 /* pid file was not written */
1281 if(wrote_pid_file==FALSE)
1282 return OK;
1283
1284 /* remove existing pid file */
1285 if(unlink(pid_file)==-1){
1286 syslog(LOG_ERR,"Cannot remove pidfile '%s' - check your privileges.",pid_file);
1287 return ERROR;
1288 }
1289
1290 return OK;
1291 }
1292
1293
1294
1295 /* get user information */
get_user_info(const char * user,uid_t * uid)1296 static int get_user_info(const char *user, uid_t *uid){
1297 const struct passwd *pw=NULL;
1298
1299 if(user!=NULL){
1300 /* see if this is a user name */
1301 if(strspn(user,"0123456789")<strlen(user)){
1302 pw=(struct passwd *)getpwnam(user);
1303 if(pw!=NULL)
1304 *uid=(uid_t)(pw->pw_uid);
1305 else
1306 syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user);
1307 endpwent();
1308 }
1309
1310 /* else we were passed the UID */
1311 else
1312 *uid=(uid_t)atoi(user);
1313
1314 }
1315 else
1316 *uid=geteuid();
1317
1318 return OK;
1319 }
1320
1321
1322
1323 /* get group information */
get_group_info(const char * group,gid_t * gid)1324 static int get_group_info(const char *group, gid_t *gid){
1325 const struct group *grp=NULL;
1326
1327 /* get group ID */
1328 if(group!=NULL){
1329 /* see if this is a group name */
1330 if(strspn(group,"0123456789")<strlen(group)){
1331 grp=(struct group *)getgrnam(group);
1332 if(grp!=NULL)
1333 *gid=(gid_t)(grp->gr_gid);
1334 else
1335 syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group);
1336 endgrent();
1337 }
1338
1339 /* else we were passed the GID */
1340 else
1341 *gid=(gid_t)atoi(group);
1342 }
1343 else
1344 *gid=getegid();
1345
1346 return OK;
1347 }
1348
1349
1350
1351 /* drops privileges */
drop_privileges(const char * user,uid_t uid,gid_t gid)1352 static int drop_privileges(const char *user, uid_t uid, gid_t gid){
1353 struct group *grp;
1354 struct passwd *pw;
1355
1356 /* only drop privileges if we're running as root, so we don't interfere with being debugged while running as some random user */
1357 if(getuid()!=0)
1358 return OK;
1359
1360 /* set effective group ID if other than current EGID */
1361 if(gid!=getegid()){
1362 if(setgid(gid)==-1){
1363 syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid);
1364 return ERROR;
1365 }
1366 }
1367
1368 #ifdef HAVE_INITGROUPS
1369 if(uid!=geteuid()){
1370 /* initialize supplementary groups */
1371 if(initgroups(user,gid)==-1){
1372 if(errno==EPERM)
1373 syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()");
1374 else{
1375 syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()");
1376 return ERROR;
1377 }
1378 }
1379 }
1380 #endif
1381
1382 if(setuid(uid)==-1){
1383 syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid);
1384 return ERROR;
1385 }
1386
1387 return OK;
1388 }
1389
1390
1391
1392 /* perform the chroot() operation if configured to do so */
do_chroot(void)1393 void do_chroot(void){
1394 int retval=0;
1395 const char *err=NULL;
1396
1397 if(nsca_chroot!=NULL){
1398 retval=chdir(nsca_chroot);
1399 if(retval!=0){
1400 err=strerror(errno);
1401 syslog(LOG_ERR, "can not chdir into chroot directory: %s", err);
1402 do_exit(STATE_UNKNOWN);
1403 }
1404 retval=chroot(".");
1405 if(retval!=0){
1406 err=strerror(errno);
1407 syslog(LOG_ERR, "can not chroot: %s", err);
1408 do_exit(STATE_UNKNOWN);
1409 }
1410 }
1411 }
1412
1413
1414
1415 /* handle signals */
sighandler(int sig)1416 void sighandler(int sig){
1417 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};
1418 int i;
1419 char temp_buffer[MAX_INPUT_BUFFER];
1420
1421 if(sig<0)
1422 sig=-sig;
1423
1424 for(i=0;sigs[i]!=(char *)NULL;i++);
1425
1426 sig%=i;
1427
1428 /* we received a SIGHUP, so restart... */
1429 if(sig==SIGHUP){
1430
1431 sigrestart=TRUE;
1432
1433 syslog(LOG_NOTICE,"Caught SIGHUP - restarting...\n");
1434 }
1435
1436 /* else begin shutting down... */
1437 if(sig==SIGTERM){
1438
1439 /* if shutdown is already true, we're in a signal trap loop! */
1440 if(sigshutdown==TRUE)
1441 exit(STATE_CRITICAL);
1442
1443 sigshutdown=TRUE;
1444
1445 syslog(LOG_NOTICE,"Caught SIG%s - shutting down...\n",sigs[sig]);
1446 }
1447
1448 return;
1449 }
1450
1451