Просмотр исходного кода

Initial support for command arguments (no native encryption yet)

Ethan Galstad 23 лет назад
Родитель
Сommit
1edf746ccc
11 измененных файлов с 964 добавлено и 150 удалено
  1. 39 0
      SECURITY
  2. 12 10
      common/common.h
  3. 3 2
      common/config.h.in
  4. 409 75
      configure
  5. 22 3
      configure.in
  6. 17 1
      nrpe.cfg.in
  7. 1 1
      nrpe.spec
  8. 53 23
      src/check_nrpe.c
  9. 314 31
      src/nrpe.c
  10. 81 2
      src/utils.c
  11. 13 2
      src/utils.h

+ 39 - 0
SECURITY

@@ -0,0 +1,39 @@
+********************
+NRPE SECURITY README
+********************
+
+NRPE 2.0 include the ability for clients to suppy arguments to
+commands which should be run.  Please note that this feature
+should be considered a security risk, and you should only use
+it if you know what you're doing!
+
+To enable support for command argument in the daemon, you must
+do two things:
+
+   1.  Run the configure script with the --enable-command-args 
+       option
+
+   2.  Set the 'dont_blame_nrpe' directive in the NRPE config
+       file to 1.	
+
+To help prevent some nasty things from being done by evil 
+clients, the following twelve metacharacters are not allowed
+in client command arguments:
+
+   | ` & > < ' " \ [ ] { }
+
+Any client request which contains the abovementioned metachars
+is discarded.
+
+If you do enable support for command arguments in the NRPE daemon,
+make sure that you encrypt communications either by using:
+
+   1.  Stunnel (see http://www.stunnel.org)
+   2.  Native SSL support
+
+Do NOT assume that just because the daemon is behind a firewall
+that you are safe!  Always encrypt NRPE traffic!
+
+
+    -- Ethan Galstad (nagios@nagios.org)
+

+ 12 - 10
common/common.h

@@ -1,8 +1,8 @@
 /************************************************************************
  *
  * COMMON.H - NRPE Common Include File
- * Copyright (c) 1999-2002 Ethan Galstad (nagios@nagios.org)
- * Last Modified: 12-30-2002
+ * Copyright (c) 1999-2003 Ethan Galstad (nagios@nagios.org)
+ * Last Modified: 01-28-2003
  *
  * License:
  *
@@ -21,9 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  ************************************************************************/
 
+#include "config.h"
 
-#define PROGRAM_VERSION "1.8"
-#define MODIFICATION_DATE "01-16-2003"
+#define PROGRAM_VERSION "2.0a1"
+#define MODIFICATION_DATE "01-28-2003"
 
 #define OK		0
 #define ERROR		-1
@@ -51,14 +52,15 @@
 #define QUERY_PACKET		1		/* id code for a packet containing a query */
 #define	RESPONSE_PACKET		2		/* id code for a packet containing a response */
 
-#define NRPE_PACKET_VERSION_1	1		/* packet version identifier (in case packet type changes in future versions) */
+#define NRPE_PACKET_VERSION_2   2               /* packet version identifier */
+#define NRPE_PACKET_VERSION_1	1		/* older packet version identifiers (no longer supported) */
 
 #define MAX_PACKETBUFFER_LENGTH	1024		/* max amount of data we'll send in one query/response */
 
 typedef struct packet_struct{
-	int packet_type;
-	int packet_version;
-	int result_code;
-	int buffer_length;
-	char buffer[MAX_PACKETBUFFER_LENGTH];
+	int16_t   packet_version;
+	int16_t   packet_type;
+	u_int32_t crc32_value;
+	int16_t   result_code;
+	char      buffer[MAX_PACKETBUFFER_LENGTH];
         }packet;

+ 3 - 2
common/config.h.in

@@ -1,8 +1,8 @@
 /************************************************************************
  *
  * NRPE Common Header File
- * Copyright (c) 1999-2002 Ethan Galstad (nagios@nagios.org)
- * Last Modified: 12-30-2002
+ * Copyright (c) 1999-2003 Ethan Galstad (nagios@nagios.org)
+ * Last Modified: 01-26-2003
  *
  * License:
  *
@@ -27,6 +27,7 @@
 
 #define DEFAULT_SERVER_PORT	@nrpe_port@	/* default port to use */
 
+#undef ENABLE_COMMAND_ARGUMENTS
 
 #undef STDC_HEADERS
 #undef HAVE_STRDUP

+ 409 - 75
configure

@@ -15,9 +15,11 @@ ac_default_prefix=/usr/local/nagios
 ac_help="$ac_help
 --with-nrpe-user=<user> sets user name to run NRPE"
 ac_help="$ac_help
---with-nrpe-grp=<grp> sets group name to run NRPE"
+--with-nrpe-group=<group> sets group name to run NRPE"
 ac_help="$ac_help
 --with-nrpe-port=<port> sets port number for NRPE to listen on"
+ac_help="$ac_help
+--enable-command-args allows clients to specify command arguments.  *** THIS IS A SECURITY RISK! *** Read the SECURITY file before using this option!"
 
 # Initialize some variables set by options.
 # The variables have the same names as the options, with
@@ -525,9 +527,9 @@ fi
 
 
 PKG_NAME=nrpe
-PKG_VERSION="1.8"
+PKG_VERSION="2.0a1"
 PKG_HOME_URL="http://www.nagios.org/"
-PKG_REL_DATE="01-16-2003"
+PKG_REL_DATE="01-28-2003"
 
 
 ac_aux_dir=
@@ -561,7 +563,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:565: checking for a BSD compatible install" >&5
+echo "configure:567: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -618,7 +620,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:622: checking for $ac_word" >&5
+echo "configure:624: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -648,7 +650,7 @@ if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:652: checking for $ac_word" >&5
+echo "configure:654: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -699,7 +701,7 @@ fi
       # Extract the first word of "cl", so it can be a program name with args.
 set dummy cl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:703: checking for $ac_word" >&5
+echo "configure:705: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -731,7 +733,7 @@ fi
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:735: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:737: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -742,12 +744,12 @@ cross_compiling=$ac_cv_prog_cc_cross
 
 cat > conftest.$ac_ext << EOF
 
-#line 746 "configure"
+#line 748 "configure"
 #include "confdefs.h"
 
 main(){return(0);}
 EOF
-if { (eval echo configure:751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:753: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -773,12 +775,12 @@ if test $ac_cv_prog_cc_works = no; then
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:777: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:779: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:782: checking whether we are using GNU C" >&5
+echo "configure:784: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -787,7 +789,7 @@ else
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:791: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:793: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -806,7 +808,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
 ac_save_CFLAGS="$CFLAGS"
 CFLAGS=
 echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:810: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:812: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -838,7 +840,7 @@ else
 fi
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:842: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:844: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -866,7 +868,7 @@ fi
 
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:870: checking how to run the C preprocessor" >&5
+echo "configure:872: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -881,13 +883,13 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 885 "configure"
+#line 887 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:891: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:893: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -898,13 +900,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 902 "configure"
+#line 904 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:908: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:910: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -915,13 +917,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 919 "configure"
+#line 921 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:925: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:927: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -946,12 +948,12 @@ fi
 echo "$ac_t""$CPP" 1>&6
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:950: checking for ANSI C header files" >&5
+echo "configure:952: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 955 "configure"
+#line 957 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -959,7 +961,7 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:965: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -976,7 +978,7 @@ rm -f conftest*
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 980 "configure"
+#line 982 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -994,7 +996,7 @@ fi
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 998 "configure"
+#line 1000 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1015,7 +1017,7 @@ if test "$cross_compiling" = yes; then
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 1019 "configure"
+#line 1021 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1026,7 +1028,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-if { (eval echo configure:1030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -1050,12 +1052,12 @@ EOF
 fi
 
 echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:1054: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:1056: checking whether time.h and sys/time.h may both be included" >&5
 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1059 "configure"
+#line 1061 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/time.h>
@@ -1064,7 +1066,7 @@ int main() {
 struct tm *tp;
 ; return 0; }
 EOF
-if { (eval echo configure:1068: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1070: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_time=yes
 else
@@ -1085,12 +1087,12 @@ EOF
 fi
 
 echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:1089: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:1091: checking for sys/wait.h that is POSIX.1 compatible" >&5
 if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1094 "configure"
+#line 1096 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -1106,7 +1108,7 @@ wait (&s);
 s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
 ; return 0; }
 EOF
-if { (eval echo configure:1110: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1112: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_sys_wait_h=yes
 else
@@ -1130,17 +1132,17 @@ for ac_hdr in ctype.h errno.h fcntl.h grp.h netdb.h pwd.h signal.h strings.h str
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1134: checking for $ac_hdr" >&5
+echo "configure:1136: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1139 "configure"
+#line 1141 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1144: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1146: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1168,12 +1170,12 @@ done
 
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1172: checking for working const" >&5
+echo "configure:1174: checking for working const" >&5
 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1177 "configure"
+#line 1179 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -1222,7 +1224,7 @@ ccp = (char const *const *) p;
 
 ; return 0; }
 EOF
-if { (eval echo configure:1226: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1228: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -1243,12 +1245,12 @@ EOF
 fi
 
 echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:1247: checking whether struct tm is in sys/time.h or time.h" >&5
+echo "configure:1249: checking whether struct tm is in sys/time.h or time.h" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1252 "configure"
+#line 1254 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <time.h>
@@ -1256,7 +1258,7 @@ int main() {
 struct tm *tp; tp->tm_sec;
 ; return 0; }
 EOF
-if { (eval echo configure:1260: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1262: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_tm=time.h
 else
@@ -1277,12 +1279,12 @@ EOF
 fi
 
 echo $ac_n "checking for mode_t""... $ac_c" 1>&6
-echo "configure:1281: checking for mode_t" >&5
+echo "configure:1283: checking for mode_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1286 "configure"
+#line 1288 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1310,12 +1312,12 @@ EOF
 fi
 
 echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:1314: checking for pid_t" >&5
+echo "configure:1316: checking for pid_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1319 "configure"
+#line 1321 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1343,12 +1345,12 @@ EOF
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:1347: checking for size_t" >&5
+echo "configure:1349: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1352 "configure"
+#line 1354 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1376,12 +1378,12 @@ EOF
 fi
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:1380: checking return type of signal handlers" >&5
+echo "configure:1382: checking return type of signal handlers" >&5
 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1385 "configure"
+#line 1387 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -1398,7 +1400,7 @@ int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:1402: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1404: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
@@ -1417,12 +1419,12 @@ EOF
 
 
 echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:1421: checking for uid_t in sys/types.h" >&5
+echo "configure:1423: checking for uid_t in sys/types.h" >&5
 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1426 "configure"
+#line 1428 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 EOF
@@ -1451,7 +1453,7 @@ EOF
 fi
 
 echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
-echo "configure:1455: checking type of array argument to getgroups" >&5
+echo "configure:1457: checking type of array argument to getgroups" >&5
 if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1459,7 +1461,7 @@ else
   ac_cv_type_getgroups=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 1463 "configure"
+#line 1465 "configure"
 #include "confdefs.h"
 
 /* Thanks to Mike Rendell for this test.  */
@@ -1484,7 +1486,7 @@ main()
 }
 
 EOF
-if { (eval echo configure:1488: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1490: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
     ac_cv_type_getgroups=gid_t
 else
@@ -1498,7 +1500,7 @@ fi
 
 if test $ac_cv_type_getgroups = cross; then
         cat > conftest.$ac_ext <<EOF
-#line 1502 "configure"
+#line 1504 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 EOF
@@ -1522,8 +1524,330 @@ EOF
 
 
 
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:1529: checking size of int" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1537 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(int));
+  return(0);
+}
+EOF
+if { (eval echo configure:1548: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_int=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_int=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking size of short""... $ac_c" 1>&6
+echo "configure:1568: checking size of short" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1576 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(short));
+  return(0);
+}
+EOF
+if { (eval echo configure:1587: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_short=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_short=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_short" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+EOF
+
+
+echo $ac_n "checking size of long""... $ac_c" 1>&6
+echo "configure:1607: checking size of long" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1615 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(long));
+  return(0);
+}
+EOF
+if { (eval echo configure:1626: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_long=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_long=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_long" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+
+if test "$ac_cv_sizeof_int" = 4 ; then
+	echo $ac_n "checking for int32_t""... $ac_c" 1>&6
+echo "configure:1647: checking for int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1652 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_int32_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_int32_t" 1>&6
+if test $ac_cv_type_int32_t = no; then
+  cat >> confdefs.h <<\EOF
+#define int32_t int
+EOF
+
+fi
+
+	echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6
+echo "configure:1680: checking for u_int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1685 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])u_int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_u_int32_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_u_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_u_int32_t" 1>&6
+if test $ac_cv_type_u_int32_t = no; then
+  cat >> confdefs.h <<\EOF
+#define u_int32_t unsigned int
+EOF
+
+fi
+
+elif test "$ac_cv_sizeof_short" = 4 ; then
+	echo $ac_n "checking for int32_t""... $ac_c" 1>&6
+echo "configure:1714: checking for int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1719 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_int32_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_int32_t" 1>&6
+if test $ac_cv_type_int32_t = no; then
+  cat >> confdefs.h <<\EOF
+#define int32_t short
+EOF
+
+fi
+
+	echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6
+echo "configure:1747: checking for u_int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1752 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])u_int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_u_int32_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_u_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_u_int32_t" 1>&6
+if test $ac_cv_type_u_int32_t = no; then
+  cat >> confdefs.h <<\EOF
+#define u_int32_t unsigned short
+EOF
+
+fi
+
+elif test "$ac_cv_sizeof_long" = 4 ; then
+	echo $ac_n "checking for int32_t""... $ac_c" 1>&6
+echo "configure:1781: checking for int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1786 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_int32_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_int32_t" 1>&6
+if test $ac_cv_type_int32_t = no; then
+  cat >> confdefs.h <<\EOF
+#define int32_t long
+EOF
+
+fi
+
+	echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6
+echo "configure:1814: checking for u_int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1819 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])u_int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_u_int32_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_u_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_u_int32_t" 1>&6
+if test $ac_cv_type_u_int32_t = no; then
+  cat >> confdefs.h <<\EOF
+#define u_int32_t unsigned long
+EOF
+
+fi
+
+else
+	{ echo "configure: error: Cannot find a type with size of 32 bits" 1>&2; exit 1; }
+fi
+
 echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
-echo "configure:1527: checking for main in -lnsl" >&5
+echo "configure:1851: checking for main in -lnsl" >&5
 ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1531,14 +1855,14 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1535 "configure"
+#line 1859 "configure"
 #include "confdefs.h"
 
 int main() {
 main()
 ; return 0; }
 EOF
-if { (eval echo configure:1542: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1866: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1559,7 +1883,7 @@ else
 fi
 
 echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
-echo "configure:1563: checking for socket in -lsocket" >&5
+echo "configure:1887: checking for socket in -lsocket" >&5
 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1567,7 +1891,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1571 "configure"
+#line 1895 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1578,7 +1902,7 @@ int main() {
 socket()
 ; return 0; }
 EOF
-if { (eval echo configure:1582: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1906: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1602,12 +1926,12 @@ fi
 for ac_func in strdup strstr strtoul initgroups
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1606: checking for $ac_func" >&5
+echo "configure:1930: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1611 "configure"
+#line 1935 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1630,7 +1954,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1634: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -1656,9 +1980,9 @@ done
 
 
 echo $ac_n "checking for type of socket size""... $ac_c" 1>&6
-echo "configure:1660: checking for type of socket size" >&5
+echo "configure:1984: checking for type of socket size" >&5
 cat > conftest.$ac_ext <<EOF
-#line 1662 "configure"
+#line 1986 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <sys/types.h>
@@ -1668,7 +1992,7 @@ int main() {
 int a = send(1, (const void *)0, (size_t *) 0, (int *) 0);
 ; return 0; }
 EOF
-if { (eval echo configure:1672: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1996: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   cat >> confdefs.h <<\EOF
 #define SOCKET_SIZE_TYPE size_t
@@ -1694,9 +2018,9 @@ else
   nrpe_user=nagios
 fi
 
-# Check whether --with-nrpe_grp or --without-nrpe_grp was given.
-if test "${with_nrpe_grp+set}" = set; then
-  withval="$with_nrpe_grp"
+# Check whether --with-nrpe_group or --without-nrpe_group was given.
+if test "${with_nrpe_group+set}" = set; then
+  withval="$with_nrpe_group"
   nrpe_grp=$withval
 else
   nrpe_grp=nagios
@@ -1718,11 +2042,21 @@ cat >> confdefs.h <<EOF
 EOF
 
 
+# Check whether --enable-command-args or --disable-command-args was given.
+if test "${enable_command_args+set}" = set; then
+  enableval="$enable_command_args"
+  cat >> confdefs.h <<EOF
+#define ENABLE_COMMAND_ARGUMENTS 1
+EOF
+
+fi
+
+
 
 # Extract the first word of "perl", so it can be a program name with args.
 set dummy perl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1726: checking for $ac_word" >&5
+echo "configure:2060: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else

+ 22 - 3
configure.in

@@ -9,9 +9,9 @@ AC_CONFIG_HEADER(common/config.h)
 AC_PREFIX_DEFAULT(/usr/local/nagios)
 
 PKG_NAME=nrpe
-PKG_VERSION="1.8"
+PKG_VERSION="2.0a1"
 PKG_HOME_URL="http://www.nagios.org/"
-PKG_REL_DATE="01-16-2003"
+PKG_REL_DATE="01-28-2003"
 
 dnl Figure out how to invoke "install" and what install options to use.
 
@@ -37,6 +37,23 @@ AC_TYPE_SIZE_T
 AC_TYPE_SIGNAL
 AC_TYPE_GETGROUPS
 
+dnl Define u_int32_t if we don't have it already (Solaris)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(long)
+if test "$ac_cv_sizeof_int" = 4 ; then
+	AC_CHECK_TYPE(int32_t, int)
+	AC_CHECK_TYPE(u_int32_t, unsigned int)
+elif test "$ac_cv_sizeof_short" = 4 ; then
+	AC_CHECK_TYPE(int32_t, short)
+	AC_CHECK_TYPE(u_int32_t, unsigned short)
+elif test "$ac_cv_sizeof_long" = 4 ; then
+	AC_CHECK_TYPE(int32_t, long)
+	AC_CHECK_TYPE(u_int32_t, unsigned long)
+else
+	AC_MSG_ERROR([Cannot find a type with size of 32 bits])
+fi
+
 dnl Checks for library functions.
 AC_CHECK_LIB(nsl,main,SOCKETLIBS="$SOCKETLIBS -lnsl")
 AC_CHECK_LIB(socket,socket,SOCKETLIBS="$SOCKETLIBS -lsocket")
@@ -54,13 +71,15 @@ AC_TRY_COMPILE([#include <stdlib.h>
 
 
 AC_ARG_WITH(nrpe_user,--with-nrpe-user=<user> sets user name to run NRPE,nrpe_user=$withval,nrpe_user=nagios)
-AC_ARG_WITH(nrpe_grp,--with-nrpe-grp=<grp> sets group name to run NRPE,nrpe_grp=$withval,nrpe_grp=nagios)
+AC_ARG_WITH(nrpe_group,--with-nrpe-group=<group> sets group name to run NRPE,nrpe_grp=$withval,nrpe_grp=nagios)
 AC_ARG_WITH(nrpe_port,--with-nrpe-port=<port> sets port number for NRPE to listen on,nrpe_port=$withval,nrpe_port=5666)
 AC_SUBST(nrpe_user)
 AC_SUBST(nrpe_grp)
 AC_SUBST(nrpe_port)
 AC_DEFINE_UNQUOTED(DEFAULT_SERVER_PORT,$nrpe_port)
 
+AC_ARG_ENABLE(command-args,--enable-command-args allows clients to specify command arguments.  *** THIS IS A SECURITY RISK! *** Read the SECURITY file before using this option!,AC_DEFINE_UNQUOTED(ENABLE_COMMAND_ARGUMENTS))
+
 
 AC_PATH_PROG(PERL,perl)
 AC_OUTPUT(Makefile src/Makefile subst)

+ 17 - 1
nrpe.cfg.in

@@ -2,7 +2,7 @@
 # Sample NRPE Config File 
 # Written by: Ethan Galstad (nagios@nagios.org)
 # 
-# Last Modified: 12-30-2002
+# Last Modified: 01-26-2003
 #
 # NOTES:
 # This is a sample configuration file for the NRPE daemon.  It needs to be
@@ -65,6 +65,22 @@ nrpe_group=@nrpe_grp@
 
 
 
+# COMMAND ARGUMENT PROCESSING
+# This option determines whether or not the NRPE daemon will allow clients
+# to specify arguments to commands that are executed.  This option only works
+# if the daemon was configured with the --enable-command-args configure script
+# option.  
+#
+# *** ENABLING THIS OPTION IS A SECURITY RISK! *** 
+# Read the SECURITY file for information on some of the security implications
+# of enabling this variable.
+#
+# Values: 0=do not allow arguments, 1=allow command arguments
+
+dont_blame_nrpe=0
+
+
+
 # DEBUGGING OPTION
 # This option determines whether or not debugging messages are logged to the
 # syslog facility.

+ 1 - 1
nrpe.spec

@@ -1,5 +1,5 @@
 %define name nrpe
-%define version 1.8
+%define version 2.0a1
 %define release 1
 %define nsusr nagios
 %define nsgrp nagios

+ 53 - 23
src/check_nrpe.c

@@ -4,7 +4,7 @@
  * Copyright (c) 1999-2003 Ethan Galstad (nagios@nagios.org)
  * License: GPL
  *
- * Last Modified: 01-16-2003
+ * Last Modified: 01-28-2003
  *
  * Command line: CHECK_NRPE -H <host_address> [-p port] [-c command] [-to to_sec]
  *
@@ -41,9 +41,11 @@ void alarm_handler(int);
 
 
 int main(int argc, char **argv){
+        u_int32_t long packet_crc32;
+        u_int32_t calculated_crc32;
+	int16_t result;
 	int sd;
 	int rc;
-	int result;
 	packet send_packet;
 	packet receive_packet;
 	int bytes_to_send;
@@ -93,6 +95,9 @@ int main(int argc, char **argv){
 		exit(STATE_UNKNOWN);
 
 
+        /* generate the CRC 32 table */
+        generate_crc32_table();
+
 	/* initialize alarm signal handling */
 	signal(SIGALRM,alarm_handler);
 
@@ -105,16 +110,30 @@ int main(int argc, char **argv){
 	/* we connected, so close connection before exiting */
 	if(result==STATE_OK){
 
-		/* send the query packet */
+		/* clear the packet buffer */
 		bzero(&send_packet,sizeof(send_packet));
-		send_packet.packet_type=htonl(QUERY_PACKET);
-		send_packet.packet_version=htonl(NRPE_PACKET_VERSION_1);
-		send_packet.buffer_length=htonl(strlen(query_string));
-		strcpy(&send_packet.buffer[0],query_string);
 
+		/* fill the packet with semi-random data */
+		randomize_buffer((char *)&send_packet,sizeof(send_packet));
+
+		/* initialize packet data */
+		send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2);
+		send_packet.packet_type=(int16_t)htons(QUERY_PACKET);
+		strncpy(&send_packet.buffer[0],query_string,MAX_PACKETBUFFER_LENGTH);
+		send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
+
+		/* calculate the crc 32 value of the packet */
+		send_packet.crc32_value=(u_int32_t)0L;
+		calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet));
+		send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32);
+
+
+		/***** ENCRYPT REQUEST *****/
+
+
+		/* send the packet */
 		bytes_to_send=sizeof(send_packet);
 		rc=sendall(sd,(char *)&send_packet,&bytes_to_send);
-
 		if(rc==-1){
 			printf("CHECK_NRPE: Error sending query to host.\n");
 			close(sd);
@@ -125,45 +144,56 @@ int main(int argc, char **argv){
 		bytes_to_recv=sizeof(receive_packet);
 		rc=recvall(sd,(char *)&receive_packet,&bytes_to_recv,socket_timeout);
 
+		/* reset timeout and close the connection */
+		alarm(0);
+		close(sd);
+
 		/* recv() error */
 		if(rc<0){
-			printf("CHECK_NRPE: Error receiving data from host.\n");
-			close(sd);
-			alarm(0);
+			printf("CHECK_NRPE: Error receiving data from daemon.\n");
 			return STATE_UNKNOWN;
 		        }
 
 		/* server disconnected */
 		else if(rc==0){
-			printf("CHECK_NRPE: Received 0 bytes.  Are we allowed to connect to the host?\n");
-			close(sd);
-			alarm(0);
+			printf("CHECK_NRPE: Received 0 bytes from daemon.  Check the remote server logs for error messages.\n");
 			return STATE_UNKNOWN;
 		        }
 
 		/* receive underflow */
 		else if(bytes_to_recv<sizeof(receive_packet)){
 			printf("CHECK_NRPE: Receive underflow - only %d bytes received (%d expected).\n",bytes_to_recv,sizeof(receive_packet));
-			close(sd);
-			alarm(0);
 			return STATE_UNKNOWN;
 		        }
 
+		
+		/***** DECRYPT RESPONSE *****/
+
+
+		/* check the crc 32 value */
+		packet_crc32=ntohl(receive_packet.crc32_value);
+		receive_packet.crc32_value=0L;
+		calculated_crc32=calculate_crc32((char *)&receive_packet,sizeof(receive_packet));
+		if(packet_crc32!=calculated_crc32){
+			printf("CHECK_NRPE: Response packet had invalid CRC32.\n");
+			close(sd);
+			return STATE_UNKNOWN;
+                        }
+	
 		/* get the return code from the remote plugin */
-		result=ntohl(receive_packet.result_code);
+		result=(int16_t)ntohl(receive_packet.result_code);
 
-		/* make sure there is something in the plugin output buffer */
+		/* print the output returned by the daemon */
+		receive_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
 		if(!strcmp(receive_packet.buffer,""))
-			printf("CHECK_NRPE: No output returned from NRPE daemon.\n");
+			printf("CHECK_NRPE: No output returned from daemon.\n");
 		else
 			printf("%s\n",receive_packet.buffer);
-
-		/* close the connection */
-		close(sd);
 	        }
 
 	/* reset the alarm */
-	alarm(0);
+	else
+		alarm(0);
 
 	return result;
         }

+ 314 - 31
src/nrpe.c

@@ -4,7 +4,7 @@
  * Copyright (c) 1999-2003 Ethan Galstad (nagios@nagios.org)
  * License: GPL
  *
- * Last Modified: 01-16-2003
+ * Last Modified: 01-28-2003
  *
  * Command line: nrpe -c <config_file> [--inetd | --daemon]
  *
@@ -25,10 +25,11 @@
 
 #define DEFAULT_COMMAND_TIMEOUT	60			/* default timeout for execution of plugins */
 #define MAXFD                   64
+#define MAX_COMMAND_ARGUMENTS   16
+#define NASTY_METACHARS         "|`&><'\"\\[]{}"
 
 
 int process_arguments(int,char **);
