Quellcode durchsuchen

Initial support for command arguments (no native encryption yet)

Ethan Galstad vor 23 Jahren
Ursprung
Commit
1edf746ccc
11 geänderte Dateien mit 964 neuen und 150 gelöschten Zeilen
  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
+