Merge lp:~logan/ubuntu/raring/nagios-nrpe/2.13-1ubuntu1 into lp:ubuntu/raring/nagios-nrpe

Proposed by Logan Rosen
Status: Merged
Merged at revision: 18
Proposed branch: lp:~logan/ubuntu/raring/nagios-nrpe/2.13-1ubuntu1
Merge into: lp:ubuntu/raring/nagios-nrpe
Diff against target: 10202 lines (+5245/-4745)
26 files modified
.cvsignore (+0/-1)
Changelog (+7/-0)
configure (+2/-2)
configure.in (+2/-2)
contrib/nrpe_check_control.c (+121/-121)
debian/changelog (+18/-0)
debian/compat (+1/-1)
debian/control (+2/-2)
debian/patches/01_nodevrandom-and-docoptions.dpatch (+34/-54)
debian/patches/04_weird_output.dpatch (+13/-13)
debian/patches/05_pid_privileges.dpatch (+20/-20)
include/acl.h (+65/-0)
include/common.h (+84/-71)
include/dh.h (+6/-6)
include/nrpe.h (+65/-61)
include/utils.h (+62/-62)
nrpe.spec (+1/-1)
sample-config/nrpe.cfg.in (+3/-1)
src/.cvsignore (+0/-1)
src/Makefile.in (+2/-2)
src/acl.c (+469/-0)
src/check_nrpe.c (+462/-462)
src/nrpe.c (+1912/-1968)
src/snprintf.c (+1452/-1452)
src/utils.c (+440/-440)
update-version (+2/-2)
To merge this branch: bzr merge lp:~logan/ubuntu/raring/nagios-nrpe/2.13-1ubuntu1
Reviewer Review Type Date Requested Status
Daniel Holbach (community) Approve
Ubuntu branches Pending
Review via email: mp+146287@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Daniel Holbach (dholbach) wrote :