-
 void wait_for_connections(void);
 void handle_connection(int);
 int read_config_file(char *);
@@ -36,13 +37,21 @@ int add_command(char *,char *);
 command *find_command(char *);
 void sighandler(int);
 int drop_privileges(char *,char *);
+int check_privileges(void);
 void free_memory(void);
 int is_an_allowed_host(char *);
-
+int validate_request(packet *);
+int contains_nasty_metachars(char *);
+int process_macros(char *,char *,int);
 int my_system(char *,int,int *,char *,int);            	/* executes a command via popen(), but also protects against timeouts */
 void my_system_sighandler(int);				/* handles timeouts when executing commands via my_system() */
 
 
+static unsigned long max_packet_age=30;
+
+char    *command_name=NULL;
+char    *macro_argv[MAX_COMMAND_ARGUMENTS];
+
 char    config_file[MAX_INPUT_BUFFER]="nrpe.cfg";
 char    allowed_hosts[MAX_INPUT_BUFFER];
 int     server_port=DEFAULT_SERVER_PORT;
@@ -55,6 +64,8 @@ command *command_list=NULL;
 char    *nrpe_user=NULL;
 char    *nrpe_group=NULL;
 
+int     allow_arguments=FALSE;
+
 int     show_help=FALSE;
 int     show_license=FALSE;
 int     show_version=FALSE;
@@ -66,7 +77,7 @@ int     debug=FALSE;
 int main(int argc, char **argv){
 	int error=FALSE;
 	int result;
-	int i;
+	int x;
 	char buffer[MAX_INPUT_BUFFER];
 
 	result=process_arguments(argc,argv);
@@ -80,9 +91,19 @@ int main(int argc, char **argv){
 		printf("Last Modified: %s\n",MODIFICATION_DATE);
 		printf("License: GPL\n");
 		printf("\n");
+#ifdef ENABLE_COMMAND_ARGUMENTS
+		printf("***************************************************************\n");
+		printf("** POSSIBLE SECURITY RISK - COMMAND ARGUMENTS ARE SUPPORTED! **\n");
+		printf("**      Read the NRPE SECURITY file for more information     **\n");
+		printf("***************************************************************\n");
+		printf("\n");
+#endif
 	        }
 
-	if(result!=OK || show_help==TRUE){
+	if(show_license==TRUE)
+		display_license();
+
+	else if(result!=OK || show_help==TRUE){
 
 		printf("Usage: %s -c <config_file> [mode]\n",argv[0]);
 		printf("\n");
@@ -103,9 +124,6 @@ int main(int argc, char **argv){
 		printf("\n");
 		}
 
-	if(show_license==TRUE)
-		display_license();
-
         if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
 		exit(STATE_UNKNOWN);
 
@@ -142,9 +160,22 @@ int main(int argc, char **argv){
 		return STATE_CRITICAL;
 		}
 
+	/* initialize macros */
+	for(x=0;x<MAX_COMMAND_ARGUMENTS;x++)
+		macro_argv[x]=NULL;
+
+        /* generate the CRC 32 table */
+        generate_crc32_table();
+
 	/* if we're running under inetd... */
-	if(use_inetd==TRUE)
+	if(use_inetd==TRUE){
+
+		/* make sure we're not root */
+		check_privileges();
+
+		/* handle the connection */
 		handle_connection(0);
+	        }
 
 	/* else daemonize and start listening for requests... */
 	else if(fork()==0){
@@ -171,6 +202,9 @@ int main(int argc, char **argv){
 		/* drop privileges */
 		drop_privileges(nrpe_user,nrpe_group);
 
+		/* make sure we're not root */
+		check_privileges();
+
 		/* wait for connections */
 		wait_for_connections();
 	        }
@@ -191,6 +225,7 @@ int read_config_file(char *filename){
 	char *varname;
 	char *varvalue;
 	int line;
+	int x;
 
 
 	/* open the config file for reading */
@@ -237,7 +272,7 @@ int read_config_file(char *filename){
 			        }
 		        }
 
-                else if(!strcmp(varname,"server_address")){
+               else if(!strcmp(varname,"server_address")){
                         strncpy(server_address,varvalue,sizeof(server_address) - 1);
                         server_address[sizeof(server_address) - 1] = '\0';
                         }
@@ -275,7 +310,14 @@ int read_config_file(char *filename){
                 else if(!strcmp(varname,"nrpe_group"))
 			nrpe_group=strdup(varvalue);
 		
-		else if(!strcmp(varname,"command_timeout")){
+		else if(!strcmp(varname,"dont_blame_nrpe")){
+			if(atoi(varvalue)==1)
+				allow_arguments=TRUE;
+			else
+				allow_arguments=FALSE;
+		        }
+
+ 		else if(!strcmp(varname,"command_timeout")){
 			command_timeout=atoi(varvalue);
 			if(command_timeout<1){
 				syslog(LOG_ERR,"Invalid command_timeout specified in config file '%s' - Line %d\n",filename,line);
@@ -354,7 +396,7 @@ void wait_for_connections(void){
 	/* exit if we couldn't create the socket */
 	if(sock<0){
 	        syslog(LOG_ERR,"Network server socket failure (%d: %s)",errno,strerror(errno));
-	        exit (STATE_CRITICAL);
+	        exit(STATE_CRITICAL);
 		}
 
         /* set the reuse address flag so we don't get errors when restarting */
@@ -374,25 +416,31 @@ void wait_for_connections(void){
 
 	else if(!my_inet_aton(server_address,&myname.sin_addr)){
 		syslog(LOG_ERR,"Server address is not a valid IP address\n");
-		exit (STATE_CRITICAL);
+		exit(STATE_CRITICAL);
                 }
 
 
 	/* bind the address to the Internet socket */
 	if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){
 		syslog(LOG_ERR,"Network server bind failure (%d: %s)\n",errno,strerror(errno));
-	        exit (STATE_CRITICAL);
+	        exit(STATE_CRITICAL);
 	        }
 
 	/* open the socket for listening */
 	if(listen(sock,5)<0){
 	    	syslog(LOG_ERR,"Network server listen failure (%d: %s)\n",errno,strerror(errno));
-	        exit (STATE_CRITICAL);
+	        exit(STATE_CRITICAL);
 		}
 
 	/* log info to syslog facility */
         syslog(LOG_NOTICE,"Starting up daemon");
 
+	/* log warning about command arguments */
+#ifdef ENABLE_COMMAND_ARGUMENTS
+	if(allow_arguments==TRUE)
+		syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments from clients!");
+#endif
+
 	/* Trap signals */
 	signal(SIGQUIT,sighandler);
 	signal(SIGTERM,sighandler);
@@ -511,15 +559,20 @@ void wait_for_connections(void){
 
 /* handles a client connection */
 void handle_connection(int sock){
+        u_int32_t calculated_crc32;
 	command *temp_command;
 	packet receive_packet;
 	packet send_packet;
 	int bytes_to_send;
 	int bytes_to_recv;
 	char buffer[MAX_INPUT_BUFFER];
+	char raw_command[MAX_INPUT_BUFFER];
+	char processed_command[MAX_INPUT_BUFFER];
 	int result=STATE_OK;
 	int early_timeout=FALSE;
 	int rc;
+	int x;
+	FILE *fp;
 
 
 	/* log info to syslog facility */
@@ -550,11 +603,25 @@ void handle_connection(int sock){
 		return;
 	        }
 
-	/* make sure this is the right type of packet */
-	if(ntohl(receive_packet.packet_type)!=QUERY_PACKET || ntohl(receive_packet.packet_version)!=NRPE_PACKET_VERSION_1){
+	fp=fopen("/tmp/packet","w");
+	if(fp){
+		fwrite(&receive_packet,1,sizeof(receive_packet),fp);
+		fclose(fp);
+	        }
 
-		/* log error to syslog facility */
-		syslog(LOG_ERR,"Received invalid packet from client, bailing out...");
+	/* make sure the request is valid */
+	if(validate_request(&receive_packet)==ERROR){
+
+		/* log an error */
+		syslog(LOG_ERR,"Client request was invalid, bailing out...");
+
+		/* free memory */
+		free(command_name);
+		command_name=NULL;
+		for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
+			free(macro_argv[x]);
+			macro_argv[x]=NULL;
+	                }
 
 		return;
 	        }
@@ -564,7 +631,7 @@ void handle_connection(int sock){
 		syslog(LOG_DEBUG,"Host is asking for command '%s' to be run...",receive_packet.buffer);
 
 	/* if this is the version check command, just spew it out */
-	if(!strcmp(&receive_packet.buffer[0],NRPE_HELLO_COMMAND)){
+	if(!strcmp(command_name,NRPE_HELLO_COMMAND)){
 
 		snprintf(buffer,sizeof(buffer),"NRPE v%s",PROGRAM_VERSION);
 		buffer[sizeof(buffer)-1]='\x0';
@@ -578,10 +645,10 @@ void handle_connection(int sock){
 
 	/* find the command we're supposed to run */
 	else{
-		temp_command=find_command(receive_packet.buffer);
+		temp_command=find_command(command_name);
 		if(temp_command==NULL){
 
-			snprintf(buffer,sizeof(buffer),"NRPE: Command '%s' not defined",receive_packet.buffer);
+			snprintf(buffer,sizeof(buffer),"NRPE: Command '%s' not defined",command_name);
 			buffer[sizeof(buffer)-1]='\x0';
 
 			/* log error to syslog facility */
@@ -593,13 +660,18 @@ void handle_connection(int sock){
 
 		else{
 
+			/* process command line */
+			strncpy(raw_command,temp_command->command_line,sizeof(raw_command)-1);
+			raw_command[sizeof(raw_command)-1]='\x0';
+			process_macros(raw_command,processed_command,sizeof(processed_command));
+
 			/* log info to syslog facility */
 			if(debug==TRUE)
-				syslog(LOG_DEBUG,"Running command: %s",temp_command->command_line);
+				syslog(LOG_DEBUG,"Running command: %s",processed_command);
 
 			/* run the command */
 			strcpy(buffer,"");
-			result=my_system(temp_command->command_line,command_timeout,&early_timeout,buffer,sizeof(buffer));
+			result=my_system(processed_command,command_timeout,&early_timeout,buffer,sizeof(buffer));
 
 			/* see if the command timed out */
 			if(early_timeout==TRUE)
@@ -620,6 +692,14 @@ void handle_connection(int sock){
 		        }
 	        }
 
+	/* free memory */
+	free(command_name);
+	command_name=NULL;
+	for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
+		free(macro_argv[x]);
+		macro_argv[x]=NULL;
+	        }
+
 	/* strip newline character from end of output buffer */
 	if(buffer[strlen(buffer)-1]=='\n')
 		buffer[strlen(buffer)-1]='\x0';
@@ -627,14 +707,25 @@ void handle_connection(int sock){
 	/* clear the response packet buffer */
 	bzero(&send_packet,sizeof(send_packet));
 
-	/* fill the response packet with data */
-	send_packet.packet_type=htonl(RESPONSE_PACKET);
-	send_packet.packet_version=htonl(NRPE_PACKET_VERSION_1);
-	send_packet.result_code=htonl(result);
-	send_packet.buffer_length=htonl(strlen(buffer));
-	strncpy(&send_packet.buffer[0],buffer,sizeof(send_packet.buffer));
-	send_packet.buffer[sizeof(send_packet.buffer)-1]='\x0';
+	/* fill the packet with semi-random data */
+	randomize_buffer((char *)&send_packet,sizeof(send_packet));
+
+	/* initialize response packet data */
+	send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2);
+	send_packet.packet_type=(int16_t)htons(RESPONSE_PACKET);
+	send_packet.result_code=(int16_t)htons(result);
+	strncpy(&send_packet.buffer[0],buffer,MAX_PACKETBUFFER_LENGTH);
+	send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
 	
+	/* calculate the crc 32 value of the packet */
+	send_packet.crc32_value=(u_int32_t)0L;
+	calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet));
+	send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32);
+
+
+	/***** ENCRYPT RESPONSE *****/
+
+
 	/* send the response back to the client */
 	bytes_to_send=sizeof(send_packet);
 	sendall(sock,(char *)&send_packet,&bytes_to_send);
@@ -942,6 +1033,198 @@ int drop_privileges(char *user, char *group){
         }
 
 
+
+
+/* bail if daemon is running as root */
+int check_privileges(void){
+	uid_t uid=-1;
+	gid_t gid=-1;
+
+	uid=geteuid();
+	gid=getegid();
+
+	if(uid==0 || gid==0){
+		syslog(LOG_ERR,"Error: NRPE daemon cannot be run as user/group root!");
+		exit(STATE_CRITICAL);
+	        }
+
+	return OK;
+        }
+
+
+
+/* tests whether or not a client request is valid */
+int validate_request(packet *pkt){
+        u_int32_t long packet_crc32;
+        u_int32_t calculated_crc32;
+	char *ptr;
+	int x;
+
+
+	/***** DECRYPT REQUEST ******/
+
+
+        /* check the crc 32 value */
+        packet_crc32=ntohl(pkt->crc32_value);
+        pkt->crc32_value=0L;
+        calculated_crc32=calculate_crc32((char *)pkt,sizeof(packet));
+        if(packet_crc32!=calculated_crc32){
+                syslog(LOG_ERR,"Error: Request packet had invalid CRC32.");
+                return ERROR;
+                }
+
+	/* make sure this is the right type of packet */
+	if(ntohs(pkt->packet_type)!=QUERY_PACKET || ntohs(pkt->packet_version)!=NRPE_PACKET_VERSION_2){
+		syslog(LOG_ERR,"Error: Request packet type/version was invalid!");
+		return ERROR;
+	        }
+
+	/* make sure buffer is terminated */
+	pkt->buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0';
+
+	/* client must send some kind of request */
+	if(!strcmp(pkt->buffer,"")){
+		syslog(LOG_ERR,"Error: Request contained no query!");
+		return ERROR;
+	        }
+
+	/* make sure request doesn't contain nasties */
+	if(contains_nasty_metachars(pkt->buffer)==TRUE){
+		syslog(LOG_ERR,"Error: Request contained illegal metachars!");
+		return ERROR;
+	        }
+
+	/* make sure the request doesn't contain arguments */
+	if(strchr(pkt->buffer,'!')){
+#ifdef ENABLE_COMMAND_ARGUMENTS
+		if(allow_arguments==FALSE){
+			syslog(LOG_ERR,"Error: Request contained command arguments, but argument option is not enabled!");
+			return ERROR;
+	                }
+#else
+		syslog(LOG_ERR,"Error: Request contained command arguments!");
+		return ERROR;
+#endif
+	        }
+
+	/* get command name */
+#ifdef ENABLE_COMMAND_ARGUMENTS
+	ptr=strtok(pkt->buffer,"!");
+#else
+	ptr=pkt->buffer;
+#endif	
+	command_name=strdup(ptr);
+	if(command_name==NULL){
+		syslog(LOG_ERR,"Error: Memory allocation failed");
+		return ERROR;
+	        }
+
+#ifdef ENABLE_COMMAND_ARGUMENTS
+	/* get command arguments */
+	if(allow_arguments==TRUE){
+
+		for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){
+			ptr=strtok(NULL,"!");
+			if(ptr==NULL)
+				break;
+			macro_argv[x]=strdup(ptr);
+			if(macro_argv[x]==NULL){
+				syslog(LOG_ERR,"Error: Memory allocation failed");
+				return ERROR;
+			        }
+			if(!strcmp(macro_argv[x],"")){
+				syslog(LOG_ERR,"Error: Request contained an empty command argument");
+				return ERROR;
+		                }
+		        }
+	        }
+#endif
+
+	return OK;
+        }
+
+
+
+/* tests whether a buffer contains illegal metachars */
+int contains_nasty_metachars(char *str){
+	int result;
+
+	if(str==NULL)
+		return FALSE;
+	
+	result=strcspn(str,NASTY_METACHARS);
+	if(result!=strlen(str))
+		return TRUE;
+
+	return FALSE;
+        }
+
+
+
+/* replace macros in buffer */
+int process_macros(char *input_buffer,char *output_buffer,int buffer_length){
+	char *temp_buffer;
+	int in_macro;
+	int arg_index=0;
+	char *selected_macro=NULL;
+
+	strcpy(output_buffer,"");
+
+	in_macro=FALSE;
+
+	for(temp_buffer=strsep(&input_buffer,"$");temp_buffer!=NULL;temp_buffer=strsep(&input_buffer,"$")){
+
+		selected_macro=NULL;
+
+		if(in_macro==FALSE){
+			if(strlen(output_buffer)+strlen(temp_buffer)<buffer_length-1){
+				strncat(output_buffer,temp_buffer,buffer_length-strlen(output_buffer)-1);
+				output_buffer[buffer_length-1]='\x0';
+			        }
+			in_macro=TRUE;
+			}
+		else{
+
+			if(strlen(output_buffer)+strlen(temp_buffer)<buffer_length-1){
+
+				/* argument macro */
+				if(strstr(temp_buffer,"ARG")==temp_buffer){
+					arg_index=atoi(temp_buffer+3);
+					if(arg_index>=1 && arg_index<=MAX_COMMAND_ARGUMENTS)
+						selected_macro=macro_argv[arg_index-1];
+				        }
+
+				/* an escaped $ is done by specifying two $$ next to each other */
+				else if(!strcmp(temp_buffer,"")){
+					strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
+				        }
+				
+				/* a non-macro, just some user-defined string between two $s */
+				else{
+					strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
+					output_buffer[buffer_length-1]='\x0';
+					strncat(output_buffer,temp_buffer,buffer_length-strlen(output_buffer)-1);
+					output_buffer[buffer_length-1]='\x0';
+					strncat(output_buffer,"$",buffer_length-strlen(output_buffer)-1);
+				        }
+
+				
+				/* insert macro */
+				if(selected_macro!=NULL)
+					strncat(output_buffer,(selected_macro==NULL)?"":selected_macro,buffer_length-strlen(output_buffer)-1);
+
+				output_buffer[buffer_length-1]='\x0';
+				}
+
+			in_macro=FALSE;
+			}
+		}
+
+	return OK;
+	}
+
+
+
 /* process command line arguments */
 int process_arguments(int argc, char **argv){
 	int x;

+ 81 - 2
src/utils.c

@@ -3,9 +3,9 @@
  * UTILS.C - NRPE Utility Functions
  *
  * License: GPL
- * Copyright (c) 1999-2002 Ethan Galstad (nagios@nagios.org)
+ * Copyright (c) 1999-2003 Ethan Galstad (nagios@nagios.org)
  *
- * Last Modified: 10-24-2002
+ * Last Modified: 01-28-2003
  *
  * Description:
  *
@@ -32,6 +32,82 @@
 #include "../common/common.h"
 #include "utils.h"
 
+static unsigned long crc32_table[256];
+
+
+
+/* build the crc table - must be called before calculating the crc value */
+void generate_crc32_table(void){
+	unsigned long crc, poly;
+	int i, j;
+
+	poly=0xEDB88320L;
+	for(i=0;i<256;i++){
+		crc=i;
+		for(j=8;j>0;j--){
+			if(crc & 1)
+				crc=(crc>>1)^poly;
+			else
+				crc>>=1;
+		        }
+		crc32_table[i]=crc;
+                }
+
+	return;
+        }
+
+
+/* calculates the CRC 32 value for a buffer */
+unsigned long calculate_crc32(char *buffer, int buffer_size){
+	register unsigned long crc;
+	int this_char;
+	int current_index;
+
+	crc=0xFFFFFFFF;
+
+	for(current_index=0;current_index<buffer_size;current_index++){
+		this_char=(int)buffer[current_index];
+		crc=((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc ^ this_char) & 0xFF];
+	        }
+
+	return (crc ^ 0xFFFFFFFF);
+        }
+
+
+/* fill a buffer with semi-random data */
+void randomize_buffer(char *buffer,int buffer_size){
+	FILE *fp;
+	int x;
+	int seed;
+
+	/**** FILL BUFFER WITH RANDOM ALPHA-NUMERIC CHARACTERS ****/
+
+	/***************************************************************
+	   Only use alpha-numeric characters becase plugins usually
+	   only generate numbers and letters in their output.  We
+	   want the buffer to contain the same set of characters as
+	   plugins, so its harder to distinguish where the real output
+	   ends and the rest of the buffer (padded randomly) starts.
+	***************************************************************/
+
+	/* try to get seed value from /dev/urandom, as its a better source of entropy */
+	fp=fopen("/dev/urandom","r");
+	if(fp!=NULL){
+		seed=fgetc(fp);
+		fclose(fp);
+	        }
+
+	/* else fallback to using the current time as the seed */
+	else
+		seed=(int)time(NULL);
+
+	srand(seed);
+	for(x=0;x<buffer_size;x++)
+		buffer[x]=(int)'0'+(int)(72.0*rand()/(RAND_MAX+1.0));
+
+	return;
+        }
+
 
 /* opens a connection to a remote host/tcp port */
 int my_tcp_connect(char *host_name,int port,int *sd){
@@ -313,3 +389,6 @@ void display_license(void){
 
 	return;
         }
+
+
+

+ 13 - 2
src/utils.h

@@ -3,9 +3,9 @@
  * UTILS.H - NRPE Utilities Include File
  *
  * License: GPL
- * Copyright (c) 1999-2002 Ethan Galstad (nagios@nagios.org)
+ * Copyright (c) 1999-2003 Ethan Galstad (nagios@nagios.org)
  *
- * Last Modified: 07-09-2002
+ * Last Modified: 01-28-2003
  *
  * Description:
  *
@@ -29,8 +29,17 @@
  *
  ************************************************************************************************/
 
+#ifndef _UTILS_H
+#define _UTILS_H
+
 #include "../common/config.h"
 
+
+void generate_crc32_table(void);
+unsigned long calculate_crc32(char *, int);
+
+void randomize_buffer(char *,int);
+
 int my_tcp_connect(char *,int,int *);
 int my_connect(char *,int,int *,char *);
 
@@ -43,6 +52,8 @@ int recvall(int,char *,int *,int);
 
 void display_license(void);
 
+#endif
+