Thanks. Uploaded.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file '.cvsignore'
2--- .cvsignore 2011-10-18 15:09:21 +0000
3+++ .cvsignore 1970-01-01 00:00:00 +0000
4@@ -1,1 +0,0 @@
5-autom4te.cache
6
7=== modified file 'Changelog' (properties changed: -x to +x)
8--- Changelog 2008-08-06 20:33:57 +0000
9+++ Changelog 2013-02-02 23:23:20 +0000
10@@ -3,6 +3,13 @@
11 **************
12
13
14+2.13 - 11/11/2011
15+-----------------
16+- Applied Kaspersky Labs supplied patch for extending allowed_hosts (Konstantin Malov)
17+- Fixed bug in allowed_hosts parsing (Eric Stanley)
18+- Updated to support compiling on Solaris 10 (thanks to Kevin Pendleton)
19+
20+
21 2.12 - 03/10/2008
22 -----------------
23 - Fix for unterminated multiline plugin (garbage) output (Krzysztof Oledzki)
24
25=== modified file 'LEGAL' (properties changed: -x to +x)
26=== modified file 'Makefile.in' (properties changed: -x to +x)
27=== modified file 'README' (properties changed: -x to +x)
28=== modified file 'README.SSL' (properties changed: -x to +x)
29=== modified file 'SECURITY' (properties changed: -x to +x)
30=== added directory 'common'
31=== modified file 'configure'
32--- configure 2008-08-06 20:33:57 +0000
33+++ configure 2013-02-02 23:23:20 +0000
34@@ -1298,9 +1298,9 @@
35
36
37 PKG_NAME=nrpe
38-PKG_VERSION="2.12"
39+PKG_VERSION="2.13"
40 PKG_HOME_URL="http://www.nagios.org/"
41-PKG_REL_DATE="03-10-2008"
42+PKG_REL_DATE="11-11-2011"
43
44 ac_aux_dir=
45 for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
46
47=== modified file 'configure.in' (properties changed: -x to +x)
48--- configure.in 2008-08-06 20:33:57 +0000
49+++ configure.in 2013-02-02 23:23:20 +0000
50@@ -9,9 +9,9 @@
51 AC_PREFIX_DEFAULT(/usr/local/nagios)
52
53 PKG_NAME=nrpe
54-PKG_VERSION="2.12"
55+PKG_VERSION="2.13"
56 PKG_HOME_URL="http://www.nagios.org/"
57-PKG_REL_DATE="03-10-2008"
58+PKG_REL_DATE="11-11-2011"
59
60 dnl Figure out how to invoke "install" and what install options to use.
61 AC_PROG_INSTALL
62
63=== modified file 'contrib/README.nrpe_check_control' (properties changed: -x to +x)
64=== modified file 'contrib/nrpe_check_control.c' (properties changed: -x to +x)
65--- contrib/nrpe_check_control.c 2004-05-15 12:02:35 +0000
66+++ contrib/nrpe_check_control.c 2013-02-02 23:23:20 +0000
67@@ -1,121 +1,121 @@
68-#include <stdio.h>
69-#include <string.h>
70-#include <time.h>
71-
72-#define MAX_CHARS 1024
73-#define SERVICE_COUNT 12
74-
75-#define COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd"
76-#define SERVICES_FILE "/usr/local/nagios/etc/services.cfg"
77-
78-int main(int argc, char *argv[])
79-{
80- char check_name[MAX_CHARS];
81- char ent_type[MAX_CHARS];
82- char input_buffer[MAX_CHARS];
83- char host_name[MAX_CHARS];
84- char service_name[MAX_CHARS];
85- char state[MAX_CHARS];
86- char state_type[MAX_CHARS];
87- char temp_input[MAX_CHARS];
88- char temp_string[MAX_CHARS];
89- char test_host[MAX_CHARS];
90-
91- char *temp_var;
92-
93- FILE *command_fp;
94- FILE *services_fp;
95-
96- int attempt;
97- int i;
98-
99- time_t current_time;
100-
101- strcpy(state,argv[1]);
102- strcpy(state_type,argv[2]);
103- attempt=atoi(argv[3]);
104- strcpy(host_name,argv[4]);
105-
106- if(strcmp(state,"OK") == 0)
107- {
108- services_fp=fopen(SERVICES_FILE,"r");
109- command_fp=fopen(COMMAND_FILE,"a");
110- while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL)
111- {
112- if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r')
113- {
114- continue;
115- }
116- else
117- {
118- strcpy(temp_input,input_buffer);
119- strcpy(temp_string,strtok(temp_input,"="));
120- strcpy(ent_type,strtok(temp_string,"["));
121- if(strcmp(ent_type,"service") == 0)
122- {
123- strcpy(test_host,strtok(NULL,"]"));
124- if(strcmp(test_host,host_name) == 0)
125- {
126- temp_var=strtok(input_buffer,"=");
127- strcpy(service_name,strtok(NULL,";"));
128- for(i=1;i<=SERVICE_COUNT;i++)
129- {
130- temp_var=strtok(NULL,";");
131- }
132- strcpy(check_name,strtok(temp_var,"!"));
133- if(strcmp(check_name,"check_nrpe") == 0)
134- {
135- time(&current_time);
136- fprintf(command_fp,"[%lu] ENABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name);
137- }
138- }
139- }
140- }
141- }
142- fclose(command_fp);
143- fclose(services_fp);
144- }
145- else if(strcmp(state,"CRITICAL") == 0)
146- {
147- if(attempt == 3)
148- {
149- services_fp=fopen(SERVICES_FILE,"r");
150- command_fp=fopen(COMMAND_FILE,"a");
151- while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL)
152- {
153- if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r')
154- {
155- continue;
156- }
157- else
158- {
159- strcpy(temp_input,input_buffer);
160- strcpy(temp_string,strtok(temp_input,"="));
161- strcpy(ent_type,strtok(temp_string,"["));
162- if(strcmp(ent_type,"service") == 0)
163- {
164- strcpy(test_host,strtok(NULL,"]"));
165- if(strcmp(test_host,host_name) == 0)
166- {
167- temp_var=strtok(input_buffer,"=");
168- strcpy(service_name,strtok(NULL,";"));
169- for(i=1;i<=SERVICE_COUNT;i++)
170- {
171- temp_var=strtok(NULL,";");
172- }
173- strcpy(check_name,strtok(temp_var,"!"));
174- if(strcmp(check_name,"check_nrpe") == 0)
175- {
176- time(&current_time);
177- fprintf(command_fp,"[%lu] DISABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name);
178- }
179- }
180- }
181- }
182- }
183- fclose(command_fp);
184- fclose(services_fp);
185- }
186- }
187- return 0;
188-}
189+#include <stdio.h>
190+#include <string.h>
191+#include <time.h>
192+
193+#define MAX_CHARS 1024
194+#define SERVICE_COUNT 12
195+
196+#define COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd"
197+#define SERVICES_FILE "/usr/local/nagios/etc/services.cfg"
198+
199+int main(int argc, char *argv[])
200+{
201+ char check_name[MAX_CHARS];
202+ char ent_type[MAX_CHARS];
203+ char input_buffer[MAX_CHARS];
204+ char host_name[MAX_CHARS];
205+ char service_name[MAX_CHARS];
206+ char state[MAX_CHARS];
207+ char state_type[MAX_CHARS];
208+ char temp_input[MAX_CHARS];
209+ char temp_string[MAX_CHARS];
210+ char test_host[MAX_CHARS];
211+
212+ char *temp_var;
213+
214+ FILE *command_fp;
215+ FILE *services_fp;
216+
217+ int attempt;
218+ int i;
219+
220+ time_t current_time;
221+
222+ strcpy(state,argv[1]);
223+ strcpy(state_type,argv[2]);
224+ attempt=atoi(argv[3]);
225+ strcpy(host_name,argv[4]);
226+
227+ if(strcmp(state,"OK") == 0)
228+ {
229+ services_fp=fopen(SERVICES_FILE,"r");
230+ command_fp=fopen(COMMAND_FILE,"a");
231+ while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL)
232+ {
233+ if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r')
234+ {
235+ continue;
236+ }
237+ else
238+ {
239+ strcpy(temp_input,input_buffer);
240+ strcpy(temp_string,strtok(temp_input,"="));
241+ strcpy(ent_type,strtok(temp_string,"["));
242+ if(strcmp(ent_type,"service") == 0)
243+ {
244+ strcpy(test_host,strtok(NULL,"]"));
245+ if(strcmp(test_host,host_name) == 0)
246+ {
247+ temp_var=strtok(input_buffer,"=");
248+ strcpy(service_name,strtok(NULL,";"));
249+ for(i=1;i<=SERVICE_COUNT;i++)
250+ {
251+ temp_var=strtok(NULL,";");
252+ }
253+ strcpy(check_name,strtok(temp_var,"!"));
254+ if(strcmp(check_name,"check_nrpe") == 0)
255+ {
256+ time(&current_time);
257+ fprintf(command_fp,"[%lu] ENABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name);
258+ }
259+ }
260+ }
261+ }
262+ }
263+ fclose(command_fp);
264+ fclose(services_fp);
265+ }
266+ else if(strcmp(state,"CRITICAL") == 0)
267+ {
268+ if(attempt == 3)
269+ {
270+ services_fp=fopen(SERVICES_FILE,"r");
271+ command_fp=fopen(COMMAND_FILE,"a");
272+ while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL)
273+ {
274+ if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r')
275+ {
276+ continue;
277+ }
278+ else
279+ {
280+ strcpy(temp_input,input_buffer);
281+ strcpy(temp_string,strtok(temp_input,"="));
282+ strcpy(ent_type,strtok(temp_string,"["));
283+ if(strcmp(ent_type,"service") == 0)
284+ {
285+ strcpy(test_host,strtok(NULL,"]"));
286+ if(strcmp(test_host,host_name) == 0)
287+ {
288+ temp_var=strtok(input_buffer,"=");
289+ strcpy(service_name,strtok(NULL,";"));
290+ for(i=1;i<=SERVICE_COUNT;i++)
291+ {
292+ temp_var=strtok(NULL,";");
293+ }
294+ strcpy(check_name,strtok(temp_var,"!"));
295+ if(strcmp(check_name,"check_nrpe") == 0)
296+ {
297+ time(&current_time);
298+ fprintf(command_fp,"[%lu] DISABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name);
299+ }
300+ }
301+ }
302+ }
303+ }
304+ fclose(command_fp);
305+ fclose(services_fp);
306+ }
307+ }
308+ return 0;
309+}
310
311=== modified file 'debian/changelog'
312--- debian/changelog 2012-05-16 17:29:52 +0000
313+++ debian/changelog 2013-02-02 23:23:20 +0000
314@@ -1,3 +1,21 @@
315+nagios-nrpe (2.13-1ubuntu1) raring; urgency=low
316+
317+ * Merge from Debian unstable. Remaining changes:
318+ - debian/{rules,control}: Add hardening-includes to gain PIE security
319+ builds.
320+ - debian/rules: Use dpkg-buildflags.
321+
322+ -- Logan Rosen <logatronico@gmail.com> Sat, 02 Feb 2013 18:16:48 -0500
323+
324+nagios-nrpe (2.13-1) unstable; urgency=low
325+
326+ * [3e113b5] Imported Upstream version 2.13
327+ * [acc152b] Bump standards version
328+ * [c707bce] Use dh9 for hardening
329+ * Updated patches
330+
331+ -- Alexander Wirt <formorer@debian.org> Sat, 30 Jun 2012 11:08:22 +0200
332+
333 nagios-nrpe (2.12-6ubuntu2) quantal; urgency=low
334
335 * Fixed compiler hardening configuration. (LP: #1000379)
336
337=== modified file 'debian/compat'
338--- debian/compat 2011-09-25 08:35:48 +0000
339+++ debian/compat 2013-02-02 23:23:20 +0000
340@@ -1,1 +1,1 @@
341-8
342+9
343
344=== modified file 'debian/control'
345--- debian/control 2012-05-03 10:11:11 +0000
346+++ debian/control 2013-02-02 23:23:20 +0000
347@@ -4,8 +4,8 @@
348 Maintainer: Ubuntu Developers <ubuntu-devel@lists.ubuntu.com>
349 XSBC-Original-Maintainer: Debian Nagios Maintainer Group <pkg-nagios-devel@lists.alioth.debian.org>
350 Uploaders: sean finney <seanius@debian.org>, Jason Thomas <jason@debian.org>, Alexander Wirt <formorer@debian.org>, Luk Claes <luk@debian.org>
351-Build-Depends: debhelper (>= 8), openssl, dpatch (>= 2.0.32~), libssl-dev, libwrap0-dev, autotools-dev (>= 20100122.1), hardening-includes
352-Standards-Version: 3.9.2
353+Build-Depends: debhelper (>= 9), openssl, dpatch (>= 2.0.32~), libssl-dev, libwrap0-dev, autotools-dev (>= 20100122.1), hardening-includes
354+Standards-Version: 3.9.3
355
356 Package: nagios-nrpe-server
357 Architecture: any
358
359=== modified file 'debian/patches/01_nodevrandom-and-docoptions.dpatch'
360--- debian/patches/01_nodevrandom-and-docoptions.dpatch 2006-05-14 21:38:48 +0000
361+++ debian/patches/01_nodevrandom-and-docoptions.dpatch 2013-02-02 23:23:20 +0000
362@@ -5,58 +5,38 @@
363 ## DP: No description.
364
365 @DPATCH@
366-diff -urNad nagios-nrpe-2.2~/src/check_nrpe.c nagios-nrpe-2.2/src/check_nrpe.c
367---- nagios-nrpe-2.2~/src/check_nrpe.c 2006-01-21 20:23:36.000000000 +0100
368-+++ nagios-nrpe-2.2/src/check_nrpe.c 2006-01-24 08:36:39.000000000 +0100
369-@@ -93,6 +93,9 @@
370- printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n");
371- printf(" arguments should be separated by a space. If provided, this must be\n");
372- printf(" the last option supplied on the command line.\n");
373-+ printf(" -h,--help Print this short help.\n");
374-+ printf(" -l,--license Print licensing information.\n");
375-+ printf(" -n,--no-ssl Do not initial an ssl handshake with the server, talk in plaintext.\n");
376- printf("\n");
377- printf("Note:\n");
378- printf("This plugin requires that you have the NRPE daemon running on the remote host.\n");
379-diff -urNad nagios-nrpe-2.2~/src/nrpe.c nagios-nrpe-2.2/src/nrpe.c
380---- nagios-nrpe-2.2~/src/nrpe.c 2006-01-21 20:23:36.000000000 +0100
381-+++ nagios-nrpe-2.2/src/nrpe.c 2006-01-24 08:38:30.000000000 +0100
382-@@ -120,11 +120,13 @@
383- printf("Usage: nrpe [-n] -c <config_file> <mode>\n");
384- printf("\n");
385- printf("Options:\n");
386-- printf(" -n = Do not use SSL\n");
387-+ printf(" -n,--no-ssl = Do not use SSL\n");
388- printf(" <config_file> = Name of config file to use\n");
389- printf(" <mode> = One of the following two operating modes:\n");
390-- printf(" -i = Run as a service under inetd or xinetd\n");
391-- printf(" -d = Run as a standalone daemon\n");
392-+ printf(" -i,--inetd Run as a service under inetd or xinetd\n");
393-+ printf(" -d,--daemon Run as a standalone daemon\n");
394-+ printf(" -h,--help Print this short help.\n");
395-+ printf(" -l,--license Print licensing information.\n");
396- printf("\n");
397- printf("Notes:\n");
398- printf("This program is designed to process requests from the check_nrpe\n");
399-diff -urNad nagios-nrpe-2.2~/src/utils.c nagios-nrpe-2.2/src/utils.c
400---- nagios-nrpe-2.2~/src/utils.c 2003-10-16 01:14:27.000000000 +0200
401-+++ nagios-nrpe-2.2/src/utils.c 2006-01-24 08:36:39.000000000 +0100
402+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' pkg-nrpe~/src/check_nrpe.c pkg-nrpe/src/check_nrpe.c
403+--- pkg-nrpe~/src/check_nrpe.c 2012-04-30 09:36:53.000000000 +0200
404++++ pkg-nrpe/src/check_nrpe.c 2012-04-30 09:45:36.129684439 +0200
405+@@ -96,6 +96,9 @@
406+ printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n");
407+ printf(" arguments should be separated by a space. If provided, this must be\n");
408+ printf(" the last option supplied on the command line.\n");
409++ printf(" -h,--help Print this short help.\n");
410++ printf(" -l,--license Print licensing information.\n");
411++ printf(" -n,--no-ssl Do not initiate an ssl handshake with the server, talk in plaintext.\n");
412+ printf("\n");
413+ printf("Note:\n");
414+ printf("This plugin requires that you have the NRPE daemon running on the remote host.\n");
415+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' pkg-nrpe~/src/utils.c pkg-nrpe/src/utils.c
416+--- pkg-nrpe~/src/utils.c 2012-04-30 09:36:53.000000000 +0200
417++++ pkg-nrpe/src/utils.c 2012-04-30 09:48:03.811163608 +0200
418 @@ -90,17 +90,7 @@
419- ends and the rest of the buffer (padded randomly) starts.
420- ***************************************************************/
421-
422-- /* try to get seed value from /dev/urandom, as its a better source of entropy */
423-- fp=fopen("/dev/urandom","r");
424-- if(fp!=NULL){
425-- seed=fgetc(fp);
426-- fclose(fp);
427-- }
428--
429-- /* else fallback to using the current time as the seed */
430-- else
431-- seed=(int)time(NULL);
432--
433-+ seed=(int)time(NULL)*311-getpid()*359+getppid()*383;
434- srand(seed);
435- for(x=0;x<buffer_size;x++)
436- buffer[x]=(int)'0'+(int)(72.0*rand()/(RAND_MAX+1.0));
437+ ends and the rest of the buffer (padded randomly) starts.
438+ ***************************************************************/
439+
440+- /* try to get seed value from /dev/urandom, as its a better source of entropy */
441+- fp=fopen("/dev/urandom","r");
442+- if(fp!=NULL){
443+- seed=fgetc(fp);
444+- fclose(fp);
445+- }
446+-
447+- /* else fallback to using the current time as the seed */
448+- else
449+- seed=(int)time(NULL);
450+-
451++ seed=(int)time(NULL)*311-getpid()*359+getppid()*383;
452+ srand(seed);
453+ for(x=0;x<buffer_size;x++)
454+ buffer[x]=(int)'0'+(int)(72.0*rand()/(RAND_MAX+1.0));
455
456=== modified file 'debian/patches/04_weird_output.dpatch'
457--- debian/patches/04_weird_output.dpatch 2009-03-21 09:33:39 +0000
458+++ debian/patches/04_weird_output.dpatch 2013-02-02 23:23:20 +0000
459@@ -5,16 +5,16 @@
460 ## DP: Clean buffer before use
461
462 @DPATCH@
463-diff -urNad nagios-nrpe-2.12~/src/nrpe.c nagios-nrpe-2.12/src/nrpe.c
464---- nagios-nrpe-2.12~/src/nrpe.c 2008-09-14 16:19:36.000000000 +0200
465-+++ nagios-nrpe-2.12/src/nrpe.c 2008-09-14 16:21:19.000000000 +0200
466-@@ -1165,6 +1165,9 @@
467- /* disable connection alarm - a new alarm will be setup during my_system */
468- alarm(0);
469-
470-+ // null buffer before using it!
471-+ memset(buffer,0,sizeof(buffer));
472-+
473- /* if this is the version check command, just spew it out */
474- if(!strcmp(command_name,NRPE_HELLO_COMMAND)){
475-
476+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' pkg-nrpe~/src/nrpe.c pkg-nrpe/src/nrpe.c
477+--- pkg-nrpe~/src/nrpe.c 2012-04-30 09:36:53.000000000 +0200
478++++ pkg-nrpe/src/nrpe.c 2012-04-30 09:52:47.890535825 +0200
479+@@ -1107,6 +1107,9 @@
480+ /* disable connection alarm - a new alarm will be setup during my_system */
481+ alarm(0);
482+
483++ // null buffer before using it!
484++ memset(buffer,0,sizeof(buffer));
485++
486+ /* if this is the version check command, just spew it out */
487+ if(!strcmp(command_name,NRPE_HELLO_COMMAND)){
488+
489
490=== modified file 'debian/patches/05_pid_privileges.dpatch'
491--- debian/patches/05_pid_privileges.dpatch 2009-07-06 07:08:26 +0000
492+++ debian/patches/05_pid_privileges.dpatch 2013-02-02 23:23:20 +0000
493@@ -5,23 +5,23 @@
494 ## DP: No description.
495
496 @DPATCH@
497-diff -urNad nagios-nrpe-2.12~/src/nrpe.c nagios-nrpe-2.12/src/nrpe.c
498---- nagios-nrpe-2.12~/src/nrpe.c 2009-07-06 10:20:37.000000000 +0200
499-+++ nagios-nrpe-2.12/src/nrpe.c 2009-07-06 10:22:00.000000000 +0200
500-@@ -296,12 +296,13 @@
501- /* log info to syslog facility */
502- syslog(LOG_NOTICE,"Starting up daemon");
503-
504-+
505-+ /* drop privileges */
506-+ drop_privileges(nrpe_user,nrpe_group);
507-+
508- /* write pid file */
509- if(write_pid_file()==ERROR)
510- return STATE_CRITICAL;
511--
512-- /* drop privileges */
513-- drop_privileges(nrpe_user,nrpe_group);
514-
515- /* make sure we're not root */
516- check_privileges();
517+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' pkg-nrpe~/src/nrpe.c pkg-nrpe/src/nrpe.c
518+--- pkg-nrpe~/src/nrpe.c 2012-06-30 11:03:29.000000000 +0200
519++++ pkg-nrpe/src/nrpe.c 2012-06-30 11:03:46.791280548 +0200
520+@@ -301,13 +301,13 @@
521+ /* log info to syslog facility */
522+ syslog(LOG_NOTICE,"Starting up daemon");
523+
524++ /* drop privileges */
525++ drop_privileges(nrpe_user,nrpe_group);
526++
527+ /* write pid file */
528+ if(write_pid_file()==ERROR)
529+ return STATE_CRITICAL;
530+
531+- /* drop privileges */
532+- drop_privileges(nrpe_user,nrpe_group);
533+-
534+ /* make sure we're not root */
535+ check_privileges();
536+
537
538=== modified file 'docs/NRPE.odt' (properties changed: -x to +x)
539=== modified file 'docs/NRPE.pdf' (properties changed: -x to +x)
540=== added file 'include/acl.h'
541--- include/acl.h 1970-01-01 00:00:00 +0000
542+++ include/acl.h 2013-02-02 23:23:20 +0000
543@@ -0,0 +1,65 @@
544+/*-
545+ * acl.c - header file for acl.c
546+ * Copyright (c) 2011 Kaspersky Lab ZAO
547+ * Last Modified: 08-10-2011 by Konstantin Malov with Oleg Koreshkov's help
548+ *
549+ * License: GPL
550+ *
551+ * This program is free software; you can redistribute it and/or modify
552+ * it under the terms of the GNU General Public License as published by
553+ * the Free Software Foundation; either version 2 of the License, or
554+ * (at your option) any later version.
555+ *
556+ * This program is distributed in the hope that it will be useful,
557+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
558+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
559+ * GNU General Public License for more details.
560+ *
561+ * You should have received a copy of the GNU General Public License
562+ * along with this program; if not, write to the Free Software
563+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
564+ */
565+
566+#ifndef ACL_H_INCLUDED
567+#define ACL_H_INCLUDED 1
568+
569+#include <sys/types.h>
570+#include <sys/socket.h>
571+
572+#include <netinet/in.h>
573+#include <arpa/inet.h>
574+
575+#include <stdio.h>
576+#include <stdlib.h>
577+#include <string.h>
578+#include <ctype.h>
579+#include <netdb.h>
580+#include <syslog.h>
581+#include <stdarg.h>
582+
583+#define CHAR_TO_NUMBER(c) ((c) - '0')
584+
585+struct ip_acl {
586+ struct in_addr addr;
587+ struct in_addr mask;
588+ struct ip_acl *next;
589+};
590+
591+struct dns_acl {
592+ char domain[255];
593+ struct dns_acl *next;
594+};
595+
596+/* Poiters to head ACL structs */
597+static struct ip_acl *ip_acl_head, *ip_acl_prev;
598+static struct dns_acl *dns_acl_head, *dns_acl_prev;
599+
600+/* Functions */
601+void parse_allowed_hosts(char *allowed_hosts);
602+int add_ipv4_to_acl(char *ipv4);
603+int add_domain_to_acl(char *domain);
604+int is_an_allowed_host(struct in_addr);
605+unsigned int prefix_from_mask(struct in_addr mask);
606+void show_acl_lists(void);
607+
608+#endif /* ACL_H_INCLUDED */
609
610=== modified file 'include/common.h' (properties changed: -x to +x)
611--- include/common.h 2008-08-06 20:33:57 +0000
612+++ include/common.h 2013-02-02 23:23:20 +0000
613@@ -1,71 +1,84 @@
614-/************************************************************************
615- *
616- * COMMON.H - NRPE Common Include File
617- * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org)
618- * Last Modified: 03-10-2008
619- *
620- * License:
621- *
622- * This program is free software; you can redistribute it and/or modify
623- * it under the terms of the GNU General Public License as published by
624- * the Free Software Foundation; either version 2 of the License, or
625- * (at your option) any later version.
626- *
627- * This program is distributed in the hope that it will be useful,
628- * but WITHOUT ANY WARRANTY; without even the implied warranty of
629- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
630- * GNU General Public License for more details.
631- *
632- * You should have received a copy of the GNU General Public License
633- * along with this program; if not, write to the Free Software
634- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
635- ************************************************************************/
636-
637-#include "config.h"
638-
639-#define PROGRAM_VERSION "2.12"
640-#define MODIFICATION_DATE "03-10-2008"
641-
642-#define OK 0
643-#define ERROR -1
644-
645-#define TRUE 1
646-#define FALSE 0
647-
648-#define STATE_UNKNOWN 3 /* service state return codes */
649-#define STATE_CRITICAL 2
650-#define STATE_WARNING 1
651-#define STATE_OK 0
652-
653-
654-#define DEFAULT_SOCKET_TIMEOUT 10 /* timeout after 10 seconds */
655-#define DEFAULT_CONNECTION_TIMEOUT 300 /* timeout if daemon is waiting for connection more than this time */
656-
657-#define MAX_INPUT_BUFFER 2048 /* max size of most buffers we use */
658-#define MAX_FILENAME_LENGTH 256
659-
660-#define MAX_HOST_ADDRESS_LENGTH 256 /* max size of a host address */
661-
662-#define NRPE_HELLO_COMMAND "_NRPE_CHECK"
663-
664-#define MAX_COMMAND_ARGUMENTS 16
665-
666-
667-/**************** PACKET STRUCTURE DEFINITION **********/
668-
669-#define QUERY_PACKET 1 /* id code for a packet containing a query */
670-#define RESPONSE_PACKET 2 /* id code for a packet containing a response */
671-
672-#define NRPE_PACKET_VERSION_3 3 /* packet version identifier */
673-#define NRPE_PACKET_VERSION_2 2
674-#define NRPE_PACKET_VERSION_1 1 /* older packet version identifiers (no longer supported) */
675-
676-#define MAX_PACKETBUFFER_LENGTH 1024 /* max amount of data we'll send in one query/response */
677-
678-typedef struct packet_struct{
679- int16_t packet_version;
680- int16_t packet_type;
681- u_int32_t crc32_value;
682- int16_t result_code;
683- char buffer[MAX_PACKETBUFFER_LENGTH];
684- }packet;
685+/************************************************************************
686+ *
687+ * COMMON.H - NRPE Common Include File
688+ * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org)
689+ * Last Modified: 11-11-2011
690+ *
691+ * License:
692+ *
693+ * This program is free software; you can redistribute it and/or modify
694+ * it under the terms of the GNU General Public License as published by
695+ * the Free Software Foundation; either version 2 of the License, or
696+ * (at your option) any later version.
697+ *
698+ * This program is distributed in the hope that it will be useful,
699+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
700+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
701+ * GNU General Public License for more details.
702+ *
703+ * You should have received a copy of the GNU General Public License
704+ * along with this program; if not, write to the Free Software
705+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
706+ ************************************************************************/
707+
708+#include "config.h"
709+
710+#define PROGRAM_VERSION "2.13"
711+#define MODIFICATION_DATE "11-11-2011"
712+
713+#define OK 0
714+#define ERROR -1
715+
716+#define TRUE 1
717+#define FALSE 0
718+
719+#define STATE_UNKNOWN 3 /* service state return codes */
720+#define STATE_CRITICAL 2
721+#define STATE_WARNING 1
722+#define STATE_OK 0
723+
724+
725+#define DEFAULT_SOCKET_TIMEOUT 10 /* timeout after 10 seconds */
726+#define DEFAULT_CONNECTION_TIMEOUT 300 /* timeout if daemon is waiting for connection more than this time */
727+
728+#define MAX_INPUT_BUFFER 2048 /* max size of most buffers we use */
729+#define MAX_FILENAME_LENGTH 256
730+
731+#define MAX_HOST_ADDRESS_LENGTH 256 /* max size of a host address */
732+
733+#define NRPE_HELLO_COMMAND "_NRPE_CHECK"
734+
735+#define MAX_COMMAND_ARGUMENTS 16
736+
737+
738+/**************** PACKET STRUCTURE DEFINITION **********/
739+
740+#define QUERY_PACKET 1 /* id code for a packet containing a query */
741+#define RESPONSE_PACKET 2 /* id code for a packet containing a response */
742+
743+#define NRPE_PACKET_VERSION_3 3 /* packet version identifier */
744+#define NRPE_PACKET_VERSION_2 2
745+#define NRPE_PACKET_VERSION_1 1 /* older packet version identifiers (no longer supported) */
746+
747+#define MAX_PACKETBUFFER_LENGTH 1024 /* max amount of data we'll send in one query/response */
748+
749+typedef struct packet_struct{
750+ int16_t packet_version;
751+ int16_t packet_type;
752+ u_int32_t crc32_value;
753+ int16_t result_code;
754+ char buffer[MAX_PACKETBUFFER_LENGTH];
755+ }packet;
756+
757+/**************** OPERATING SYSTEM SPECIFIC DEFINITIONS **********/
758+#ifdef __sun
759+
760+# ifndef LOG_AUTHPRIV
761+# define LOG_AUTHPRIV LOG_AUTH
762+# endif
763+
764+# ifndef LOG_FTP
765+# define LOG_FTP LOG_DAEMON
766+# endif
767+
768+#endif
769
770=== modified file 'include/config.h.in' (properties changed: -x to +x)
771=== modified file 'include/dh.h' (properties changed: -x to +x)
772--- include/dh.h 2008-08-06 20:33:57 +0000
773+++ include/dh.h 2013-02-02 23:23:20 +0000
774@@ -4,12 +4,12 @@
775 DH *get_dh512()
776 {
777 static unsigned char dh512_p[]={
778- 0xA0,0xC9,0x8F,0x6D,0x75,0x7A,0x4E,0xED,0xED,0x80,0x11,0x32,
779- 0x77,0x14,0xEA,0xE0,0xE7,0x38,0x55,0x01,0x03,0x02,0xC5,0x34,
780- 0xCA,0x2D,0xA7,0xFA,0x2E,0x1C,0x5F,0xD9,0xF4,0xDA,0x54,0x40,
781- 0xD7,0xB4,0x7B,0x00,0xE5,0x19,0x30,0x69,0xC5,0x93,0x52,0x09,
782- 0xB7,0x2D,0x5B,0xAB,0x27,0x0C,0x0D,0xAA,0xCE,0x56,0xB7,0x4D,
783- 0xE9,0x8A,0xFB,0x43,
784+ 0xA4,0x56,0x47,0x7F,0x90,0xF0,0xDE,0xFE,0x73,0x1A,0xBD,0x3E,
785+ 0xA9,0xF5,0x69,0x46,0x29,0x0B,0x47,0x55,0x8C,0xE8,0xF3,0xDF,
786+ 0xF6,0x1B,0xC5,0x29,0x1B,0x81,0x97,0x3E,0xE4,0xD9,0xC8,0x2B,
787+ 0xBB,0x2B,0x7A,0x37,0xE1,0x18,0xDF,0xEC,0x6B,0xEC,0x04,0x77,
788+ 0x6D,0x51,0x3C,0x7C,0xB7,0x81,0xBD,0x7F,0xC9,0x5A,0x04,0xB4,
789+ 0xA4,0x3E,0x8B,0x5B,
790 };
791 static unsigned char dh512_g[]={
792 0x02,
793
794=== modified file 'include/nrpe.h' (properties changed: -x to +x)
795--- include/nrpe.h 2008-08-06 20:33:57 +0000
796+++ include/nrpe.h 2013-02-02 23:23:20 +0000
797@@ -1,61 +1,65 @@
798-/************************************************************************
799- *
800- * NRPE.H - NRPE Include File
801- * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org)
802- * Last Modified: 11-23-2007
803- *
804- * License:
805- *
806- * This program is free software; you can redistribute it and/or modify
807- * it under the terms of the GNU General Public License as published by
808- * the Free Software Foundation; either version 2 of the License, or
809- * (at your option) any later version.
810- *
811- * This program is distributed in the hope that it will be useful,
812- * but WITHOUT ANY WARRANTY; without even the implied warranty of
813- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
814- * GNU General Public License for more details.
815- *
816- * You should have received a copy of the GNU General Public License
817- * along with this program; if not, write to the Free Software
818- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
819- *
820- ************************************************************************/
821-
822-
823-/**************** COMMAND STRUCTURE DEFINITION **********/
824-
825-typedef struct command_struct{
826- char *command_name;
827- char *command_line;
828- struct command_struct *next;
829- }command;
830-
831-int process_arguments(int,char **);
832-void wait_for_connections(void);
833-void handle_connection(int);
834-int read_config_file(char *);
835-int read_config_dir(char *);
836-int get_log_facility(char *);
837-int add_command(char *,char *);
838-command *find_command(char *);
839-void sighandler(int);
840-int drop_privileges(char *,char *);
841-int check_privileges(void);
842-
843-int write_pid_file(void);
844-int remove_pid_file(void);
845-
846-void free_memory(void);
847-int is_an_allowed_host(char *);
848-int validate_request(packet *);
849-int contains_nasty_metachars(char *);
850-int process_macros(char *,char *,int);
851-int my_system(char *,int,int *,char *,int); /* executes a command via popen(), but also protects against timeouts */
852-void my_system_sighandler(int); /* handles timeouts when executing commands via my_system() */
853-void my_connection_sighandler(int); /* handles timeouts of connection */
854-
855-void sighandler(int);
856-void child_sighandler(int);
857-
858-
859+/************************************************************************
860+ *
861+ * NRPE.H - NRPE Include File
862+ * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org)
863+ * Last Modified: 08-10-2011 by Konstantin Malov
864+ *
865+ * License:
866+ *
867+ * This program is free software; you can redistribute it and/or modify
868+ * it under the terms of the GNU General Public License as published by
869+ * the Free Software Foundation; either version 2 of the License, or
870+ * (at your option) any later version.
871+ *
872+ * This program is distributed in the hope that it will be useful,
873+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
874+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
875+ * GNU General Public License for more details.
876+ *
877+ * You should have received a copy of the GNU General Public License
878+ * along with this program; if not, write to the Free Software
879+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
880+ *
881+ ************************************************************************/
882+
883+ /*
884+ * 08-10-2011 IPv4 subnetworks support added.
885+ * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c
886+ *
887+ */
888+
889+/**************** COMMAND STRUCTURE DEFINITION **********/
890+
891+typedef struct command_struct{
892+ char *command_name;
893+ char *command_line;
894+ struct command_struct *next;
895+ }command;
896+
897+int process_arguments(int,char **);
898+void wait_for_connections(void);
899+void handle_connection(int);
900+int read_config_file(char *);
901+int read_config_dir(char *);
902+int get_log_facility(char *);
903+int add_command(char *,char *);
904+command *find_command(char *);
905+void sighandler(int);
906+int drop_privileges(char *,char *);
907+int check_privileges(void);
908+
909+int write_pid_file(void);
910+int remove_pid_file(void);
911+
912+void free_memory(void);
913+int validate_request(packet *);
914+int contains_nasty_metachars(char *);
915+int process_macros(char *,char *,int);
916+int my_system(char *,int,int *,char *,int); /* executes a command via popen(), but also protects against timeouts */
917+void my_system_sighandler(int); /* handles timeouts when executing commands via my_system() */
918+void my_connection_sighandler(int); /* handles timeouts of connection */
919+
920+void sighandler(int);
921+void child_sighandler(int);
922+
923+
924
925=== modified file 'include/utils.h' (properties changed: -x to +x)
926--- include/utils.h 2007-05-12 12:27:30 +0000
927+++ include/utils.h 2013-02-02 23:23:20 +0000
928@@ -1,62 +1,62 @@
929-/************************************************************************************************
930- *
931- * UTILS.H - NRPE Utilities Include File
932- *
933- * License: GPL
934- * Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org)
935- *
936- * Last Modified: 12-11-2006
937- *
938- * Description:
939- *
940- * This file contains common include files and function definitions used in many of the plugins.
941- *
942- * License Information:
943- *
944- * This program is free software; you can redistribute it and/or modify
945- * it under the terms of the GNU General Public License as published by
946- * the Free Software Foundation; either version 2 of the License, or
947- * (at your option) any later version.
948- *
949- * This program is distributed in the hope that it will be useful,
950- * but WITHOUT ANY WARRANTY; without even the implied warranty of
951- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
952- * GNU General Public License for more details.
953- *
954- * You should have received a copy of the GNU General Public License
955- * along with this program; if not, write to the Free Software
956- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
957- *
958- ************************************************************************************************/
959-
960-#ifndef _UTILS_H
961-#define _UTILS_H
962-
963-#include "../include/config.h"
964-
965-
966-void generate_crc32_table(void);
967-unsigned long calculate_crc32(char *, int);
968-
969-void randomize_buffer(char *,int);
970-
971-int my_tcp_connect(char *,int,int *);
972-int my_connect(char *,int,int *,char *);
973-
974-int my_inet_aton(register const char *,struct in_addr *);
975-
976-void strip(char *);
977-
978-int sendall(int,char *,int *);
979-int recvall(int,char *,int *,int);
980-
981-char *my_strsep(char **,const char *);
982-
983-void display_license(void);
984-
985-#endif
986-
987-
988-
989-
990-
991+/************************************************************************************************
992+ *
993+ * UTILS.H - NRPE Utilities Include File
994+ *
995+ * License: GPL
996+ * Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org)
997+ *
998+ * Last Modified: 12-11-2006
999+ *
1000+ * Description:
1001+ *
1002+ * This file contains common include files and function definitions used in many of the plugins.
1003+ *
1004+ * License Information:
1005+ *
1006+ * This program is free software; you can redistribute it and/or modify
1007+ * it under the terms of the GNU General Public License as published by
1008+ * the Free Software Foundation; either version 2 of the License, or
1009+ * (at your option) any later version.
1010+ *
1011+ * This program is distributed in the hope that it will be useful,
1012+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1013+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1014+ * GNU General Public License for more details.
1015+ *
1016+ * You should have received a copy of the GNU General Public License
1017+ * along with this program; if not, write to the Free Software
1018+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1019+ *
1020+ ************************************************************************************************/
1021+
1022+#ifndef _UTILS_H
1023+#define _UTILS_H
1024+
1025+#include "../include/config.h"
1026+
1027+
1028+void generate_crc32_table(void);
1029+unsigned long calculate_crc32(char *, int);
1030+
1031+void randomize_buffer(char *,int);
1032+
1033+int my_tcp_connect(char *,int,int *);
1034+int my_connect(char *,int,int *,char *);
1035+
1036+int my_inet_aton(register const char *,struct in_addr *);
1037+
1038+void strip(char *);
1039+
1040+int sendall(int,char *,int *);
1041+int recvall(int,char *,int *,int);
1042+
1043+char *my_strsep(char **,const char *);
1044+
1045+void display_license(void);
1046+
1047+#endif
1048+
1049+
1050+
1051+
1052+
1053
1054=== modified file 'init-script.debian.in' (properties changed: -x to +x)
1055=== modified file 'init-script.in' (properties changed: -x to +x)
1056=== modified file 'init-script.suse.in' (properties changed: -x to +x)
1057=== modified file 'nrpe.spec' (properties changed: -x to +x)
1058--- nrpe.spec 2008-08-06 20:33:57 +0000
1059+++ nrpe.spec 2013-02-02 23:23:20 +0000
1060@@ -1,5 +1,5 @@
1061 %define name nrpe
1062-%define version 2.12
1063+%define version 2.13
1064 %define release 1
1065 %define nsusr nagios
1066 %define nsgrp nagios
1067
1068=== modified file 'sample-config/nrpe.cfg.in' (properties changed: -x to +x)
1069--- sample-config/nrpe.cfg.in 2008-08-06 20:33:57 +0000
1070+++ sample-config/nrpe.cfg.in 2013-02-02 23:23:20 +0000
1071@@ -67,7 +67,9 @@
1072
1073 # ALLOWED HOST ADDRESSES
1074 # This is an optional comma-delimited list of IP address or hostnames
1075-# that are allowed to talk to the NRPE daemon.
1076+# that are allowed to talk to the NRPE daemon. Network addresses with a bit mask
1077+# (i.e. 192.168.1.0/24) are also supported. Hostname wildcards are not currently
1078+# supported.
1079 #
1080 # Note: The daemon only does rudimentary checking of the client's IP
1081 # address. I would highly recommend adding entries in your /etc/hosts.allow
1082
1083=== modified file 'sample-config/nrpe.xinetd.in' (properties changed: -x to +x)
1084=== removed file 'src/.cvsignore'
1085--- src/.cvsignore 2011-10-18 15:09:21 +0000
1086+++ src/.cvsignore 1970-01-01 00:00:00 +0000
1087@@ -1,1 +0,0 @@
1088-dh.h
1089
1090=== modified file 'src/Makefile.in' (properties changed: -x to +x)
1091--- src/Makefile.in 2008-08-06 20:33:57 +0000
1092+++ src/Makefile.in 2013-02-02 23:23:20 +0000
1093@@ -33,8 +33,8 @@
1094
1095 all: nrpe check_nrpe
1096
1097-nrpe: nrpe.c utils.c $(SRC_INCLUDE)/nrpe.h $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h $(SNPRINTF_O)
1098- $(CC) $(CFLAGS) -o $@ nrpe.c utils.c $(LDFLAGS) $(SOCKETLIBS) $(LIBWRAPLIBS) $(SNPRINTF_O) $(OTHERLIBS)
1099+nrpe: nrpe.c utils.c acl.c $(SRC_INCLUDE)/nrpe.h $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/acl.h $(SNPRINTF_O)
1100+ $(CC) $(CFLAGS) -o $@ nrpe.c utils.c acl.c $(LDFLAGS) $(SOCKETLIBS) $(LIBWRAPLIBS) $(SNPRINTF_O) $(OTHERLIBS)
1101
1102 check_nrpe: check_nrpe.c utils.c $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h
1103 $(CC) $(CFLAGS) -o $@ check_nrpe.c utils.c $(LDFLAGS) $(SOCKETLIBS) $(OTHERLIBS)
1104
1105=== added file 'src/acl.c'
1106--- src/acl.c 1970-01-01 00:00:00 +0000
1107+++ src/acl.c 2013-02-02 23:23:20 +0000
1108@@ -0,0 +1,469 @@
1109+/*-
1110+ * acl.c - a small library for nrpe.c. It adds IPv4 subnets support to ACL in nrpe.
1111+ * Copyright (c) 2011 Kaspersky Lab ZAO
1112+ * Last Modified: 08-10-2011 by Konstantin Malov with Oleg Koreshkov's help
1113+ *
1114+ * Description:
1115+ * acl.c creates two linked lists. One is for IPv4 hosts and networks, another is for domain names.
1116+ * All connecting hosts (if allowed_hosts is defined) are checked in these two lists.
1117+ *
1118+ * Some notes:
1119+ * 1) IPv6 isn't supported in ACL.
1120+ * 2) Only ANCII names are supported in ACL.
1121+ *
1122+ * License: GPL
1123+ *
1124+ * This program is free software; you can redistribute it and/or modify
1125+ * it under the terms of the GNU General Public License as published by
1126+ * the Free Software Foundation; either version 2 of the License, or
1127+ * (at your option) any later version.
1128+ *
1129+ * This program is distributed in the hope that it will be useful,
1130+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1131+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1132+ * GNU General Public License for more details.
1133+ *
1134+ * You should have received a copy of the GNU General Public License
1135+ * along with this program; if not, write to the Free Software
1136+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1137+ */
1138+
1139+#include <sys/types.h>
1140+#include <sys/socket.h>
1141+
1142+#include <netinet/in.h>
1143+#include <arpa/inet.h>
1144+
1145+#include <stdio.h>
1146+#include <stdlib.h>
1147+#include <string.h>
1148+#include <ctype.h>
1149+#include <netdb.h>
1150+#include <syslog.h>
1151+#include <stdarg.h>
1152+
1153+#include "../include/acl.h"
1154+
1155+/* This function checks if a char argumnet from valid char range.
1156+ * Valid range is: ASCII only, a number or a letter, a space, a dot, a slash, a dash, a comma.
1157+ *
1158+ * Returns:
1159+ * 0 - char isn't from valid group
1160+ * 1 - char is a number
1161+ * 2 - char is a letter
1162+ * 3 - char is a space(' ')
1163+ * 4 - char is a dot('.')
1164+ * 5 - char is a slash('/')
1165+ * 6 - char is a dash('-')
1166+ * 7 - char is a comma(',')
1167+ */
1168+
1169+int isvalidchar(int c) {
1170+ if (!isascii(c))
1171+ return 0;
1172+
1173+ if (isdigit(c))
1174+ return 1;
1175+
1176+ if (isalpha(c))
1177+ return 2;
1178+
1179+ if (isspace(c))
1180+ return 3;
1181+
1182+ switch (c) {
1183+ case '.':
1184+ return 4;
1185+ break;
1186+ case '/':
1187+ return 5;
1188+ break;
1189+ case '-':
1190+ return 6;
1191+ break;
1192+ case ',':
1193+ return 7;
1194+ break;
1195+ default:
1196+ return 0;
1197+ }
1198+}
1199+
1200+/*
1201+ * Get substring from allowed_hosts from s position to e position.
1202+ */
1203+
1204+char * acl_substring(char *string, int s, int e) {
1205+ char *substring;
1206+ int len = e - s;
1207+
1208+ if (len < 0)
1209+ return NULL;
1210+
1211+ if ( (substring = malloc(len + 1)) == NULL)
1212+ return NULL;
1213+
1214+ memmove(substring, string + s, len + 1);
1215+ return substring;
1216+}
1217+
1218+/*
1219+ * Add IPv4 host or network to IP ACL. IPv4 format is X.X.X.X[/X].
1220+ * Host will be added to ACL only if it has passed IPv4 format check.
1221+ *
1222+ * Returns:
1223+ * 1 - on success
1224+ * 0 - on failure
1225+ *
1226+ * States for IPv4 format check:
1227+ * 0 - numbers(-> 1), dot(-> -1), slash(-> -1), other(-> -1)
1228+ * 1 - numbers(-> 1), dot(-> 2), slash(-> -1), other(-> -1)
1229+ * 2 - numbers(-> 3), dot(-> -1), slash(-> -1), other(-> -1)
1230+ * 3 - numbers(-> 3), dot(-> 4), slash(-> -1), other(-> -1)
1231+ * 4 - numbers(-> 5), dot(-> -1), slash(-> -1), other(-> -1)
1232+ * 5 - numbers(-> 5), dot(-> 6), slash(-> -1), other(-> -1)
1233+ * 6 - numbers(-> 7), dot(-> -1), slash(-> -1), other(-> -1)
1234+ * 7 - numbers(-> 7), dor(-> -1), slash(-> 8), other(-> -1)
1235+ * 8 - numbers(-> 9), dor(-> -1), slash(-> -1), other(-> -1)
1236+ * 9 - numbers(-> 9), dot(-> -1), slash(-> -1), other(-> -1)
1237+ *
1238+ * Good states are 7(IPv4 host) and 9(IPv4 network)
1239+ */
1240+
1241+int add_ipv4_to_acl(char *ipv4) {
1242+ int state = 0;
1243+ int octet = 0;
1244+ int index = 0; /* position in data array */
1245+ int data[5]; /* array to store ip octets and mask */
1246+ int len = strlen(ipv4);
1247+ int i, c;
1248+ unsigned long ip, mask;
1249+ struct ip_acl *ip_acl_curr;
1250+
1251+ /* Check for min and max IPv4 valid length */
1252+ if (len < 7 || len > 18)
1253+ return 0;
1254+
1255+ /* default mask for ipv4 */
1256+ data[4] = 32;
1257+
1258+ /* Basic IPv4 format check */
1259+ for (i = 0; i < len; i++) {
1260+ /* Return 0 on error state */
1261+ if (state == -1)
1262+ return 0;
1263+
1264+ c = ipv4[i];
1265+
1266+ switch (c) {
1267+ case '0': case '1': case '2': case '3': case '4':
1268+ case '5': case '6': case '7': case '8': case '9':
1269+ octet = octet * 10 + CHAR_TO_NUMBER(c);
1270+ switch (state) {
1271+ case 0: case 2: case 4: case 6: case 8:
1272+ state++;
1273+ break;
1274+ }
1275+ break;
1276+ case '.':
1277+ switch (state) {
1278+ case 1: case 3: case 5:
1279+ data[index++] = octet;
1280+ octet = 0;
1281+ state++;
1282+ break;
1283+ default:
1284+ state = -1;
1285+ }
1286+ break;
1287+ case '/':
1288+ switch (state) {
1289+ case 7:
1290+ data[index++] = octet;
1291+ octet = 0;
1292+ state++;
1293+ break;
1294+ default:
1295+ state = -1;
1296+ }
1297+ break;
1298+ default:
1299+ state = -1;
1300+ }
1301+ }
1302+
1303+ /* Exit state handling */
1304+ switch (state) {
1305+ case 7: case 9:
1306+ data[index] = octet;
1307+ break;
1308+ default:
1309+ /* Bad states */
1310+ return 0;
1311+ }
1312+
1313+ /*
1314+ * Final IPv4 format check.
1315+ */
1316+ for (i=0; i < 4; i++) {
1317+ if (data[i] < 0 || data[i] > 255) {
1318+ syslog(LOG_ERR,"Invalid IPv4 address/network format(%s) in allowed_hosts option\n",ipv4);
1319+ return 0;
1320+ }
1321+ }
1322+
1323+ if (data[4] < 0 || data[4] > 32) {
1324+ syslog(LOG_ERR,"Invalid IPv4 network mask format(%s) in allowed_hosts option\n",ipv4);
1325+ return 0;
1326+ }
1327+
1328+ /* Conver ip and mask to unsigned long */
1329+ ip = htonl((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]);
1330+ mask = htonl(-1 << (32 - data[4]));
1331+
1332+ /* Wrong network address */
1333+ if ( (ip & mask) != ip) {
1334+ syslog(LOG_ERR,"IP address and mask do not match in %s\n",ipv4);
1335+ return 0;
1336+ }
1337+
1338+ /* Add addr to ip_acl list */
1339+ if ( (ip_acl_curr = malloc(sizeof(*ip_acl_curr))) == NULL) {
1340+ syslog(LOG_ERR,"Can't allocate memory for ACL, malloc error\n");
1341+ return 0;
1342+ }
1343+
1344+ /* Save result in ACL ip list */
1345+ ip_acl_curr->addr.s_addr = ip;
1346+ ip_acl_curr->mask.s_addr = mask;
1347+ ip_acl_curr->next = NULL;
1348+
1349+ if (ip_acl_head == NULL) {
1350+ ip_acl_head = ip_acl_curr;
1351+ } else {
1352+ ip_acl_prev->next = ip_acl_curr;
1353+ }
1354+ ip_acl_prev = ip_acl_curr;
1355+ return 1;
1356+}
1357+
1358+/*
1359+ * Add domain to DNS ACL list
1360+ * Domain will be added only if it has passed domain name check.
1361+ *
1362+ * In this case domain valid format is:
1363+ * 1) Domain names must use only alphanumeric characters and dashes (-).
1364+ * 2) Domain names mustn't begin or end with dashes (-).
1365+ * 3) Domain names mustn't have more than 63 characters.
1366+ *
1367+ * Return:
1368+ * 1 - for success
1369+ * 0 - for failure
1370+ *
1371+ * 0 - alpha(-> 1), number(-> 1), dot(-> -1), dash(-> -1), all other(-> -1)
1372+ * 1 - alpha(-> 1), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
1373+ * 2 - alpha(-> 3), number(-> 1), dot(-> -1), dash(-> -1), all other(-> -1)
1374+ * 3 - alpha(-> 4), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
1375+ * 4 - alpha(-> 5), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
1376+ * 5 - alpha(-> 1), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
1377+ * 6 - alpha(-> 1), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
1378+
1379+ * For real FQDN only 4 and 5 states are good for exit.
1380+ * I don't check if top domain exists (com, ru and etc.)
1381+ * But in real life NRPE could work in LAN,
1382+ * with local domain zones like .local or with names like 'mars' added to /etc/hosts.
1383+ * So 1 is good state too. And maybe this check is not necessary at all...
1384+ */
1385+
1386+int add_domain_to_acl(char *domain) {
1387+ int state = 0;
1388+ int len = strlen(domain);
1389+ int i, c;
1390+
1391+ struct dns_acl *dns_acl_curr;
1392+
1393+ if (len > 63)
1394+ return 0;
1395+
1396+ for (i = 0; i < len; i++) {
1397+ c = domain[i];
1398+ switch (isvalidchar(c)) {
1399+ case 1:
1400+ state = 1;
1401+ break;
1402+ case 2:
1403+ switch (state) {
1404+ case 0: case 1: case 5: case 6:
1405+ state = 1;
1406+ break;
1407+ case 2: case 3: case 4:
1408+ state++;
1409+ break;
1410+ }
1411+ break;
1412+
1413+ case 4:
1414+ switch (state) {
1415+ case 0: case 2:
1416+ state = -1;
1417+ break;
1418+ default:
1419+ state = 2;
1420+ }
1421+ break;
1422+ case 6:
1423+ switch (state) {
1424+ case 0: case 2:
1425+ state = -1;
1426+ break;
1427+ default:
1428+ state = 6;
1429+ }
1430+ break;
1431+ default:
1432+ /* Not valid chars */
1433+ return 0;
1434+ }
1435+ }
1436+
1437+ /* Check exit code */
1438+ switch (state) {
1439+ case 1: case 4: case 5:
1440+ /* Add name to domain ACL list */
1441+ if ( (dns_acl_curr = malloc(sizeof(*dns_acl_curr))) == NULL) {
1442+ syslog(LOG_ERR,"Can't allocate memory for ACL, malloc error\n");
1443+ return 0;
1444+ }
1445+ strcpy(dns_acl_curr->domain, domain);
1446+ dns_acl_curr->next = NULL;
1447+
1448+ if (dns_acl_head == NULL)
1449+ dns_acl_head = dns_acl_curr;
1450+ else
1451+ dns_acl_prev->next = dns_acl_curr;
1452+
1453+ dns_acl_prev = dns_acl_curr;
1454+ return 1;
1455+ default:
1456+ return 0;
1457+ }
1458+}
1459+
1460+/* Checks connectiong host in ACL
1461+ *
1462+ * Returns:
1463+ * 1 - on success
1464+ * 0 - on failure
1465+ */
1466+
1467+int is_an_allowed_host(struct in_addr host) {
1468+ struct ip_acl *ip_acl_curr = ip_acl_head;
1469+ struct dns_acl *dns_acl_curr = dns_acl_head;
1470+ struct in_addr addr;
1471+ struct hostent *he;
1472+
1473+ while (ip_acl_curr != NULL) {
1474+ if ( (host.s_addr & ip_acl_curr->mask.s_addr) == ip_acl_curr->addr.s_addr)
1475+ return 1;
1476+
1477+ ip_acl_curr = ip_acl_curr->next;
1478+ }
1479+
1480+ while(dns_acl_curr != NULL) {
1481+ he = gethostbyname(dns_acl_curr->domain);
1482+ if (he == NULL)
1483+ return 0;
1484+
1485+ while (*he->h_addr_list) {
1486+ memmove((char *)&addr,*he->h_addr_list++, sizeof(addr));
1487+ if (addr.s_addr == host.s_addr)
1488+ return 1;
1489+ }
1490+ dns_acl_curr = dns_acl_curr->next;
1491+ }
1492+ return 0;
1493+}
1494+
1495+/* The trim() function takes a source string and copies it to the destination string,
1496+ * stripped of leading and training whitespace. The destination string must be
1497+ * allocated at least as large as the source string.
1498+ */
1499+
1500+void trim( char *src, char *dest) {
1501+ char *sptr, *dptr;
1502+
1503+ for( sptr = src; isblank( *sptr) && *sptr; sptr++); /* Jump past leading spaces */
1504+ for( dptr = dest; !isblank( *sptr) && *sptr; ) {
1505+ *dptr = *sptr;
1506+ sptr++;
1507+ dptr++;
1508+ }
1509+ *dptr = '\0';
1510+ return;
1511+}
1512+
1513+/* This function splits allowed_hosts to substrings with comma(,) as a delimeter.
1514+ * It doesn't check validness of ACL record (add_ipv4_to_acl() and add_domain_to_acl() do),
1515+ * just trims spaces from ACL records.
1516+ * After this it sends ACL records to add_ipv4_to_acl() or add_domain_to_acl().
1517+ */
1518+
1519+void parse_allowed_hosts(char *allowed_hosts) {
1520+ char *hosts = strdup( allowed_hosts); /* Copy since strtok* modifes original */
1521+ char *saveptr;
1522+ char *tok;
1523+ const char *delim = ",";
1524+ char *trimmed_tok;
1525+
1526+ tok = strtok_r( hosts, delim, &saveptr);
1527+ while( tok) {
1528+ trimmed_tok = malloc( sizeof( char) * ( strlen( tok) + 1));
1529+ trim( tok, trimmed_tok);
1530+ if( strlen( trimmed_tok) > 0) {
1531+ if (!add_ipv4_to_acl(trimmed_tok) && !add_domain_to_acl(trimmed_tok)) {
1532+ syslog(LOG_ERR,"Can't add to ACL this record (%s). Check allowed_hosts option!\n",trimmed_tok);
1533+ }
1534+ }
1535+ free( trimmed_tok);
1536+ tok = strtok_r(( char *)0, delim, &saveptr);
1537+ }
1538+
1539+ free( hosts);
1540+}
1541+
1542+/*
1543+ * Converts mask in unsigned long format to two digit prefix
1544+ */
1545+
1546+unsigned int prefix_from_mask(struct in_addr mask) {
1547+ int prefix = 0;
1548+ unsigned long bit = 1;
1549+ int i;
1550+
1551+ for (i = 0; i < 32; i++) {
1552+ if (mask.s_addr & bit)
1553+ prefix++;
1554+
1555+ bit = bit << 1;
1556+ }
1557+ return (prefix);
1558+}
1559+
1560+/*
1561+ * It shows all hosts in ACL lists
1562+ */
1563+
1564+void show_acl_lists(void) {
1565+ struct ip_acl *ip_acl_curr = ip_acl_head;
1566+ struct dns_acl *dns_acl_curr = dns_acl_head;
1567+
1568+ while (ip_acl_curr != NULL) {
1569+ printf(" IP ACL: %s/%u %u\n", inet_ntoa(ip_acl_curr->addr), prefix_from_mask(ip_acl_curr->mask), ip_acl_curr->addr.s_addr);
1570+ ip_acl_curr = ip_acl_curr->next;
1571+ }
1572+
1573+ while (dns_acl_curr != NULL) {
1574+ printf("DNS ACL: %s\n", dns_acl_curr->domain);
1575+ dns_acl_curr = dns_acl_curr->next;
1576+ }
1577+}
1578
1579=== modified file 'src/check_nrpe.c' (properties changed: -x to +x)
1580--- src/check_nrpe.c 2008-08-06 20:33:57 +0000
1581+++ src/check_nrpe.c 2013-02-02 23:23:20 +0000
1582@@ -1,462 +1,462 @@
1583-/********************************************************************************************
1584- *
1585- * CHECK_NRPE.C - NRPE Plugin For Nagios
1586- * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)
1587- * License: GPL
1588- *
1589- * Last Modified: 03-10-2008
1590- *
1591- * Command line: CHECK_NRPE -H <host_address> [-p port] [-c command] [-to to_sec]
1592- *
1593- * Description:
1594- *
1595- * This plugin will attempt to connect to the NRPE daemon on the specified server and port.
1596- * The daemon will attempt to run the command defined as [command]. Program output and
1597- * return code are sent back from the daemon and displayed as this plugin's own output and
1598- * return code.
1599- *
1600- ********************************************************************************************/
1601-
1602-#include "../include/common.h"
1603-#include "../include/config.h"
1604-#include "../include/utils.h"
1605-
1606-
1607-#define DEFAULT_NRPE_COMMAND "_NRPE_CHECK" /* check version of NRPE daemon */
1608-
1609-int server_port=DEFAULT_SERVER_PORT;
1610-char *server_name=NULL;
1611-char *command_name=NULL;
1612-int socket_timeout=DEFAULT_SOCKET_TIMEOUT;
1613-int timeout_return_code=STATE_CRITICAL;
1614-int sd;
1615-
1616-char query[MAX_INPUT_BUFFER]="";
1617-
1618-int show_help=FALSE;
1619-int show_license=FALSE;
1620-int show_version=FALSE;
1621-
1622-#ifdef HAVE_SSL
1623-SSL_METHOD *meth;
1624-SSL_CTX *ctx;
1625-SSL *ssl;
1626-int use_ssl=TRUE;
1627-#else
1628-int use_ssl=FALSE;
1629-#endif
1630-
1631-
1632-int process_arguments(int,char **);
1633-void alarm_handler(int);
1634-int graceful_close(int,int);
1635-
1636-
1637-
1638-
1639-int main(int argc, char **argv){
1640- u_int32_t packet_crc32;
1641- u_int32_t calculated_crc32;
1642- int16_t result;
1643- int rc;
1644- packet send_packet;
1645- packet receive_packet;
1646- int bytes_to_send;
1647- int bytes_to_recv;
1648-
1649- result=process_arguments(argc,argv);
1650-
1651- if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){
1652-
1653- if(result!=OK)
1654- printf("Incorrect command line arguments supplied\n");
1655- printf("\n");
1656- printf("NRPE Plugin for Nagios\n");
1657- printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n");
1658- printf("Version: %s\n",PROGRAM_VERSION);
1659- printf("Last Modified: %s\n",MODIFICATION_DATE);
1660- printf("License: GPL v2 with exemptions (-l for more info)\n");
1661-#ifdef HAVE_SSL
1662- printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n");
1663-#endif
1664- printf("\n");
1665- }
1666-
1667- if(result!=OK || show_help==TRUE){
1668-
1669- printf("Usage: check_nrpe -H <host> [-n] [-u] [-p <port>] [-t <timeout>] [-c <command>] [-a <arglist...>]\n");
1670- printf("\n");
1671- printf("Options:\n");
1672- printf(" -n = Do no use SSL\n");
1673- printf(" -u = Make socket timeouts return an UNKNOWN state instead of CRITICAL\n");
1674- printf(" <host> = The address of the host running the NRPE daemon\n");
1675- printf(" [port] = The port on which the daemon is running (default=%d)\n",DEFAULT_SERVER_PORT);
1676- printf(" [timeout] = Number of seconds before connection times out (default=%d)\n",DEFAULT_SOCKET_TIMEOUT);
1677- printf(" [command] = The name of the command that the remote daemon should run\n");
1678- printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n");
1679- printf(" arguments should be separated by a space. If provided, this must be\n");
1680- printf(" the last option supplied on the command line.\n");
1681- printf("\n");
1682- printf("Note:\n");
1683- printf("This plugin requires that you have the NRPE daemon running on the remote host.\n");
1684- printf("You must also have configured the daemon to associate a specific plugin command\n");
1685- printf("with the [command] option you are specifying here. Upon receipt of the\n");
1686- printf("[command] argument, the NRPE daemon will run the appropriate plugin command and\n");
1687- printf("send the plugin output and return code back to *this* plugin. This allows you\n");
1688- printf("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n");
1689- printf("the plugin is being run locally.\n");
1690- printf("\n");
1691- }
1692-
1693- if(show_license==TRUE)
1694- display_license();
1695-
1696- if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
1697- exit(STATE_UNKNOWN);
1698-
1699-
1700- /* generate the CRC 32 table */
1701- generate_crc32_table();
1702-
1703-#ifdef HAVE_SSL
1704- /* initialize SSL */
1705- if(use_ssl==TRUE){
1706- SSL_library_init();
1707- SSLeay_add_ssl_algorithms();
1708- meth=SSLv23_client_method();
1709- SSL_load_error_strings();
1710- if((ctx=SSL_CTX_new(meth))==NULL){
1711- printf("CHECK_NRPE: Error - could not create SSL context.\n");
1712- exit(STATE_CRITICAL);
1713- }
1714-
1715- /* ADDED 01/19/2004 */
1716- /* use only TLSv1 protocol */
1717- SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
1718- }
1719-#endif
1720-
1721- /* initialize alarm signal handling */
1722- signal(SIGALRM,alarm_handler);
1723-
1724- /* set socket timeout */
1725- alarm(socket_timeout);
1726-
1727- /* try to connect to the host at the given port number */
1728- result=my_tcp_connect(server_name,server_port,&sd);
1729-
1730-#ifdef HAVE_SSL
1731- /* do SSL handshake */
1732- if(result==STATE_OK && use_ssl==TRUE){
1733- if((ssl=SSL_new(ctx))!=NULL){
1734- SSL_CTX_set_cipher_list(ctx,"ADH");
1735- SSL_set_fd(ssl,sd);
1736- if((rc=SSL_connect(ssl))!=1){
1737- printf("CHECK_NRPE: Error - Could not complete SSL handshake.\n");
1738-#ifdef DEBUG
1739- printf("SSL_connect=%d\n",rc);
1740- /*
1741- rc=SSL_get_error(ssl,rc);
1742- printf("SSL_get_error=%d\n",rc);
1743- printf("ERR_get_error=%lu\n",ERR_get_error());
1744- printf("%s\n",ERR_error_string(rc,NULL));
1745- */
1746- ERR_print_errors_fp(stdout);
1747-#endif
1748- result=STATE_CRITICAL;
1749- }
1750- }
1751- else{
1752- printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n");
1753- result=STATE_CRITICAL;
1754- }
1755-
1756- /* bail if we had errors */
1757- if(result!=STATE_OK){
1758- SSL_CTX_free(ctx);
1759- close(sd);
1760- exit(result);
1761- }
1762- }
1763-#endif
1764-
1765- /* we're connected and ready to go */
1766- if(result==STATE_OK){
1767-
1768- /* clear the packet buffer */
1769- bzero(&send_packet,sizeof(send_packet));
1770-
1771- /* fill the packet with semi-random data */
1772- randomize_buffer((char *)&send_packet,sizeof(send_packet));
1773-
1774- /* initialize packet data */
1775- send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2);
1776- send_packet.packet_type=(int16_t)htons(QUERY_PACKET);
1777- strncpy(&send_packet.buffer[0],query,MAX_PACKETBUFFER_LENGTH);
1778- send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
1779-
1780- /* calculate the crc 32 value of the packet */
1781- send_packet.crc32_value=(u_int32_t)0L;
1782- calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet));
1783- send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32);
1784-
1785-
1786- /***** ENCRYPT REQUEST *****/
1787-
1788-
1789- /* send the packet */
1790- bytes_to_send=sizeof(send_packet);
1791- if(use_ssl==FALSE)
1792- rc=sendall(sd,(char *)&send_packet,&bytes_to_send);
1793-#ifdef HAVE_SSL
1794- else{
1795- rc=SSL_write(ssl,&send_packet,bytes_to_send);
1796- if(rc<0)
1797- rc=-1;
1798- }
1799-#endif
1800- if(rc==-1){
1801- printf("CHECK_NRPE: Error sending query to host.\n");
1802- close(sd);
1803- return STATE_UNKNOWN;
1804- }
1805-
1806- /* wait for the response packet */
1807- bytes_to_recv=sizeof(receive_packet);
1808- if(use_ssl==FALSE)
1809- rc=recvall(sd,(char *)&receive_packet,&bytes_to_recv,socket_timeout);
1810-#ifdef HAVE_SSL
1811- else
1812- rc=SSL_read(ssl,&receive_packet,bytes_to_recv);
1813-#endif
1814-
1815- /* reset timeout */
1816- alarm(0);
1817-
1818- /* close the connection */
1819-#ifdef HAVE_SSL
1820- if(use_ssl==TRUE){
1821- SSL_shutdown(ssl);
1822- SSL_free(ssl);
1823- SSL_CTX_free(ctx);
1824- }
1825-#endif
1826- graceful_close(sd,1000);
1827-
1828- /* recv() error */
1829- if(rc<0){
1830- printf("CHECK_NRPE: Error receiving data from daemon.\n");
1831- return STATE_UNKNOWN;
1832- }
1833-
1834- /* server disconnected */
1835- else if(rc==0){
1836- printf("CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages.\n");
1837- return STATE_UNKNOWN;
1838- }
1839-
1840- /* receive underflow */
1841- else if(bytes_to_recv<sizeof(receive_packet)){
1842- printf("CHECK_NRPE: Receive underflow - only %d bytes received (%d expected).\n",bytes_to_recv,sizeof(receive_packet));
1843- return STATE_UNKNOWN;
1844- }
1845-
1846-
1847- /***** DECRYPT RESPONSE *****/
1848-
1849-
1850- /* check the crc 32 value */
1851- packet_crc32=ntohl(receive_packet.crc32_value);
1852- receive_packet.crc32_value=0L;
1853- calculated_crc32=calculate_crc32((char *)&receive_packet,sizeof(receive_packet));
1854- if(packet_crc32!=calculated_crc32){
1855- printf("CHECK_NRPE: Response packet had invalid CRC32.\n");
1856- close(sd);
1857- return STATE_UNKNOWN;
1858- }
1859-
1860- /* check packet version */
1861- if(ntohs(receive_packet.packet_version)!=NRPE_PACKET_VERSION_2){
1862- printf("CHECK_NRPE: Invalid packet version received from server.\n");
1863- close(sd);
1864- return STATE_UNKNOWN;
1865- }
1866-
1867- /* check packet type */
1868- if(ntohs(receive_packet.packet_type)!=RESPONSE_PACKET){
1869- printf("CHECK_NRPE: Invalid packet type received from server.\n");
1870- close(sd);
1871- return STATE_UNKNOWN;
1872- }
1873-
1874- /* get the return code from the remote plugin */
1875- result=(int16_t)ntohs(receive_packet.result_code);
1876-
1877- /* print the output returned by the daemon */
1878- receive_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
1879- if(!strcmp(receive_packet.buffer,""))
1880- printf("CHECK_NRPE: No output returned from daemon.\n");
1881- else
1882- printf("%s\n",receive_packet.buffer);
1883- }
1884-
1885- /* reset the alarm */
1886- else
1887- alarm(0);
1888-
1889- return result;
1890- }
1891-
1892-
1893-
1894-/* process command line arguments */
1895-int process_arguments(int argc, char **argv){
1896- char optchars[MAX_INPUT_BUFFER];
1897- int argindex=0;
1898- int c=1;
1899- int i=1;
1900-
1901-#ifdef HAVE_GETOPT_LONG
1902- int option_index=0;
1903- static struct option long_options[]={
1904- {"host", required_argument, 0, 'H'},
1905- {"command", required_argument, 0, 'c'},
1906- {"args", required_argument, 0, 'a'},
1907- {"no-ssl", no_argument, 0, 'n'},
1908- {"unknown-timeout", no_argument, 0, 'u'},
1909- {"timeout", required_argument, 0, 't'},
1910- {"port", required_argument, 0, 'p'},
1911- {"help", no_argument, 0, 'h'},
1912- {"license", no_argument, 0, 'l'},
1913- {0, 0, 0, 0}
1914- };
1915-#endif
1916-
1917- /* no options were supplied */
1918- if(argc<2)
1919- return ERROR;
1920-
1921- snprintf(optchars,MAX_INPUT_BUFFER,"H:c:a:t:p:nuhl");
1922-
1923- while(1){
1924-#ifdef HAVE_GETOPT_LONG
1925- c=getopt_long(argc,argv,optchars,long_options,&option_index);
1926-#else
1927- c=getopt(argc,argv,optchars);
1928-#endif
1929- if(c==-1 || c==EOF)
1930- break;
1931-
1932- /* process all arguments */
1933- switch(c){
1934-
1935- case '?':
1936- case 'h':
1937- show_help=TRUE;
1938- break;
1939- case 'V':
1940- show_version=TRUE;
1941- break;
1942- case 'l':
1943- show_license=TRUE;
1944- break;
1945- case 't':
1946- socket_timeout=atoi(optarg);
1947- if(socket_timeout<=0)
1948- return ERROR;
1949- break;
1950- case 'p':
1951- server_port=atoi(optarg);
1952- if(server_port<=0)
1953- return ERROR;
1954- break;
1955- case 'H':
1956- server_name=strdup(optarg);
1957- break;
1958- case 'c':
1959- command_name=strdup(optarg);
1960- break;
1961- case 'a':
1962- argindex=optind;
1963- break;
1964- case 'n':
1965- use_ssl=FALSE;
1966- break;
1967- case 'u':
1968- timeout_return_code=STATE_UNKNOWN;
1969- break;
1970- default:
1971- return ERROR;
1972- break;
1973- }
1974- }
1975-
1976- /* determine (base) command query */
1977- snprintf(query,sizeof(query),"%s",(command_name==NULL)?DEFAULT_NRPE_COMMAND:command_name);
1978- query[sizeof(query)-1]='\x0';
1979-
1980- /* get the command args */
1981- if(argindex>0){
1982-
1983- for(c=argindex-1;c<argc;c++){
1984-
1985- i=sizeof(query)-strlen(query)-2;
1986- if(i<=0)
1987- break;
1988-
1989- strcat(query,"!");
1990- strncat(query,argv[c],i);
1991- query[sizeof(query)-1]='\x0';
1992- }
1993- }
1994-
1995- /* make sure required args were supplied */
1996- if(server_name==NULL && show_help==FALSE && show_version==FALSE && show_license==FALSE)
1997- return ERROR;
1998-
1999-
2000- return OK;
2001- }
2002-
2003-
2004-
2005-void alarm_handler(int sig){
2006-
2007- printf("CHECK_NRPE: Socket timeout after %d seconds.\n",socket_timeout);
2008-
2009- exit(timeout_return_code);
2010- }
2011-
2012-
2013-/* submitted by Mark Plaksin 08/31/2006 */
2014-int graceful_close(int sd, int timeout){
2015- fd_set in;
2016- struct timeval tv;
2017- char buf[1000];
2018-
2019- /* send FIN packet */
2020- shutdown(sd,SHUT_WR);
2021- for(;;){
2022-
2023- FD_ZERO(&in);
2024- FD_SET(sd,&in);
2025- tv.tv_sec=timeout/1000;
2026- tv.tv_usec=(timeout % 1000)*1000;
2027-
2028- /* timeout or error */
2029- if(1!=select(sd+1,&in,NULL,NULL,&tv))
2030- break;
2031-
2032- /* no more data (FIN or RST) */
2033- if(0>=recv(sd,buf,sizeof(buf),0))
2034- break;
2035- }
2036-
2037-#ifdef HAVE_CLOSESOCKET
2038- closesocket(sd);
2039-#else
2040- close(sd);
2041-#endif
2042-
2043- return OK;
2044- }
2045+/********************************************************************************************
2046+ *
2047+ * CHECK_NRPE.C - NRPE Plugin For Nagios
2048+ * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)
2049+ * License: GPL
2050+ *
2051+ * Last Modified: 11-11-2011
2052+ *
2053+ * Command line: CHECK_NRPE -H <host_address> [-p port] [-c command] [-to to_sec]
2054+ *
2055+ * Description:
2056+ *
2057+ * This plugin will attempt to connect to the NRPE daemon on the specified server and port.
2058+ * The daemon will attempt to run the command defined as [command]. Program output and
2059+ * return code are sent back from the daemon and displayed as this plugin's own output and
2060+ * return code.
2061+ *
2062+ ********************************************************************************************/
2063+
2064+#include "../include/common.h"
2065+#include "../include/config.h"
2066+#include "../include/utils.h"
2067+
2068+
2069+#define DEFAULT_NRPE_COMMAND "_NRPE_CHECK" /* check version of NRPE daemon */
2070+
2071+int server_port=DEFAULT_SERVER_PORT;
2072+char *server_name=NULL;
2073+char *command_name=NULL;
2074+int socket_timeout=DEFAULT_SOCKET_TIMEOUT;
2075+int timeout_return_code=STATE_CRITICAL;
2076+int sd;
2077+
2078+char query[MAX_INPUT_BUFFER]="";
2079+
2080+int show_help=FALSE;
2081+int show_license=FALSE;
2082+int show_version=FALSE;
2083+
2084+#ifdef HAVE_SSL
2085+SSL_METHOD *meth;
2086+SSL_CTX *ctx;
2087+SSL *ssl;
2088+int use_ssl=TRUE;
2089+#else
2090+int use_ssl=FALSE;
2091+#endif
2092+
2093+
2094+int process_arguments(int,char **);
2095+void alarm_handler(int);
2096+int graceful_close(int,int);
2097+
2098+
2099+
2100+
2101+int main(int argc, char **argv){
2102+ u_int32_t packet_crc32;
2103+ u_int32_t calculated_crc32;
2104+ int16_t result;
2105+ int rc;
2106+ packet send_packet;
2107+ packet receive_packet;
2108+ int bytes_to_send;
2109+ int bytes_to_recv;
2110+
2111+ result=process_arguments(argc,argv);
2112+
2113+ if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){
2114+
2115+ if(result!=OK)
2116+ printf("Incorrect command line arguments supplied\n");
2117+ printf("\n");
2118+ printf("NRPE Plugin for Nagios\n");
2119+ printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n");
2120+ printf("Version: %s\n",PROGRAM_VERSION);
2121+ printf("Last Modified: %s\n",MODIFICATION_DATE);
2122+ printf("License: GPL v2 with exemptions (-l for more info)\n");
2123+#ifdef HAVE_SSL
2124+ printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n");
2125+#endif
2126+ printf("\n");
2127+ }
2128+
2129+ if(result!=OK || show_help==TRUE){
2130+
2131+ printf("Usage: check_nrpe -H <host> [-n] [-u] [-p <port>] [-t <timeout>] [-c <command>] [-a <arglist...>]\n");
2132+ printf("\n");
2133+ printf("Options:\n");
2134+ printf(" -n = Do no use SSL\n");
2135+ printf(" -u = Make socket timeouts return an UNKNOWN state instead of CRITICAL\n");
2136+ printf(" <host> = The address of the host running the NRPE daemon\n");
2137+ printf(" [port] = The port on which the daemon is running (default=%d)\n",DEFAULT_SERVER_PORT);
2138+ printf(" [timeout] = Number of seconds before connection times out (default=%d)\n",DEFAULT_SOCKET_TIMEOUT);
2139+ printf(" [command] = The name of the command that the remote daemon should run\n");
2140+ printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n");
2141+ printf(" arguments should be separated by a space. If provided, this must be\n");
2142+ printf(" the last option supplied on the command line.\n");
2143+ printf("\n");
2144+ printf("Note:\n");
2145+ printf("This plugin requires that you have the NRPE daemon running on the remote host.\n");
2146+ printf("You must also have configured the daemon to associate a specific plugin command\n");
2147+ printf("with the [command] option you are specifying here. Upon receipt of the\n");
2148+ printf("[command] argument, the NRPE daemon will run the appropriate plugin command and\n");
2149+ printf("send the plugin output and return code back to *this* plugin. This allows you\n");
2150+ printf("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n");
2151+ printf("the plugin is being run locally.\n");
2152+ printf("\n");
2153+ }
2154+
2155+ if(show_license==TRUE)
2156+ display_license();
2157+
2158+ if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
2159+ exit(STATE_UNKNOWN);
2160+
2161+
2162+ /* generate the CRC 32 table */
2163+ generate_crc32_table();
2164+
2165+#ifdef HAVE_SSL
2166+ /* initialize SSL */
2167+ if(use_ssl==TRUE){
2168+ SSL_library_init();
2169+ SSLeay_add_ssl_algorithms();
2170+ meth=SSLv23_client_method();
2171+ SSL_load_error_strings();
2172+ if((ctx=SSL_CTX_new(meth))==NULL){
2173+ printf("CHECK_NRPE: Error - could not create SSL context.\n");
2174+ exit(STATE_CRITICAL);
2175+ }
2176+
2177+ /* ADDED 01/19/2004 */
2178+ /* use only TLSv1 protocol */
2179+ SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
2180+ }
2181+#endif
2182+
2183+ /* initialize alarm signal handling */
2184+ signal(SIGALRM,alarm_handler);
2185+
2186+ /* set socket timeout */
2187+ alarm(socket_timeout);
2188+
2189+ /* try to connect to the host at the given port number */
2190+ result=my_tcp_connect(server_name,server_port,&sd);
2191+
2192+#ifdef HAVE_SSL
2193+ /* do SSL handshake */
2194+ if(result==STATE_OK && use_ssl==TRUE){
2195+ if((ssl=SSL_new(ctx))!=NULL){
2196+ SSL_CTX_set_cipher_list(ctx,"ADH");
2197+ SSL_set_fd(ssl,sd);
2198+ if((rc=SSL_connect(ssl))!=1){
2199+ printf("CHECK_NRPE: Error - Could not complete SSL handshake.\n");
2200+#ifdef DEBUG
2201+ printf("SSL_connect=%d\n",rc);
2202+ /*
2203+ rc=SSL_get_error(ssl,rc);
2204+ printf("SSL_get_error=%d\n",rc);
2205+ printf("ERR_get_error=%lu\n",ERR_get_error());
2206+ printf("%s\n",ERR_error_string(rc,NULL));
2207+ */
2208+ ERR_print_errors_fp(stdout);
2209+#endif
2210+ result=STATE_CRITICAL;
2211+ }
2212+ }
2213+ else{
2214+ printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n");
2215+ result=STATE_CRITICAL;
2216+ }
2217+
2218+ /* bail if we had errors */
2219+ if(result!=STATE_OK){
2220+ SSL_CTX_free(ctx);
2221+ close(sd);
2222+ exit(result);
2223+ }
2224+ }
2225+#endif
2226+
2227+ /* we're connected and ready to go */
2228+ if(result==STATE_OK){
2229+
2230+ /* clear the packet buffer */
2231+ bzero(&send_packet,sizeof(send_packet));
2232+
2233+ /* fill the packet with semi-random data */
2234+ randomize_buffer((char *)&send_packet,sizeof(send_packet));
2235+
2236+ /* initialize packet data */
2237+ send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2);
2238+ send_packet.packet_type=(int16_t)htons(QUERY_PACKET);
2239+ strncpy(&send_packet.buffer[0],query,MAX_PACKETBUFFER_LENGTH);
2240+ send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
2241+
2242+ /* calculate the crc 32 value of the packet */
2243+ send_packet.crc32_value=(u_int32_t)0L;
2244+ calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet));
2245+ send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32);
2246+
2247+
2248+ /***** ENCRYPT REQUEST *****/
2249+
2250+
2251+ /* send the packet */
2252+ bytes_to_send=sizeof(send_packet);
2253+ if(use_ssl==FALSE)
2254+ rc=sendall(sd,(char *)&send_packet,&bytes_to_send);
2255+#ifdef HAVE_SSL
2256+ else{
2257+ rc=SSL_write(ssl,&send_packet,bytes_to_send);
2258+ if(rc<0)
2259+ rc=-1;
2260+ }
2261+#endif
2262+ if(rc==-1){
2263+ printf("CHECK_NRPE: Error sending query to host.\n");
2264+ close(sd);
2265+ return STATE_UNKNOWN;
2266+ }
2267+
2268+ /* wait for the response packet */
2269+ bytes_to_recv=sizeof(receive_packet);
2270+ if(use_ssl==FALSE)
2271+ rc=recvall(sd,(char *)&receive_packet,&bytes_to_recv,socket_timeout);
2272+#ifdef HAVE_SSL
2273+ else
2274+ rc=SSL_read(ssl,&receive_packet,bytes_to_recv);
2275+#endif
2276+
2277+ /* reset timeout */
2278+ alarm(0);
2279+
2280+ /* close the connection */
2281+#ifdef HAVE_SSL
2282+ if(use_ssl==TRUE){
2283+ SSL_shutdown(ssl);
2284+ SSL_free(ssl);
2285+ SSL_CTX_free(ctx);
2286+ }
2287+#endif
2288+ graceful_close(sd,1000);
2289+
2290+ /* recv() error */
2291+ if(rc<0){
2292+ printf("CHECK_NRPE: Error receiving data from daemon.\n");
2293+ return STATE_UNKNOWN;
2294+ }
2295+
2296+ /* server disconnected */
2297+ else if(rc==0){
2298+ printf("CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages.\n");
2299+ return STATE_UNKNOWN;
2300+ }
2301+
2302+ /* receive underflow */
2303+ else if(bytes_to_recv<sizeof(receive_packet)){
2304+ printf("CHECK_NRPE: Receive underflow - only %d bytes received (%d expected).\n",bytes_to_recv,sizeof(receive_packet));
2305+ return STATE_UNKNOWN;
2306+ }
2307+
2308+
2309+ /***** DECRYPT RESPONSE *****/
2310+
2311+
2312+ /* check the crc 32 value */
2313+ packet_crc32=ntohl(receive_packet.crc32_value);
2314+ receive_packet.crc32_value=0L;
2315+ calculated_crc32=calculate_crc32((char *)&receive_packet,sizeof(receive_packet));
2316+ if(packet_crc32!=calculated_crc32){
2317+ printf("CHECK_NRPE: Response packet had invalid CRC32.\n");
2318+ close(sd);
2319+ return STATE_UNKNOWN;
2320+ }
2321+
2322+ /* check packet version */
2323+ if(ntohs(receive_packet.packet_version)!=NRPE_PACKET_VERSION_2){
2324+ printf("CHECK_NRPE: Invalid packet version received from server.\n");
2325+ close(sd);
2326+ return STATE_UNKNOWN;
2327+ }
2328+
2329+ /* check packet type */
2330+ if(ntohs(receive_packet.packet_type)!=RESPONSE_PACKET){
2331+ printf("CHECK_NRPE: Invalid packet type received from server.\n");
2332+ close(sd);
2333+ return STATE_UNKNOWN;
2334+ }
2335+
2336+ /* get the return code from the remote plugin */
2337+ result=(int16_t)ntohs(receive_packet.result_code);
2338+
2339+ /* print the output returned by the daemon */
2340+ receive_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
2341+ if(!strcmp(receive_packet.buffer,""))
2342+ printf("CHECK_NRPE: No output returned from daemon.\n");
2343+ else
2344+ printf("%s\n",receive_packet.buffer);
2345+ }
2346+
2347+ /* reset the alarm */
2348+ else
2349+ alarm(0);
2350+
2351+ return result;
2352+ }
2353+
2354+
2355+
2356+/* process command line arguments */
2357+int process_arguments(int argc, char **argv){
2358+ char optchars[MAX_INPUT_BUFFER];
2359+ int argindex=0;
2360+ int c=1;
2361+ int i=1;
2362+
2363+#ifdef HAVE_GETOPT_LONG
2364+ int option_index=0;
2365+ static struct option long_options[]={
2366+ {"host", required_argument, 0, 'H'},
2367+ {"command", required_argument, 0, 'c'},
2368+ {"args", required_argument, 0, 'a'},
2369+ {"no-ssl", no_argument, 0, 'n'},
2370+ {"unknown-timeout", no_argument, 0, 'u'},
2371+ {"timeout", required_argument, 0, 't'},
2372+ {"port", required_argument, 0, 'p'},
2373+ {"help", no_argument, 0, 'h'},
2374+ {"license", no_argument, 0, 'l'},
2375+ {0, 0, 0, 0}
2376+ };
2377+#endif
2378+
2379+ /* no options were supplied */
2380+ if(argc<2)
2381+ return ERROR;
2382+
2383+ snprintf(optchars,MAX_INPUT_BUFFER,"H:c:a:t:p:nuhl");
2384+
2385+ while(1){
2386+#ifdef HAVE_GETOPT_LONG
2387+ c=getopt_long(argc,argv,optchars,long_options,&option_index);
2388+#else
2389+ c=getopt(argc,argv,optchars);
2390+#endif
2391+ if(c==-1 || c==EOF)
2392+ break;
2393+
2394+ /* process all arguments */
2395+ switch(c){
2396+
2397+ case '?':
2398+ case 'h':
2399+ show_help=TRUE;
2400+ break;
2401+ case 'V':
2402+ show_version=TRUE;
2403+ break;
2404+ case 'l':
2405+ show_license=TRUE;
2406+ break;
2407+ case 't':
2408+ socket_timeout=atoi(optarg);
2409+ if(socket_timeout<=0)
2410+ return ERROR;
2411+ break;
2412+ case 'p':
2413+ server_port=atoi(optarg);
2414+ if(server_port<=0)
2415+ return ERROR;
2416+ break;
2417+ case 'H':
2418+ server_name=strdup(optarg);
2419+ break;
2420+ case 'c':
2421+ command_name=strdup(optarg);
2422+ break;
2423+ case 'a':
2424+ argindex=optind;
2425+ break;
2426+ case 'n':
2427+ use_ssl=FALSE;
2428+ break;
2429+ case 'u':
2430+ timeout_return_code=STATE_UNKNOWN;
2431+ break;
2432+ default:
2433+ return ERROR;
2434+ break;
2435+ }
2436+ }
2437+
2438+ /* determine (base) command query */
2439+ snprintf(query,sizeof(query),"%s",(command_name==NULL)?DEFAULT_NRPE_COMMAND:command_name);
2440+ query[sizeof(query)-1]='\x0';
2441+
2442+ /* get the command args */
2443+ if(argindex>0){
2444+
2445+ for(c=argindex-1;c<argc;c++){
2446+
2447+ i=sizeof(query)-strlen(query)-2;
2448+ if(i<=0)
2449+ break;
2450+
2451+ strcat(query,"!");
2452+ strncat(query,argv[c],i);
2453+ query[sizeof(query)-1]='\x0';
2454+ }
2455+ }
2456+
2457+ /* make sure required args were supplied */
2458+ if(server_name==NULL && show_help==FALSE && show_version==FALSE && show_license==FALSE)
2459+ return ERROR;
2460+
2461+
2462+ return OK;
2463+ }
2464+
2465+
2466+
2467+void alarm_handler(int sig){
2468+
2469+ printf("CHECK_NRPE: Socket timeout after %d seconds.\n",socket_timeout);
2470+
2471+ exit(timeout_return_code);
2472+ }
2473+
2474+
2475+/* submitted by Mark Plaksin 08/31/2006 */
2476+int graceful_close(int sd, int timeout){
2477+ fd_set in;
2478+ struct timeval tv;
2479+ char buf[1000];
2480+
2481+ /* send FIN packet */
2482+ shutdown(sd,SHUT_WR);
2483+ for(;;){
2484+
2485+ FD_ZERO(&in);
2486+ FD_SET(sd,&in);
2487+ tv.tv_sec=timeout/1000;
2488+ tv.tv_usec=(timeout % 1000)*1000;
2489+
2490+ /* timeout or error */
2491+ if(1!=select(sd+1,&in,NULL,NULL,&tv))
2492+ break;
2493+
2494+ /* no more data (FIN or RST) */
2495+ if(0>=recv(sd,buf,sizeof(buf),0))
2496+ break;
2497+ }
2498+
2499+#ifdef HAVE_CLOSESOCKET
2500+ closesocket(sd);
2501+#else
2502+ close(sd);
2503+#endif
2504+
2505+ return OK;
2506+ }
2507
2508=== modified file 'src/nrpe.c' (properties changed: -x to +x)
2509--- src/nrpe.c 2008-08-06 20:33:57 +0000
2510+++ src/nrpe.c 2013-02-02 23:23:20 +0000
2511@@ -1,1968 +1,1912 @@
2512-/*******************************************************************************
2513- *
2514- * NRPE.C - Nagios Remote Plugin Executor
2515- * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)
2516- * License: GPL
2517- *
2518- * Last Modified: 03-10-2008
2519- *
2520- * Command line: nrpe -c <config_file> [--inetd | --daemon]
2521- *
2522- * Description:
2523- *
2524- * This program is designed to run as a background process and
2525- * handle incoming requests (from the host running Nagios) for
2526- * plugin execution. It is useful for running "local" plugins
2527- * such as check_users, check_load, check_disk, etc. without
2528- * having to use rsh or ssh.
2529- *
2530- ******************************************************************************/
2531-
2532-#include "../include/common.h"
2533-#include "../include/config.h"
2534-#include "../include/nrpe.h"
2535-#include "../include/utils.h"
2536-
2537-#ifdef HAVE_SSL
2538-#include "../include/dh.h"
2539-#endif
2540-
2541-#ifdef HAVE_LIBWRAP
2542-int allow_severity=LOG_INFO;
2543-int deny_severity=LOG_WARNING;
2544-#endif
2545-
2546-#ifdef HAVE_SSL
2547-SSL_METHOD *meth;
2548-SSL_CTX *ctx;
2549-int use_ssl=TRUE;
2550-#else
2551-int use_ssl=FALSE;
2552-#endif
2553-
2554-#define DEFAULT_COMMAND_TIMEOUT 60 /* default timeout for execution of plugins */
2555-#define MAXFD 64
2556-#define NASTY_METACHARS "|`&><'\"\\[]{};"
2557-
2558-char *command_name=NULL;
2559-char *macro_argv[MAX_COMMAND_ARGUMENTS];
2560-
2561-char config_file[MAX_INPUT_BUFFER]="nrpe.cfg";
2562-int log_facility=LOG_DAEMON;
2563-int server_port=DEFAULT_SERVER_PORT;
2564-char server_address[16]="0.0.0.0";
2565-int socket_timeout=DEFAULT_SOCKET_TIMEOUT;
2566-int command_timeout=DEFAULT_COMMAND_TIMEOUT;
2567-int connection_timeout=DEFAULT_CONNECTION_TIMEOUT;
2568-char *command_prefix=NULL;
2569-
2570-command *command_list=NULL;
2571-
2572-char *nrpe_user=NULL;
2573-char *nrpe_group=NULL;
2574-
2575-char *allowed_hosts=NULL;
2576-
2577-char *pid_file=NULL;
2578-int wrote_pid_file=FALSE;
2579-
2580-int allow_arguments=FALSE;
2581-
2582-int allow_weak_random_seed=FALSE;
2583-
2584-int sigrestart=FALSE;
2585-int sigshutdown=FALSE;
2586-
2587-int show_help=FALSE;
2588-int show_license=FALSE;
2589-int show_version=FALSE;
2590-int use_inetd=TRUE;
2591-int debug=FALSE;
2592-
2593-
2594-
2595-
2596-int main(int argc, char **argv){
2597- int result=OK;
2598- int x;
2599- char buffer[MAX_INPUT_BUFFER];
2600- char *env_string=NULL;
2601-#ifdef HAVE_SSL
2602- DH *dh;
2603- char seedfile[FILENAME_MAX];
2604- int i,c;
2605-#endif
2606-
2607- /* set some environment variables */
2608- asprintf(&env_string,"NRPE_MULTILINESUPPORT=1");
2609- putenv(env_string);
2610- asprintf(&env_string,"NRPE_PROGRAMVERSION=%s",PROGRAM_VERSION);
2611- putenv(env_string);
2612-
2613- /* process command-line args */
2614- result=process_arguments(argc,argv);
2615-
2616- if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){
2617-
2618- printf("\n");
2619- printf("NRPE - Nagios Remote Plugin Executor\n");
2620- printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n");
2621- printf("Version: %s\n",PROGRAM_VERSION);
2622- printf("Last Modified: %s\n",MODIFICATION_DATE);
2623- printf("License: GPL v2 with exemptions (-l for more info)\n");
2624-#ifdef HAVE_SSL
2625- printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n");
2626-#endif
2627-#ifdef HAVE_LIBWRAP
2628- printf("TCP Wrappers Available\n");
2629-#endif
2630- printf("\n");
2631-#ifdef ENABLE_COMMAND_ARGUMENTS
2632- printf("***************************************************************\n");
2633- printf("** POSSIBLE SECURITY RISK - COMMAND ARGUMENTS ARE SUPPORTED! **\n");
2634- printf("** Read the NRPE SECURITY file for more information **\n");
2635- printf("***************************************************************\n");
2636- printf("\n");
2637-#endif
2638-#ifndef HAVE_LIBWRAP
2639- printf("***************************************************************\n");
2640- printf("** POSSIBLE SECURITY RISK - TCP WRAPPERS ARE NOT AVAILABLE! **\n");
2641- printf("** Read the NRPE SECURITY file for more information **\n");
2642- printf("***************************************************************\n");
2643- printf("\n");
2644-#endif
2645- }
2646-
2647- if(show_license==TRUE)
2648- display_license();
2649-
2650- else if(result!=OK || show_help==TRUE){
2651-
2652- printf("Usage: nrpe [-n] -c <config_file> <mode>\n");
2653- printf("\n");
2654- printf("Options:\n");
2655- printf(" -n = Do not use SSL\n");
2656- printf(" <config_file> = Name of config file to use\n");
2657- printf(" <mode> = One of the following two operating modes:\n");
2658- printf(" -i = Run as a service under inetd or xinetd\n");
2659- printf(" -d = Run as a standalone daemon\n");
2660- printf("\n");
2661- printf("Notes:\n");
2662- printf("This program is designed to process requests from the check_nrpe\n");
2663- printf("plugin on the host(s) running Nagios. It can run as a service\n");
2664- printf("under inetd or xinetd (read the docs for info on this), or as a\n");
2665- printf("standalone daemon. Once a request is received from an authorized\n");
2666- printf("host, NRPE will execute the command/plugin (as defined in the\n");
2667- printf("config file) and return the plugin output and return code to the\n");
2668- printf("check_nrpe plugin.\n");
2669- printf("\n");
2670- }
2671-
2672- if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
2673- exit(STATE_UNKNOWN);
2674-
2675-
2676- /* open a connection to the syslog facility */
2677- /* facility name may be overridden later */
2678- get_log_facility(NRPE_LOG_FACILITY);
2679- openlog("nrpe",LOG_PID,log_facility);
2680-
2681- /* make sure the config file uses an absolute path */
2682- if(config_file[0]!='/'){
2683-
2684- /* save the name of the config file */
2685- strncpy(buffer,config_file,sizeof(buffer));
2686- buffer[sizeof(buffer)-1]='\x0';
2687-
2688- /* get absolute path of current working directory */
2689- strcpy(config_file,"");
2690- getcwd(config_file,sizeof(config_file));
2691-
2692- /* append a forward slash */
2693- strncat(config_file,"/",sizeof(config_file)-2);
2694- config_file[sizeof(config_file)-1]='\x0';
2695-
2696- /* append the config file to the path */
2697- strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1);
2698- config_file[sizeof(config_file)-1]='\x0';
2699- }
2700-
2701- /* read the config file */
2702- result=read_config_file(config_file);
2703-
2704- /* exit if there are errors... */
2705- if(result==ERROR){
2706- syslog(LOG_ERR,"Config file '%s' contained errors, aborting...",config_file);
2707- return STATE_CRITICAL;
2708- }
2709-
2710- /* generate the CRC 32 table */
2711- generate_crc32_table();
2712-
2713- /* initialize macros */
2714- for(x=0;x<MAX_COMMAND_ARGUMENTS;x++)
2715- macro_argv[x]=NULL;
2716-
2717-#ifdef HAVE_SSL
2718- /* initialize SSL */
2719- if(use_ssl==TRUE){
2720- SSL_library_init();
2721- SSLeay_add_ssl_algorithms();
2722- meth=SSLv23_server_method();
2723- SSL_load_error_strings();
2724-
2725- /* use week random seed if necessary */
2726- if(allow_weak_random_seed && (RAND_status()==0)){
2727-
2728- if(RAND_file_name(seedfile,sizeof(seedfile)-1))
2729- if(RAND_load_file(seedfile,-1))
2730- RAND_write_file(seedfile);
2731-
2732- if(RAND_status()==0){
2733- syslog(LOG_ERR,"Warning: SSL/TLS uses a weak random seed which is highly discouraged");
2734- srand(time(NULL));
2735- for(i=0;i<500 && RAND_status()==0;i++){
2736- for(c=0;c<sizeof(seedfile);c+=sizeof(int)){
2737- *((int *)(seedfile+c))=rand();
2738- }
2739- RAND_seed(seedfile,sizeof(seedfile));
2740- }
2741- }
2742- }
2743-
2744- if((ctx=SSL_CTX_new(meth))==NULL){
2745- syslog(LOG_ERR,"Error: could not create SSL context.\n");
2746- exit(STATE_CRITICAL);
2747- }
2748-
2749- /* ADDED 01/19/2004 */
2750- /* use only TLSv1 protocol */
2751- SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
2752-
2753- /* use anonymous DH ciphers */
2754- SSL_CTX_set_cipher_list(ctx,"ADH");
2755- dh=get_dh512();
2756- SSL_CTX_set_tmp_dh(ctx,dh);
2757- DH_free(dh);
2758- if(debug==TRUE)
2759- syslog(LOG_INFO,"INFO: SSL/TLS initialized. All network traffic will be encrypted.");
2760- }
2761- else{
2762- if(debug==TRUE)
2763- syslog(LOG_INFO,"INFO: SSL/TLS NOT initialized. Network encryption DISABLED.");
2764- }
2765-#endif
2766-
2767- /* if we're running under inetd... */
2768- if(use_inetd==TRUE){
2769-
2770- /* make sure we're not root */
2771- check_privileges();
2772-
2773- /* redirect STDERR to /dev/null */
2774- close(2);
2775- open("/dev/null",O_WRONLY);
2776-
2777- /* handle the connection */
2778- handle_connection(0);
2779- }
2780-
2781- /* else daemonize and start listening for requests... */
2782- else if(fork()==0){
2783-
2784- /* we're a daemon - set up a new process group */
2785- setsid();
2786-
2787- /* close standard file descriptors */
2788- close(0);
2789- close(1);
2790- close(2);
2791-
2792- /* redirect standard descriptors to /dev/null */
2793- open("/dev/null",O_RDONLY);
2794- open("/dev/null",O_WRONLY);
2795- open("/dev/null",O_WRONLY);
2796-
2797- chdir("/");
2798- /*umask(0);*/
2799-
2800- /* handle signals */
2801- signal(SIGQUIT,sighandler);
2802- signal(SIGTERM,sighandler);
2803- signal(SIGHUP,sighandler);
2804-
2805- /* log info to syslog facility */
2806- syslog(LOG_NOTICE,"Starting up daemon");
2807-
2808- /* write pid file */
2809- if(write_pid_file()==ERROR)
2810- return STATE_CRITICAL;
2811-
2812- /* drop privileges */
2813- drop_privileges(nrpe_user,nrpe_group);
2814-
2815- /* make sure we're not root */
2816- check_privileges();
2817-
2818- do{
2819-
2820- /* reset flags */
2821- sigrestart=FALSE;
2822- sigshutdown=FALSE;
2823-
2824- /* wait for connections */
2825- wait_for_connections();
2826-
2827- /* free all memory we allocated */
2828- free_memory();
2829-
2830- if(sigrestart==TRUE){
2831-
2832- /* read the config file */
2833- result=read_config_file(config_file);
2834-
2835- /* exit if there are errors... */
2836- if(result==ERROR){
2837- syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file);
2838- return STATE_CRITICAL;
2839- }
2840- }
2841-
2842- }while(sigrestart==TRUE && sigshutdown==FALSE);
2843-
2844- /* remove pid file */
2845- remove_pid_file();
2846-
2847- syslog(LOG_NOTICE,"Daemon shutdown\n");
2848- }
2849-
2850-#ifdef HAVE_SSL
2851- if(use_ssl==TRUE)
2852- SSL_CTX_free(ctx);
2853-#endif
2854-
2855- /* We are now running in daemon mode, or the connection handed over by inetd has
2856- been completed, so the parent process exits */
2857- return STATE_OK;
2858- }
2859-
2860-
2861-
2862-
2863-/* read in the configuration file */
2864-int read_config_file(char *filename){
2865- FILE *fp;
2866- char config_file[MAX_FILENAME_LENGTH];
2867- char input_buffer[MAX_INPUT_BUFFER];
2868- char *input_line;
2869- char *temp_buffer;
2870- char *varname;
2871- char *varvalue;
2872- int line=0;
2873- int len=0;
2874- int x=0;
2875-
2876-
2877- /* open the config file for reading */
2878- fp=fopen(filename,"r");
2879-
2880- /* exit if we couldn't open the config file */
2881- if(fp==NULL){
2882- syslog(LOG_ERR,"Unable to open config file '%s' for reading\n",filename);
2883- return ERROR;
2884- }
2885-
2886- while(fgets(input_buffer,MAX_INPUT_BUFFER-1,fp)){
2887-
2888- line++;
2889- input_line=input_buffer;
2890-
2891- /* skip leading whitespace */
2892- while(isspace(*input_line))
2893- ++input_line;
2894-
2895- /* trim trailing whitespace */
2896- len=strlen(input_line);
2897- for(x=len-1;x>=0;x--){
2898- if(isspace(input_line[x]))
2899- input_line[x]='\x0';
2900- else
2901- break;
2902- }
2903-
2904- /* skip comments and blank lines */
2905- if(input_line[0]=='#')
2906- continue;
2907- if(input_line[0]=='\x0')
2908- continue;
2909- if(input_line[0]=='\n')
2910- continue;
2911-
2912- /* get the variable name */
2913- varname=strtok(input_line,"=");
2914- if(varname==NULL){
2915- syslog(LOG_ERR,"No variable name specified in config file '%s' - Line %d\n",filename,line);
2916- return ERROR;
2917- }
2918-
2919- /* get the variable value */
2920- varvalue=strtok(NULL,"\n");
2921- if(varvalue==NULL){
2922- syslog(LOG_ERR,"No variable value specified in config file '%s' - Line %d\n",filename,line);
2923- return ERROR;
2924- }
2925-
2926- /* allow users to specify directories to recurse into for config files */
2927- else if(!strcmp(varname,"include_dir")){
2928-
2929- strncpy(config_file,varvalue,sizeof(config_file)-1);
2930- config_file[sizeof(config_file)-1]='\x0';
2931-
2932- /* strip trailing / if necessary */
2933- if(config_file[strlen(config_file)-1]=='/')
2934- config_file[strlen(config_file)-1]='\x0';
2935-
2936- /* process the config directory... */
2937- if(read_config_dir(config_file)==ERROR)
2938- syslog(LOG_ERR,"Continuing with errors...");
2939- }
2940-
2941- /* allow users to specify individual config files to include */
2942- else if(!strcmp(varname,"include") || !strcmp(varname,"include_file")){
2943-
2944- /* process the config file... */
2945- if(read_config_file(varvalue)==ERROR)
2946- syslog(LOG_ERR,"Continuing with errors...");
2947- }
2948-
2949- else if(!strcmp(varname,"server_port")){
2950- server_port=atoi(varvalue);
2951- if(server_port<1024){
2952- syslog(LOG_ERR,"Invalid port number specified in config file '%s' - Line %d\n",filename,line);
2953- return ERROR;
2954- }
2955- }
2956- else if(!strcmp(varname,"command_prefix"))
2957- command_prefix=strdup(varvalue);
2958-
2959- else if(!strcmp(varname,"server_address")){
2960- strncpy(server_address,varvalue,sizeof(server_address) - 1);
2961- server_address[sizeof(server_address)-1]='\0';
2962- }
2963-
2964- else if(!strcmp(varname,"allowed_hosts"))
2965- allowed_hosts=strdup(varvalue);
2966-
2967- else if(strstr(input_line,"command[")){
2968- temp_buffer=strtok(varname,"[");
2969- temp_buffer=strtok(NULL,"]");
2970- if(temp_buffer==NULL){
2971- syslog(LOG_ERR,"Invalid command specified in config file '%s' - Line %d\n",filename,line);
2972- return ERROR;
2973- }
2974- add_command(temp_buffer,varvalue);
2975- }
2976-
2977- else if(strstr(input_buffer,"debug")){
2978- debug=atoi(varvalue);
2979- if(debug>0)
2980- debug=TRUE;
2981- else
2982- debug=FALSE;
2983- }
2984-
2985- else if(!strcmp(varname,"nrpe_user"))
2986- nrpe_user=strdup(varvalue);
2987-
2988- else if(!strcmp(varname,"nrpe_group"))
2989- nrpe_group=strdup(varvalue);
2990-
2991- else if(!strcmp(varname,"dont_blame_nrpe"))
2992- allow_arguments=(atoi(varvalue)==1)?TRUE:FALSE;
2993-
2994- else if(!strcmp(varname,"command_timeout")){
2995- command_timeout=atoi(varvalue);
2996- if(command_timeout<1){
2997- syslog(LOG_ERR,"Invalid command_timeout specified in config file '%s' - Line %d\n",filename,line);
2998- return ERROR;
2999- }
3000- }
3001-
3002- else if(!strcmp(varname,"connection_timeout")){
3003- connection_timeout=atoi(varvalue);
3004- if(connection_timeout<1){
3005- syslog(LOG_ERR,"Invalid connection_timeout specified in config file '%s' - Line %d\n",filename,line);
3006- return ERROR;
3007- }
3008- }
3009-
3010- else if(!strcmp(varname,"allow_weak_random_seed"))
3011- allow_weak_random_seed=(atoi(varvalue)==1)?TRUE:FALSE;
3012-
3013- else if(!strcmp(varname,"pid_file"))
3014- pid_file=strdup(varvalue);
3015-
3016- else if(!strcmp(varname,"log_facility")){
3017- if((get_log_facility(varvalue))==OK){
3018- /* re-open log using new facility */
3019- closelog();
3020- openlog("nrpe",LOG_PID,log_facility);
3021- }
3022- else
3023- syslog(LOG_WARNING,"Invalid log_facility specified in config file '%s' - Line %d\n",filename,line);
3024- }
3025-
3026- else{
3027- syslog(LOG_WARNING,"Unknown option specified in config file '%s' - Line %d\n",filename,line);
3028- continue;
3029- }
3030-
3031- }
3032-
3033-
3034- /* close the config file */
3035- fclose(fp);
3036-
3037- return OK;
3038- }
3039-
3040-
3041-/* process all config files in a specific config directory (with directory recursion) */
3042-int read_config_dir(char *dirname){
3043- char config_file[MAX_FILENAME_LENGTH];
3044- DIR *dirp;
3045- struct dirent *dirfile;
3046- struct stat buf;
3047- int result=OK;
3048- int x;
3049-
3050- /* open the directory for reading */
3051- dirp=opendir(dirname);
3052- if(dirp==NULL){
3053- syslog(LOG_ERR,"Could not open config directory '%s' for reading.\n",dirname);
3054- return ERROR;
3055- }
3056-
3057- /* process all files in the directory... */
3058- while((dirfile=readdir(dirp))!=NULL){
3059-
3060- /* create the full path to the config file or subdirectory */
3061- snprintf(config_file,sizeof(config_file)-1,"%s/%s",dirname,dirfile->d_name);
3062- config_file[sizeof(config_file)-1]='\x0';
3063- stat(config_file, &buf);
3064-
3065- /* process this if it's a config file... */
3066- x=strlen(dirfile->d_name);
3067- if(x>4 && !strcmp(dirfile->d_name+(x-4),".cfg")){
3068-
3069- /* only process normal files */
3070- if(!S_ISREG(buf.st_mode))
3071- continue;
3072-
3073- /* process the config file */
3074- result=read_config_file(config_file);
3075-
3076- /* break out if we encountered an error */
3077- if(result==ERROR)
3078- break;
3079- }
3080-
3081- /* recurse into subdirectories... */
3082- if(S_ISDIR(buf.st_mode)){
3083-
3084- /* ignore current, parent and hidden directory entries */
3085- if(dirfile->d_name[0]=='.')
3086- continue;
3087-
3088- /* process the config directory */
3089- result=read_config_dir(config_file);
3090-
3091- /* break out if we encountered an error */
3092- if(result==ERROR)
3093- break;
3094- }
3095- }
3096-
3097- closedir(dirp);
3098-
3099- return result;
3100- }
3101-
3102-
3103-
3104-/* determines facility to use with syslog */
3105-int get_log_facility(char *varvalue){
3106-
3107- if(!strcmp(varvalue,"kern"))
3108- log_facility=LOG_KERN;
3109- else if(!strcmp(varvalue,"user"))
3110- log_facility=LOG_USER;
3111- else if(!strcmp(varvalue,"mail"))
3112- log_facility=LOG_MAIL;
3113- else if(!strcmp(varvalue,"daemon"))
3114- log_facility=LOG_DAEMON;
3115- else if(!strcmp(varvalue,"auth"))
3116- log_facility=LOG_AUTH;
3117- else if(!strcmp(varvalue,"syslog"))
3118- log_facility=LOG_SYSLOG;
3119- else if(!strcmp(varvalue,"lrp"))
3120- log_facility=LOG_LPR;
3121- else if(!strcmp(varvalue,"news"))
3122- log_facility=LOG_NEWS;
3123- else if(!strcmp(varvalue,"uucp"))
3124- log_facility=LOG_UUCP;
3125- else if(!strcmp(varvalue,"cron"))
3126- log_facility=LOG_CRON;
3127- else if(!strcmp(varvalue,"authpriv"))
3128- log_facility=LOG_AUTHPRIV;
3129- else if(!strcmp(varvalue,"ftp"))
3130- log_facility=LOG_FTP;
3131- else if(!strcmp(varvalue,"local0"))
3132- log_facility=LOG_LOCAL0;
3133- else if(!strcmp(varvalue,"local1"))
3134- log_facility=LOG_LOCAL1;
3135- else if(!strcmp(varvalue,"local2"))
3136- log_facility=LOG_LOCAL2;
3137- else if(!strcmp(varvalue,"local3"))
3138- log_facility=LOG_LOCAL3;
3139- else if(!strcmp(varvalue,"local4"))
3140- log_facility=LOG_LOCAL4;
3141- else if(!strcmp(varvalue,"local5"))
3142- log_facility=LOG_LOCAL5;
3143- else if(!strcmp(varvalue,"local6"))
3144- log_facility=LOG_LOCAL6;
3145- else if(!strcmp(varvalue,"local7"))
3146- log_facility=LOG_LOCAL7;
3147- else{
3148- log_facility=LOG_DAEMON;
3149- return ERROR;
3150- }
3151-
3152- return OK;
3153- }
3154-
3155-
3156-
3157-/* adds a new command definition from the config file to the list in memory */
3158-int add_command(char *command_name, char *command_line){
3159- command *new_command;
3160-
3161- if(command_name==NULL || command_line==NULL)
3162- return ERROR;
3163-
3164- /* allocate memory for the new command */
3165- new_command=(command *)malloc(sizeof(command));
3166- if(new_command==NULL)
3167- return ERROR;
3168-
3169- new_command->command_name=strdup(command_name);
3170- if(new_command->command_name==NULL){
3171- free(new_command);
3172- return ERROR;
3173- }
3174- new_command->command_line=strdup(command_line);
3175- if(new_command->command_line==NULL){
3176- free(new_command->command_name);
3177- free(new_command);
3178- return ERROR;
3179- }
3180-
3181- /* add new command to head of list in memory */
3182- new_command->next=command_list;
3183- command_list=new_command;
3184-
3185- if(debug==TRUE)
3186- syslog(LOG_DEBUG,"Added command[%s]=%s\n",command_name,command_line);
3187-
3188- return OK;
3189- }
3190-
3191-
3192-
3193-/* given a command name, find the structure in memory */
3194-command *find_command(char *command_name){
3195- command *temp_command;
3196-
3197- for(temp_command=command_list;temp_command!=NULL;temp_command=temp_command->next)
3198- if(!strcmp(command_name,temp_command->command_name))
3199- return temp_command;
3200-
3201- return NULL;
3202- }
3203-
3204-
3205-
3206-/* wait for incoming connection requests */
3207-void wait_for_connections(void){
3208- struct sockaddr_in myname;
3209- struct sockaddr_in *nptr;
3210- struct sockaddr addr;
3211- int rc;
3212- int sock, new_sd;
3213- socklen_t addrlen;
3214- pid_t pid;
3215- int flag=1;
3216- fd_set fdread;
3217- struct timeval timeout;
3218- int retval;
3219-#ifdef HAVE_LIBWRAP
3220- struct request_info req;
3221-#endif
3222-
3223- /* create a socket for listening */
3224- sock=socket(AF_INET,SOCK_STREAM,0);
3225-
3226- /* exit if we couldn't create the socket */
3227- if(sock<0){
3228- syslog(LOG_ERR,"Network server socket failure (%d: %s)",errno,strerror(errno));
3229- exit(STATE_CRITICAL);
3230- }
3231-
3232- /* socket should be non-blocking */
3233- fcntl(sock,F_SETFL,O_NONBLOCK);
3234-
3235- /* set the reuse address flag so we don't get errors when restarting */
3236- flag=1;
3237- if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){
3238- syslog(LOG_ERR,"Could not set reuse address option on socket!\n");
3239- exit(STATE_UNKNOWN);
3240- }
3241-
3242- myname.sin_family=AF_INET;
3243- myname.sin_port=htons(server_port);
3244- bzero(&myname.sin_zero,8);
3245-
3246- /* what address should we bind to? */
3247- if(!strlen(server_address))
3248- myname.sin_addr.s_addr=INADDR_ANY;
3249-
3250- else if(!my_inet_aton(server_address,&myname.sin_addr)){
3251- syslog(LOG_ERR,"Server address is not a valid IP address\n");
3252- exit(STATE_CRITICAL);
3253- }
3254-
3255- /* bind the address to the Internet socket */
3256- if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){
3257- syslog(LOG_ERR,"Network server bind failure (%d: %s)\n",errno,strerror(errno));
3258- exit(STATE_CRITICAL);
3259- }
3260-
3261- /* open the socket for listening */
3262- if(listen(sock,5)<0){
3263- syslog(LOG_ERR,"Network server listen failure (%d: %s)\n",errno,strerror(errno));
3264- exit(STATE_CRITICAL);
3265- }
3266-
3267- /* log warning about command arguments */
3268-#ifdef ENABLE_COMMAND_ARGUMENTS
3269- if(allow_arguments==TRUE)
3270- syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments from clients!");
3271-#endif
3272-
3273- syslog(LOG_INFO,"Listening for connections on port %d\n",htons(myname.sin_port));
3274-
3275- if(allowed_hosts)
3276- syslog(LOG_INFO,"Allowing connections from: %s\n",allowed_hosts);
3277-
3278- /* listen for connection requests - fork() if we get one */
3279- while(1){
3280-
3281- /* wait for a connection request */
3282- while(1){
3283-
3284- /* wait until there's something to do */
3285- FD_ZERO(&fdread);
3286- FD_SET(sock,&fdread);
3287- timeout.tv_sec=0;
3288- timeout.tv_usec=500000;
3289- retval=select(sock+1,&fdread,NULL,&fdread,&timeout);
3290-
3291- /* bail out if necessary */
3292- if(sigrestart==TRUE || sigshutdown==TRUE)
3293- break;
3294-
3295- /* error */
3296- if(retval<0)
3297- continue;
3298-
3299- /* accept a new connection request */
3300- new_sd=accept(sock,0,0);
3301-
3302- /* some kind of error occurred... */
3303- if(new_sd<0){
3304-
3305- /* bail out if necessary */
3306- if(sigrestart==TRUE || sigshutdown==TRUE)
3307- break;
3308-
3309- /* retry */
3310- if(errno==EWOULDBLOCK || errno==EINTR)
3311- continue;
3312-
3313- /* socket is nonblocking and we don't have a connection yet */
3314- if(errno==EAGAIN)
3315- continue;
3316-
3317- /* fix for HP-UX 11.0 - just retry */
3318- if(errno==ENOBUFS)
3319- continue;
3320-
3321- /* else handle the error later */
3322- break;
3323- }
3324-
3325- /* connection was good */
3326- break;
3327- }
3328-
3329- /* bail out if necessary */
3330- if(sigrestart==TRUE || sigshutdown==TRUE)
3331- break;
3332-
3333- /* child process should handle the connection */
3334- pid=fork();
3335- if(pid==0){
3336-
3337- /* fork again so we don't create zombies */
3338- pid=fork();
3339- if(pid==0){
3340-
3341- /* hey, there was an error... */
3342- if(new_sd<0){
3343-
3344- /* log error to syslog facility */
3345- syslog(LOG_ERR,"Network server accept failure (%d: %s)",errno,strerror(errno));
3346-
3347- /* close socket prioer to exiting */
3348- close(sock);
3349-
3350- return;
3351- }
3352-
3353- /* handle signals */
3354- signal(SIGQUIT,child_sighandler);
3355- signal(SIGTERM,child_sighandler);
3356- signal(SIGHUP,child_sighandler);
3357-
3358- /* grandchild does not need to listen for connections, so close the socket */
3359- close(sock);
3360-
3361- /* find out who just connected... */
3362- addrlen=sizeof(addr);
3363- rc=getpeername(new_sd,&addr,&addrlen);
3364-
3365- if(rc<0){
3366-
3367- /* log error to syslog facility */
3368- syslog(LOG_ERR,"Error: Network server getpeername() failure (%d: %s)",errno,strerror(errno));
3369-
3370- /* close socket prior to exiting */
3371- close(new_sd);
3372-
3373- return;
3374- }
3375-
3376- nptr=(struct sockaddr_in *)&addr;
3377-
3378- /* log info to syslog facility */
3379- if(debug==TRUE)
3380- syslog(LOG_DEBUG,"Connection from %s port %d",inet_ntoa(nptr->sin_addr),nptr->sin_port);
3381-
3382- /* is this is a blessed machine? */
3383- if(allowed_hosts){
3384-
3385- if(!is_an_allowed_host(inet_ntoa(nptr->sin_addr))){
3386-
3387- /* log error to syslog facility */
3388- syslog(LOG_ERR,"Host %s is not allowed to talk to us!",inet_ntoa(nptr->sin_addr));
3389-
3390- /* log info to syslog facility */
3391- if(debug==TRUE)
3392- syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr));
3393-
3394- /* close socket prior to exiting */
3395- close(new_sd);
3396-
3397- exit(STATE_OK);
3398- }
3399- else{
3400-
3401- /* log info to syslog facility */
3402- if(debug==TRUE)
3403- syslog(LOG_DEBUG,"Host address is in allowed_hosts");
3404- }
3405- }
3406-
3407-#ifdef HAVE_LIBWRAP
3408-
3409- /* Check whether or not connections are allowed from this host */
3410- request_init(&req,RQ_DAEMON,"nrpe",RQ_FILE,new_sd,0);
3411- fromhost(&req);
3412-
3413- if(!hosts_access(&req)){
3414-
3415- syslog(LOG_DEBUG,"Connection refused by TCP wrapper");
3416-
3417- /* refuse the connection */
3418- refuse(&req);
3419- close(new_sd);
3420-
3421- /* should not be reached */
3422- syslog(LOG_ERR,"libwrap refuse() returns!");
3423- exit(STATE_CRITICAL);
3424- }
3425-#endif
3426-
3427- /* handle the client connection */
3428- handle_connection(new_sd);
3429-
3430- /* log info to syslog facility */
3431- if(debug==TRUE)
3432- syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr));
3433-
3434- /* close socket prior to exiting */
3435- close(new_sd);
3436-
3437- exit(STATE_OK);
3438- }
3439-
3440- /* first child returns immediately, grandchild is inherited by INIT process -> no zombies... */
3441- else
3442- exit(STATE_OK);
3443- }
3444-
3445- /* parent ... */
3446- else{
3447- /* parent doesn't need the new connection */
3448- close(new_sd);
3449-
3450- /* parent waits for first child to exit */
3451- waitpid(pid,NULL,0);
3452- }
3453- }
3454-
3455- /* close the socket we're listening on */
3456- close(sock);
3457-
3458- return;
3459- }
3460-
3461-
3462-
3463-/* checks to see if a given host is allowed to talk to us */
3464-int is_an_allowed_host(char *connecting_host){
3465- char *temp_buffer=NULL;
3466- char *temp_ptr=NULL;
3467- int result=0;
3468- struct hostent *myhost;
3469- char **pptr=NULL;
3470- char *save_connecting_host=NULL;
3471- struct in_addr addr;
3472-
3473- /* make sure we have something */
3474- if(connecting_host==NULL)
3475- return 0;
3476- if(allowed_hosts==NULL)
3477- return 1;
3478-
3479- if((temp_buffer=strdup(allowed_hosts))==NULL)
3480- return 0;
3481-
3482- /* try and match IP addresses first */
3483- for(temp_ptr=strtok(temp_buffer,",");temp_ptr!=NULL;temp_ptr=strtok(NULL,",")){
3484-
3485- if(!strcmp(connecting_host,temp_ptr)){
3486- result=1;
3487- break;
3488- }
3489- }
3490-
3491- /* try DNS lookups if needed */
3492- if(result==0){
3493-
3494- free(temp_buffer);
3495- if((temp_buffer=strdup(allowed_hosts))==NULL)
3496- return 0;
3497-
3498- save_connecting_host=strdup(connecting_host);
3499- for(temp_ptr=strtok(temp_buffer,",");temp_ptr!=NULL;temp_ptr=strtok(NULL,",")){
3500-
3501- myhost=gethostbyname(temp_ptr);
3502- if(myhost!=NULL){
3503-
3504- /* check all addresses for the host... */
3505- for(pptr=myhost->h_addr_list;*pptr!=NULL;pptr++){
3506- memcpy(&addr, *pptr, sizeof(addr));
3507- if(!strcmp(save_connecting_host, inet_ntoa(addr))){
3508- result=1;
3509- break;
3510- }
3511- }
3512- }
3513-
3514- if(result==1)
3515- break;
3516- }
3517-
3518- strcpy(connecting_host, save_connecting_host);
3519- free(save_connecting_host);
3520- }
3521-
3522- free(temp_buffer);
3523-
3524- return result;
3525- }
3526-
3527-
3528-
3529-/* handles a client connection */
3530-void handle_connection(int sock){
3531- u_int32_t calculated_crc32;
3532- command *temp_command;
3533- packet receive_packet;
3534- packet send_packet;
3535- int bytes_to_send;
3536- int bytes_to_recv;
3537- char buffer[MAX_INPUT_BUFFER];
3538- char raw_command[MAX_INPUT_BUFFER];
3539- char processed_command[MAX_INPUT_BUFFER];
3540- int result=STATE_OK;
3541- int early_timeout=FALSE;
3542- int rc;
3543- int x;
3544-#ifdef DEBUG
3545- FILE *errfp;
3546-#endif
3547-#ifdef HAVE_SSL
3548- SSL *ssl=NULL;
3549-#endif
3550-
3551-
3552- /* log info to syslog facility */
3553- if(debug==TRUE)
3554- syslog(LOG_DEBUG,"Handling the connection...");
3555-
3556-#ifdef OLDSTUFF
3557- /* socket should be non-blocking */
3558- fcntl(sock,F_SETFL,O_NONBLOCK);
3559-#endif
3560-
3561- /* set connection handler */
3562- signal(SIGALRM,my_connection_sighandler);
3563- alarm(connection_timeout);
3564-
3565-#ifdef HAVE_SSL
3566- /* do SSL handshake */
3567- if(result==STATE_OK && use_ssl==TRUE){
3568- if((ssl=SSL_new(ctx))!=NULL){
3569- SSL_set_fd(ssl,sock);
3570-
3571- /* keep attempting the request if needed */
3572- while(((rc=SSL_accept(ssl))!=1) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ));
3573-
3574- if(rc!=1){
3575- syslog(LOG_ERR,"Error: Could not complete SSL handshake. %d\n",SSL_get_error(ssl,rc));
3576-#ifdef DEBUG
3577- errfp=fopen("/tmp/err.log","w");
3578- ERR_print_errors_fp(errfp);
3579- fclose(errfp);
3580-#endif
3581- return;
3582- }
3583- }
3584- else{
3585- syslog(LOG_ERR,"Error: Could not create SSL connection structure.\n");
3586-#ifdef DEBUG
3587- errfp=fopen("/tmp/err.log","w");
3588- ERR_print_errors_fp(errfp);
3589- fclose(errfp);
3590-#endif
3591- return;
3592- }
3593- }
3594-#endif
3595-
3596- bytes_to_recv=sizeof(receive_packet);
3597- if(use_ssl==FALSE)
3598- rc=recvall(sock,(char *)&receive_packet,&bytes_to_recv,socket_timeout);
3599-#ifdef HAVE_SSL
3600- else{
3601- while(((rc=SSL_read(ssl,&receive_packet,bytes_to_recv))<=0) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ));
3602- }
3603-#endif
3604-
3605- /* recv() error or client disconnect */
3606- if(rc<=0){
3607-
3608- /* log error to syslog facility */
3609- syslog(LOG_ERR,"Could not read request from client, bailing out...");
3610-
3611-#ifdef HAVE_SSL
3612- if(ssl){
3613- SSL_shutdown(ssl);
3614- SSL_free(ssl);
3615- syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n");
3616- }
3617-#endif
3618-
3619- return;
3620- }
3621-
3622- /* we couldn't read the correct amount of data, so bail out */
3623- else if(bytes_to_recv!=sizeof(receive_packet)){
3624-
3625- /* log error to syslog facility */
3626- syslog(LOG_ERR,"Data packet from client was too short, bailing out...");
3627-
3628-#ifdef HAVE_SSL
3629- if(ssl){
3630- SSL_shutdown(ssl);
3631- SSL_free(ssl);
3632- }
3633-#endif
3634-
3635- return;
3636- }
3637-
3638-#ifdef DEBUG
3639- fp=fopen("/tmp/packet","w");
3640- if(fp){
3641- fwrite(&receive_packet,1,sizeof(receive_packet),fp);
3642- fclose(fp);
3643- }
3644-#endif
3645-
3646- /* make sure the request is valid */
3647- if(validate_request(&receive_packet)==ERROR){
3648-
3649- /* log an error */
3650- syslog(LOG_ERR,"Client request was invalid, bailing out...");
3651-
3652- /* free memory */
3653- free(command_name);
3654- command_name=NULL;
3655- for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
3656- free(macro_argv[x]);
3657- macro_argv[x]=NULL;
3658- }
3659-
3660-#ifdef HAVE_SSL
3661- if(ssl){
3662- SSL_shutdown(ssl);
3663- SSL_free(ssl);
3664- }
3665-#endif
3666-
3667- return;
3668- }
3669-
3670- /* log info to syslog facility */
3671- if(debug==TRUE)
3672- syslog(LOG_DEBUG,"Host is asking for command '%s' to be run...",receive_packet.buffer);
3673-
3674- /* disable connection alarm - a new alarm will be setup during my_system */
3675- alarm(0);
3676-
3677- /* if this is the version check command, just spew it out */
3678- if(!strcmp(command_name,NRPE_HELLO_COMMAND)){
3679-
3680- snprintf(buffer,sizeof(buffer),"NRPE v%s",PROGRAM_VERSION);
3681- buffer[sizeof(buffer)-1]='\x0';
3682-
3683- /* log info to syslog facility */
3684- if(debug==TRUE)
3685- syslog(LOG_DEBUG,"Response: %s",buffer);
3686-
3687- result=STATE_OK;
3688- }
3689-
3690- /* find the command we're supposed to run */
3691- else{
3692- temp_command=find_command(command_name);
3693- if(temp_command==NULL){
3694-
3695- snprintf(buffer,sizeof(buffer),"NRPE: Command '%s' not defined",command_name);
3696- buffer[sizeof(buffer)-1]='\x0';
3697-
3698- /* log error to syslog facility */
3699- if(debug==TRUE)
3700- syslog(LOG_DEBUG,"%s",buffer);
3701-
3702- result=STATE_CRITICAL;
3703- }
3704-
3705- else{
3706-
3707- /* process command line */
3708- if(command_prefix==NULL)
3709- strncpy(raw_command,temp_command->command_line,sizeof(raw_command)-1);
3710- else
3711- snprintf(raw_command,sizeof(raw_command)-1,"%s %s",command_prefix,temp_command->command_line);
3712- raw_command[sizeof(raw_command)-1]='\x0';
3713- process_macros(raw_command,processed_command,sizeof(processed_command));
3714-
3715- /* log info to syslog facility */
3716- if(debug==TRUE)
3717- syslog(LOG_DEBUG,"Running command: %s",processed_command);
3718-
3719- /* run the command */
3720- strcpy(buffer,"");
3721- result=my_system(processed_command,command_timeout,&early_timeout,buffer,sizeof(buffer));
3722-
3723- /* log debug info */
3724- if(debug==TRUE)
3725- syslog(LOG_DEBUG,"Command completed with return code %d and output: %s",result,buffer);
3726-
3727- /* see if the command timed out */
3728- if(early_timeout==TRUE)
3729- snprintf(buffer,sizeof(buffer)-1,"NRPE: Command timed out after %d seconds\n",command_timeout);
3730- else if(!strcmp(buffer,""))
3731- snprintf(buffer,sizeof(buffer)-1,"NRPE: Unable to read output\n");
3732-
3733- buffer[sizeof(buffer)-1]='\x0';
3734-
3735- /* check return code bounds */
3736- if((result<0) || (result>3)){
3737-
3738- /* log error to syslog facility */
3739- syslog(LOG_ERR,"Bad return code for [%s]: %d", buffer,result);
3740-
3741- result=STATE_UNKNOWN;
3742- }
3743- }
3744- }
3745-
3746- /* free memory */
3747- free(command_name);
3748- command_name=NULL;
3749- for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
3750- free(macro_argv[x]);
3751- macro_argv[x]=NULL;
3752- }
3753-
3754- /* strip newline character from end of output buffer */
3755- if(buffer[strlen(buffer)-1]=='\n')
3756- buffer[strlen(buffer)-1]='\x0';
3757-
3758- /* clear the response packet buffer */
3759- bzero(&send_packet,sizeof(send_packet));
3760-
3761- /* fill the packet with semi-random data */
3762- randomize_buffer((char *)&send_packet,sizeof(send_packet));
3763-
3764- /* initialize response packet data */
3765- send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2);
3766- send_packet.packet_type=(int16_t)htons(RESPONSE_PACKET);
3767- send_packet.result_code=(int16_t)htons(result);
3768- strncpy(&send_packet.buffer[0],buffer,MAX_PACKETBUFFER_LENGTH);
3769- send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
3770-
3771- /* calculate the crc 32 value of the packet */
3772- send_packet.crc32_value=(u_int32_t)0L;
3773- calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet));
3774- send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32);
3775-
3776-
3777- /***** ENCRYPT RESPONSE *****/
3778-
3779-
3780- /* send the response back to the client */
3781- bytes_to_send=sizeof(send_packet);
3782- if(use_ssl==FALSE)
3783- sendall(sock,(char *)&send_packet,&bytes_to_send);
3784-#ifdef HAVE_SSL
3785- else
3786- SSL_write(ssl,&send_packet,bytes_to_send);
3787-#endif
3788-
3789-#ifdef HAVE_SSL
3790- if(ssl){
3791- SSL_shutdown(ssl);
3792- SSL_free(ssl);
3793- }
3794-#endif
3795-
3796- /* log info to syslog facility */
3797- if(debug==TRUE)
3798- syslog(LOG_DEBUG,"Return Code: %d, Output: %s",result,buffer);
3799-
3800- return;
3801- }
3802-
3803-
3804-
3805-/* free all allocated memory */
3806-void free_memory(void){
3807- command *this_command;
3808- command *next_command;
3809-
3810- /* free memory for the command list */
3811- this_command=command_list;
3812- while(this_command!=NULL){
3813- next_command=this_command->next;
3814- if(this_command->command_name)
3815- free(this_command->command_name);
3816- if(this_command->command_line)
3817- free(this_command->command_line);
3818- free(this_command);
3819- this_command=next_command;
3820- }
3821-
3822- command_list=NULL;
3823-
3824- return;
3825- }
3826-
3827-
3828-
3829-/* executes a system command via popen(), but protects against timeouts */
3830-int my_system(char *command,int timeout,int *early_timeout,char *output,int output_length){
3831- pid_t pid;
3832- int status;
3833- int result;
3834- extern int errno;
3835- char buffer[MAX_INPUT_BUFFER];
3836- int fd[2];
3837- FILE *fp;
3838- int bytes_read=0;
3839- time_t start_time,end_time;
3840-
3841- /* initialize return variables */
3842- if(output!=NULL)
3843- strcpy(output,"");
3844- *early_timeout=FALSE;
3845-
3846- /* if no command was passed, return with no error */
3847- if(command==NULL)
3848- return STATE_OK;
3849-
3850- /* create a pipe */
3851- pipe(fd);
3852-
3853- /* make the pipe non-blocking */
3854- fcntl(fd[0],F_SETFL,O_NONBLOCK);
3855- fcntl(fd[1],F_SETFL,O_NONBLOCK);
3856-
3857- /* get the command start time */
3858- time(&start_time);
3859-
3860- /* fork */
3861- pid=fork();
3862-
3863- /* return an error if we couldn't fork */
3864- if(pid==-1){
3865-
3866- snprintf(buffer,sizeof(buffer)-1,"NRPE: Call to fork() failed\n");
3867- buffer[sizeof(buffer)-1]='\x0';
3868-
3869- if(output!=NULL){
3870- strncpy(output,buffer,output_length-1);
3871- output[output_length-1]='\x0';
3872- }
3873-
3874- /* close both ends of the pipe */
3875- close(fd[0]);
3876- close(fd[1]);
3877-
3878- return STATE_UNKNOWN;
3879- }
3880-
3881- /* execute the command in the child process */
3882- if(pid==0){
3883-
3884- /* close pipe for reading */
3885- close(fd[0]);
3886-
3887- /* become process group leader */
3888- setpgid(0,0);
3889-
3890- /* trap commands that timeout */
3891- signal(SIGALRM,my_system_sighandler);
3892- alarm(timeout);
3893-
3894- /* run the command */
3895- fp=popen(command,"r");
3896-
3897- /* report an error if we couldn't run the command */
3898- if(fp==NULL){
3899-
3900- strncpy(buffer,"NRPE: Call to popen() failed\n",sizeof(buffer)-1);
3901- buffer[sizeof(buffer)-1]='\x0';
3902-
3903- /* write the error back to the parent process */
3904- write(fd[1],buffer,strlen(buffer)+1);
3905-
3906- result=STATE_CRITICAL;
3907- }
3908- else{
3909-
3910- /* read all lines of output - supports Nagios 3.x multiline output */
3911- while((bytes_read=fread(buffer,1,sizeof(buffer)-1,fp))>0){
3912-
3913- /* write the output back to the parent process */
3914- write(fd[1],buffer,bytes_read);
3915- }
3916-
3917- /* close the command and get termination status */
3918- status=pclose(fp);
3919-
3920- /* report an error if we couldn't close the command */
3921- if(status==-1)
3922- result=STATE_CRITICAL;
3923- /* report an error if child died due to signal (Klas Lindfors) */
3924- else if(!WIFEXITED(status))
3925- result=STATE_CRITICAL;
3926- else
3927- result=WEXITSTATUS(status);
3928- }
3929-
3930- /* close pipe for writing */
3931- close(fd[1]);
3932-
3933- /* reset the alarm */
3934- alarm(0);
3935-
3936- /* return plugin exit code to parent process */
3937- exit(result);
3938- }
3939-
3940- /* parent waits for child to finish executing command */
3941- else{
3942-
3943- /* close pipe for writing */
3944- close(fd[1]);
3945-
3946- /* wait for child to exit */
3947- waitpid(pid,&status,0);
3948-
3949- /* get the end time for running the command */
3950- time(&end_time);
3951-
3952- /* get the exit code returned from the program */
3953- result=WEXITSTATUS(status);
3954-
3955- /* because of my idiotic idea of having UNKNOWN states be equivalent to -1, I must hack things a bit... */
3956- if(result==255)
3957- result=STATE_UNKNOWN;
3958-
3959- /* check bounds on the return value */
3960- if(result<0 || result>3)
3961- result=STATE_UNKNOWN;
3962-
3963- /* try and read the results from the command output (retry if we encountered a signal) */
3964- if(output!=NULL){
3965- do{
3966- bytes_read=read(fd[0], output, output_length-1);
3967- }while (bytes_read==-1 && errno==EINTR);
3968-
3969- if(bytes_read==-1)
3970- *output='\0';
3971- else
3972- output[bytes_read]='\0';
3973- }
3974-
3975- /* if there was a critical return code and no output AND the command time exceeded the timeout thresholds, assume a timeout */
3976- if(result==STATE_CRITICAL && bytes_read==-1 && (end_time-start_time)>=timeout){
3977- *early_timeout=TRUE;
3978-
3979- /* send termination signal to child process group */
3980- kill((pid_t)(-pid),SIGTERM);
3981- kill((pid_t)(-pid),SIGKILL);
3982- }
3983-
3984- /* close the pipe for reading */
3985- close(fd[0]);
3986- }
3987-
3988-#ifdef DEBUG
3989- printf("my_system() end\n");
3990-#endif
3991-
3992- return result;
3993- }
3994-
3995-
3996-
3997-/* handle timeouts when executing commands via my_system() */
3998-void my_system_sighandler(int sig){
3999-
4000- /* force the child process to exit... */
4001- exit(STATE_CRITICAL);
4002- }
4003-
4004-
4005-/* handle errors where connection takes too long */
4006-void my_connection_sighandler(int sig) {
4007-
4008- syslog(LOG_ERR,"Connection has taken too long to establish. Exiting...");
4009-
4010- exit(STATE_CRITICAL);
4011- }
4012-
4013-
4014-/* drops privileges */
4015-int drop_privileges(char *user, char *group){
4016- uid_t uid=-1;
4017- gid_t gid=-1;
4018- struct group *grp;
4019- struct passwd *pw;
4020-
4021- /* set effective group ID */
4022- if(group!=NULL){
4023-
4024- /* see if this is a group name */
4025- if(strspn(group,"0123456789")<strlen(group)){
4026- grp=(struct group *)getgrnam(group);
4027- if(grp!=NULL)
4028- gid=(gid_t)(grp->gr_gid);
4029- else
4030- syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group);
4031- endgrent();
4032- }
4033-
4034- /* else we were passed the GID */
4035- else
4036- gid=(gid_t)atoi(group);
4037-
4038- /* set effective group ID if other than current EGID */
4039- if(gid!=getegid()){
4040-
4041- if(setgid(gid)==-1)
4042- syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid);
4043- }
4044- }
4045-
4046-
4047- /* set effective user ID */
4048- if(user!=NULL){
4049-
4050- /* see if this is a user name */
4051- if(strspn(user,"0123456789")<strlen(user)){
4052- pw=(struct passwd *)getpwnam(user);
4053- if(pw!=NULL)
4054- uid=(uid_t)(pw->pw_uid);
4055- else
4056- syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user);
4057- endpwent();
4058- }
4059-
4060- /* else we were passed the UID */
4061- else
4062- uid=(uid_t)atoi(user);
4063-
4064- /* set effective user ID if other than current EUID */
4065- if(uid!=geteuid()){
4066-
4067-#ifdef HAVE_INITGROUPS
4068- /* initialize supplementary groups */
4069- if(initgroups(user,gid)==-1){
4070- if(errno==EPERM)
4071- syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()");
4072- else{
4073- syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()");
4074- return ERROR;
4075- }
4076- }
4077-#endif
4078-
4079- if(setuid(uid)==-1)
4080- syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid);
4081- }
4082- }
4083-
4084- return OK;
4085- }
4086-
4087-
4088-/* write an optional pid file */
4089-int write_pid_file(void){
4090- int fd;
4091- int result=0;
4092- pid_t pid=0;
4093- char pbuf[16];
4094-
4095- /* no pid file was specified */
4096- if(pid_file==NULL)
4097- return OK;
4098-
4099- /* read existing pid file */
4100- if((fd=open(pid_file,O_RDONLY))>=0){
4101-
4102- result=read(fd,pbuf,(sizeof pbuf)-1);
4103-
4104- close(fd);
4105-
4106- if(result>0){
4107-
4108- pbuf[result]='\x0';
4109- pid=(pid_t)atoi(pbuf);
4110-
4111- /* if previous process is no longer running running, remove the old pid file */
4112- if(pid && (pid==getpid() || kill(pid,0)<0))
4113- unlink(pid_file);
4114-
4115- /* previous process is still running */
4116- else{
4117- syslog(LOG_ERR,"There's already an NRPE server running (PID %lu). Bailing out...",(unsigned long)pid);
4118- return ERROR;
4119- }
4120- }
4121- }
4122-
4123- /* write new pid file */
4124- if((fd=open(pid_file,O_WRONLY | O_CREAT,0644))>=0){
4125- sprintf(pbuf,"%d\n",(int)getpid());
4126- write(fd,pbuf,strlen(pbuf));
4127- close(fd);
4128- wrote_pid_file=TRUE;
4129- }
4130- else{
4131- syslog(LOG_ERR,"Cannot write to pidfile '%s' - check your privileges.",pid_file);
4132- }
4133-
4134- return OK;
4135- }
4136-
4137-
4138-
4139-/* remove pid file */
4140-int remove_pid_file(void){
4141-
4142- /* no pid file was specified */
4143- if(pid_file==NULL)
4144- return OK;
4145-
4146- /* pid file was not written */
4147- if(wrote_pid_file==FALSE)
4148- return OK;
4149-
4150- /* remove existing pid file */
4151- if(unlink(pid_file)==-1){
4152- syslog(LOG_ERR,"Cannot remove pidfile '%s' - check your privileges.",pid_file);
4153- return ERROR;
4154- }
4155-
4156- return OK;
4157- }
4158-
4159-
4160-
4161-/* bail if daemon is running as root */
4162-int check_privileges(void){
4163- uid_t uid=-1;
4164- gid_t gid=-1;
4165-
4166- uid=geteuid();
4167- gid=getegid();
4168-
4169- if(uid==0 || gid==0){
4170- syslog(LOG_ERR,"Error: NRPE daemon cannot be run as user/group root!");
4171- exit(STATE_CRITICAL);
4172- }
4173-
4174- return OK;
4175- }
4176-
4177-
4178-
4179-/* handle signals (parent process) */
4180-void sighandler(int sig){
4181- 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};
4182- int i;
4183-
4184- if(sig<0)
4185- sig=-sig;
4186-
4187- for(i=0;sigs[i]!=(char *)NULL;i++);
4188-
4189- sig%=i;
4190-
4191- /* we received a SIGHUP, so restart... */
4192- if(sig==SIGHUP){
4193-
4194- sigrestart=TRUE;
4195-
4196- syslog(LOG_NOTICE,"Caught SIGHUP - restarting...\n");
4197- }
4198-
4199- /* else begin shutting down... */
4200- if(sig==SIGTERM){
4201-
4202- /* if shutdown is already true, we're in a signal trap loop! */
4203- if(sigshutdown==TRUE)
4204- exit(STATE_CRITICAL);
4205-
4206- sigshutdown=TRUE;
4207-
4208- syslog(LOG_NOTICE,"Caught SIG%s - shutting down...\n",sigs[sig]);
4209- }
4210-
4211- return;
4212- }
4213-
4214-
4215-
4216-/* handle signals (child processes) */
4217-void child_sighandler(int sig){
4218-
4219- /* free all memory we allocated */
4220- free_memory();
4221-
4222- /* terminate */
4223- exit(0);
4224-
4225- /* so the compiler doesn't complain... */
4226- return;
4227- }
4228-
4229-
4230-
4231-/* tests whether or not a client request is valid */
4232-int validate_request(packet *pkt){
4233- u_int32_t packet_crc32;
4234- u_int32_t calculated_crc32;
4235- char *ptr;
4236-#ifdef ENABLE_COMMAND_ARGUMENTS
4237- int x;
4238-#endif
4239-
4240-
4241- /***** DECRYPT REQUEST ******/
4242-
4243-
4244- /* check the crc 32 value */
4245- packet_crc32=ntohl(pkt->crc32_value);
4246- pkt->crc32_value=0L;
4247- calculated_crc32=calculate_crc32((char *)pkt,sizeof(packet));
4248- if(packet_crc32!=calculated_crc32){
4249- syslog(LOG_ERR,"Error: Request packet had invalid CRC32.");
4250- return ERROR;
4251- }
4252-
4253- /* make sure this is the right type of packet */
4254- if(ntohs(pkt->packet_type)!=QUERY_PACKET || ntohs(pkt->packet_version)!=NRPE_PACKET_VERSION_2){
4255- syslog(LOG_ERR,"Error: Request packet type/version was invalid!");
4256- return ERROR;
4257- }
4258-
4259- /* make sure buffer is terminated */
4260- pkt->buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
4261-
4262- /* client must send some kind of request */
4263- if(!strcmp(pkt->buffer,"")){
4264- syslog(LOG_ERR,"Error: Request contained no query!");
4265- return ERROR;
4266- }
4267-
4268- /* make sure request doesn't contain nasties */
4269- if(contains_nasty_metachars(pkt->buffer)==TRUE){
4270- syslog(LOG_ERR,"Error: Request contained illegal metachars!");
4271- return ERROR;
4272- }
4273-
4274- /* make sure the request doesn't contain arguments */
4275- if(strchr(pkt->buffer,'!')){
4276-#ifdef ENABLE_COMMAND_ARGUMENTS
4277- if(allow_arguments==FALSE){
4278- syslog(LOG_ERR,"Error: Request contained command arguments, but argument option is not enabled!");
4279- return ERROR;
4280- }
4281-#else
4282- syslog(LOG_ERR,"Error: Request contained command arguments!");
4283- return ERROR;
4284-#endif
4285- }
4286-
4287- /* get command name */
4288-#ifdef ENABLE_COMMAND_ARGUMENTS
4289- ptr=strtok(pkt->buffer,"!");
4290-#else
4291- ptr=pkt->buffer;
4292-#endif
4293- command_name=strdup(ptr);
4294- if(command_name==NULL){
4295- syslog(LOG_ERR,"Error: Memory allocation failed");
4296- return ERROR;
4297- }
4298-
4299-#ifdef ENABLE_COMMAND_ARGUMENTS
4300- /* get command arguments */
4301- if(allow_arguments==TRUE){
4302-
4303- for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
4304- ptr=strtok(NULL,"!");
4305- if(ptr==NULL)
4306- break;
4307- macro_argv[x]=strdup(ptr);
4308- if(macro_argv[x]==NULL){
4309- syslog(LOG_ERR,"Error: Memory allocation failed");
4310- return ERROR;
4311- }
4312- if(!strcmp(macro_argv[x],"")){
4313- syslog(LOG_ERR,"Error: Request contained an empty command argument");
4314- return ERROR;
4315- }
4316- }
4317- }
4318-#endif
4319-
4320- return OK;
4321- }
4322-
4323-
4324-
4325-/* tests whether a buffer contains illegal metachars */
4326-int contains_nasty_metachars(char *str){
4327- int result;
4328-
4329- if(str==NULL)
4330- return FALSE;
4331-
4332- result=strcspn(str,NASTY_METACHARS);
4333- if(result!=strlen(str))
4334- return TRUE;
4335-
4336- return FALSE;
4337- }
4338-
4339-
4340-
4341-/* replace macros in buffer */
4342-int process_macros(char *input_buffer,char *output_buffer,int buffer_length){
4343- char *temp_buffer;
4344- int in_macro;
4345- int arg_index=0;
4346- char *selected_macro=NULL;
4347-
4348- strcpy(output_buffer,"");
4349-
4350- in_macro=FALSE;
4351-
4352- for(temp_buffer=my_strsep(&input_buffer,"$");temp_buffer!=NULL;temp_buffer=my_strsep(&input_buffer,"$")){
4353-
4354- selected_macro=NULL;
4355-
4356- if(in_macro==FALSE){
4357- if(strlen(output_buffer)+strlen(temp_buffer)<buffer_length-1){
4358- strncat(output_buffer,temp_buffer,buffer_length-strlen(output_buffer)-1);
4359- output_buffer[buffer_length-1]='\x0';
4360- }
4361- in_macro=TRUE;
4362- }
4363- else{
4364-
4365- if(strlen(output_buffer)+strlen(temp_buffer)<buffer_length-1){
4366-
4367- /* argument macro */
4368- if(strstr(temp_buffer,"ARG")==temp_buffer){
4369- arg_index=atoi(temp_buffer+3);
4370- if(arg_index>=1 && arg_index<=MAX_COMMAND_ARGUMENTS)
4371- selected_macro=macro_argv[arg_index-1];
4372- }
4373-
4374- /* an escaped $ is done by specifying two $$ next to each other */
4375- else if(!strcmp(temp_buffer,"")){
4376- strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
4377- }
4378-
4379- /* a non-macro, just some user-defined string between two $s */
4380- else{
4381- strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
4382- output_buffer[buffer_length-1]='\x0';
4383- strncat(output_buffer,temp_buffer,buffer_length-strlen(output_buffer)-1);
4384- output_buffer[buffer_length-1]='\x0';
4385- strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
4386- }
4387-
4388-
4389- /* insert macro */
4390- if(selected_macro!=NULL)
4391- strncat(output_buffer,(selected_macro==NULL)?"":selected_macro,buffer_length-strlen(output_buffer)-1);
4392-
4393- output_buffer[buffer_length-1]='\x0';
4394- }
4395-
4396- in_macro=FALSE;
4397- }
4398- }
4399-
4400- return OK;
4401- }
4402-
4403-
4404-
4405-/* process command line arguments */
4406-int process_arguments(int argc, char **argv){
4407- char optchars[MAX_INPUT_BUFFER];
4408- int c=1;
4409- int have_mode=FALSE;
4410-
4411-#ifdef HAVE_GETOPT_LONG
4412- int option_index=0;
4413- static struct option long_options[]={
4414- {"config", required_argument, 0, 'c'},
4415- {"inetd", no_argument, 0, 'i'},
4416- {"daemon", no_argument, 0, 'd'},
4417- {"no-ssl", no_argument, 0, 'n'},
4418- {"help", no_argument, 0, 'h'},
4419- {"license", no_argument, 0, 'l'},
4420- {0, 0, 0, 0}
4421- };
4422-#endif
4423-
4424- /* no options were supplied */
4425- if(argc<2)
4426- return ERROR;
4427-
4428- snprintf(optchars,MAX_INPUT_BUFFER,"c:hVldin");
4429-
4430- while(1){
4431-#ifdef HAVE_GETOPT_LONG
4432- c=getopt_long(argc,argv,optchars,long_options,&option_index);
4433-#else
4434- c=getopt(argc,argv,optchars);
4435-#endif
4436- if(c==-1 || c==EOF)
4437- break;
4438-
4439- /* process all arguments */
4440- switch(c){
4441-
4442- case '?':
4443- case 'h':
4444- show_help=TRUE;
4445- break;
4446- case 'V':
4447- show_version=TRUE;
4448- break;
4449- case 'l':
4450- show_license=TRUE;
4451- break;
4452- case 'c':
4453- strncpy(config_file,optarg,sizeof(config_file));
4454- config_file[sizeof(config_file)-1]='\x0';
4455- break;
4456- case 'd':
4457- use_inetd=FALSE;
4458- have_mode=TRUE;
4459- break;
4460- case 'i':
4461- use_inetd=TRUE;
4462- have_mode=TRUE;
4463- break;
4464- case 'n':
4465- use_ssl=FALSE;
4466- break;
4467- default:
4468- return ERROR;
4469- break;
4470- }
4471- }
4472-
4473- /* bail if we didn't get required args */
4474- if(have_mode==FALSE)
4475- return ERROR;
4476-
4477- return OK;
4478- }
4479-
4480+/*******************************************************************************
4481+ *
4482+ * NRPE.C - Nagios Remote Plugin Executor
4483+ * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)
4484+ * License: GPL
4485+ *
4486+ * Last Modified: 11-11-2011
4487+ *
4488+ * Command line: nrpe -c <config_file> [--inetd | --daemon]
4489+ *
4490+ * Description:
4491+ *
4492+ * This program is designed to run as a background process and
4493+ * handle incoming requests (from the host running Nagios) for
4494+ * plugin execution. It is useful for running "local" plugins
4495+ * such as check_users, check_load, check_disk, etc. without
4496+ * having to use rsh or ssh.
4497+ *
4498+ ******************************************************************************/
4499+
4500+/*
4501+ * 08-10-2011 IPv4 subnetworks support added.
4502+ * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c.
4503+ * now allowed_hosts is parsed by parse_allowed_hosts() from acl.c.
4504+ */
4505+
4506+#include "../include/common.h"
4507+#include "../include/config.h"
4508+#include "../include/nrpe.h"
4509+#include "../include/utils.h"
4510+#include "../include/acl.h"
4511+
4512+#ifdef HAVE_SSL
4513+#include "../include/dh.h"
4514+#endif
4515+
4516+#ifdef HAVE_LIBWRAP
4517+int allow_severity=LOG_INFO;
4518+int deny_severity=LOG_WARNING;
4519+#endif
4520+
4521+#ifdef HAVE_SSL
4522+SSL_METHOD *meth;
4523+SSL_CTX *ctx;
4524+int use_ssl=TRUE;
4525+#else
4526+int use_ssl=FALSE;
4527+#endif
4528+
4529+#define DEFAULT_COMMAND_TIMEOUT 60 /* default timeout for execution of plugins */
4530+#define MAXFD 64
4531+#define NASTY_METACHARS "|`&><'\"\\[]{};"
4532+
4533+char *command_name=NULL;
4534+char *macro_argv[MAX_COMMAND_ARGUMENTS];
4535+
4536+char config_file[MAX_INPUT_BUFFER]="nrpe.cfg";
4537+int log_facility=LOG_DAEMON;
4538+int server_port=DEFAULT_SERVER_PORT;
4539+char server_address[16]="0.0.0.0";
4540+int socket_timeout=DEFAULT_SOCKET_TIMEOUT;
4541+int command_timeout=DEFAULT_COMMAND_TIMEOUT;
4542+int connection_timeout=DEFAULT_CONNECTION_TIMEOUT;
4543+char *command_prefix=NULL;
4544+
4545+command *command_list=NULL;
4546+
4547+char *nrpe_user=NULL;
4548+char *nrpe_group=NULL;
4549+
4550+char *allowed_hosts=NULL;
4551+
4552+char *pid_file=NULL;
4553+int wrote_pid_file=FALSE;
4554+
4555+int allow_arguments=FALSE;
4556+
4557+int allow_weak_random_seed=FALSE;
4558+
4559+int sigrestart=FALSE;
4560+int sigshutdown=FALSE;
4561+
4562+int show_help=FALSE;
4563+int show_license=FALSE;
4564+int show_version=FALSE;
4565+int use_inetd=TRUE;
4566+int debug=FALSE;
4567+
4568+
4569+
4570+
4571+int main(int argc, char **argv){
4572+ int result=OK;
4573+ int x;
4574+ char buffer[MAX_INPUT_BUFFER];
4575+ char *env_string=NULL;
4576+#ifdef HAVE_SSL
4577+ DH *dh;
4578+ char seedfile[FILENAME_MAX];
4579+ int i,c;
4580+#endif
4581+
4582+ /* set some environment variables */
4583+ asprintf(&env_string,"NRPE_MULTILINESUPPORT=1");
4584+ putenv(env_string);
4585+ asprintf(&env_string,"NRPE_PROGRAMVERSION=%s",PROGRAM_VERSION);
4586+ putenv(env_string);
4587+
4588+ /* process command-line args */
4589+ result=process_arguments(argc,argv);
4590+
4591+ if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){
4592+
4593+ printf("\n");
4594+ printf("NRPE - Nagios Remote Plugin Executor\n");
4595+ printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n");
4596+ printf("Version: %s\n",PROGRAM_VERSION);
4597+ printf("Last Modified: %s\n",MODIFICATION_DATE);
4598+ printf("License: GPL v2 with exemptions (-l for more info)\n");
4599+#ifdef HAVE_SSL
4600+ printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n");
4601+#endif
4602+#ifdef HAVE_LIBWRAP
4603+ printf("TCP Wrappers Available\n");
4604+#endif
4605+ printf("\n");
4606+#ifdef ENABLE_COMMAND_ARGUMENTS
4607+ printf("***************************************************************\n");
4608+ printf("** POSSIBLE SECURITY RISK - COMMAND ARGUMENTS ARE SUPPORTED! **\n");
4609+ printf("** Read the NRPE SECURITY file for more information **\n");
4610+ printf("***************************************************************\n");
4611+ printf("\n");
4612+#endif
4613+#ifndef HAVE_LIBWRAP
4614+ printf("***************************************************************\n");
4615+ printf("** POSSIBLE SECURITY RISK - TCP WRAPPERS ARE NOT AVAILABLE! **\n");
4616+ printf("** Read the NRPE SECURITY file for more information **\n");
4617+ printf("***************************************************************\n");
4618+ printf("\n");
4619+#endif
4620+ }
4621+
4622+ if(show_license==TRUE)
4623+ display_license();
4624+
4625+ else if(result!=OK || show_help==TRUE){
4626+
4627+ printf("Usage: nrpe [-n] -c <config_file> <mode>\n");
4628+ printf("\n");
4629+ printf("Options:\n");
4630+ printf(" -n = Do not use SSL\n");
4631+ printf(" <config_file> = Name of config file to use\n");
4632+ printf(" <mode> = One of the following two operating modes:\n");
4633+ printf(" -i = Run as a service under inetd or xinetd\n");
4634+ printf(" -d = Run as a standalone daemon\n");
4635+ printf("\n");
4636+ printf("Notes:\n");
4637+ printf("This program is designed to process requests from the check_nrpe\n");
4638+ printf("plugin on the host(s) running Nagios. It can run as a service\n");
4639+ printf("under inetd or xinetd (read the docs for info on this), or as a\n");
4640+ printf("standalone daemon. Once a request is received from an authorized\n");
4641+ printf("host, NRPE will execute the command/plugin (as defined in the\n");
4642+ printf("config file) and return the plugin output and return code to the\n");
4643+ printf("check_nrpe plugin.\n");
4644+ printf("\n");
4645+ }
4646+
4647+ if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
4648+ exit(STATE_UNKNOWN);
4649+
4650+
4651+ /* open a connection to the syslog facility */
4652+ /* facility name may be overridden later */
4653+ get_log_facility(NRPE_LOG_FACILITY);
4654+ openlog("nrpe",LOG_PID,log_facility);
4655+
4656+ /* make sure the config file uses an absolute path */
4657+ if(config_file[0]!='/'){
4658+
4659+ /* save the name of the config file */
4660+ strncpy(buffer,config_file,sizeof(buffer));
4661+ buffer[sizeof(buffer)-1]='\x0';
4662+
4663+ /* get absolute path of current working directory */
4664+ strcpy(config_file,"");
4665+ getcwd(config_file,sizeof(config_file));
4666+
4667+ /* append a forward slash */
4668+ strncat(config_file,"/",sizeof(config_file)-2);
4669+ config_file[sizeof(config_file)-1]='\x0';
4670+
4671+ /* append the config file to the path */
4672+ strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1);
4673+ config_file[sizeof(config_file)-1]='\x0';
4674+ }
4675+
4676+ /* read the config file */
4677+ result=read_config_file(config_file);
4678+
4679+ /* exit if there are errors... */
4680+ if(result==ERROR){
4681+ syslog(LOG_ERR,"Config file '%s' contained errors, aborting...",config_file);
4682+ return STATE_CRITICAL;
4683+ }
4684+
4685+ /* generate the CRC 32 table */
4686+ generate_crc32_table();
4687+
4688+ /* initialize macros */
4689+ for(x=0;x<MAX_COMMAND_ARGUMENTS;x++)
4690+ macro_argv[x]=NULL;
4691+
4692+#ifdef HAVE_SSL
4693+ /* initialize SSL */
4694+ if(use_ssl==TRUE){
4695+ SSL_library_init();
4696+ SSLeay_add_ssl_algorithms();
4697+ meth=SSLv23_server_method();
4698+ SSL_load_error_strings();
4699+
4700+ /* use week random seed if necessary */
4701+ if(allow_weak_random_seed && (RAND_status()==0)){
4702+
4703+ if(RAND_file_name(seedfile,sizeof(seedfile)-1))
4704+ if(RAND_load_file(seedfile,-1))
4705+ RAND_write_file(seedfile);
4706+
4707+ if(RAND_status()==0){
4708+ syslog(LOG_ERR,"Warning: SSL/TLS uses a weak random seed which is highly discouraged");
4709+ srand(time(NULL));
4710+ for(i=0;i<500 && RAND_status()==0;i++){
4711+ for(c=0;c<sizeof(seedfile);c+=sizeof(int)){
4712+ *((int *)(seedfile+c))=rand();
4713+ }
4714+ RAND_seed(seedfile,sizeof(seedfile));
4715+ }
4716+ }
4717+ }
4718+
4719+ if((ctx=SSL_CTX_new(meth))==NULL){
4720+ syslog(LOG_ERR,"Error: could not create SSL context.\n");
4721+ exit(STATE_CRITICAL);
4722+ }
4723+
4724+ /* ADDED 01/19/2004 */
4725+ /* use only TLSv1 protocol */
4726+ SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
4727+
4728+ /* use anonymous DH ciphers */
4729+ SSL_CTX_set_cipher_list(ctx,"ADH");
4730+ dh=get_dh512();
4731+ SSL_CTX_set_tmp_dh(ctx,dh);
4732+ DH_free(dh);
4733+ if(debug==TRUE)
4734+ syslog(LOG_INFO,"INFO: SSL/TLS initialized. All network traffic will be encrypted.");
4735+ }
4736+ else{
4737+ if(debug==TRUE)
4738+ syslog(LOG_INFO,"INFO: SSL/TLS NOT initialized. Network encryption DISABLED.");
4739+ }
4740+#endif
4741+
4742+ /* if we're running under inetd... */
4743+ if(use_inetd==TRUE){
4744+
4745+ /* make sure we're not root */
4746+ check_privileges();
4747+
4748+ /* redirect STDERR to /dev/null */
4749+ close(2);
4750+ open("/dev/null",O_WRONLY);
4751+
4752+ /* handle the connection */
4753+ handle_connection(0);
4754+ }
4755+
4756+ /* else daemonize and start listening for requests... */
4757+ else if(fork()==0){
4758+
4759+ /* we're a daemon - set up a new process group */
4760+ setsid();
4761+
4762+ /* close standard file descriptors */
4763+ close(0);
4764+ close(1);
4765+ close(2);
4766+
4767+ /* redirect standard descriptors to /dev/null */
4768+ open("/dev/null",O_RDONLY);
4769+ open("/dev/null",O_WRONLY);
4770+ open("/dev/null",O_WRONLY);
4771+
4772+ chdir("/");
4773+ /*umask(0);*/
4774+
4775+ /* handle signals */
4776+ signal(SIGQUIT,sighandler);
4777+ signal(SIGTERM,sighandler);
4778+ signal(SIGHUP,sighandler);
4779+
4780+ /* log info to syslog facility */
4781+ syslog(LOG_NOTICE,"Starting up daemon");
4782+
4783+ /* write pid file */
4784+ if(write_pid_file()==ERROR)
4785+ return STATE_CRITICAL;
4786+
4787+ /* drop privileges */
4788+ drop_privileges(nrpe_user,nrpe_group);
4789+
4790+ /* make sure we're not root */
4791+ check_privileges();
4792+
4793+ do{
4794+
4795+ /* reset flags */
4796+ sigrestart=FALSE;
4797+ sigshutdown=FALSE;
4798+
4799+ /* wait for connections */
4800+ wait_for_connections();
4801+
4802+ /* free all memory we allocated */
4803+ free_memory();
4804+
4805+ if(sigrestart==TRUE){
4806+
4807+ /* read the config file */
4808+ result=read_config_file(config_file);
4809+
4810+ /* exit if there are errors... */
4811+ if(result==ERROR){
4812+ syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file);
4813+ return STATE_CRITICAL;
4814+ }
4815+ }
4816+
4817+ }while(sigrestart==TRUE && sigshutdown==FALSE);
4818+
4819+ /* remove pid file */
4820+ remove_pid_file();
4821+
4822+ syslog(LOG_NOTICE,"Daemon shutdown\n");
4823+ }
4824+
4825+#ifdef HAVE_SSL
4826+ if(use_ssl==TRUE)
4827+ SSL_CTX_free(ctx);
4828+#endif
4829+
4830+ /* We are now running in daemon mode, or the connection handed over by inetd has
4831+ been completed, so the parent process exits */
4832+ return STATE_OK;
4833+ }
4834+
4835+
4836+
4837+
4838+/* read in the configuration file */
4839+int read_config_file(char *filename){
4840+ FILE *fp;
4841+ char config_file[MAX_FILENAME_LENGTH];
4842+ char input_buffer[MAX_INPUT_BUFFER];
4843+ char *input_line;
4844+ char *temp_buffer;
4845+ char *varname;
4846+ char *varvalue;
4847+ int line=0;
4848+ int len=0;
4849+ int x=0;
4850+
4851+
4852+ /* open the config file for reading */
4853+ fp=fopen(filename,"r");
4854+
4855+ /* exit if we couldn't open the config file */
4856+ if(fp==NULL){
4857+ syslog(LOG_ERR,"Unable to open config file '%s' for reading\n",filename);
4858+ return ERROR;
4859+ }
4860+
4861+ while(fgets(input_buffer,MAX_INPUT_BUFFER-1,fp)){
4862+
4863+ line++;
4864+ input_line=input_buffer;
4865+
4866+ /* skip leading whitespace */
4867+ while(isspace(*input_line))
4868+ ++input_line;
4869+
4870+ /* trim trailing whitespace */
4871+ len=strlen(input_line);
4872+ for(x=len-1;x>=0;x--){
4873+ if(isspace(input_line[x]))
4874+ input_line[x]='\x0';
4875+ else
4876+ break;
4877+ }
4878+
4879+ /* skip comments and blank lines */
4880+ if(input_line[0]=='#')
4881+ continue;
4882+ if(input_line[0]=='\x0')
4883+ continue;
4884+ if(input_line[0]=='\n')
4885+ continue;
4886+
4887+ /* get the variable name */
4888+ varname=strtok(input_line,"=");
4889+ if(varname==NULL){
4890+ syslog(LOG_ERR,"No variable name specified in config file '%s' - Line %d\n",filename,line);
4891+ return ERROR;
4892+ }
4893+
4894+ /* get the variable value */
4895+ varvalue=strtok(NULL,"\n");
4896+ if(varvalue==NULL){
4897+ syslog(LOG_ERR,"No variable value specified in config file '%s' - Line %d\n",filename,line);
4898+ return ERROR;
4899+ }
4900+
4901+ /* allow users to specify directories to recurse into for config files */
4902+ else if(!strcmp(varname,"include_dir")){
4903+
4904+ strncpy(config_file,varvalue,sizeof(config_file)-1);
4905+ config_file[sizeof(config_file)-1]='\x0';
4906+
4907+ /* strip trailing / if necessary */
4908+ if(config_file[strlen(config_file)-1]=='/')
4909+ config_file[strlen(config_file)-1]='\x0';
4910+
4911+ /* process the config directory... */
4912+ if(read_config_dir(config_file)==ERROR)
4913+ syslog(LOG_ERR,"Continuing with errors...");
4914+ }
4915+
4916+ /* allow users to specify individual config files to include */
4917+ else if(!strcmp(varname,"include") || !strcmp(varname,"include_file")){
4918+
4919+ /* process the config file... */
4920+ if(read_config_file(varvalue)==ERROR)
4921+ syslog(LOG_ERR,"Continuing with errors...");
4922+ }
4923+
4924+ else if(!strcmp(varname,"server_port")){
4925+ server_port=atoi(varvalue);
4926+ if(server_port<1024){
4927+ syslog(LOG_ERR,"Invalid port number specified in config file '%s' - Line %d\n",filename,line);
4928+ return ERROR;
4929+ }
4930+ }
4931+ else if(!strcmp(varname,"command_prefix"))
4932+ command_prefix=strdup(varvalue);
4933+
4934+ else if(!strcmp(varname,"server_address")){
4935+ strncpy(server_address,varvalue,sizeof(server_address) - 1);
4936+ server_address[sizeof(server_address)-1]='\0';
4937+ }
4938+ else if(!strcmp(varname,"allowed_hosts")) {
4939+ allowed_hosts=strdup(varvalue);
4940+ parse_allowed_hosts(allowed_hosts);
4941+ }
4942+ else if(strstr(input_line,"command[")){
4943+ temp_buffer=strtok(varname,"[");
4944+ temp_buffer=strtok(NULL,"]");
4945+ if(temp_buffer==NULL){
4946+ syslog(LOG_ERR,"Invalid command specified in config file '%s' - Line %d\n",filename,line);
4947+ return ERROR;
4948+ }
4949+ add_command(temp_buffer,varvalue);
4950+ }
4951+
4952+ else if(strstr(input_buffer,"debug")){
4953+ debug=atoi(varvalue);
4954+ if(debug>0)
4955+ debug=TRUE;
4956+ else
4957+ debug=FALSE;
4958+ }
4959+
4960+ else if(!strcmp(varname,"nrpe_user"))
4961+ nrpe_user=strdup(varvalue);
4962+
4963+ else if(!strcmp(varname,"nrpe_group"))
4964+ nrpe_group=strdup(varvalue);
4965+
4966+ else if(!strcmp(varname,"dont_blame_nrpe"))
4967+ allow_arguments=(atoi(varvalue)==1)?TRUE:FALSE;
4968+
4969+ else if(!strcmp(varname,"command_timeout")){
4970+ command_timeout=atoi(varvalue);
4971+ if(command_timeout<1){
4972+ syslog(LOG_ERR,"Invalid command_timeout specified in config file '%s' - Line %d\n",filename,line);
4973+ return ERROR;
4974+ }
4975+ }
4976+
4977+ else if(!strcmp(varname,"connection_timeout")){
4978+ connection_timeout=atoi(varvalue);
4979+ if(connection_timeout<1){
4980+ syslog(LOG_ERR,"Invalid connection_timeout specified in config file '%s' - Line %d\n",filename,line);
4981+ return ERROR;
4982+ }
4983+ }
4984+
4985+ else if(!strcmp(varname,"allow_weak_random_seed"))
4986+ allow_weak_random_seed=(atoi(varvalue)==1)?TRUE:FALSE;
4987+
4988+ else if(!strcmp(varname,"pid_file"))
4989+ pid_file=strdup(varvalue);
4990+
4991+ else if(!strcmp(varname,"log_facility")){
4992+ if((get_log_facility(varvalue))==OK){
4993+ /* re-open log using new facility */
4994+ closelog();
4995+ openlog("nrpe",LOG_PID,log_facility);
4996+ }
4997+ else
4998+ syslog(LOG_WARNING,"Invalid log_facility specified in config file '%s' - Line %d\n",filename,line);
4999+ }
5000+
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: