diffstat for nagios-nrpe-2.13 nagios-nrpe-2.15 Changelog | 12 Makefile.in | 9 README.Solaris | 18 SECURITY | 26 configure | 218 - configure.in | 167 contrib/nrpe_check_control.c | 242 - debian/changelog | 109 debian/control | 5 debian/patches/00list | 1 debian/patches/01_nodevrandom-and-docoptions.dpatch | 70 debian/patches/04_weird_output.dpatch | 27 debian/patches/05_pid_privileges.dpatch | 41 debian/patches/08_CVE-2013-1362.dpatch | 26 debian/patches/09_noremove_pid.dpatch | 43 debian/rules | 7 include/acl.h | 13 include/common.h | 176 include/config.h.in | 2 include/dh.h | 12 include/nrpe.h | 130 include/utils.h | 125 nrpe.spec | 180 nrpe.spec.in | 252 + package/solaris/Makefile.in | 81 package/solaris/pkg/i.config | 58 package/solaris/pkg/nrpe | 32 package/solaris/pkg/nrpe.xml | 131 package/solaris/pkg/postinstall | 5 package/solaris/pkg/preinstall | 35 package/solaris/pkg/r.config | 33 sample-config/nrpe.cfg.in | 18 src/Makefile.in | 15 src/acl.c | 196 src/check_nrpe.c | 952 ++-- src/nrpe.c | 4074 ++++++++++---------- src/snprintf.c | 2904 +++++++------- src/utils.c | 830 +--- subst.in | 84 update-version | 32 40 files changed, 6444 insertions(+), 4947 deletions(-) diff -Nru nagios-nrpe-2.13/Changelog nagios-nrpe-2.15/Changelog --- nagios-nrpe-2.13/Changelog 2011-11-11 18:32:58.000000000 +0000 +++ nagios-nrpe-2.15/Changelog 2013-09-06 15:27:13.000000000 +0000 @@ -2,6 +2,18 @@ NRPE Changelog ************** +2.15 - 09/06/2013 +----------------- +- Now compiles on HP-UX (Grant Byers) +- Added support for IPv6 (Leo Baltus, Eric Stanley) + +2.14 - 12/21/2012 +----------------- +- Added configure option to allow bash command substitutions, disabled by default [bug #400] (Eric Stanley) +- Patched to shutdown SSL connection completely (Jari Takkala) +- Added SRC support on AIX (Thierry Bertaud) +- Updated RPM SPEC file to support creating RPMs on AIX (Eric Stanley) +- Updated logging to support compiling on AIX (Eric Stanley) 2.13 - 11/11/2011 ----------------- diff -Nru nagios-nrpe-2.13/Makefile.in nagios-nrpe-2.15/Makefile.in --- nagios-nrpe-2.13/Makefile.in 2007-03-14 15:30:10.000000000 +0000 +++ nagios-nrpe-2.15/Makefile.in 2013-09-06 15:27:13.000000000 +0000 @@ -62,13 +62,22 @@ $(INSTALL) -m 775 $(NAGIOS_INSTALL_OPTS) -d $(DESTDIR)$(CFGDIR) $(INSTALL) -m 644 $(NRPE_INSTALL_OPTS) sample-config/nrpe.cfg $(DESTDIR)$(CFGDIR) +solaris-package: + @if [ `uname -s` != "SunOS" ] ; then \ + echo "It is recommended you be running on Solaris to build a Solaris package"; \ + else \ + cd package/solaris; $(MAKE) build ; $(MAKE) pkg ; cd ../..; \ + fi + clean: cd $(SRC_BASE); $(MAKE) $@ ; cd .. + cd package/solaris; $(MAKE) $@ ; cd ../.. rm -f core rm -f *~ */*~ distclean: clean cd $(SRC_BASE); $(MAKE) $@ ; cd .. + cd package/solaris; $(MAKE) $@ ; cd ../.. rm -f config.log config.status config.cache nrpe.cfg nrpe.xinetd subst $(SRC_INCLUDE)/config.h init-script init-script.debian init-script.freebsd init-script.suse rm -f sample-config/*.cfg sample-config/*.xinetd rm -f Makefile diff -Nru nagios-nrpe-2.13/README.Solaris nagios-nrpe-2.15/README.Solaris --- nagios-nrpe-2.13/README.Solaris 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/README.Solaris 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,18 @@ +Compiling on Solaris + +Several changes may be necessary in order to compile NRPE on Solaris. +This information is known to apply to Solaris 10 and may apply to other +verisions of Solaris. This has been tested on Solaris 10 x86. + +There are three things that you may need to compile NRPE on Solaris: + + 1. Add /usr/sfw/bin to your path + $ PATH="$PATH:/usr/sfw/bin" + 2. Specify the binary to be used for make-ing + $ MAKE=gmake ./configure + 3. Use gmake to build the code + $ gmake all + +Thanks to Kevin Pendleton at UtahSysAdmin.com +(http://www.utahsysadmin.com/2008/03/14/configuring-nagios-plugins-nrpe-on-solaris-10/) +for the instructions on finding the SSL libraries. diff -Nru nagios-nrpe-2.13/SECURITY nagios-nrpe-2.15/SECURITY --- nagios-nrpe-2.13/SECURITY 2007-03-09 18:08:58.000000000 +0000 +++ nagios-nrpe-2.15/SECURITY 2013-09-06 15:27:13.000000000 +0000 @@ -27,6 +27,17 @@ it if you know what you're doing! +BASH COMMAND SUBSTITUTION +------------------------- + +Even with the metacharacter restrictions below, if command arguments +are enabled, it is still possible to send bash command substitions +in the form $(...) as an agrument. This is explicity disabled by +default, but can be enabled by a configure-time option and a +configuration file option. Enabling this option is VERY RISKY and +its use is HIGHLY DISCOURAGED. + + ENABLING ARGUMENTS ------------------ @@ -40,6 +51,21 @@ file to 1. +ENABLING BASH COMMAND SUBSTITUTION +---------------------------------- + +To enable support for arguments containing bash command substitions, +you must do two things: + + 1. Enable arguments as described above + + 2. Include the --enable-bash-command-substitution configure + option when running the configure script + + 3. Set the 'allow_bash_command_substitutions' directive in the + NRPE config file to 1. + + ILLEGAL METACHARS ----------------- diff -Nru nagios-nrpe-2.13/configure nagios-nrpe-2.15/configure --- nagios-nrpe-2.13/configure 2011-11-11 18:45:49.000000000 +0000 +++ nagios-nrpe-2.15/configure 2013-09-06 15:27:13.000000000 +0000 @@ -1,6 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59. +# Generated by GNU Autoconf 2.59 for nrpe 2.15. +# +# Report bugs to . # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation @@ -265,11 +267,11 @@ : ${ac_max_here_lines=38} # Identity of this package. -PACKAGE_NAME= -PACKAGE_TARNAME= -PACKAGE_VERSION= -PACKAGE_STRING= -PACKAGE_BUGREPORT= +PACKAGE_NAME='nrpe' +PACKAGE_TARNAME='nrpe' +PACKAGE_VERSION='2.15' +PACKAGE_STRING='nrpe 2.15' +PACKAGE_BUGREPORT='nagios-users@lists.sourceforge.net' ac_unique_file="src/nrpe.c" ac_default_prefix=/usr/local/nagios @@ -310,7 +312,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA INSTALL build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT SET_MAKE CPP EGREP SNPRINTF_O OTHERLIBS SOCKETLIBS LIBWRAPLIBS HAVE_SSL log_facility nrpe_user nrpe_group NRPE_INSTALL_OPTS nrpe_port nagios_user nagios_group NAGIOS_INSTALL_OPTS PERL LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PKG_NAME PKG_VERSION PKG_HOME_URL PKG_REL_DATE RPM_RELEASE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA INSTALL build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT SET_MAKE CPP EGREP SNPRINTF_O OTHERLIBS SOCKETLIBS LIBWRAPLIBS HAVE_SSL log_facility nrpe_user nrpe_group NRPE_INSTALL_OPTS nrpe_port nagios_user nagios_group NAGIOS_INSTALL_OPTS TARGET_VER TARGET_OS TARGET_ARCH TARGET_PLATFORM PERL LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -779,7 +781,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures this package to adapt to many kinds of systems. +\`configure' configures nrpe 2.15 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -839,28 +841,41 @@ fi if test -n "$ac_init_help"; then - + case $ac_init_help in + short | recursive ) echo "Configuration of nrpe 2.15:";; + esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] ---enable-ssl enables native SSL support ---enable-command-args allows clients to specify command arguments. *** THIS IS A SECURITY RISK! *** Read the SECURITY file before using this option! + --enable-ssl enables native SSL support + --enable-command-args allows clients to specify command arguments. *** + THIS IS A SECURITY RISK! *** Read the SECURITY file + before using this option! + --enable-bash-command-substitution + allows clients to pass bash command substitutions of + the form $(command). *** THIS IS A HIGH SECURITY + RISK! *** Read the SECURITY file before using this + option! Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) ---with-ssl=DIR sets location of the SSL installation ---with-ssl-inc=DIR sets location of the SSL include files ---with-ssl-lib=DIR sets location of the SSL libraries ---with-kerberos-inc=DIR sets location of the Kerberos include files ---with-log-facility= sets NRPE syslog facility ---with-nrpe-user= sets user name to run NRPE ---with-nrpe-group= sets group name to run NRPE ---with-nrpe-port= sets port number for NRPE to listen on ---with-nagios-user= sets user name for file permissions ---with-nagios-group= sets group name file permissions + --with-ssl=DIR sets location of the SSL installation + --with-ssl-inc=DIR sets location of the SSL include files + --with-ssl-lib=DIR sets location of the SSL libraries + --with-kerberos-inc=DIR sets location of the Kerberos include files + --with-log-facility= + sets NRPE syslog facility + --with-nrpe-user= sets user name to run NRPE + --with-nrpe-group= + sets group name to run NRPE + --with-nrpe-port= sets port number for NRPE to listen on + --with-nagios-user= + sets user name for file permissions + --with-nagios-group= + sets group name file permissions Some influential environment variables: CC C compiler command @@ -874,6 +889,7 @@ Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. +Report bugs to . _ACEOF fi @@ -969,6 +985,8 @@ test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF +nrpe configure 2.15 +generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation @@ -981,7 +999,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by $as_me, which was +It was created by nrpe $as_me 2.15, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -1293,14 +1311,31 @@ + + + + + + + + + ac_config_headers="$ac_config_headers include/config.h" + ac_config_files="$ac_config_files Makefile subst src/Makefile package/solaris/Makefile init-script init-script.debian init-script.suse nrpe.spec sample-config/nrpe.cfg sample-config/nrpe.xinetd" + PKG_NAME=nrpe -PKG_VERSION="2.13" +PKG_VERSION="2.15" PKG_HOME_URL="http://www.nagios.org/" -PKG_REL_DATE="11-11-2011" +PKG_REL_DATE="09-06-2013" +RPM_RELEASE=1 + + + + + ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do @@ -3194,9 +3229,9 @@ echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX -## ------------------------------------------ ## -## Report this to the AC_PACKAGE_NAME lists. ## -## ------------------------------------------ ## +## ------------------------------------------------- ## +## Report this to nagios-users@lists.sourceforge.net ## +## ------------------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 @@ -5163,25 +5198,29 @@ if test "$ac_cv_type_u_int32_t" = no ; then if test "$ac_cv_type_u_int32_t" = yes ; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define U_INT32_T_IS_UINT32_T 1 _ACEOF else if test "$ac_cv_sizeof_int" = 4 ; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define U_INT32_T_IS_UINT 1 _ACEOF else if test "$ac_cv_sizeof_long" = 4 ; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define U_INT32_T_IS_ULONG 1 _ACEOF else if test "$ac_cv_sizeof_short" = 4 ; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define U_INT32_T_IS_USHORT 1 _ACEOF @@ -5259,19 +5298,22 @@ if test "$ac_cv_type_int32_t" = no ; then if test "$ac_cv_sizeof_int" = 4 ; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define INT32_T_IS_UINT 1 _ACEOF else if test "$ac_cv_sizeof_long" = 4 ; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define INT32_T_IS_ULONG 1 _ACEOF else if test "$ac_cv_sizeof_short" = 4 ; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define INT32_T_IS_USHORT 1 _ACEOF @@ -6234,7 +6276,8 @@ if test $ac_cv_lib_wrap_main = yes; then LIBWRAPLIBS="$LIBWRAPLIBS -lwrap" - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define HAVE_LIBWRAP 1 _ACEOF @@ -6545,7 +6588,8 @@ ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define SOCKET_SIZE_TYPE size_t _ACEOF echo "$as_me:$LINENO: result: size_t" >&5 @@ -6554,6 +6598,7 @@ echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 + cat >>confdefs.h <<\_ACEOF #define SOCKET_SIZE_TYPE int _ACEOF @@ -6594,40 +6639,32 @@ # Check whether --with-ssl or --without-ssl was given. if test "${with_ssl+set}" = set; then withval="$with_ssl" - - ssl_dir=$withval - + ssl_dir=$withval fi; # Check whether --with-ssl-inc or --without-ssl-inc was given. if test "${with_ssl_inc+set}" = set; then withval="$with_ssl_inc" - - ssl_inc_dir=$withval - + ssl_inc_dir=$withval fi; # Check whether --with-ssl-lib or --without-ssl-lib was given. if test "${with_ssl_lib+set}" = set; then withval="$with_ssl_lib" - - ssl_lib_dir=$withval - + ssl_lib_dir=$withval fi; # Check whether --with-kerberos-inc or --without-kerberos-inc was given. if test "${with_kerberos_inc+set}" = set; then withval="$with_kerberos_inc" - - kerberos_inc_dir=$withval - + kerberos_inc_dir=$withval fi; if test x$check_for_ssl = xyes; then echo "$as_me:$LINENO: checking for SSL headers" >&5 echo $ECHO_N "checking for SSL headers... $ECHO_C" >&6 found_ssl=no - for dir in $ssl_inc_dir $ssl_dir /usr/local/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr /usr/freeware/lib/openssl; do + for dir in $ssl_inc_dir $ssl_dir /usr/local/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr /usr/freeware/lib/openssl /usr/sfw/include; do ssldir="$dir" if test -f "$dir/include/openssl/ssl.h"; then found_ssl=yes @@ -6668,9 +6705,16 @@ echo "$as_me:$LINENO: checking for SSL libraries" >&5 echo $ECHO_N "checking for SSL libraries... $ECHO_C" >&6 found_ssl=no - for dir in $ssl_lib_dir $ssl_dir /usr/lib64 /usr/lib /usr/local/lib /usr/lib/ssl /usr/ssl/lib /usr/openssl/lib /usr/pkg/lib /usr/freeware/lib/openssl; do + for dir in $ssl_lib_dir $ssl_dir /usr/lib64 /usr/lib /usr/local/lib /usr/lib/ssl /usr/ssl/lib /usr/openssl/lib /usr/pkg/lib /usr/freeware/lib/openssl /usr/sfw/lib /opt/freeware/lib; do ssllibdir="$dir" - if test -f "$dir/libssl.so"; then + if test "`uname -s`" = "Darwin" ; then + soext="dylib" + elif test "`uname -s`" = "HP-UX" ; then + soext="sl" + else + soext="so" + fi + if test -f "$dir/libssl.$soext"; then found_ssl=yes break fi @@ -6686,7 +6730,8 @@ LDFLAGS="$LDFLAGS -L$ssllibdir"; LIBS="$LIBS -lssl -lcrypto"; - cat >>confdefs.h <<_ACEOF + +cat >>confdefs.h <<_ACEOF #define HAVE_SSL 1 _ACEOF @@ -6712,7 +6757,8 @@ if test -f "$dir/krb5.h"; then found_kerberos=yes CFLAGS="$CFLAGS -I$kerbdir" - cat >>confdefs.h <<_ACEOF + +cat >>confdefs.h <<_ACEOF #define HAVE_KRB5_H 1 _ACEOF @@ -6738,6 +6784,7 @@ log_facility=daemon fi; + cat >>confdefs.h <<_ACEOF #define NRPE_LOG_FACILITY "$log_facility" _ACEOF @@ -6752,6 +6799,7 @@ nrpe_user=nagios fi; + # Check whether --with-nrpe_group or --without-nrpe_group was given. if test "${with_nrpe_group+set}" = set; then withval="$with_nrpe_group" @@ -6760,6 +6808,7 @@ nrpe_group=nagios fi; + # Check whether --with-nrpe_port or --without-nrpe_port was given. if test "${with_nrpe_port+set}" = set; then withval="$with_nrpe_port" @@ -6772,6 +6821,7 @@ NRPE_INSTALL_OPTS="-o $nrpe_user -g $nrpe_group" + cat >>confdefs.h <<_ACEOF #define DEFAULT_SERVER_PORT $nrpe_port _ACEOF @@ -6798,16 +6848,53 @@ NAGIOS_INSTALL_OPTS="-o $nagios_user -g $nagios_group" +# Determine target OS, version and architecture for package build macros +if test "x$target_ver" = "x" ; then + TARGET_VER=`uname -r` +else + TARGET_VER=$target_ver +fi + +if test "x$target_os" = "x" ; then + TARGET_OS=`uname -s` +else + TARGET_OS=$target_os +fi + +if test "x$target_cpu" = "x" ; then + TARGET_ARCH=`uname -p` +else + TARGET_ARCH=$target_cpu +fi + +TARGET_PLATFORM="" +if test "x$TARGET_OS" = "xSunOS" ; then + if test "x$TARGET_VER" = "x5.10" ; then + TARGET_PLATFORM="sol10" + fi +fi + # 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 <<_ACEOF + +cat >>confdefs.h <<_ACEOF #define ENABLE_COMMAND_ARGUMENTS 1 _ACEOF fi; +# Check whether --enable-bash-command-substitution or --disable-bash-command-substitution was given. +if test "${enable_bash_command_substitution+set}" = set; then + enableval="$enable_bash_command_substitution" + +cat >>confdefs.h <<_ACEOF +#define ENABLE_BASH_COMMAND_SUBSTITUTION 1 +_ACEOF + +fi; + # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 @@ -6848,7 +6935,6 @@ echo "${ECHO_T}no" >&6 fi - ac_config_files="$ac_config_files Makefile src/Makefile subst" test "x$prefix" = xNONE && prefix=$ac_default_prefix @@ -7158,7 +7244,7 @@ } >&5 cat >&5 <<_CSEOF -This file was extended by $as_me, which was +This file was extended by nrpe $as_me 2.15, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7218,7 +7304,7 @@ cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -config.status +nrpe config.status 2.15 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" @@ -7322,8 +7408,15 @@ case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "subst" ) CONFIG_FILES="$CONFIG_FILES subst" ;; + "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "package/solaris/Makefile" ) CONFIG_FILES="$CONFIG_FILES package/solaris/Makefile" ;; + "init-script" ) CONFIG_FILES="$CONFIG_FILES init-script" ;; + "init-script.debian" ) CONFIG_FILES="$CONFIG_FILES init-script.debian" ;; + "init-script.suse" ) CONFIG_FILES="$CONFIG_FILES init-script.suse" ;; + "nrpe.spec" ) CONFIG_FILES="$CONFIG_FILES nrpe.spec" ;; + "sample-config/nrpe.cfg" ) CONFIG_FILES="$CONFIG_FILES sample-config/nrpe.cfg" ;; + "sample-config/nrpe.xinetd" ) CONFIG_FILES="$CONFIG_FILES sample-config/nrpe.xinetd" ;; "include/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -7409,6 +7502,11 @@ s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t +s,@PKG_NAME@,$PKG_NAME,;t t +s,@PKG_VERSION@,$PKG_VERSION,;t t +s,@PKG_HOME_URL@,$PKG_HOME_URL,;t t +s,@PKG_REL_DATE@,$PKG_REL_DATE,;t t +s,@RPM_RELEASE@,$RPM_RELEASE,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t @@ -7444,6 +7542,10 @@ s,@nagios_user@,$nagios_user,;t t s,@nagios_group@,$nagios_group,;t t s,@NAGIOS_INSTALL_OPTS@,$NAGIOS_INSTALL_OPTS,;t t +s,@TARGET_VER@,$TARGET_VER,;t t +s,@TARGET_OS@,$TARGET_OS,;t t +s,@TARGET_ARCH@,$TARGET_ARCH,;t t +s,@TARGET_PLATFORM@,$TARGET_PLATFORM,;t t s,@PERL@,$PERL,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t diff -Nru nagios-nrpe-2.13/configure.in nagios-nrpe-2.15/configure.in --- nagios-nrpe-2.13/configure.in 2011-11-11 18:45:49.000000000 +0000 +++ nagios-nrpe-2.15/configure.in 2013-09-06 15:27:13.000000000 +0000 @@ -4,14 +4,31 @@ define([AC_CACHE_LOAD],) define([AC_CACHE_SAVE],) -AC_INIT(src/nrpe.c) -AC_CONFIG_HEADER(include/config.h) +AC_INIT([nrpe],[2.15],[nagios-users@lists.sourceforge.net],[nrpe],[http://www.nagios.org]) +AC_CONFIG_SRCDIR([src/nrpe.c]) +AC_CONFIG_HEADERS([include/config.h]) +AC_CONFIG_FILES([Makefile + subst + src/Makefile + package/solaris/Makefile + init-script + init-script.debian + init-script.suse + nrpe.spec + sample-config/nrpe.cfg + sample-config/nrpe.xinetd]) AC_PREFIX_DEFAULT(/usr/local/nagios) PKG_NAME=nrpe -PKG_VERSION="2.13" +PKG_VERSION="2.15" PKG_HOME_URL="http://www.nagios.org/" -PKG_REL_DATE="11-11-2011" +PKG_REL_DATE="09-06-2013" +RPM_RELEASE=1 +AC_SUBST(PKG_NAME) +AC_SUBST(PKG_VERSION) +AC_SUBST(PKG_HOME_URL) +AC_SUBST(PKG_REL_DATE) +AC_SUBST(RPM_RELEASE) dnl Figure out how to invoke "install" and what install options to use. AC_PROG_INSTALL @@ -49,16 +66,16 @@ AC_CHECK_TYPE(u_int32_t,unsigned int) if test "$ac_cv_type_u_int32_t" = no ; then if test "$ac_cv_type_u_int32_t" = yes ; then - AC_DEFINE(U_INT32_T_IS_UINT32_T) + AC_DEFINE(U_INT32_T_IS_UINT32_T,[1],[u_int32_t is uint32_t]) else if test "$ac_cv_sizeof_int" = 4 ; then - AC_DEFINE(U_INT32_T_IS_UINT) + AC_DEFINE(U_INT32_T_IS_UINT,[1],[u_int32_t is uint]) else if test "$ac_cv_sizeof_long" = 4 ; then - AC_DEFINE(U_INT32_T_IS_ULONG) + AC_DEFINE(U_INT32_T_IS_ULONG,[1],[u_int32_t is ulong]) else if test "$ac_cv_sizeof_short" = 4 ; then - AC_DEFINE(U_INT32_T_IS_USHORT) + AC_DEFINE(U_INT32_T_IS_USHORT,[1],[u_int32_t is ushort]) fi fi fi @@ -69,13 +86,13 @@ AC_CHECK_TYPE(int32_t,int) if test "$ac_cv_type_int32_t" = no ; then if test "$ac_cv_sizeof_int" = 4 ; then - AC_DEFINE(INT32_T_IS_UINT) + AC_DEFINE(INT32_T_IS_UINT,[1],[int32_t is uint]) else if test "$ac_cv_sizeof_long" = 4 ; then - AC_DEFINE(INT32_T_IS_ULONG) + AC_DEFINE(INT32_T_IS_ULONG,[1],[int32_t is ulong]) else if test "$ac_cv_sizeof_short" = 4 ; then - AC_DEFINE(INT32_T_IS_USHORT) + AC_DEFINE(INT32_T_IS_USHORT,[1],[int32_t is ushort]) fi fi fi @@ -149,7 +166,7 @@ AC_SUBST(SOCKETLIBS) AC_CHECK_LIB(wrap,main,[ LIBWRAPLIBS="$LIBWRAPLIBS -lwrap" - AC_DEFINE(HAVE_LIBWRAP) + AC_DEFINE(HAVE_LIBWRAP,[1],[Have the TCP wrappers library]) ]) AC_SUBST(LIBWRAPLIBS) AC_CHECK_FUNCS(strdup strstr strtoul initgroups closesocket) @@ -200,8 +217,8 @@ #include ], [int a = send(1, (const void *)0, (size_t *) 0, (int *) 0);], -[AC_DEFINE(SOCKET_SIZE_TYPE, size_t) AC_MSG_RESULT(size_t)], -[AC_DEFINE(SOCKET_SIZE_TYPE, int) AC_MSG_RESULT(int)]) +[AC_DEFINE(SOCKET_SIZE_TYPE, size_t, [Socket Size Type]) AC_MSG_RESULT(size_t)], +[AC_DEFINE(SOCKET_SIZE_TYPE, int, [Socket Size Type]) AC_MSG_RESULT(int)]) dnl Stolen from Python code: loewis@users.sourceforge.net #AC_CHECK_TYPE(socklen_t,int, @@ -216,7 +233,8 @@ # ]) dnl Does user want to check for SSL? -AC_ARG_ENABLE(ssl,--enable-ssl enables native SSL support,[ +AC_ARG_ENABLE([ssl], + AS_HELP_STRING([--enable-ssl],[enables native SSL support]),[ if test x$enableval = xyes; then check_for_ssl=yes else @@ -228,25 +246,27 @@ ssl_dir= ssl_inc_dir= ssl_lib_dir= -AC_ARG_WITH(ssl,--with-ssl=DIR sets location of the SSL installation,[ - ssl_dir=$withval - ]) -AC_ARG_WITH(ssl-inc,--with-ssl-inc=DIR sets location of the SSL include files,[ - ssl_inc_dir=$withval - ]) -AC_ARG_WITH(ssl-lib,--with-ssl-lib=DIR sets location of the SSL libraries,[ - ssl_lib_dir=$withval - ]) -AC_ARG_WITH(kerberos-inc,--with-kerberos-inc=DIR sets location of the Kerberos include files,[ - kerberos_inc_dir=$withval - ]) +AC_ARG_WITH([ssl], + AS_HELP_STRING([--with-ssl=DIR],[sets location of the SSL installation]), + [ssl_dir=$withval]) +AC_ARG_WITH([ssl-inc], + AS_HELP_STRING([--with-ssl-inc=DIR], + [sets location of the SSL include files]), + [ ssl_inc_dir=$withval]) +AC_ARG_WITH([ssl-lib], + AS_HELP_STRING([--with-ssl-lib=DIR],[sets location of the SSL libraries]), + [ssl_lib_dir=$withval]) +AC_ARG_WITH([kerberos-inc], + AS_HELP_STRING([--with-kerberos-inc=DIR], + [sets location of the Kerberos include files]), + [kerberos_inc_dir=$withval]) dnl Check for SSL support dnl Modified version of Mark Ethan Trostler's macro if test x$check_for_ssl = xyes; then AC_MSG_CHECKING(for SSL headers) found_ssl=no - for dir in $ssl_inc_dir $ssl_dir /usr/local/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr /usr/freeware/lib/openssl; do + for dir in $ssl_inc_dir $ssl_dir /usr/local/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr /usr/freeware/lib/openssl /usr/sfw/include; do ssldir="$dir" if test -f "$dir/include/openssl/ssl.h"; then found_ssl=yes @@ -285,9 +305,16 @@ dnl Now try and find SSL libraries AC_MSG_CHECKING(for SSL libraries) found_ssl=no - for dir in $ssl_lib_dir $ssl_dir /usr/lib64 /usr/lib /usr/local/lib /usr/lib/ssl /usr/ssl/lib /usr/openssl/lib /usr/pkg/lib /usr/freeware/lib/openssl; do + for dir in $ssl_lib_dir $ssl_dir /usr/lib64 /usr/lib /usr/local/lib /usr/lib/ssl /usr/ssl/lib /usr/openssl/lib /usr/pkg/lib /usr/freeware/lib/openssl /usr/sfw/lib /opt/freeware/lib; do ssllibdir="$dir" - if test -f "$dir/libssl.so"; then + if test "`uname -s`" = "Darwin" ; then + soext="dylib" + elif test "`uname -s`" = "HP-UX" ; then + soext="sl" + else + soext="so" + fi + if test -f "$dir/libssl.$soext"; then found_ssl=yes break fi @@ -301,7 +328,7 @@ LDFLAGS="$LDFLAGS -L$ssllibdir"; LIBS="$LIBS -lssl -lcrypto"; - AC_DEFINE_UNQUOTED(HAVE_SSL) + AC_DEFINE_UNQUOTED(HAVE_SSL,[1],[Have SSL support]) AC_SUBST(HAVE_SSL) dnl Generate DH parameters @@ -325,7 +352,7 @@ if test -f "$dir/krb5.h"; then found_kerberos=yes CFLAGS="$CFLAGS -I$kerbdir" - AC_DEFINE_UNQUOTED(HAVE_KRB5_H) + AC_DEFINE_UNQUOTED(HAVE_KRB5_H,[1],[Have the krb5.h header file]) dnl AC_CHECK_HEADERS(krb5.h) break fi @@ -340,33 +367,89 @@ fi -AC_ARG_WITH(log_facility,--with-log-facility= sets NRPE syslog facility,log_facility=$withval,log_facility=daemon) +AC_ARG_WITH([log_facility], + AS_HELP_STRING([--with-log-facility=], + [sets NRPE syslog facility]), + [log_facility=$withval], + [log_facility=daemon]) AC_SUBST(log_facility) -AC_DEFINE_UNQUOTED(NRPE_LOG_FACILITY,["$log_facility"]) +AC_DEFINE_UNQUOTED(NRPE_LOG_FACILITY,["$log_facility"],[NRPE syslog facility]) -AC_ARG_WITH(nrpe_user,--with-nrpe-user= sets user name to run NRPE,nrpe_user=$withval,nrpe_user=nagios) -AC_ARG_WITH(nrpe_group,--with-nrpe-group= sets group name to run NRPE,nrpe_group=$withval,nrpe_group=nagios) -AC_ARG_WITH(nrpe_port,--with-nrpe-port= sets port number for NRPE to listen on,nrpe_port=$withval,nrpe_port=5666) +AC_ARG_WITH([nrpe_user], + AS_HELP_STRING([--with-nrpe-user=],[sets user name to run NRPE]), + [nrpe_user=$withval], + [nrpe_user=nagios]) + +AC_ARG_WITH([nrpe_group], + AS_HELP_STRING([--with-nrpe-group=],[sets group name to run NRPE]), + [nrpe_group=$withval], + [nrpe_group=nagios]) + +AC_ARG_WITH([nrpe_port], + AS_HELP_STRING([--with-nrpe-port=], + [sets port number for NRPE to listen on]), + [nrpe_port=$withval], + [nrpe_port=5666]) AC_SUBST(nrpe_user) AC_SUBST(nrpe_group) NRPE_INSTALL_OPTS="-o $nrpe_user -g $nrpe_group" AC_SUBST(NRPE_INSTALL_OPTS) AC_SUBST(nrpe_port) -AC_DEFINE_UNQUOTED(DEFAULT_SERVER_PORT,$nrpe_port) +AC_DEFINE_UNQUOTED(DEFAULT_SERVER_PORT,$nrpe_port,[Default port for NRPE daemon]) -AC_ARG_WITH(nagios_user,--with-nagios-user= sets user name for file permissions,nagios_user=$withval,nagios_user=nagios) -AC_ARG_WITH(nagios_group,--with-nagios-group= sets group name file permissions,nagios_group=$withval,nagios_group=nagios) +AC_ARG_WITH([nagios_user], + AS_HELP_STRING([--with-nagios-user=], + [sets user name for file permissions]), + [nagios_user=$withval], + [nagios_user=nagios]) +AC_ARG_WITH([nagios_group], + AS_HELP_STRING([--with-nagios-group=], + [sets group name file permissions]), + [nagios_group=$withval], + [nagios_group=nagios]) AC_SUBST(nagios_user) AC_SUBST(nagios_group) NAGIOS_INSTALL_OPTS="-o $nagios_user -g $nagios_group" AC_SUBST(NAGIOS_INSTALL_OPTS) +# Determine target OS, version and architecture for package build macros +if test "x$target_ver" = "x" ; then + TARGET_VER=`uname -r` +else + TARGET_VER=$target_ver +fi +AC_SUBST(TARGET_VER) +if test "x$target_os" = "x" ; then + TARGET_OS=`uname -s` +else + TARGET_OS=$target_os +fi +AC_SUBST(TARGET_OS) +if test "x$target_cpu" = "x" ; then + TARGET_ARCH=`uname -p` +else + TARGET_ARCH=$target_cpu +fi +AC_SUBST(TARGET_ARCH) +TARGET_PLATFORM="" +if test "x$TARGET_OS" = "xSunOS" ; then + if test "x$TARGET_VER" = "x5.10" ; then + TARGET_PLATFORM="sol10" + fi +fi +AC_SUBST(TARGET_PLATFORM) -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_ARG_ENABLE([command-args], + AS_HELP_STRING([--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,[1],[Enable command-line arguments])) + +AC_ARG_ENABLE([bash-command-substitution], + AS_HELP_STRING([--enable-bash-command-substitution],[allows clients to pass bash command substitutions of the form $(command). *** THIS IS A HIGH SECURITY RISK! *** Read the SECURITY file before using this option!]), + AC_DEFINE_UNQUOTED(ENABLE_BASH_COMMAND_SUBSTITUTION,[1],[Enable bash command substitution])) AC_PATH_PROG(PERL,perl) -AC_OUTPUT(Makefile src/Makefile subst) +AC_OUTPUT() perl subst init-script perl subst init-script.debian diff -Nru nagios-nrpe-2.13/contrib/nrpe_check_control.c nagios-nrpe-2.15/contrib/nrpe_check_control.c --- nagios-nrpe-2.13/contrib/nrpe_check_control.c 2002-02-22 01:15:34.000000000 +0000 +++ nagios-nrpe-2.15/contrib/nrpe_check_control.c 2013-09-06 15:27:13.000000000 +0000 @@ -1,121 +1,121 @@ -#include -#include -#include - -#define MAX_CHARS 1024 -#define SERVICE_COUNT 12 - -#define COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd" -#define SERVICES_FILE "/usr/local/nagios/etc/services.cfg" - -int main(int argc, char *argv[]) -{ - char check_name[MAX_CHARS]; - char ent_type[MAX_CHARS]; - char input_buffer[MAX_CHARS]; - char host_name[MAX_CHARS]; - char service_name[MAX_CHARS]; - char state[MAX_CHARS]; - char state_type[MAX_CHARS]; - char temp_input[MAX_CHARS]; - char temp_string[MAX_CHARS]; - char test_host[MAX_CHARS]; - - char *temp_var; - - FILE *command_fp; - FILE *services_fp; - - int attempt; - int i; - - time_t current_time; - - strcpy(state,argv[1]); - strcpy(state_type,argv[2]); - attempt=atoi(argv[3]); - strcpy(host_name,argv[4]); - - if(strcmp(state,"OK") == 0) - { - services_fp=fopen(SERVICES_FILE,"r"); - command_fp=fopen(COMMAND_FILE,"a"); - while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL) - { - if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r') - { - continue; - } - else - { - strcpy(temp_input,input_buffer); - strcpy(temp_string,strtok(temp_input,"=")); - strcpy(ent_type,strtok(temp_string,"[")); - if(strcmp(ent_type,"service") == 0) - { - strcpy(test_host,strtok(NULL,"]")); - if(strcmp(test_host,host_name) == 0) - { - temp_var=strtok(input_buffer,"="); - strcpy(service_name,strtok(NULL,";")); - for(i=1;i<=SERVICE_COUNT;i++) - { - temp_var=strtok(NULL,";"); - } - strcpy(check_name,strtok(temp_var,"!")); - if(strcmp(check_name,"check_nrpe") == 0) - { - time(¤t_time); - fprintf(command_fp,"[%lu] ENABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name); - } - } - } - } - } - fclose(command_fp); - fclose(services_fp); - } - else if(strcmp(state,"CRITICAL") == 0) - { - if(attempt == 3) - { - services_fp=fopen(SERVICES_FILE,"r"); - command_fp=fopen(COMMAND_FILE,"a"); - while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL) - { - if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r') - { - continue; - } - else - { - strcpy(temp_input,input_buffer); - strcpy(temp_string,strtok(temp_input,"=")); - strcpy(ent_type,strtok(temp_string,"[")); - if(strcmp(ent_type,"service") == 0) - { - strcpy(test_host,strtok(NULL,"]")); - if(strcmp(test_host,host_name) == 0) - { - temp_var=strtok(input_buffer,"="); - strcpy(service_name,strtok(NULL,";")); - for(i=1;i<=SERVICE_COUNT;i++) - { - temp_var=strtok(NULL,";"); - } - strcpy(check_name,strtok(temp_var,"!")); - if(strcmp(check_name,"check_nrpe") == 0) - { - time(¤t_time); - fprintf(command_fp,"[%lu] DISABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name); - } - } - } - } - } - fclose(command_fp); - fclose(services_fp); - } - } - return 0; -} +#include +#include +#include + +#define MAX_CHARS 1024 +#define SERVICE_COUNT 12 + +#define COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd" +#define SERVICES_FILE "/usr/local/nagios/etc/services.cfg" + +int main(int argc, char *argv[]) +{ + char check_name[MAX_CHARS]; + char ent_type[MAX_CHARS]; + char input_buffer[MAX_CHARS]; + char host_name[MAX_CHARS]; + char service_name[MAX_CHARS]; + char state[MAX_CHARS]; + char state_type[MAX_CHARS]; + char temp_input[MAX_CHARS]; + char temp_string[MAX_CHARS]; + char test_host[MAX_CHARS]; + + char *temp_var; + + FILE *command_fp; + FILE *services_fp; + + int attempt; + int i; + + time_t current_time; + + strcpy(state,argv[1]); + strcpy(state_type,argv[2]); + attempt=atoi(argv[3]); + strcpy(host_name,argv[4]); + + if(strcmp(state,"OK") == 0) + { + services_fp=fopen(SERVICES_FILE,"r"); + command_fp=fopen(COMMAND_FILE,"a"); + while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL) + { + if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r') + { + continue; + } + else + { + strcpy(temp_input,input_buffer); + strcpy(temp_string,strtok(temp_input,"=")); + strcpy(ent_type,strtok(temp_string,"[")); + if(strcmp(ent_type,"service") == 0) + { + strcpy(test_host,strtok(NULL,"]")); + if(strcmp(test_host,host_name) == 0) + { + temp_var=strtok(input_buffer,"="); + strcpy(service_name,strtok(NULL,";")); + for(i=1;i<=SERVICE_COUNT;i++) + { + temp_var=strtok(NULL,";"); + } + strcpy(check_name,strtok(temp_var,"!")); + if(strcmp(check_name,"check_nrpe") == 0) + { + time(¤t_time); + fprintf(command_fp,"[%lu] ENABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name); + } + } + } + } + } + fclose(command_fp); + fclose(services_fp); + } + else if(strcmp(state,"CRITICAL") == 0) + { + if(attempt == 3) + { + services_fp=fopen(SERVICES_FILE,"r"); + command_fp=fopen(COMMAND_FILE,"a"); + while((fgets(input_buffer,MAX_CHARS-1,services_fp)) != NULL) + { + if(input_buffer[0]=='#' || input_buffer[0]=='\x0' || input_buffer[0]=='\n' || input_buffer[0]=='\r') + { + continue; + } + else + { + strcpy(temp_input,input_buffer); + strcpy(temp_string,strtok(temp_input,"=")); + strcpy(ent_type,strtok(temp_string,"[")); + if(strcmp(ent_type,"service") == 0) + { + strcpy(test_host,strtok(NULL,"]")); + if(strcmp(test_host,host_name) == 0) + { + temp_var=strtok(input_buffer,"="); + strcpy(service_name,strtok(NULL,";")); + for(i=1;i<=SERVICE_COUNT;i++) + { + temp_var=strtok(NULL,";"); + } + strcpy(check_name,strtok(temp_var,"!")); + if(strcmp(check_name,"check_nrpe") == 0) + { + time(¤t_time); + fprintf(command_fp,"[%lu] DISABLE_SVC_CHECK;%s;%s\n",current_time,host_name,service_name); + } + } + } + } + } + fclose(command_fp); + fclose(services_fp); + } + } + return 0; +} diff -Nru nagios-nrpe-2.13/debian/changelog nagios-nrpe-2.15/debian/changelog --- nagios-nrpe-2.13/debian/changelog 2019-03-09 23:03:09.000000000 +0000 +++ nagios-nrpe-2.15/debian/changelog 2019-03-09 23:03:10.000000000 +0000 @@ -1,3 +1,25 @@ +nagios-nrpe (2.15-0ubuntu1) trusty; urgency=medium + + * New upstream release (2.15). + * Updated patches: + - 01_nodevrandom-and-docoptions.dpatch + - 04_weird_output.dpatch + - 05_pid_privileges.dpatch + - 09_noremove_pid.dpatch + * Dropped patches (upstream): + - 08_CVE-2013-1362.dpatch + + -- Stéphane Graber Mon, 13 Jan 2014 11:34:11 -0500 + +nagios-nrpe (2.13-3.1ubuntu1) trusty; urgency=low + + * Merge from Debian unstable. Remaining changes: + - debian/{rules,control}: Add hardening-includes to gain PIE security + builds. + - debian/rules: Use dpkg-buildflags. + + -- Michael Terry Tue, 29 Oct 2013 09:14:34 -0700 + nagios-nrpe (2.13-3.1) unstable; urgency=low [ Ivo De Decker ] @@ -11,6 +33,23 @@ -- Ivo De Decker Sat, 05 Oct 2013 20:23:24 +0200 +nagios-nrpe (2.13-3ubuntu2) saucy; urgency=low + + * debian/patches/09_noremove_pid.dpatch: + - Do not remove the PID file after a connection error + (original patch from Hiren Patel). (LP: #1126890) + + -- Michael Terry Fri, 24 May 2013 17:01:05 -0400 + +nagios-nrpe (2.13-3ubuntu1) saucy; urgency=low + + * Merge from Debian unstable. Remaining changes: + - debian/{rules,control}: Add hardening-includes to gain PIE security + builds. + - debian/rules: Use dpkg-buildflags. + + -- Michael Terry Tue, 30 Apr 2013 09:24:13 -0700 + nagios-nrpe (2.13-3) unstable; urgency=high * [e55afd1] Add 08_CVE-2013-1362.dpatch patch. @@ -22,6 +61,15 @@ -- Alexander Wirt Sat, 09 Mar 2013 08:42:05 +0100 +nagios-nrpe (2.13-2ubuntu1) raring; urgency=low + + * Merge from Debian unstable. Remaining changes: + - debian/{rules,control}: Add hardening-includes to gain PIE security + builds. + - debian/rules: Use dpkg-buildflags. + + -- Logan Rosen Sun, 24 Feb 2013 15:29:43 -0500 + nagios-nrpe (2.13-2) unstable; urgency=high [ Thijs Kinkhorst ] @@ -29,6 +77,15 @@ -- Alexander Wirt Mon, 11 Feb 2013 17:45:20 +0100 +nagios-nrpe (2.13-1ubuntu1) raring; urgency=low + + * Merge from Debian unstable. Remaining changes: + - debian/{rules,control}: Add hardening-includes to gain PIE security + builds. + - debian/rules: Use dpkg-buildflags. + + -- Logan Rosen Sat, 02 Feb 2013 18:16:48 -0500 + nagios-nrpe (2.13-1) unstable; urgency=low * [3e113b5] Imported Upstream version 2.13 @@ -38,6 +95,29 @@ -- Alexander Wirt Sat, 30 Jun 2012 11:08:22 +0200 +nagios-nrpe (2.12-6ubuntu2) quantal; urgency=low + + * Fixed compiler hardening configuration. (LP: #1000379) + + -- Bryan D. Payne Wed, 16 May 2012 17:29:52 +0000 + +nagios-nrpe (2.12-6ubuntu1) quantal; urgency=low + + [ Dmitrijs Ledkovs ] + * Merge with Debian; remaining changes: + - debian/{rules,control}: add hardening-includes to gain PIE + security builds. + - Use dpkg-buildflags. + * Changes gained from Debian: + - [4dc53fb] Use retry argument for start-stop-daemon when stopping nrpe + (LP: #896388) + + [ Stéphane Graber ] + * Drop useless diff file in source package (xxx) that was added by + mistake in a previous merge. + + -- Stéphane Graber Thu, 03 May 2012 09:55:10 -0400 + nagios-nrpe (2.12-6) unstable; urgency=low * [36b1062] Add add icinga to the list of recommends @@ -47,6 +127,15 @@ -- Alexander Wirt Mon, 30 Apr 2012 09:25:45 +0200 +nagios-nrpe (2.12-5ubuntu1) precise; urgency=low + + * Merge with Debian; remaining changes: + - debian/{rules,control}: add hardening-includes to gain PIE + security builds. + * Use dpkg-buildflags. + + -- Matthias Klose Tue, 18 Oct 2011 15:09:21 +0200 + nagios-nrpe (2.12-5) unstable; urgency=low [ Alexander Wirt ] @@ -71,6 +160,26 @@ -- Alexander Wirt Sun, 25 Sep 2011 08:35:48 +0200 +nagios-nrpe (2.12-4ubuntu3) oneiric; urgency=low + + * Configure with --with-ssl-lib=. LP: #829434. + + -- Matthias Klose Thu, 25 Aug 2011 21:10:45 +0200 + +nagios-nrpe (2.12-4ubuntu2) oneiric; urgency=low + + * Rebuild for OpenSSL 1.0.0. + + -- Colin Watson Tue, 17 May 2011 12:16:15 +0100 + +nagios-nrpe (2.12-4ubuntu1) lucid; urgency=low + + * debian/{rules,control}: add hardening-includes to gain PIE + security builds. + * debian/control: Update maintainer according to spec. + + -- Chuck Short Thu, 07 Jan 2010 14:31:00 -0500 + nagios-nrpe (2.12-4) unstable; urgency=low * Build against libwrap0-dev (Closes: #412705) diff -Nru nagios-nrpe-2.13/debian/control nagios-nrpe-2.15/debian/control --- nagios-nrpe-2.13/debian/control 2019-03-09 23:03:09.000000000 +0000 +++ nagios-nrpe-2.15/debian/control 2019-03-09 23:03:10.000000000 +0000 @@ -1,9 +1,10 @@ Source: nagios-nrpe Section: net Priority: optional -Maintainer: Debian Nagios Maintainer Group +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Nagios Maintainer Group Uploaders: sean finney , Jason Thomas , Alexander Wirt -Build-Depends: debhelper (>= 9), openssl, dpatch (>= 2.0.32~), libssl-dev, libwrap0-dev, autotools-dev (>= 20100122.1) +Build-Depends: debhelper (>= 9), openssl, dpatch (>= 2.0.32~), libssl-dev, libwrap0-dev, autotools-dev (>= 20100122.1), hardening-includes Standards-Version: 3.9.3 Package: nagios-nrpe-server diff -Nru nagios-nrpe-2.13/debian/patches/00list nagios-nrpe-2.15/debian/patches/00list --- nagios-nrpe-2.13/debian/patches/00list 2019-03-09 23:03:09.000000000 +0000 +++ nagios-nrpe-2.15/debian/patches/00list 2019-03-09 23:03:10.000000000 +0000 @@ -5,5 +5,4 @@ 05_pid_privileges.dpatch 06_pid_directory.dpatch 07_warn_ssloption.dpatch -08_CVE-2013-1362.dpatch 09_noremove_pid.dpatch diff -Nru nagios-nrpe-2.13/debian/patches/01_nodevrandom-and-docoptions.dpatch nagios-nrpe-2.15/debian/patches/01_nodevrandom-and-docoptions.dpatch --- nagios-nrpe-2.13/debian/patches/01_nodevrandom-and-docoptions.dpatch 2019-03-09 23:03:09.000000000 +0000 +++ nagios-nrpe-2.15/debian/patches/01_nodevrandom-and-docoptions.dpatch 2019-03-09 23:03:10.000000000 +0000 @@ -5,38 +5,38 @@ ## DP: No description. @DPATCH@ -diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' pkg-nrpe~/src/check_nrpe.c pkg-nrpe/src/check_nrpe.c ---- pkg-nrpe~/src/check_nrpe.c 2012-04-30 09:36:53.000000000 +0200 -+++ pkg-nrpe/src/check_nrpe.c 2012-04-30 09:45:36.129684439 +0200 -@@ -96,6 +96,9 @@ - printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n"); - printf(" arguments should be separated by a space. If provided, this must be\n"); - printf(" the last option supplied on the command line.\n"); -+ printf(" -h,--help Print this short help.\n"); -+ printf(" -l,--license Print licensing information.\n"); -+ printf(" -n,--no-ssl Do not initiate an ssl handshake with the server, talk in plaintext.\n"); - printf("\n"); - printf("Note:\n"); - printf("This plugin requires that you have the NRPE daemon running on the remote host.\n"); -diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' pkg-nrpe~/src/utils.c pkg-nrpe/src/utils.c ---- pkg-nrpe~/src/utils.c 2012-04-30 09:36:53.000000000 +0200 -+++ pkg-nrpe/src/utils.c 2012-04-30 09:48:03.811163608 +0200 -@@ -90,17 +90,7 @@ - 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); -- -+ seed=(int)time(NULL)*311-getpid()*359+getppid()*383; - srand(seed); - for(x=0;x [ -b ] [-4] [-6] [-n] [-u] [-p ] [-t ] [-c ] [-a ]\n"); + printf("\n"); + printf("Options:\n"); ++ printf(" -h = Print this short help.\n"); ++ printf(" -l = Print licensing information.\n"); + printf(" -n = Do no use SSL\n"); + printf(" -u = Make socket timeouts return an UNKNOWN state instead of CRITICAL\n"); + printf(" = The address of the host running the NRPE daemon\n"); + +=== modified file 'src/utils.c' +--- old/src/utils.c 2014-01-13 16:06:39 +0000 ++++ new/src/utils.c 2014-01-13 16:18:26 +0000 +@@ -98,16 +98,7 @@ + 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); ++ seed=(int)time(NULL)*311-getpid()*359+getppid()*383; + + srand(seed); + for(x=0;x -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: nagios-nrpe prior to 2.14 allows the passing of $() as command -## DP: arguments to execute shell commands if command arguments are -## DP: explicitly enabled. Filtering out nasty caracters is not -## DP: strict enough to disallow $(), allowing executing shell commands -## DP: under a subprocess and pass the output as a parameter to the -## DP: called script (if run under bash). - -@DPATCH@ -diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' pkg-nrpe~/src/nrpe.c pkg-nrpe/src/nrpe.c ---- pkg-nrpe~/src/nrpe.c 2013-03-09 08:12:53.000000000 +0100 -+++ pkg-nrpe/src/nrpe.c 2013-03-09 08:15:25.714710355 +0100 -@@ -1746,6 +1746,10 @@ - syslog(LOG_ERR,"Error: Request contained an empty command argument"); - return ERROR; - } -+ if(strstr(macro_argv[x],"$(")) { -+ syslog(LOG_ERR,"Error: Request contained a bash command substitution!"); -+ return ERROR; -+ } - } - } - #endif diff -Nru nagios-nrpe-2.13/debian/patches/09_noremove_pid.dpatch nagios-nrpe-2.15/debian/patches/09_noremove_pid.dpatch --- nagios-nrpe-2.13/debian/patches/09_noremove_pid.dpatch 2019-03-09 23:03:09.000000000 +0000 +++ nagios-nrpe-2.15/debian/patches/09_noremove_pid.dpatch 2019-03-09 23:03:10.000000000 +0000 @@ -10,24 +10,25 @@ # Bug-Ubuntu: https://launchpad.net/bugs/1126890 @DPATCH@ -diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' nagios-nrpe-2.13~/src/nrpe.c nagios-nrpe-2.13/src/nrpe.c ---- nagios-nrpe-2.13~/src/nrpe.c 2013-05-24 17:15:38.000000000 -0400 -+++ nagios-nrpe-2.13/src/nrpe.c 2013-05-24 17:16:16.512293650 -0400 -@@ -843,7 +843,7 @@ - /* close socket prioer to exiting */ - close(sock); - -- return; -+ exit(STATE_CRITICAL); - } - - /* handle signals */ -@@ -866,7 +866,7 @@ - /* close socket prior to exiting */ - close(new_sd); - -- return; -+ exit(STATE_CRITICAL); - } - - nptr=(struct sockaddr_in *)&addr; +=== modified file 'src/nrpe.c' +--- old/src/nrpe.c 2014-01-13 16:06:39 +0000 ++++ new/src/nrpe.c 2014-01-13 16:28:26 +0000 +@@ -998,7 +998,7 @@ + /* close socket prioer to exiting */ + close(sock); + +- return; ++ exit(STATE_CRITICAL); + } + + /* handle signals */ +@@ -1022,7 +1022,7 @@ + /* close socket prior to exiting */ + close(new_sd); + +- return; ++ exit(STATE_CRITICAL); + } + + /* is this is a blessed machine? */ + diff -Nru nagios-nrpe-2.13/debian/rules nagios-nrpe-2.15/debian/rules --- nagios-nrpe-2.13/debian/rules 2019-03-09 23:03:09.000000000 +0000 +++ nagios-nrpe-2.15/debian/rules 2019-03-09 23:03:10.000000000 +0000 @@ -6,11 +6,16 @@ # Include dpatch stuff. include /usr/share/dpatch/dpatch.make +include /usr/share/hardening-includes/hardening.make +CFLAGS := $(shell dpkg-buildflags --get CFLAGS) $(HARDENING_CFLAGS) +CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS) $(HARDENING_CFLAGS) +LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS) $(HARDENING_LDFLAGS) + %: dh $@ --with dpatch,autotools_dev override_dh_auto_configure: - ./configure \ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure \ --prefix=/usr \ --enable-ssl \ --with-ssl-lib=/usr/lib/$(DEB_HOST_MULTIARCH) \ diff -Nru nagios-nrpe-2.13/include/acl.h nagios-nrpe-2.15/include/acl.h --- nagios-nrpe-2.13/include/acl.h 2011-11-04 18:57:41.000000000 +0000 +++ nagios-nrpe-2.15/include/acl.h 2013-09-06 15:27:13.000000000 +0000 @@ -40,9 +40,12 @@ #define CHAR_TO_NUMBER(c) ((c) - '0') struct ip_acl { - struct in_addr addr; - struct in_addr mask; - struct ip_acl *next; + int family; + struct in_addr addr; + struct in_addr mask; + struct in6_addr addr6; + struct in6_addr mask6; + struct ip_acl *next; }; struct dns_acl { @@ -57,8 +60,10 @@ /* Functions */ void parse_allowed_hosts(char *allowed_hosts); int add_ipv4_to_acl(char *ipv4); +int add_ipv6_to_acl(char *ipv6); int add_domain_to_acl(char *domain); -int is_an_allowed_host(struct in_addr); +//int is_an_allowed_host(struct in_addr); +int is_an_allowed_host(int, void *); unsigned int prefix_from_mask(struct in_addr mask); void show_acl_lists(void); diff -Nru nagios-nrpe-2.13/include/common.h nagios-nrpe-2.15/include/common.h --- nagios-nrpe-2.13/include/common.h 2011-11-11 18:45:49.000000000 +0000 +++ nagios-nrpe-2.15/include/common.h 2013-09-06 15:27:13.000000000 +0000 @@ -1,84 +1,92 @@ -/************************************************************************ - * - * COMMON.H - NRPE Common Include File - * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org) - * Last Modified: 11-11-2011 - * - * License: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ************************************************************************/ - -#include "config.h" - -#define PROGRAM_VERSION "2.13" -#define MODIFICATION_DATE "11-11-2011" - -#define OK 0 -#define ERROR -1 - -#define TRUE 1 -#define FALSE 0 - -#define STATE_UNKNOWN 3 /* service state return codes */ -#define STATE_CRITICAL 2 -#define STATE_WARNING 1 -#define STATE_OK 0 - - -#define DEFAULT_SOCKET_TIMEOUT 10 /* timeout after 10 seconds */ -#define DEFAULT_CONNECTION_TIMEOUT 300 /* timeout if daemon is waiting for connection more than this time */ - -#define MAX_INPUT_BUFFER 2048 /* max size of most buffers we use */ -#define MAX_FILENAME_LENGTH 256 - -#define MAX_HOST_ADDRESS_LENGTH 256 /* max size of a host address */ - -#define NRPE_HELLO_COMMAND "_NRPE_CHECK" - -#define MAX_COMMAND_ARGUMENTS 16 - - -/**************** PACKET STRUCTURE DEFINITION **********/ - -#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_3 3 /* packet version identifier */ -#define NRPE_PACKET_VERSION_2 2 -#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{ - int16_t packet_version; - int16_t packet_type; - u_int32_t crc32_value; - int16_t result_code; - char buffer[MAX_PACKETBUFFER_LENGTH]; - }packet; - -/**************** OPERATING SYSTEM SPECIFIC DEFINITIONS **********/ -#ifdef __sun - -# ifndef LOG_AUTHPRIV -# define LOG_AUTHPRIV LOG_AUTH -# endif - -# ifndef LOG_FTP -# define LOG_FTP LOG_DAEMON -# endif - -#endif +/************************************************************************ + * + * COMMON.H - NRPE Common Include File + * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org) + * Last Modified: 09-06-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************/ + +#include "config.h" + +#define PROGRAM_VERSION "2.15" +#define MODIFICATION_DATE "09-06-2013" + +#define OK 0 +#define ERROR -1 + +#define TRUE 1 +#define FALSE 0 + +#define STATE_UNKNOWN 3 /* service state return codes */ +#define STATE_CRITICAL 2 +#define STATE_WARNING 1 +#define STATE_OK 0 + + +#define DEFAULT_SOCKET_TIMEOUT 10 /* timeout after 10 seconds */ +#define DEFAULT_CONNECTION_TIMEOUT 300 /* timeout if daemon is waiting for connection more than this time */ + +#define MAX_INPUT_BUFFER 2048 /* max size of most buffers we use */ +#define MAX_FILENAME_LENGTH 256 + +#define MAX_HOST_ADDRESS_LENGTH 256 /* max size of a host address */ + +#define NRPE_HELLO_COMMAND "_NRPE_CHECK" + +#define MAX_COMMAND_ARGUMENTS 16 + + +/**************** PACKET STRUCTURE DEFINITION **********/ + +#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_3 3 /* packet version identifier */ +#define NRPE_PACKET_VERSION_2 2 +#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{ + int16_t packet_version; + int16_t packet_type; + u_int32_t crc32_value; + int16_t result_code; + char buffer[MAX_PACKETBUFFER_LENGTH]; + }packet; + +/**************** OPERATING SYSTEM SPECIFIC DEFINITIONS **********/ +#if defined(__sun) || defined(__hpux) + +# ifndef LOG_AUTHPRIV +# define LOG_AUTHPRIV LOG_AUTH +# endif + +# ifndef LOG_FTP +# define LOG_FTP LOG_DAEMON +# endif + +#elif _AIX + +# include + +# ifndef LOG_FTP +# define LOG_FTP LOG_DAEMON +# endif + +#endif diff -Nru nagios-nrpe-2.13/include/config.h.in nagios-nrpe-2.15/include/config.h.in --- nagios-nrpe-2.13/include/config.h.in 2007-11-23 17:32:14.000000000 +0000 +++ nagios-nrpe-2.15/include/config.h.in 2013-09-06 15:27:13.000000000 +0000 @@ -34,6 +34,8 @@ #undef ENABLE_COMMAND_ARGUMENTS +#undef ENABLE_BASH_COMMAND_SUBSTITUTION + #undef socklen_t #undef HAVE_GETOPT_LONG diff -Nru nagios-nrpe-2.13/include/dh.h nagios-nrpe-2.15/include/dh.h --- nagios-nrpe-2.13/include/dh.h 2011-11-11 18:50:37.000000000 +0000 +++ nagios-nrpe-2.15/include/dh.h 2013-09-06 15:27:13.000000000 +0000 @@ -4,12 +4,12 @@ DH *get_dh512() { static unsigned char dh512_p[]={ - 0xA4,0x56,0x47,0x7F,0x90,0xF0,0xDE,0xFE,0x73,0x1A,0xBD,0x3E, - 0xA9,0xF5,0x69,0x46,0x29,0x0B,0x47,0x55,0x8C,0xE8,0xF3,0xDF, - 0xF6,0x1B,0xC5,0x29,0x1B,0x81,0x97,0x3E,0xE4,0xD9,0xC8,0x2B, - 0xBB,0x2B,0x7A,0x37,0xE1,0x18,0xDF,0xEC,0x6B,0xEC,0x04,0x77, - 0x6D,0x51,0x3C,0x7C,0xB7,0x81,0xBD,0x7F,0xC9,0x5A,0x04,0xB4, - 0xA4,0x3E,0x8B,0x5B, + 0xDA,0xD8,0xF0,0xA2,0x9A,0x64,0xC2,0x9F,0x22,0x9D,0x47,0xA1, + 0xB2,0xED,0xD6,0x89,0xB5,0x46,0x6D,0x4E,0x1F,0x14,0xF4,0xF4, + 0xEB,0xCA,0x4D,0x41,0x89,0x60,0x0D,0x1F,0xB3,0x50,0xC4,0x54, + 0xE1,0x60,0xB5,0xDD,0x57,0x0C,0xF9,0xF5,0x19,0x73,0x6C,0x0C, + 0x45,0x33,0xA9,0xC1,0xD7,0xF3,0x27,0x68,0xEE,0xDA,0x8C,0x4A, + 0x1C,0x52,0xA1,0x9B, }; static unsigned char dh512_g[]={ 0x02, diff -Nru nagios-nrpe-2.13/include/nrpe.h nagios-nrpe-2.15/include/nrpe.h --- nagios-nrpe-2.13/include/nrpe.h 2011-11-04 18:57:41.000000000 +0000 +++ nagios-nrpe-2.15/include/nrpe.h 2013-09-06 15:27:13.000000000 +0000 @@ -1,65 +1,65 @@ -/************************************************************************ - * - * NRPE.H - NRPE Include File - * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org) - * Last Modified: 08-10-2011 by Konstantin Malov - * - * License: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ************************************************************************/ - - /* - * 08-10-2011 IPv4 subnetworks support added. - * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c - * - */ - -/**************** COMMAND STRUCTURE DEFINITION **********/ - -typedef struct command_struct{ - char *command_name; - char *command_line; - struct command_struct *next; - }command; - -int process_arguments(int,char **); -void wait_for_connections(void); -void handle_connection(int); -int read_config_file(char *); -int read_config_dir(char *); -int get_log_facility(char *); -int add_command(char *,char *); -command *find_command(char *); -void sighandler(int); -int drop_privileges(char *,char *); -int check_privileges(void); - -int write_pid_file(void); -int remove_pid_file(void); - -void free_memory(void); -int validate_request(packet *); -int contains_nasty_metachars(char *); -int process_macros(char *,char *,int); -int my_system(char *,int,int *,char *,int); /* executes a command via popen(), but also protects against timeouts */ -void my_system_sighandler(int); /* handles timeouts when executing commands via my_system() */ -void my_connection_sighandler(int); /* handles timeouts of connection */ - -void sighandler(int); -void child_sighandler(int); - - +/************************************************************************ + * + * NRPE.H - NRPE Include File + * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org) + * Last Modified: 08-10-2011 by Konstantin Malov + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ************************************************************************/ + + /* + * 08-10-2011 IPv4 subnetworks support added. + * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c + * + */ + +/**************** COMMAND STRUCTURE DEFINITION **********/ + +typedef struct command_struct{ + char *command_name; + char *command_line; + struct command_struct *next; + }command; + +int process_arguments(int,char **); +void wait_for_connections(void); +void handle_connection(int); +int read_config_file(char *); +int read_config_dir(char *); +int get_log_facility(char *); +int add_command(char *,char *); +command *find_command(char *); +void sighandler(int); +int drop_privileges(char *,char *); +int check_privileges(void); + +int write_pid_file(void); +int remove_pid_file(void); + +void free_memory(void); +int validate_request(packet *); +int contains_nasty_metachars(char *); +int process_macros(char *,char *,int); +int my_system(char *,int,int *,char *,int); /* executes a command via popen(), but also protects against timeouts */ +void my_system_sighandler(int); /* handles timeouts when executing commands via my_system() */ +void my_connection_sighandler(int); /* handles timeouts of connection */ + +void sighandler(int); +void child_sighandler(int); + + diff -Nru nagios-nrpe-2.13/include/utils.h nagios-nrpe-2.15/include/utils.h --- nagios-nrpe-2.13/include/utils.h 2006-12-12 02:04:01.000000000 +0000 +++ nagios-nrpe-2.15/include/utils.h 2013-09-06 15:27:13.000000000 +0000 @@ -1,62 +1,63 @@ -/************************************************************************************************ - * - * UTILS.H - NRPE Utilities Include File - * - * License: GPL - * Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org) - * - * Last Modified: 12-11-2006 - * - * Description: - * - * This file contains common include files and function definitions used in many of the plugins. - * - * License Information: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ************************************************************************************************/ - -#ifndef _UTILS_H -#define _UTILS_H - -#include "../include/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 *); - -int my_inet_aton(register const char *,struct in_addr *); - -void strip(char *); - -int sendall(int,char *,int *); -int recvall(int,char *,int *,int); - -char *my_strsep(char **,const char *); - -void display_license(void); - -#endif - - - - - +/************************************************************************************************ + * + * UTILS.H - NRPE Utilities Include File + * + * License: GPL + * Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org) + * + * Last Modified: 12-11-2006 + * + * Description: + * + * This file contains common include files and function definitions used in many of the plugins. + * + * License Information: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ************************************************************************************************/ + +#ifndef _UTILS_H +#define _UTILS_H + +#include "../include/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(const char *, struct sockaddr_storage *, u_short, int, + const char *); + +void add_listen_addr(struct addrinfo **, int, char *, int); + +void strip(char *); + +int sendall(int,char *,int *); +int recvall(int,char *,int *,int); + +char *my_strsep(char **,const char *); + +void display_license(void); + +#endif + + + + + diff -Nru nagios-nrpe-2.13/nrpe.spec nagios-nrpe-2.15/nrpe.spec --- nagios-nrpe-2.13/nrpe.spec 2011-11-11 18:45:49.000000000 +0000 +++ nagios-nrpe-2.15/nrpe.spec 2013-09-06 15:27:13.000000000 +0000 @@ -1,5 +1,27 @@ +%define isaix %(test "`uname -s`" = "AIX" && echo "1" || echo "0") +%define islinux %(test "`uname -s`" = "Linux" && echo "1" || echo "0") + +%if %{isaix} + %define _prefix /opt/nagios + %define _docdir %{_prefix}/doc/nrpe-2.15 + %define nshome /opt/nagios + %define _make gmake +%endif +%if %{islinux} + %define _init_dir /etc/init.d + %define _exec_prefix %{_prefix}/sbin + %define _bindir %{_prefix}/sbin + %define _sbindir %{_prefix}/lib/nagios/cgi + %define _libexecdir %{_prefix}/lib/nagios/plugins + %define _datadir %{_prefix}/share/nagios + %define _localstatedir /var/log/nagios + %define nshome /var/log/nagios + %define _make make +%endif +%define _sysconfdir /etc/nagios + %define name nrpe -%define version 2.13 +%define version 2.15 %define release 1 %define nsusr nagios %define nsgrp nagios @@ -24,17 +46,21 @@ Prefix: %{_prefix} Prefix: /etc/init.d Prefix: /etc/nagios -Requires: bash, grep, nagios-plugins -PreReq: /usr/bin/logger, chkconfig, sh-utils, shadow-utils, sed, initscripts, fileutils, mktemp +%if %{isaix} +Requires: nagios-plugins +%endif +%if %{islinux} +Requires: bash, grep, nagios-plugins, util-linux, chkconfig, shadow-utils, sed, initscripts, mktemp +%endif %description -Nrpe is a system daemon that will execute various Nagios plugins -locally on behalf of a remote (monitoring) host that uses the -check_nrpe plugin. Various plugins that can be executed by the -daemon are available at: -http://sourceforge.net/projects/nagiosplug +NPRE (Nagios Remote Plugin Executor) is a system daemon that +will execute various Nagios plugins locally on behalf of a +remote (monitoring) host that uses the check_nrpe plugin. +Various plugins that can be executed by the daemon are available +at: http://sourceforge.net/projects/nagiosplug -This package provides the core agent. +This package provides the client-side NRPE agent (daemon). %package plugin Group: Application/System @@ -42,13 +68,14 @@ Requires: nagios-plugins %description plugin -Nrpe is a system daemon that will execute various Nagios plugins -locally on behalf of a remote (monitoring) host that uses the -check_nrpe plugin. Various plugins that can be executed by the -daemon are available at: -http://sourceforge.net/projects/nagiosplug +NPRE (Nagios Remote Plugin Executor) is a system daemon that +will execute various Nagios plugins locally on behalf of a +remote (monitoring) host that uses the check_nrpe plugin. +Various plugins that can be executed by the daemon are available +at: http://sourceforge.net/projects/nagiosplug -This package provides the nrpe plugin for Nagios-related applications. +This package provides the server-side NRPE plugin for +Nagios-related applications. %prep %setup -q @@ -56,20 +83,47 @@ %pre # Create `nagios' group on the system if necessary -if grep ^nagios: /etc/group; then - : # group already exists -else - /usr/sbin/groupadd %{nsgrp} || %nnmmsg Unexpected error adding group "%{nsgrp}". Aborting install process. +%if %{isaix} +lsgroup %{nsgrp} > /dev/null 2> /dev/null +if [ $? -eq 2 ] ; then + mkgroup %{nsgrp} || %nnmmsg Unexpected error adding group "%{nsgrp}". Aborting install process. +fi +%endif +%if %{islinux} +getent group %{nsgrp} > /dev/null 2> /dev/null +if [ $? -ne 0 ] ; then + groupadd %{nsgrp} || %nnmmsg Unexpected error adding group "%{nsgrp}". Aborting install process. fi +%endif # Create `nagios' user on the system if necessary -if id %{nsusr} ; then - : # user already exists -else - /usr/sbin/useradd -r -d /var/log/nagios -s /bin/sh -c "%{nsusr}" -g %{nsgrp} %{nsusr} || \ +%if %{isaix} +lsuser %{nsusr} > /dev/null 2> /dev/null +if [ $? -eq 2 ] ; then + useradd -d %{nshome} -c "%{nsusr}" -g %{nsgrp} %{nsusr} || \ %nnmmsg Unexpected error adding user "%{nsusr}". Aborting install process. fi +%endif +%if %{islinux} +getent passwd %{nsusr} > /dev/null 2> /dev/null +if [ $? -ne 0 ] ; then + useradd -r -d %{nshome} -c "%{nsusr}" -g %{nsgrp} %{nsusr} || \ + %nnmmsg Unexpected error adding user "%{nsusr}". Aborting install process. +fi +%endif +%if %{isaix} +# Check to see if the nrpe service is running and, if so, stop it. +/usr/bin/lssrc -s nrpe > /dev/null 2> /dev/null +if [ $? -eq 0 ] ; then + status=`/usr/bin/lssrc -s nrpe | /usr/bin/gawk '$1=="nrpe" {print $NF}'` + if [ "$status" = "active" ] ; then + /usr/bin/stopsrc -s nrpe + fi +fi +%endif + +%if %{islinux} # if LSB standard /etc/init.d does not exist, # create it as a symlink to the first match we find if [ -d /etc/init.d -o -L /etc/init.d ]; then @@ -81,73 +135,103 @@ elif [ -d /sbin/init.d ]; then ln -s /sbin/init.d /etc/init.d fi +%endif +%if %{isaix} +%post +/usr/bin/lssrc -s nrpe > /dev/null 2> /dev/null +if [ $? -eq 1 ] ; then + /usr/bin/mkssys -p %{_bindir}/nrpe -s nrpe -u 0 -a "-c %{_sysconfdir}/nrpe.cfg -d -s" -Q -R -S -n 15 -f 9 +fi +/usr/bin/startsrc -s nrpe +%endif %preun +%if %{isaix} +status=`/usr/bin/lssrc -s nrpe | /usr/bin/gawk '$1=="nrpe" {print $NF}'` +if [ "$status" = "active" ] ; then + /usr/bin/stopsrc -s nrpe +fi +/usr/bin/rmssys -s nrpe +%endif +%if %{islinux} if [ "$1" = 0 ]; then /sbin/service nrpe stop > /dev/null 2>&1 /sbin/chkconfig --del nrpe fi +%endif +%if %{islinux} %postun if [ "$1" -ge "1" ]; then /sbin/service nrpe condrestart >/dev/null 2>&1 || : fi +%endif %build export PATH=$PATH:/usr/sbin CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" \ -./configure \ +MAKE=%{_make} ./configure \ --with-init-dir=/etc/init.d \ --with-nrpe-port=%{nsport} \ --with-nrpe-user=%{nsusr} \ --with-nrpe-group=%{nsgrp} \ --prefix=%{_prefix} \ - --exec-prefix=%{_prefix}/sbin \ - --bindir=%{_prefix}/sbin \ - --sbindir=%{_prefix}/lib/nagios/cgi \ - --libexecdir=%{_prefix}/lib/nagios/plugins \ - --datadir=%{_prefix}/share/nagios \ - --sysconfdir=/etc/nagios \ - --localstatedir=/var/log/nagios \ + --exec-prefix=%{_exec_prefix} \ + --bindir=%{_bindir} \ + --sbindir=%{_sbindir} \ + --libexecdir=%{_libexecdir} \ + --datadir=%{_datadir} \ + --sysconfdir=%{_sysconfdir} \ + --localstatedir=%{_localstatedir} \ --enable-command-args - -make all +%{_make} all %install [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT -install -d -m 0755 ${RPM_BUILD_ROOT}/etc/init.d -install -d -m 0755 ${RPM_BUILD_ROOT}/etc/nagios -install -d -m 0755 ${RPM_BUILD_ROOT}/usr/sbin -install -d -m 0755 ${RPM_BUILD_ROOT}/usr/lib/nagios/plugins +%if %{islinux} +install -d -m 0755 ${RPM_BUILD_ROOT}%{_init_dir} +%endif +DESTDIR=${RPM_BUILD_ROOT} %{_make} install install-daemon-config +#install -d -m 0755 ${RPM_BUILD_ROOT}%{_sysconfdir} +#install -d -m 0755 ${RPM_BUILD_ROOT}%{_bindir} +#install -d -m 0755 ${RPM_BUILD_ROOT}%{_libexecdir} # install templated configuration files -cp sample-config/nrpe.cfg ${RPM_BUILD_ROOT}/etc/nagios/nrpe.cfg -cp init-script ${RPM_BUILD_ROOT}/etc/init.d/nrpe -cp src/nrpe ${RPM_BUILD_ROOT}/usr/sbin -cp src/check_nrpe ${RPM_BUILD_ROOT}/usr/lib/nagios/plugins +#cp sample-config/nrpe.cfg ${RPM_BUILD_ROOT}%{_sysconfdir}/nrpe.cfg +#%if %{isaix} +#cp init-script ${RPM_BUILD_ROOT}%{_init_dir}/nrpe +#%endif +#cp src/nrpe ${RPM_BUILD_ROOT}%{_bindir} +#cp src/check_nrpe ${RPM_BUILD_ROOT}%{_libexecdir} %clean rm -rf $RPM_BUILD_ROOT %files +%if %{islinux} %defattr(755,root,root) /etc/init.d/nrpe -%{_prefix}/sbin/nrpe -%dir /etc/nagios -%defattr(644,root,root) -%config(noreplace) /etc/nagios/*.cfg +%endif +%{_bindir}/nrpe +%dir %{_sysconfdir} +%defattr(600,%{nsusr},%{nsgrp}) +%config(noreplace) %{_sysconfdir}/*.cfg %defattr(755,%{nsusr},%{nsgrp}) %doc Changelog LEGAL README %files plugin -%defattr(755,root,root) -%{_prefix}/lib/nagios/plugins %defattr(755,%{nsusr},%{nsgrp}) -%doc Changelog LEGAL README +%{_libexecdir} +%defattr(644,%{nsusr},%{nsgrp}) +%doc Changelog LEGAL README %changelog +* Mon Mar 12 2012 Eric Stanley estanley<@>nagios.com +- Created autoconf input file +- Updated to support building on AIX +- Updated install to use make install* * Mon Jan 23 2006 Andreas Kasenides ank<@>cs.ucy.ac.cy - fixed nrpe.cfg relocation to sample-config - replaced Copyright label with License diff -Nru nagios-nrpe-2.13/nrpe.spec.in nagios-nrpe-2.15/nrpe.spec.in --- nagios-nrpe-2.13/nrpe.spec.in 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/nrpe.spec.in 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,252 @@ +%define isaix %(test "`uname -s`" = "AIX" && echo "1" || echo "0") +%define islinux %(test "`uname -s`" = "Linux" && echo "1" || echo "0") + +%if %{isaix} + %define _prefix /opt/nagios + %define _docdir %{_prefix}/doc/@PACKAGE_NAME@-@PACKAGE_VERSION@ + %define nshome /opt/nagios + %define _make gmake +%endif +%if %{islinux} + %define _init_dir /etc/init.d + %define _exec_prefix %{_prefix}/sbin + %define _bindir %{_prefix}/sbin + %define _sbindir %{_prefix}/lib/nagios/cgi + %define _libexecdir %{_prefix}/lib/nagios/plugins + %define _datadir %{_prefix}/share/nagios + %define _localstatedir /var/log/nagios + %define nshome /var/log/nagios + %define _make make +%endif +%define _sysconfdir /etc/nagios + +%define name @PACKAGE_NAME@ +%define version @PACKAGE_VERSION@ +%define release @RPM_RELEASE@ +%define nsusr @nrpe_user@ +%define nsgrp @nrpe_group@ +%define nsport @nrpe_port@ + +# Reserve option to override port setting with: +# rpm -ba|--rebuild --define 'nsport 5666' +%{?port:%define nsport %{port}} + +# Macro that print mesages to syslog at package (un)install time +%define nnmmsg logger -t %{name}/rpm + +Summary: Host/service/network monitoring agent for Nagios +URL: http://www.nagios.org +Name: %{name} +Version: %{version} +Release: %{release} +License: GPL +Group: Application/System +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-buildroot +Prefix: %{_prefix} +Prefix: /etc/init.d +Prefix: /etc/nagios +%if %{isaix} +Requires: nagios-plugins +%endif +%if %{islinux} +Requires: bash, grep, nagios-plugins, util-linux, chkconfig, shadow-utils, sed, initscripts, mktemp +%endif + +%description +NPRE (Nagios Remote Plugin Executor) is a system daemon that +will execute various Nagios plugins locally on behalf of a +remote (monitoring) host that uses the check_nrpe plugin. +Various plugins that can be executed by the daemon are available +at: http://sourceforge.net/projects/nagiosplug + +This package provides the client-side NRPE agent (daemon). + +%package plugin +Group: Application/System +Summary: Provides nrpe plugin for Nagios. +Requires: nagios-plugins + +%description plugin +NPRE (Nagios Remote Plugin Executor) is a system daemon that +will execute various Nagios plugins locally on behalf of a +remote (monitoring) host that uses the check_nrpe plugin. +Various plugins that can be executed by the daemon are available +at: http://sourceforge.net/projects/nagiosplug + +This package provides the server-side NRPE plugin for +Nagios-related applications. + +%prep +%setup -q + + +%pre +# Create `nagios' group on the system if necessary +%if %{isaix} +lsgroup %{nsgrp} > /dev/null 2> /dev/null +if [ $? -eq 2 ] ; then + mkgroup %{nsgrp} || %nnmmsg Unexpected error adding group "%{nsgrp}". Aborting install process. +fi +%endif +%if %{islinux} +getent group %{nsgrp} > /dev/null 2> /dev/null +if [ $? -ne 0 ] ; then + groupadd %{nsgrp} || %nnmmsg Unexpected error adding group "%{nsgrp}". Aborting install process. +fi +%endif + +# Create `nagios' user on the system if necessary +%if %{isaix} +lsuser %{nsusr} > /dev/null 2> /dev/null +if [ $? -eq 2 ] ; then + useradd -d %{nshome} -c "%{nsusr}" -g %{nsgrp} %{nsusr} || \ + %nnmmsg Unexpected error adding user "%{nsusr}". Aborting install process. +fi +%endif +%if %{islinux} +getent passwd %{nsusr} > /dev/null 2> /dev/null +if [ $? -ne 0 ] ; then + useradd -r -d %{nshome} -c "%{nsusr}" -g %{nsgrp} %{nsusr} || \ + %nnmmsg Unexpected error adding user "%{nsusr}". Aborting install process. +fi +%endif + +%if %{isaix} +# Check to see if the nrpe service is running and, if so, stop it. +/usr/bin/lssrc -s nrpe > /dev/null 2> /dev/null +if [ $? -eq 0 ] ; then + status=`/usr/bin/lssrc -s nrpe | /usr/bin/gawk '$1=="nrpe" {print $NF}'` + if [ "$status" = "active" ] ; then + /usr/bin/stopsrc -s nrpe + fi +fi +%endif + +%if %{islinux} +# if LSB standard /etc/init.d does not exist, +# create it as a symlink to the first match we find +if [ -d /etc/init.d -o -L /etc/init.d ]; then + : # we're done +elif [ -d /etc/rc.d/init.d ]; then + ln -s /etc/rc.d/init.d /etc/init.d +elif [ -d /usr/local/etc/rc.d ]; then + ln -s /usr/local/etc/rc.d /etc/init.d +elif [ -d /sbin/init.d ]; then + ln -s /sbin/init.d /etc/init.d +fi +%endif + +%if %{isaix} +%post +/usr/bin/lssrc -s nrpe > /dev/null 2> /dev/null +if [ $? -eq 1 ] ; then + /usr/bin/mkssys -p %{_bindir}/nrpe -s nrpe -u 0 -a "-c %{_sysconfdir}/nrpe.cfg -d -s" -Q -R -S -n 15 -f 9 +fi +/usr/bin/startsrc -s nrpe +%endif + +%preun +%if %{isaix} +status=`/usr/bin/lssrc -s nrpe | /usr/bin/gawk '$1=="nrpe" {print $NF}'` +if [ "$status" = "active" ] ; then + /usr/bin/stopsrc -s nrpe +fi +/usr/bin/rmssys -s nrpe +%endif +%if %{islinux} +if [ "$1" = 0 ]; then + /sbin/service nrpe stop > /dev/null 2>&1 + /sbin/chkconfig --del nrpe +fi +%endif + +%if %{islinux} +%postun +if [ "$1" -ge "1" ]; then + /sbin/service nrpe condrestart >/dev/null 2>&1 || : +fi +%endif + +%build +export PATH=$PATH:/usr/sbin +CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" \ +MAKE=%{_make} ./configure \ + --with-init-dir=/etc/init.d \ + --with-nrpe-port=%{nsport} \ + --with-nrpe-user=%{nsusr} \ + --with-nrpe-group=%{nsgrp} \ + --prefix=%{_prefix} \ + --exec-prefix=%{_exec_prefix} \ + --bindir=%{_bindir} \ + --sbindir=%{_sbindir} \ + --libexecdir=%{_libexecdir} \ + --datadir=%{_datadir} \ + --sysconfdir=%{_sysconfdir} \ + --localstatedir=%{_localstatedir} \ + --enable-command-args +%{_make} all + +%install +[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT +%if %{islinux} +install -d -m 0755 ${RPM_BUILD_ROOT}%{_init_dir} +%endif +DESTDIR=${RPM_BUILD_ROOT} %{_make} install install-daemon-config +#install -d -m 0755 ${RPM_BUILD_ROOT}%{_sysconfdir} +#install -d -m 0755 ${RPM_BUILD_ROOT}%{_bindir} +#install -d -m 0755 ${RPM_BUILD_ROOT}%{_libexecdir} + +# install templated configuration files +#cp sample-config/nrpe.cfg ${RPM_BUILD_ROOT}%{_sysconfdir}/nrpe.cfg +#%if %{isaix} +#cp init-script ${RPM_BUILD_ROOT}%{_init_dir}/nrpe +#%endif +#cp src/nrpe ${RPM_BUILD_ROOT}%{_bindir} +#cp src/check_nrpe ${RPM_BUILD_ROOT}%{_libexecdir} + +%clean +rm -rf $RPM_BUILD_ROOT + + +%files +%if %{islinux} +%defattr(755,root,root) +/etc/init.d/nrpe +%endif +%{_bindir}/nrpe +%dir %{_sysconfdir} +%defattr(600,%{nsusr},%{nsgrp}) +%config(noreplace) %{_sysconfdir}/*.cfg +%defattr(755,%{nsusr},%{nsgrp}) +%doc Changelog LEGAL README + +%files plugin +%defattr(755,%{nsusr},%{nsgrp}) +%{_libexecdir} +%defattr(644,%{nsusr},%{nsgrp}) +%doc Changelog LEGAL README + +%changelog +* Mon Mar 12 2012 Eric Stanley estanley<@>nagios.com +- Created autoconf input file +- Updated to support building on AIX +- Updated install to use make install* +* Mon Jan 23 2006 Andreas Kasenides ank<@>cs.ucy.ac.cy +- fixed nrpe.cfg relocation to sample-config +- replaced Copyright label with License +- added --enable-command-args to enable remote arg passing (if desired can be disabled by commenting out) + +* Wed Nov 12 2003 Ingimar Robertsson +- Added adding of nagios group if it does not exist. + +* Tue Jan 07 2003 James 'Showkilr' Peterson +- Removed the lines which removed the nagios user and group from the system +- changed the patch release version from 3 to 1 + +* Mon Jan 06 2003 James 'Showkilr' Peterson +- Removed patch files required for nrpe 1.5 +- Update spec file for version 1.6 (1.6-1) + +* Sat Dec 28 2002 James 'Showkilr' Peterson +- First RPM build (1.5-1) diff -Nru nagios-nrpe-2.13/package/solaris/Makefile.in nagios-nrpe-2.15/package/solaris/Makefile.in --- nagios-nrpe-2.13/package/solaris/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/package/solaris/Makefile.in 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,81 @@ +################################### +# Makefile for NRPE Solaris Package +# +# Last Modified: 2 Dec 2011 +################################### + +TARGET_OS=@TARGET_OS@ +TARGET_VER=@TARGET_VER@ +TARGET_ARCH=@TARGET_ARCH@ +TARGET_PLATFORM=@TARGET_PLATFORM@ + +SOLARIS_CONFIG_OPTS=--prefix=/opt/nagios --sysconfdir=/etc/nagios --enable-command-args + +PKG_NAME=NGOSnrpe +PKG_VERSION=@PKG_VERSION@ +PKG_FILE=@PACKAGE_NAME@-$(PKG_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH)-local + +TOPDIR=@top_builddir@ +PKGDIR=@builddir@/pkg +SRCDIR=@builddir@/build/src +INSTALLDIR=@builddir@/install +ABSINSTALLDIR=@abs_builddir@/install + +build: + if [ ! -d build ] ; then mkdir build ; fi + if [ ! -d install ] ; then mkdir install ; fi + cd build; ../../../configure $(SOLARIS_CONFIG_OPTS); $(MAKE) all; DESTDIR=$(ABSINSTALLDIR) $(MAKE) install install-daemon-config + +prototype: $(PKGDIR) + @echo "i pkginfo" > $(PKGDIR)/prototype + @echo "i copyright=../$(TOPDIR)/LEGAL" >> $(PKGDIR)/prototype + @echo "i preinstall" >> $(PKGDIR)/prototype + @echo "i i.config" >> $(PKGDIR)/prototype + @echo "i r.config" >> $(PKGDIR)/prototype + @echo "i i.manifest=/usr/sadm/install/scripts/i.manifest" >> $(PKGDIR)/prototype + @echo "i r.manifest=/usr/sadm/install/scripts/r.manifest" >> $(PKGDIR)/prototype + @echo "d none /etc/nagios 0755 nagios nagios" >> $(PKGDIR)/prototype + @echo "f config /etc/nagios/nrpe.cfg=$(INSTALLDIR)/etc/nagios/nrpe.cfg 0600 nagios nagios" >> $(PKGDIR)/prototype + @echo "d none /opt/nagios/bin 0755 nagios bin" >> $(PKGDIR)/prototype + @echo "f none /opt/nagios/bin/nrpe=$(SRCDIR)/nrpe 0755 nagios bin" >> $(PKGDIR)/prototype + @echo "d none /opt/nagios/libexec 0755 nagios bin" >> $(PKGDIR)/prototype + @echo "f none /opt/nagios/libexec/check_nrpe=$(SRCDIR)/check_nrpe 0755 nagios bin" >> $(PKGDIR)/prototype + @echo "f none /lib/svc/method/nrpe=$(PKGDIR)/nrpe 0555 root bin" >> $(PKGDIR)/prototype + @echo "d none /var/svc/manifest/application/nagios 0755 root sys" >> $(PKGDIR)/prototype + @echo "f manifest /var/svc/manifest/application/nagios/nrpe.xml=$(PKGDIR)/nrpe.xml 0444 root sys" >> $(PKGDIR)/prototype + +pkginfo: $(PKGDIR) + @echo PKG="$(PKG_NAME)" > $(PKGDIR)/pkginfo + @echo NAME="Nagios Remote Plugin Executor $(PKG_VERSION)" >> $(PKGDIR)/pkginfo + @echo VERSION="$(PKG_VERSION)" >> $(PKGDIR)/pkginfo + @echo ARCH="$(TARGET_ARCH)" >> $(PKGDIR)/pkginfo + @echo CATEGORY="utility" >> $(PKGDIR)/pkginfo + @echo CLASSES="none config manifest" >> $(PKGDIR)/pkginfo + @echo VENDOR="www.nagios.org" >> $(PKGDIR)/pkginfo + @echo EMAIL="nagios-users@lists.sourceforge.net" >> $(PKGDIR)/pkginfo + @echo ISTATES="S s 1 2 3" >> $(PKGDIR)/pkginfo + @echo RSTATES="S s 1 2 3" >> $(PKGDIR)/pkginfo + @echo BASEDIR="/" >> $(PKGDIR)/pkginfo + +$(PKG_FILE): pkginfo prototype + pkgmk -o -d $(PKGDIR) -f $(PKGDIR)/prototype -r . + pkgtrans ./pkg $(PKG_FILE) $(PKG_NAME) + +pkg: $(PKG_FILE) + +all: pkg + +clean: + rm -rf build install package + rm -rf $(PKGDIR)/$(PKG_NAME) + rm -f $(PKGDIR)/prototype $(PKGDIR)/pkginfo + rm -f $(PKGDIR)/$(PKG_FILE) + rm -f core + rm -f *~ */*~ + +distclean: clean + rm -f Makefile + rm -f config.log + +devclean: distclean + diff -Nru nagios-nrpe-2.13/package/solaris/pkg/i.config nagios-nrpe-2.15/package/solaris/pkg/i.config --- nagios-nrpe-2.13/package/solaris/pkg/i.config 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/package/solaris/pkg/i.config 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,58 @@ +#!/usr/bin/sh + +create_cksum_file() { + srcfile=$1 + destfile=$2 + cksumfile=$3 + + echo "# DO NOT EDIT OR REMOVE THIS FILE - It is used to determine whether to" > $cksumfile + echo "# overwrite $destfile on package update or to remove" >> $cksumfile + echo "# it on package deletion." >> $cksumfile + /usr/bin/cat $srcfile | /usr/bin/cksum >> $cksumfile + /usr/bin/chmod 400 $cksumfile +} + +compare_cksum() { + destfile=$1 + cksumfile=$2 + + installed_cksum=`/usr/bin/tail -1 $cksumfile | /usr/bin/awk '{print $1}'` + current_cksum=`/usr/bin/cksum $destfile | /usr/bin/awk '{print $1}'` + test $installed_cksum = $current_cksum +} + +while read src dest ; do + destpath=`echo $dest | /usr/bin/sed -e 's/\/[^/]*$//'` + destbase=`/usr/bin/basename $dest` + cksumfile="${destpath}/.${destbase}.cksum" + if [ -f $dest ] ; then + if [ -f $cksumfile ] ; then + compare_cksum $dest $cksumfile + if [ $? -eq 0 ] ; then + /usr/bin/cp $src $dest + /usr/bin/chmod 600 $dest + /usr/bin/chown nagios:nagios $dest + else + echo "Existing $dest has been found --" + echo " installing $destbase as $dest.pkgnew" + /usr/bin/cp $src $dest.pkgnew + /usr/bin/chmod 600 $dest.pkgnew + /usr/bin/chown nagios:nagios $dest.pkgnew + fi + else + echo "Existing $dest has been found --" + echo " installing $destbase as $dest.pkgnew" + /usr/bin/cp $src $dest.pkgnew + /usr/bin/chmod 600 $dest.pkgnew + /usr/bin/chown nagios:nagios $dest.pkgnew + fi + else + create_cksum_file $src $dest $cksumfile + /usr/bin/cp $src $dest + /usr/bin/chmod 600 $dest + /usr/bin/chown nagios:nagios $dest + fi +done +if [ "$1" = "ENDOFCLASS" ] ; then + exit 0 +fi diff -Nru nagios-nrpe-2.13/package/solaris/pkg/nrpe nagios-nrpe-2.15/package/solaris/pkg/nrpe --- nagios-nrpe-2.13/package/solaris/pkg/nrpe 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/package/solaris/pkg/nrpe 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,32 @@ +#!/sbin/sh +# + +NRPE=/opt/nagios/bin/nrpe +CFGFILE=/etc/nagios/nrpe.cfg +PIDFILE=/var/run/nrpe.pid + +case $1 in +'start') + $NRPE -c $CFGFILE -d + ;; + +'restart') + if [ -f "$PIDFILE" ]; then + /usr/bin/kill -HUP `/usr/bin/cat $PIDFILE` + fi + ;; + +'stop') + if [ -f "$PIDFILE" ]; then + /usr/bin/kill `/usr/bin/cat $PIDFILE` + /bin/rm -f $PIDFILE + fi + ;; + +*) + echo "Usage: $0 { start | restart | stop }" + exit 1 + ;; +esac + +exit $? diff -Nru nagios-nrpe-2.13/package/solaris/pkg/nrpe.xml nagios-nrpe-2.15/package/solaris/pkg/nrpe.xml --- nagios-nrpe-2.13/package/solaris/pkg/nrpe.xml 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/package/solaris/pkg/nrpe.xml 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru nagios-nrpe-2.13/package/solaris/pkg/postinstall nagios-nrpe-2.15/package/solaris/pkg/postinstall --- nagios-nrpe-2.13/package/solaris/pkg/postinstall 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/package/solaris/pkg/postinstall 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,5 @@ +#!/usr/bin/sh + +echo "To begin using NRPE, first edit /etc/nagios/nrpe.cfg, update the" +echo "allowed_hosts line and any command lines. Then start the nrpe service" +echo "by running the command 'svcadm enable nrpe' as root." diff -Nru nagios-nrpe-2.13/package/solaris/pkg/preinstall nagios-nrpe-2.15/package/solaris/pkg/preinstall --- nagios-nrpe-2.13/package/solaris/pkg/preinstall 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/package/solaris/pkg/preinstall 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,35 @@ +#!/usr/bin/sh + +user="nagios" +uid=-1 +group="nagios" +gid=-1 + +/usr/bin/getent group $group > /dev/null 2> /dev/null +result=$? +if [ $result -eq 2 ] ; then + echo "Group $group does not exist. Creating..." + if [ $gid -ne -1 ] ; then + /usr/sbin/groupadd -g $gid $group + else + /usr/sbin/groupadd $group + fi +elif [ $result -ne 0 ] ; then + echo "An error occurred determining the existence of the groug $group. Terminating." + exit 1; +fi + +/usr/bin/getent passwd $user > /dev/null 2> /dev/null +result=$? +if [ $result -eq 2 ] ; then + echo "User $user does not exist. Creating..." + if [ $uid -ne -1 ] ; then + /usr/sbin/useradd -u $uid -g $group $user + else + /usr/sbin/useradd -g $group $user + fi +elif [ $result -ne 0 ] ; then + echo "An error occurred determining the existence of the user $user. Terminating." + exit 1; +fi + diff -Nru nagios-nrpe-2.13/package/solaris/pkg/r.config nagios-nrpe-2.15/package/solaris/pkg/r.config --- nagios-nrpe-2.13/package/solaris/pkg/r.config 1970-01-01 00:00:00.000000000 +0000 +++ nagios-nrpe-2.15/package/solaris/pkg/r.config 2013-09-06 15:27:13.000000000 +0000 @@ -0,0 +1,33 @@ +#!/usr/bin/sh + +compare_cksum() { + destfile=$1 + cksumfile=$2 + + installed_cksum=`/usr/bin/tail -1 $cksumfile | /usr/bin/awk '{print $1}'` + current_cksum=`/usr/bin/cksum $destfile | /usr/bin/awk '{print $1}'` + test $installed_cksum = $current_cksum +} + +while read path ; do + destpath=`echo $path | /usr/bin/sed -e 's/\/[^/]*$//'` + destbase=`/usr/bin/basename $path` + cksumfile="${destpath}/.${destbase}.cksum" + if [ -f $path ] ; then + if [ -f $cksumfile ] ; then + compare_cksum $path $cksumfile + if [ $? -eq 0 ] ; then + /usr/bin/rm -f $path $cksumfile + else + echo "$path has been modified since it was installed -- " + echo " leaving it in place." + fi + else + echo "$path may have been modified since it was installed -- " + echo " leaving it in place." + fi + fi +done +if [ "$1" = "ENDOFCLASS" ] ; then + exit 0 +fi diff -Nru nagios-nrpe-2.13/sample-config/nrpe.cfg.in nagios-nrpe-2.15/sample-config/nrpe.cfg.in --- nagios-nrpe-2.13/sample-config/nrpe.cfg.in 2011-11-04 18:57:41.000000000 +0000 +++ nagios-nrpe-2.15/sample-config/nrpe.cfg.in 2013-09-06 15:27:13.000000000 +0000 @@ -98,6 +98,24 @@ +# BASH COMMAND SUBTITUTION +# This option determines whether or not the NRPE daemon will allow clients +# to specify arguments that contain bash command substitutions of the form +# $(...). This option only works if the daemon was configured with both +# the --enable-command-args and --enable-bash-command-substitution configure +# script options. +# +# *** ENABLING THIS OPTION IS A HIGH SECURITY RISK! *** +# Read the SECURITY file for information on some of the security implications +# of enabling this variable. +# +# Values: 0=do not allow bash command substitutions, +# 1=allow bash command substitutions + +allow_bash_command_substitution=0 + + + # COMMAND PREFIX # This option allows you to prefix all commands with a user-defined string. # A space is automatically added between the specified prefix string and the diff -Nru nagios-nrpe-2.13/src/Makefile.in nagios-nrpe-2.15/src/Makefile.in --- nagios-nrpe-2.13/src/Makefile.in 2011-11-04 18:57:41.000000000 +0000 +++ nagios-nrpe-2.15/src/Makefile.in 2013-09-06 15:27:13.000000000 +0000 @@ -4,12 +4,14 @@ # Last Modified: 08-13-2007 ############################### +srcdir=@srcdir@ # Source code directories -SRC_INCLUDE=../include +SRC_INCLUDE=@srcdir@/../include +CFG_INCLUDE=../include CC=@CC@ -CFLAGS=@CFLAGS@ @DEFS@ +CFLAGS=@CFLAGS@ @DEFS@ -I $(CFG_INCLUDE) -I $(SRC_INCLUDE) LDFLAGS=@LDFLAGS@ @LIBS@ SOCKETLIBS=@SOCKETLIBS@ LIBWRAPLIBS=@LIBWRAPLIBS@ @@ -33,11 +35,11 @@ all: nrpe check_nrpe -nrpe: nrpe.c utils.c acl.c $(SRC_INCLUDE)/nrpe.h $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/acl.h $(SNPRINTF_O) - $(CC) $(CFLAGS) -o $@ nrpe.c utils.c acl.c $(LDFLAGS) $(SOCKETLIBS) $(LIBWRAPLIBS) $(SNPRINTF_O) $(OTHERLIBS) +nrpe: $(srcdir)/nrpe.c $(srcdir)/utils.c $(srcdir)/acl.c $(SRC_INCLUDE)/nrpe.h $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(CFG_INCLUDE)/config.h $(SRC_INCLUDE)/acl.h $(SNPRINTF_O) + $(CC) $(CFLAGS) -o $@ $(srcdir)/nrpe.c $(srcdir)/utils.c $(srcdir)/acl.c $(LDFLAGS) $(SOCKETLIBS) $(LIBWRAPLIBS) $(SNPRINTF_O) $(OTHERLIBS) -check_nrpe: check_nrpe.c utils.c $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/config.h - $(CC) $(CFLAGS) -o $@ check_nrpe.c utils.c $(LDFLAGS) $(SOCKETLIBS) $(OTHERLIBS) +check_nrpe: $(srcdir)/check_nrpe.c $(srcdir)/utils.c $(SRC_INCLUDE)/utils.h $(SRC_INCLUDE)/common.h $(CFG_INCLUDE)/config.h + $(CC) $(CFLAGS) -o $@ $(srcdir)/check_nrpe.c $(srcdir)/utils.c $(LDFLAGS) $(SOCKETLIBS) $(OTHERLIBS) install: $(MAKE) install-plugin @@ -54,6 +56,7 @@ clean: rm -f core nrpe check_nrpe $(SNPRINTF_O) rm -f *~ */*~ + rm -rf nrpe.dSYM check_nrpe.dSYM distclean: clean rm -f Makefile diff -Nru nagios-nrpe-2.13/src/acl.c nagios-nrpe-2.15/src/acl.c --- nagios-nrpe-2.13/src/acl.c 2011-11-04 18:57:41.000000000 +0000 +++ nagios-nrpe-2.15/src/acl.c 2013-09-06 15:27:13.000000000 +0000 @@ -234,6 +234,7 @@ } /* Save result in ACL ip list */ + ip_acl_curr->family = AF_INET; ip_acl_curr->addr.s_addr = ip; ip_acl_curr->mask.s_addr = mask; ip_acl_curr->next = NULL; @@ -248,6 +249,107 @@ } /* + * Add IPv6 host or network to IP ACL. Host will be added to ACL only if + * it has passed IPv6 format check. + * + */ + +int add_ipv6_to_acl(char *ipv6) { + char *ipv6tmp; + char *addrtok; + char *addrsave; + struct in6_addr addr; + struct in6_addr mask; + int maskval; + int byte, bit; + int nbytes = sizeof(mask.s6_addr) / sizeof(mask.s6_addr[0]); + int x; + struct ip_acl *ip_acl_curr; + + /* Save temporary copy of ipv6 so we can use the original in error + messages if needed */ + ipv6tmp = strdup(ipv6); + if(NULL == ipv6tmp) { + syslog(LOG_ERR, "Memory allocation failed for copy of address: %s\n", + ipv6); + return 0; + } + + /* Parse the address itself */ + addrtok = strtok_r(ipv6tmp, "/", &addrsave); + if(inet_pton(AF_INET6, addrtok, &addr) <= 0) { + syslog(LOG_ERR, "Invalid IPv6 address in ACL: %s\n", ipv6); + free(ipv6tmp); + return 0; + } + + /* Check whether there is a netmask */ + addrtok = strtok_r(NULL, "/", &addrsave); + if(NULL != addrtok) { + /* If so, build a netmask */ + + /* Get the number of bits in the mask */ + maskval = atoi(addrtok); + if(maskval < 0 || maskval > 128) { + syslog(LOG_ERR, "Invalid IPv6 netmask in ACL: %s\n", ipv6); + free(ipv6tmp); + return 0; + } + + /* Initialize to zero */ + for(x = 0; x < nbytes; x++) { + mask.s6_addr[x] = 0; + } + + /* Set mask based on mask bits */ + byte = 0; + bit = 7; + while(maskval > 0) { + mask.s6_addr[byte] |= 1 << bit; + bit -= 1; + if(bit < 0) { + bit = 7; + byte++; + } + maskval--; + } + } + else { + /* Otherwise, this is a single address */ + for(x = 0; x < nbytes; x++) { + mask.s6_addr[x] = 0xFF; + } + } + + /* Add address to ip_acl list */ + ip_acl_curr = malloc(sizeof(*ip_acl_curr)); + if(NULL == ip_acl_curr) { + syslog(LOG_ERR, "Memory allocation failed for ACL: %s\n", ipv6); + return 0; + } + + /* Save result in ACL ip list */ + ip_acl_curr->family = AF_INET6; + for(x = 0; x < nbytes; x++) { + ip_acl_curr->addr6.s6_addr[x] = + addr.s6_addr[x] & mask.s6_addr[x]; + ip_acl_curr->mask6.s6_addr[x] = mask.s6_addr[x]; + } + ip_acl_curr->next = NULL; + + if(NULL == ip_acl_head) { + ip_acl_head = ip_acl_curr; + } + else { + ip_acl_prev->next = ip_acl_curr; + } + ip_acl_prev = ip_acl_curr; + + free(ipv6tmp); + return 1; + } + +/* * Add domain to DNS ACL list * Domain will be added only if it has passed domain name check. * @@ -356,33 +458,74 @@ * 0 - on failure */ -int is_an_allowed_host(struct in_addr host) { - struct ip_acl *ip_acl_curr = ip_acl_head; - struct dns_acl *dns_acl_curr = dns_acl_head; - struct in_addr addr; - struct hostent *he; - - while (ip_acl_curr != NULL) { - if ( (host.s_addr & ip_acl_curr->mask.s_addr) == ip_acl_curr->addr.s_addr) - return 1; - - ip_acl_curr = ip_acl_curr->next; +int is_an_allowed_host(int family, void *host) { + struct ip_acl *ip_acl_curr = ip_acl_head; + int nbytes; + int x; + struct dns_acl *dns_acl_curr = dns_acl_head; + struct in_addr addr; + struct in6_addr addr6; + struct hostent *he; + + while (ip_acl_curr != NULL) { + if(ip_acl_curr->family == family) { + switch(ip_acl_curr->family) { + case AF_INET: + if((((struct in_addr *)host)->s_addr & + ip_acl_curr->mask.s_addr) == + ip_acl_curr->addr.s_addr) { + return 1; + } + break; + case AF_INET6: + nbytes = sizeof(ip_acl_curr->mask6.s6_addr) / + sizeof(ip_acl_curr->mask6.s6_addr[0]); + for(x = 0; x < nbytes; x++) { + if((((struct in6_addr *)host)->s6_addr[x] & + ip_acl_curr->mask6.s6_addr[x]) != + ip_acl_curr->addr6.s6_addr[x]) { + break; + } + } + if(x == nbytes) { + /* All bytes in host's address pass the netmask mask */ + return 1; + } + break; + } + } + ip_acl_curr = ip_acl_curr->next; } - while(dns_acl_curr != NULL) { - he = gethostbyname(dns_acl_curr->domain); - if (he == NULL) - return 0; - - while (*he->h_addr_list) { - memmove((char *)&addr,*he->h_addr_list++, sizeof(addr)); - if (addr.s_addr == host.s_addr) - return 1; - } - dns_acl_curr = dns_acl_curr->next; - } - return 0; -} + while(dns_acl_curr != NULL) { + he = gethostbyname(dns_acl_curr->domain); + if (he == NULL) return 0; + + while (*he->h_addr_list) { + switch(he->h_addrtype) { + case AF_INET: + memmove((char *)&addr,*he->h_addr_list++, sizeof(addr)); + if (addr.s_addr == ((struct in_addr *)host)->s_addr) return 1; + break; + case AF_INET6: + memcpy((char *)&addr6, *he->h_addr_list++, sizeof(addr6)); + for(x = 0; x < nbytes; x++) { + if(addr6.s6_addr[x] != + ((struct in6_addr *)host)->s6_addr[x]) { + break; + } + } + if(x == nbytes) { + /* All bytes in host's address match the ACL */ + return 1; + } + break; + } + } + dns_acl_curr = dns_acl_curr->next; + } + return 0; + } /* The trim() function takes a source string and copies it to the destination string, * stripped of leading and training whitespace. The destination string must be @@ -420,7 +563,8 @@ trimmed_tok = malloc( sizeof( char) * ( strlen( tok) + 1)); trim( tok, trimmed_tok); if( strlen( trimmed_tok) > 0) { - if (!add_ipv4_to_acl(trimmed_tok) && !add_domain_to_acl(trimmed_tok)) { + if (!add_ipv4_to_acl(trimmed_tok) && !add_ipv6_to_acl(trimmed_tok) + && !add_domain_to_acl(trimmed_tok)) { syslog(LOG_ERR,"Can't add to ACL this record (%s). Check allowed_hosts option!\n",trimmed_tok); } } diff -Nru nagios-nrpe-2.13/src/check_nrpe.c nagios-nrpe-2.15/src/check_nrpe.c --- nagios-nrpe-2.13/src/check_nrpe.c 2011-11-11 18:45:49.000000000 +0000 +++ nagios-nrpe-2.15/src/check_nrpe.c 2013-09-06 15:27:13.000000000 +0000 @@ -1,462 +1,490 @@ -/******************************************************************************************** - * - * CHECK_NRPE.C - NRPE Plugin For Nagios - * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org) - * License: GPL - * - * Last Modified: 11-11-2011 - * - * Command line: CHECK_NRPE -H [-p port] [-c command] [-to to_sec] - * - * Description: - * - * This plugin will attempt to connect to the NRPE daemon on the specified server and port. - * The daemon will attempt to run the command defined as [command]. Program output and - * return code are sent back from the daemon and displayed as this plugin's own output and - * return code. - * - ********************************************************************************************/ - -#include "../include/common.h" -#include "../include/config.h" -#include "../include/utils.h" - - -#define DEFAULT_NRPE_COMMAND "_NRPE_CHECK" /* check version of NRPE daemon */ - -int server_port=DEFAULT_SERVER_PORT; -char *server_name=NULL; -char *command_name=NULL; -int socket_timeout=DEFAULT_SOCKET_TIMEOUT; -int timeout_return_code=STATE_CRITICAL; -int sd; - -char query[MAX_INPUT_BUFFER]=""; - -int show_help=FALSE; -int show_license=FALSE; -int show_version=FALSE; - -#ifdef HAVE_SSL -SSL_METHOD *meth; -SSL_CTX *ctx; -SSL *ssl; -int use_ssl=TRUE; -#else -int use_ssl=FALSE; -#endif - - -int process_arguments(int,char **); -void alarm_handler(int); -int graceful_close(int,int); - - - - -int main(int argc, char **argv){ - u_int32_t packet_crc32; - u_int32_t calculated_crc32; - int16_t result; - int rc; - packet send_packet; - packet receive_packet; - int bytes_to_send; - int bytes_to_recv; - - result=process_arguments(argc,argv); - - if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){ - - if(result!=OK) - printf("Incorrect command line arguments supplied\n"); - printf("\n"); - printf("NRPE Plugin for Nagios\n"); - printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n"); - printf("Version: %s\n",PROGRAM_VERSION); - printf("Last Modified: %s\n",MODIFICATION_DATE); - printf("License: GPL v2 with exemptions (-l for more info)\n"); -#ifdef HAVE_SSL - printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); -#endif - printf("\n"); - } - - if(result!=OK || show_help==TRUE){ - - printf("Usage: check_nrpe -H [-n] [-u] [-p ] [-t ] [-c ] [-a ]\n"); - printf("\n"); - printf("Options:\n"); - printf(" -n = Do no use SSL\n"); - printf(" -u = Make socket timeouts return an UNKNOWN state instead of CRITICAL\n"); - printf(" = The address of the host running the NRPE daemon\n"); - printf(" [port] = The port on which the daemon is running (default=%d)\n",DEFAULT_SERVER_PORT); - printf(" [timeout] = Number of seconds before connection times out (default=%d)\n",DEFAULT_SOCKET_TIMEOUT); - printf(" [command] = The name of the command that the remote daemon should run\n"); - printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n"); - printf(" arguments should be separated by a space. If provided, this must be\n"); - printf(" the last option supplied on the command line.\n"); - printf("\n"); - printf("Note:\n"); - printf("This plugin requires that you have the NRPE daemon running on the remote host.\n"); - printf("You must also have configured the daemon to associate a specific plugin command\n"); - printf("with the [command] option you are specifying here. Upon receipt of the\n"); - printf("[command] argument, the NRPE daemon will run the appropriate plugin command and\n"); - printf("send the plugin output and return code back to *this* plugin. This allows you\n"); - printf("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n"); - printf("the plugin is being run locally.\n"); - printf("\n"); - } - - if(show_license==TRUE) - display_license(); - - if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE) - exit(STATE_UNKNOWN); - - - /* generate the CRC 32 table */ - generate_crc32_table(); - -#ifdef HAVE_SSL - /* initialize SSL */ - if(use_ssl==TRUE){ - SSL_library_init(); - SSLeay_add_ssl_algorithms(); - meth=SSLv23_client_method(); - SSL_load_error_strings(); - if((ctx=SSL_CTX_new(meth))==NULL){ - printf("CHECK_NRPE: Error - could not create SSL context.\n"); - exit(STATE_CRITICAL); - } - - /* ADDED 01/19/2004 */ - /* use only TLSv1 protocol */ - SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - } -#endif - - /* initialize alarm signal handling */ - signal(SIGALRM,alarm_handler); - - /* set socket timeout */ - alarm(socket_timeout); - - /* try to connect to the host at the given port number */ - result=my_tcp_connect(server_name,server_port,&sd); - -#ifdef HAVE_SSL - /* do SSL handshake */ - if(result==STATE_OK && use_ssl==TRUE){ - if((ssl=SSL_new(ctx))!=NULL){ - SSL_CTX_set_cipher_list(ctx,"ADH"); - SSL_set_fd(ssl,sd); - if((rc=SSL_connect(ssl))!=1){ - printf("CHECK_NRPE: Error - Could not complete SSL handshake.\n"); -#ifdef DEBUG - printf("SSL_connect=%d\n",rc); - /* - rc=SSL_get_error(ssl,rc); - printf("SSL_get_error=%d\n",rc); - printf("ERR_get_error=%lu\n",ERR_get_error()); - printf("%s\n",ERR_error_string(rc,NULL)); - */ - ERR_print_errors_fp(stdout); -#endif - result=STATE_CRITICAL; - } - } - else{ - printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n"); - result=STATE_CRITICAL; - } - - /* bail if we had errors */ - if(result!=STATE_OK){ - SSL_CTX_free(ctx); - close(sd); - exit(result); - } - } -#endif - - /* we're connected and ready to go */ - if(result==STATE_OK){ - - /* clear the packet buffer */ - bzero(&send_packet,sizeof(send_packet)); - - /* 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,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); - if(use_ssl==FALSE) - rc=sendall(sd,(char *)&send_packet,&bytes_to_send); -#ifdef HAVE_SSL - else{ - rc=SSL_write(ssl,&send_packet,bytes_to_send); - if(rc<0) - rc=-1; - } -#endif - if(rc==-1){ - printf("CHECK_NRPE: Error sending query to host.\n"); - close(sd); - return STATE_UNKNOWN; - } - - /* wait for the response packet */ - bytes_to_recv=sizeof(receive_packet); - if(use_ssl==FALSE) - rc=recvall(sd,(char *)&receive_packet,&bytes_to_recv,socket_timeout); -#ifdef HAVE_SSL - else - rc=SSL_read(ssl,&receive_packet,bytes_to_recv); -#endif - - /* reset timeout */ - alarm(0); - - /* close the connection */ -#ifdef HAVE_SSL - if(use_ssl==TRUE){ - SSL_shutdown(ssl); - SSL_free(ssl); - SSL_CTX_free(ctx); - } -#endif - graceful_close(sd,1000); - - /* recv() error */ - if(rc<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 from daemon. Check the remote server logs for error messages.\n"); - return STATE_UNKNOWN; - } - - /* receive underflow */ - else if(bytes_to_recv0){ - - for(c=argindex-1;c=recv(sd,buf,sizeof(buf),0)) - break; - } - -#ifdef HAVE_CLOSESOCKET - closesocket(sd); -#else - close(sd); -#endif - - return OK; - } +/******************************************************************************************** + * + * CHECK_NRPE.C - NRPE Plugin For Nagios + * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org) + * License: GPL + * + * Last Modified: 09-06-2013 + * + * Command line: CHECK_NRPE -H [-p port] [-c command] [-to to_sec] + * + * Description: + * + * This plugin will attempt to connect to the NRPE daemon on the specified server and port. + * The daemon will attempt to run the command defined as [command]. Program output and + * return code are sent back from the daemon and displayed as this plugin's own output and + * return code. + * + ********************************************************************************************/ + +#include "config.h" +#include "common.h" +#include "utils.h" + + +#define DEFAULT_NRPE_COMMAND "_NRPE_CHECK" /* check version of NRPE daemon */ + +u_short server_port=DEFAULT_SERVER_PORT; +char *server_name=NULL; +char *bind_address=NULL; +struct sockaddr_storage hostaddr; +int address_family=AF_UNSPEC; +char *command_name=NULL; +int socket_timeout=DEFAULT_SOCKET_TIMEOUT; +int timeout_return_code=STATE_CRITICAL; +int sd; + +char query[MAX_INPUT_BUFFER]=""; + +int show_help=FALSE; +int show_license=FALSE; +int show_version=FALSE; + +#ifdef HAVE_SSL +#ifdef __sun +SSL_METHOD *meth; +#else +const SSL_METHOD *meth; +#endif +SSL_CTX *ctx; +SSL *ssl; +int use_ssl=TRUE; +#else +int use_ssl=FALSE; +#endif + + +int process_arguments(int,char **); +void alarm_handler(int); +int graceful_close(int,int); + + + + +int main(int argc, char **argv){ + u_int32_t packet_crc32; + u_int32_t calculated_crc32; + int16_t result; + int rc; + packet send_packet; + packet receive_packet; + int bytes_to_send; + int bytes_to_recv; + + result=process_arguments(argc,argv); + + if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){ + + if(result!=OK) + printf("Incorrect command line arguments supplied\n"); + printf("\n"); + printf("NRPE Plugin for Nagios\n"); + printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n"); + printf("Version: %s\n",PROGRAM_VERSION); + printf("Last Modified: %s\n",MODIFICATION_DATE); + printf("License: GPL v2 with exemptions (-l for more info)\n"); +#ifdef HAVE_SSL + printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); +#endif + printf("\n"); + } + + if(result!=OK || show_help==TRUE){ + + printf("Usage: check_nrpe -H [ -b ] [-4] [-6] [-n] [-u] [-p ] [-t ] [-c ] [-a ]\n"); + printf("\n"); + printf("Options:\n"); + printf(" -n = Do no use SSL\n"); + printf(" -u = Make socket timeouts return an UNKNOWN state instead of CRITICAL\n"); + printf(" = The address of the host running the NRPE daemon\n"); + printf(" = bind to local address\n"); + printf(" -4 = user ipv4 only\n"); + printf(" -6 = user ipv6 only\n"); + printf(" [port] = The port on which the daemon is running (default=%d)\n",DEFAULT_SERVER_PORT); + printf(" [timeout] = Number of seconds before connection times out (default=%d)\n",DEFAULT_SOCKET_TIMEOUT); + printf(" [command] = The name of the command that the remote daemon should run\n"); + printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n"); + printf(" arguments should be separated by a space. If provided, this must be\n"); + printf(" the last option supplied on the command line.\n"); + printf("\n"); + printf("Note:\n"); + printf("This plugin requires that you have the NRPE daemon running on the remote host.\n"); + printf("You must also have configured the daemon to associate a specific plugin command\n"); + printf("with the [command] option you are specifying here. Upon receipt of the\n"); + printf("[command] argument, the NRPE daemon will run the appropriate plugin command and\n"); + printf("send the plugin output and return code back to *this* plugin. This allows you\n"); + printf("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n"); + printf("the plugin is being run locally.\n"); + printf("\n"); + } + + if(show_license==TRUE) + display_license(); + + if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE) + exit(STATE_UNKNOWN); + + + /* generate the CRC 32 table */ + generate_crc32_table(); + +#ifdef HAVE_SSL + /* initialize SSL */ + if(use_ssl==TRUE){ + SSL_library_init(); + SSLeay_add_ssl_algorithms(); + meth=SSLv23_client_method(); + SSL_load_error_strings(); + if((ctx=SSL_CTX_new(meth))==NULL){ + printf("CHECK_NRPE: Error - could not create SSL context.\n"); + exit(STATE_CRITICAL); + } + + /* ADDED 01/19/2004 */ + /* use only TLSv1 protocol */ + SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + } +#endif + + /* initialize alarm signal handling */ + signal(SIGALRM,alarm_handler); + + /* set socket timeout */ + alarm(socket_timeout); + + /* try to connect to the host at the given port number */ + if((sd=my_connect(server_name, &hostaddr, server_port, address_family, + bind_address)) < 0 ) { + exit (255); + } + else { + result=STATE_OK; + } + +#ifdef HAVE_SSL + /* do SSL handshake */ + if(result==STATE_OK && use_ssl==TRUE){ + if((ssl=SSL_new(ctx))!=NULL){ + SSL_CTX_set_cipher_list(ctx,"ADH"); + SSL_set_fd(ssl,sd); + if((rc=SSL_connect(ssl))!=1){ + printf("CHECK_NRPE: Error - Could not complete SSL handshake.\n"); +#ifdef DEBUG + printf("SSL_connect=%d\n",rc); + /* + rc=SSL_get_error(ssl,rc); + printf("SSL_get_error=%d\n",rc); + printf("ERR_get_error=%lu\n",ERR_get_error()); + printf("%s\n",ERR_error_string(rc,NULL)); + */ + ERR_print_errors_fp(stdout); +#endif + result=STATE_CRITICAL; + } + } + else{ + printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n"); + result=STATE_CRITICAL; + } + + /* bail if we had errors */ + if(result!=STATE_OK){ + SSL_CTX_free(ctx); + close(sd); + exit(result); + } + } +#endif + + /* we're connected and ready to go */ + if(result==STATE_OK){ + + /* clear the packet buffer */ + bzero(&send_packet,sizeof(send_packet)); + + /* 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,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); + if(use_ssl==FALSE) + rc=sendall(sd,(char *)&send_packet,&bytes_to_send); +#ifdef HAVE_SSL + else{ + rc=SSL_write(ssl,&send_packet,bytes_to_send); + if(rc<0) + rc=-1; + } +#endif + if(rc==-1){ + printf("CHECK_NRPE: Error sending query to host.\n"); + close(sd); + return STATE_UNKNOWN; + } + + /* wait for the response packet */ + bytes_to_recv=sizeof(receive_packet); + if(use_ssl==FALSE) + rc=recvall(sd,(char *)&receive_packet,&bytes_to_recv,socket_timeout); +#ifdef HAVE_SSL + else + rc=SSL_read(ssl,&receive_packet,bytes_to_recv); +#endif + + /* reset timeout */ + alarm(0); + + /* close the connection */ +#ifdef HAVE_SSL + if(use_ssl==TRUE){ + SSL_shutdown(ssl); + SSL_free(ssl); + SSL_CTX_free(ctx); + } +#endif + graceful_close(sd,1000); + + /* recv() error */ + if(rc<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 from daemon. Check the remote server logs for error messages.\n"); + return STATE_UNKNOWN; + } + + /* receive underflow */ + else if(bytes_to_recv0){ + + for(c=argindex-1;c=recv(sd,buf,sizeof(buf),0)) + break; + } + +#ifdef HAVE_CLOSESOCKET + closesocket(sd); +#else + close(sd); +#endif + + return OK; + } diff -Nru nagios-nrpe-2.13/src/nrpe.c nagios-nrpe-2.15/src/nrpe.c --- nagios-nrpe-2.13/src/nrpe.c 2011-11-11 18:45:49.000000000 +0000 +++ nagios-nrpe-2.15/src/nrpe.c 2013-09-06 15:27:13.000000000 +0000 @@ -1,1912 +1,2162 @@ -/******************************************************************************* - * - * NRPE.C - Nagios Remote Plugin Executor - * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org) - * License: GPL - * - * Last Modified: 11-11-2011 - * - * Command line: nrpe -c [--inetd | --daemon] - * - * Description: - * - * This program is designed to run as a background process and - * handle incoming requests (from the host running Nagios) for - * plugin execution. It is useful for running "local" plugins - * such as check_users, check_load, check_disk, etc. without - * having to use rsh or ssh. - * - ******************************************************************************/ - -/* - * 08-10-2011 IPv4 subnetworks support added. - * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c. - * now allowed_hosts is parsed by parse_allowed_hosts() from acl.c. - */ - -#include "../include/common.h" -#include "../include/config.h" -#include "../include/nrpe.h" -#include "../include/utils.h" -#include "../include/acl.h" - -#ifdef HAVE_SSL -#include "../include/dh.h" -#endif - -#ifdef HAVE_LIBWRAP -int allow_severity=LOG_INFO; -int deny_severity=LOG_WARNING; -#endif - -#ifdef HAVE_SSL -SSL_METHOD *meth; -SSL_CTX *ctx; -int use_ssl=TRUE; -#else -int use_ssl=FALSE; -#endif - -#define DEFAULT_COMMAND_TIMEOUT 60 /* default timeout for execution of plugins */ -#define MAXFD 64 -#define NASTY_METACHARS "|`&><'\"\\[]{};" - -char *command_name=NULL; -char *macro_argv[MAX_COMMAND_ARGUMENTS]; - -char config_file[MAX_INPUT_BUFFER]="nrpe.cfg"; -int log_facility=LOG_DAEMON; -int server_port=DEFAULT_SERVER_PORT; -char server_address[16]="0.0.0.0"; -int socket_timeout=DEFAULT_SOCKET_TIMEOUT; -int command_timeout=DEFAULT_COMMAND_TIMEOUT; -int connection_timeout=DEFAULT_CONNECTION_TIMEOUT; -char *command_prefix=NULL; - -command *command_list=NULL; - -char *nrpe_user=NULL; -char *nrpe_group=NULL; - -char *allowed_hosts=NULL; - -char *pid_file=NULL; -int wrote_pid_file=FALSE; - -int allow_arguments=FALSE; - -int allow_weak_random_seed=FALSE; - -int sigrestart=FALSE; -int sigshutdown=FALSE; - -int show_help=FALSE; -int show_license=FALSE; -int show_version=FALSE; -int use_inetd=TRUE; -int debug=FALSE; - - - - -int main(int argc, char **argv){ - int result=OK; - int x; - char buffer[MAX_INPUT_BUFFER]; - char *env_string=NULL; -#ifdef HAVE_SSL - DH *dh; - char seedfile[FILENAME_MAX]; - int i,c; -#endif - - /* set some environment variables */ - asprintf(&env_string,"NRPE_MULTILINESUPPORT=1"); - putenv(env_string); - asprintf(&env_string,"NRPE_PROGRAMVERSION=%s",PROGRAM_VERSION); - putenv(env_string); - - /* process command-line args */ - result=process_arguments(argc,argv); - - if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){ - - printf("\n"); - printf("NRPE - Nagios Remote Plugin Executor\n"); - printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n"); - printf("Version: %s\n",PROGRAM_VERSION); - printf("Last Modified: %s\n",MODIFICATION_DATE); - printf("License: GPL v2 with exemptions (-l for more info)\n"); -#ifdef HAVE_SSL - printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); -#endif -#ifdef HAVE_LIBWRAP - printf("TCP Wrappers Available\n"); -#endif - 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 -#ifndef HAVE_LIBWRAP - printf("***************************************************************\n"); - printf("** POSSIBLE SECURITY RISK - TCP WRAPPERS ARE NOT AVAILABLE! **\n"); - printf("** Read the NRPE SECURITY file for more information **\n"); - printf("***************************************************************\n"); - printf("\n"); -#endif - } - - if(show_license==TRUE) - display_license(); - - else if(result!=OK || show_help==TRUE){ - - printf("Usage: nrpe [-n] -c \n"); - printf("\n"); - printf("Options:\n"); - printf(" -n = Do not use SSL\n"); - printf(" = Name of config file to use\n"); - printf(" = One of the following two operating modes:\n"); - printf(" -i = Run as a service under inetd or xinetd\n"); - printf(" -d = Run as a standalone daemon\n"); - printf("\n"); - printf("Notes:\n"); - printf("This program is designed to process requests from the check_nrpe\n"); - printf("plugin on the host(s) running Nagios. It can run as a service\n"); - printf("under inetd or xinetd (read the docs for info on this), or as a\n"); - printf("standalone daemon. Once a request is received from an authorized\n"); - printf("host, NRPE will execute the command/plugin (as defined in the\n"); - printf("config file) and return the plugin output and return code to the\n"); - printf("check_nrpe plugin.\n"); - printf("\n"); - } - - if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE) - exit(STATE_UNKNOWN); - - - /* open a connection to the syslog facility */ - /* facility name may be overridden later */ - get_log_facility(NRPE_LOG_FACILITY); - openlog("nrpe",LOG_PID,log_facility); - - /* make sure the config file uses an absolute path */ - if(config_file[0]!='/'){ - - /* save the name of the config file */ - strncpy(buffer,config_file,sizeof(buffer)); - buffer[sizeof(buffer)-1]='\x0'; - - /* get absolute path of current working directory */ - strcpy(config_file,""); - getcwd(config_file,sizeof(config_file)); - - /* append a forward slash */ - strncat(config_file,"/",sizeof(config_file)-2); - config_file[sizeof(config_file)-1]='\x0'; - - /* append the config file to the path */ - strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1); - config_file[sizeof(config_file)-1]='\x0'; - } - - /* read the config file */ - result=read_config_file(config_file); - - /* exit if there are errors... */ - if(result==ERROR){ - syslog(LOG_ERR,"Config file '%s' contained errors, aborting...",config_file); - return STATE_CRITICAL; - } - - /* generate the CRC 32 table */ - generate_crc32_table(); - - /* initialize macros */ - for(x=0;x=0;x--){ - if(isspace(input_line[x])) - input_line[x]='\x0'; - else - break; - } - - /* skip comments and blank lines */ - if(input_line[0]=='#') - continue; - if(input_line[0]=='\x0') - continue; - if(input_line[0]=='\n') - continue; - - /* get the variable name */ - varname=strtok(input_line,"="); - if(varname==NULL){ - syslog(LOG_ERR,"No variable name specified in config file '%s' - Line %d\n",filename,line); - return ERROR; - } - - /* get the variable value */ - varvalue=strtok(NULL,"\n"); - if(varvalue==NULL){ - syslog(LOG_ERR,"No variable value specified in config file '%s' - Line %d\n",filename,line); - return ERROR; - } - - /* allow users to specify directories to recurse into for config files */ - else if(!strcmp(varname,"include_dir")){ - - strncpy(config_file,varvalue,sizeof(config_file)-1); - config_file[sizeof(config_file)-1]='\x0'; - - /* strip trailing / if necessary */ - if(config_file[strlen(config_file)-1]=='/') - config_file[strlen(config_file)-1]='\x0'; - - /* process the config directory... */ - if(read_config_dir(config_file)==ERROR) - syslog(LOG_ERR,"Continuing with errors..."); - } - - /* allow users to specify individual config files to include */ - else if(!strcmp(varname,"include") || !strcmp(varname,"include_file")){ - - /* process the config file... */ - if(read_config_file(varvalue)==ERROR) - syslog(LOG_ERR,"Continuing with errors..."); - } - - else if(!strcmp(varname,"server_port")){ - server_port=atoi(varvalue); - if(server_port<1024){ - syslog(LOG_ERR,"Invalid port number specified in config file '%s' - Line %d\n",filename,line); - return ERROR; - } - } - else if(!strcmp(varname,"command_prefix")) - command_prefix=strdup(varvalue); - - else if(!strcmp(varname,"server_address")){ - strncpy(server_address,varvalue,sizeof(server_address) - 1); - server_address[sizeof(server_address)-1]='\0'; - } - else if(!strcmp(varname,"allowed_hosts")) { - allowed_hosts=strdup(varvalue); - parse_allowed_hosts(allowed_hosts); - } - else if(strstr(input_line,"command[")){ - temp_buffer=strtok(varname,"["); - temp_buffer=strtok(NULL,"]"); - if(temp_buffer==NULL){ - syslog(LOG_ERR,"Invalid command specified in config file '%s' - Line %d\n",filename,line); - return ERROR; - } - add_command(temp_buffer,varvalue); - } - - else if(strstr(input_buffer,"debug")){ - debug=atoi(varvalue); - if(debug>0) - debug=TRUE; - else - debug=FALSE; - } - - else if(!strcmp(varname,"nrpe_user")) - nrpe_user=strdup(varvalue); - - else if(!strcmp(varname,"nrpe_group")) - nrpe_group=strdup(varvalue); - - else if(!strcmp(varname,"dont_blame_nrpe")) - allow_arguments=(atoi(varvalue)==1)?TRUE:FALSE; - - else if(!strcmp(varname,"command_timeout")){ - command_timeout=atoi(varvalue); - if(command_timeout<1){ - syslog(LOG_ERR,"Invalid command_timeout specified in config file '%s' - Line %d\n",filename,line); - return ERROR; - } - } - - else if(!strcmp(varname,"connection_timeout")){ - connection_timeout=atoi(varvalue); - if(connection_timeout<1){ - syslog(LOG_ERR,"Invalid connection_timeout specified in config file '%s' - Line %d\n",filename,line); - return ERROR; - } - } - - else if(!strcmp(varname,"allow_weak_random_seed")) - allow_weak_random_seed=(atoi(varvalue)==1)?TRUE:FALSE; - - else if(!strcmp(varname,"pid_file")) - pid_file=strdup(varvalue); - - else if(!strcmp(varname,"log_facility")){ - if((get_log_facility(varvalue))==OK){ - /* re-open log using new facility */ - closelog(); - openlog("nrpe",LOG_PID,log_facility); - } - else - syslog(LOG_WARNING,"Invalid log_facility specified in config file '%s' - Line %d\n",filename,line); - } - - else{ - syslog(LOG_WARNING,"Unknown option specified in config file '%s' - Line %d\n",filename,line); - continue; - } - - } - - - /* close the config file */ - fclose(fp); - - return OK; - } - - -/* process all config files in a specific config directory (with directory recursion) */ -int read_config_dir(char *dirname){ - char config_file[MAX_FILENAME_LENGTH]; - DIR *dirp; - struct dirent *dirfile; - struct stat buf; - int result=OK; - int x; - - /* open the directory for reading */ - dirp=opendir(dirname); - if(dirp==NULL){ - syslog(LOG_ERR,"Could not open config directory '%s' for reading.\n",dirname); - return ERROR; - } - - /* process all files in the directory... */ - while((dirfile=readdir(dirp))!=NULL){ - - /* create the full path to the config file or subdirectory */ - snprintf(config_file,sizeof(config_file)-1,"%s/%s",dirname,dirfile->d_name); - config_file[sizeof(config_file)-1]='\x0'; - stat(config_file, &buf); - - /* process this if it's a config file... */ - x=strlen(dirfile->d_name); - if(x>4 && !strcmp(dirfile->d_name+(x-4),".cfg")){ - - /* only process normal files */ - if(!S_ISREG(buf.st_mode)) - continue; - - /* process the config file */ - result=read_config_file(config_file); - - /* break out if we encountered an error */ - if(result==ERROR) - break; - } - - /* recurse into subdirectories... */ - if(S_ISDIR(buf.st_mode)){ - - /* ignore current, parent and hidden directory entries */ - if(dirfile->d_name[0]=='.') - continue; - - /* process the config directory */ - result=read_config_dir(config_file); - - /* break out if we encountered an error */ - if(result==ERROR) - break; - } - } - - closedir(dirp); - - return result; - } - - - -/* determines facility to use with syslog */ -int get_log_facility(char *varvalue){ - - if(!strcmp(varvalue,"kern")) - log_facility=LOG_KERN; - else if(!strcmp(varvalue,"user")) - log_facility=LOG_USER; - else if(!strcmp(varvalue,"mail")) - log_facility=LOG_MAIL; - else if(!strcmp(varvalue,"daemon")) - log_facility=LOG_DAEMON; - else if(!strcmp(varvalue,"auth")) - log_facility=LOG_AUTH; - else if(!strcmp(varvalue,"syslog")) - log_facility=LOG_SYSLOG; - else if(!strcmp(varvalue,"lrp")) - log_facility=LOG_LPR; - else if(!strcmp(varvalue,"news")) - log_facility=LOG_NEWS; - else if(!strcmp(varvalue,"uucp")) - log_facility=LOG_UUCP; - else if(!strcmp(varvalue,"cron")) - log_facility=LOG_CRON; - else if(!strcmp(varvalue,"authpriv")) - log_facility=LOG_AUTHPRIV; - else if(!strcmp(varvalue,"ftp")) - log_facility=LOG_FTP; - else if(!strcmp(varvalue,"local0")) - log_facility=LOG_LOCAL0; - else if(!strcmp(varvalue,"local1")) - log_facility=LOG_LOCAL1; - else if(!strcmp(varvalue,"local2")) - log_facility=LOG_LOCAL2; - else if(!strcmp(varvalue,"local3")) - log_facility=LOG_LOCAL3; - else if(!strcmp(varvalue,"local4")) - log_facility=LOG_LOCAL4; - else if(!strcmp(varvalue,"local5")) - log_facility=LOG_LOCAL5; - else if(!strcmp(varvalue,"local6")) - log_facility=LOG_LOCAL6; - else if(!strcmp(varvalue,"local7")) - log_facility=LOG_LOCAL7; - else{ - log_facility=LOG_DAEMON; - return ERROR; - } - - return OK; - } - - - -/* adds a new command definition from the config file to the list in memory */ -int add_command(char *command_name, char *command_line){ - command *new_command; - - if(command_name==NULL || command_line==NULL) - return ERROR; - - /* allocate memory for the new command */ - new_command=(command *)malloc(sizeof(command)); - if(new_command==NULL) - return ERROR; - - new_command->command_name=strdup(command_name); - if(new_command->command_name==NULL){ - free(new_command); - return ERROR; - } - new_command->command_line=strdup(command_line); - if(new_command->command_line==NULL){ - free(new_command->command_name); - free(new_command); - return ERROR; - } - - /* add new command to head of list in memory */ - new_command->next=command_list; - command_list=new_command; - - if(debug==TRUE) - syslog(LOG_DEBUG,"Added command[%s]=%s\n",command_name,command_line); - - return OK; - } - - - -/* given a command name, find the structure in memory */ -command *find_command(char *command_name){ - command *temp_command; - - for(temp_command=command_list;temp_command!=NULL;temp_command=temp_command->next) - if(!strcmp(command_name,temp_command->command_name)) - return temp_command; - - return NULL; - } - - - -/* wait for incoming connection requests */ -void wait_for_connections(void){ - struct sockaddr_in myname; - struct sockaddr_in *nptr; - struct sockaddr addr; - int rc; - int sock, new_sd; - socklen_t addrlen; - pid_t pid; - int flag=1; - fd_set fdread; - struct timeval timeout; - int retval; -#ifdef HAVE_LIBWRAP - struct request_info req; -#endif - - /* create a socket for listening */ - sock=socket(AF_INET,SOCK_STREAM,0); - - /* exit if we couldn't create the socket */ - if(sock<0){ - syslog(LOG_ERR,"Network server socket failure (%d: %s)",errno,strerror(errno)); - exit(STATE_CRITICAL); - } - - /* socket should be non-blocking */ - fcntl(sock,F_SETFL,O_NONBLOCK); - - /* set the reuse address flag so we don't get errors when restarting */ - flag=1; - if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ - syslog(LOG_ERR,"Could not set reuse address option on socket!\n"); - exit(STATE_UNKNOWN); - } - - myname.sin_family=AF_INET; - myname.sin_port=htons(server_port); - bzero(&myname.sin_zero,8); - - /* what address should we bind to? */ - if(!strlen(server_address)) - myname.sin_addr.s_addr=INADDR_ANY; - - else if(!my_inet_aton(server_address,&myname.sin_addr)){ - syslog(LOG_ERR,"Server address is not a valid IP address\n"); - exit(STATE_CRITICAL); - } - - /* bind the address to the Internet socket */ - if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ - syslog(LOG_ERR,"Network server bind failure (%d: %s)\n",errno,strerror(errno)); - exit(STATE_CRITICAL); - } - - /* open the socket for listening */ - if(listen(sock,5)<0){ - syslog(LOG_ERR,"Network server listen failure (%d: %s)\n",errno,strerror(errno)); - exit(STATE_CRITICAL); - } - - /* log warning about command arguments */ -#ifdef ENABLE_COMMAND_ARGUMENTS - if(allow_arguments==TRUE) - syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments from clients!"); -#endif - - syslog(LOG_INFO,"Listening for connections on port %d\n",htons(myname.sin_port)); - - if(allowed_hosts) - syslog(LOG_INFO,"Allowing connections from: %s\n",allowed_hosts); - - /* listen for connection requests - fork() if we get one */ - while(1){ - - /* wait for a connection request */ - while(1){ - - /* wait until there's something to do */ - FD_ZERO(&fdread); - FD_SET(sock,&fdread); - timeout.tv_sec=0; - timeout.tv_usec=500000; - retval=select(sock+1,&fdread,NULL,&fdread,&timeout); - - /* bail out if necessary */ - if(sigrestart==TRUE || sigshutdown==TRUE) - break; - - /* error */ - if(retval<0) - continue; - - /* accept a new connection request */ - new_sd=accept(sock,0,0); - - /* some kind of error occurred... */ - if(new_sd<0){ - - /* bail out if necessary */ - if(sigrestart==TRUE || sigshutdown==TRUE) - break; - - /* retry */ - if(errno==EWOULDBLOCK || errno==EINTR) - continue; - - /* socket is nonblocking and we don't have a connection yet */ - if(errno==EAGAIN) - continue; - - /* fix for HP-UX 11.0 - just retry */ - if(errno==ENOBUFS) - continue; - - /* else handle the error later */ - break; - } - - /* connection was good */ - break; - } - - /* bail out if necessary */ - if(sigrestart==TRUE || sigshutdown==TRUE) - break; - - /* child process should handle the connection */ - pid=fork(); - if(pid==0){ - - /* fork again so we don't create zombies */ - pid=fork(); - if(pid==0){ - - /* hey, there was an error... */ - if(new_sd<0){ - - /* log error to syslog facility */ - syslog(LOG_ERR,"Network server accept failure (%d: %s)",errno,strerror(errno)); - - /* close socket prioer to exiting */ - close(sock); - - return; - } - - /* handle signals */ - signal(SIGQUIT,child_sighandler); - signal(SIGTERM,child_sighandler); - signal(SIGHUP,child_sighandler); - - /* grandchild does not need to listen for connections, so close the socket */ - close(sock); - - /* find out who just connected... */ - addrlen=sizeof(addr); - rc=getpeername(new_sd,&addr,&addrlen); - - if(rc<0){ - - /* log error to syslog facility */ - syslog(LOG_ERR,"Error: Network server getpeername() failure (%d: %s)",errno,strerror(errno)); - - /* close socket prior to exiting */ - close(new_sd); - - return; - } - - nptr=(struct sockaddr_in *)&addr; - - /* log info to syslog facility */ - if(debug==TRUE) - syslog(LOG_DEBUG,"Connection from %s port %d",inet_ntoa(nptr->sin_addr),nptr->sin_port); - - /* is this is a blessed machine? */ - if(allowed_hosts){ - switch(nptr->sin_family) { - case AF_INET: - if(!is_an_allowed_host(nptr->sin_addr)) { - /* log error to syslog facility */ - syslog(LOG_ERR,"Host %s is not allowed to talk to us!",inet_ntoa(nptr->sin_addr)); - - /* log info to syslog facility */ - if ( debug==TRUE ) - syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr)); - - /* close socket prior to exiting */ - close(new_sd); - exit(STATE_OK); - } else { - /* log info to syslog facility */ - if(debug==TRUE) - syslog(LOG_DEBUG,"Host address is in allowed_hosts"); - - } - break; - - case AF_INET6: - syslog(LOG_DEBUG,"Connection from %s closed. We don't support AF_INET6 addreess family in ACL\n", inet_ntoa(nptr->sin_addr)); - break; - } - } - -#ifdef HAVE_LIBWRAP - - /* Check whether or not connections are allowed from this host */ - request_init(&req,RQ_DAEMON,"nrpe",RQ_FILE,new_sd,0); - fromhost(&req); - - if(!hosts_access(&req)){ - - syslog(LOG_DEBUG,"Connection refused by TCP wrapper"); - - /* refuse the connection */ - refuse(&req); - close(new_sd); - - /* should not be reached */ - syslog(LOG_ERR,"libwrap refuse() returns!"); - exit(STATE_CRITICAL); - } -#endif - - /* handle the client connection */ - handle_connection(new_sd); - - /* log info to syslog facility */ - if(debug==TRUE) - syslog(LOG_DEBUG,"Connection from %s closed.",inet_ntoa(nptr->sin_addr)); - - /* close socket prior to exiting */ - close(new_sd); - - exit(STATE_OK); - } - - /* first child returns immediately, grandchild is inherited by INIT process -> no zombies... */ - else - exit(STATE_OK); - } - - /* parent ... */ - else{ - /* parent doesn't need the new connection */ - close(new_sd); - - /* parent waits for first child to exit */ - waitpid(pid,NULL,0); - } - } - - /* close the socket we're listening on */ - close(sock); - - return; - } - - -/* 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; -#ifdef DEBUG - FILE *errfp; -#endif -#ifdef HAVE_SSL - SSL *ssl=NULL; -#endif - - - /* log info to syslog facility */ - if(debug==TRUE) - syslog(LOG_DEBUG,"Handling the connection..."); - -#ifdef OLDSTUFF - /* socket should be non-blocking */ - fcntl(sock,F_SETFL,O_NONBLOCK); -#endif - - /* set connection handler */ - signal(SIGALRM,my_connection_sighandler); - alarm(connection_timeout); - -#ifdef HAVE_SSL - /* do SSL handshake */ - if(result==STATE_OK && use_ssl==TRUE){ - if((ssl=SSL_new(ctx))!=NULL){ - SSL_set_fd(ssl,sock); - - /* keep attempting the request if needed */ - while(((rc=SSL_accept(ssl))!=1) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); - - if(rc!=1){ - syslog(LOG_ERR,"Error: Could not complete SSL handshake. %d\n",SSL_get_error(ssl,rc)); -#ifdef DEBUG - errfp=fopen("/tmp/err.log","w"); - ERR_print_errors_fp(errfp); - fclose(errfp); -#endif - return; - } - } - else{ - syslog(LOG_ERR,"Error: Could not create SSL connection structure.\n"); -#ifdef DEBUG - errfp=fopen("/tmp/err.log","w"); - ERR_print_errors_fp(errfp); - fclose(errfp); -#endif - return; - } - } -#endif - - bytes_to_recv=sizeof(receive_packet); - if(use_ssl==FALSE) - rc=recvall(sock,(char *)&receive_packet,&bytes_to_recv,socket_timeout); -#ifdef HAVE_SSL - else{ - while(((rc=SSL_read(ssl,&receive_packet,bytes_to_recv))<=0) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); - } -#endif - - /* recv() error or client disconnect */ - if(rc<=0){ - - /* log error to syslog facility */ - syslog(LOG_ERR,"Could not read request from client, bailing out..."); - -#ifdef HAVE_SSL - if(ssl){ - SSL_shutdown(ssl); - SSL_free(ssl); - syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n"); - } -#endif - - return; - } - - /* we couldn't read the correct amount of data, so bail out */ - else if(bytes_to_recv!=sizeof(receive_packet)){ - - /* log error to syslog facility */ - syslog(LOG_ERR,"Data packet from client was too short, bailing out..."); - -#ifdef HAVE_SSL - if(ssl){ - SSL_shutdown(ssl); - SSL_free(ssl); - } -#endif - - return; - } - -#ifdef DEBUG - fp=fopen("/tmp/packet","w"); - if(fp){ - fwrite(&receive_packet,1,sizeof(receive_packet),fp); - fclose(fp); - } -#endif - - /* make sure the request is valid */ - if(validate_request(&receive_packet)==ERROR){ - - /* log an error */ - syslog(LOG_ERR,"Client request was invalid, bailing out..."); - - /* free memory */ - free(command_name); - command_name=NULL; - for(x=0;xcommand_line,sizeof(raw_command)-1); - else - snprintf(raw_command,sizeof(raw_command)-1,"%s %s",command_prefix,temp_command->command_line); - raw_command[sizeof(raw_command)-1]='\x0'; - process_macros(raw_command,processed_command,sizeof(processed_command)); - - /* log info to syslog facility */ - if(debug==TRUE) - syslog(LOG_DEBUG,"Running command: %s",processed_command); - - /* run the command */ - strcpy(buffer,""); - result=my_system(processed_command,command_timeout,&early_timeout,buffer,sizeof(buffer)); - - /* log debug info */ - if(debug==TRUE) - syslog(LOG_DEBUG,"Command completed with return code %d and output: %s",result,buffer); - - /* see if the command timed out */ - if(early_timeout==TRUE) - snprintf(buffer,sizeof(buffer)-1,"NRPE: Command timed out after %d seconds\n",command_timeout); - else if(!strcmp(buffer,"")) - snprintf(buffer,sizeof(buffer)-1,"NRPE: Unable to read output\n"); - - buffer[sizeof(buffer)-1]='\x0'; - - /* check return code bounds */ - if((result<0) || (result>3)){ - - /* log error to syslog facility */ - syslog(LOG_ERR,"Bad return code for [%s]: %d", buffer,result); - - result=STATE_UNKNOWN; - } - } - } - - /* free memory */ - free(command_name); - command_name=NULL; - for(x=0;xnext; - if(this_command->command_name) - free(this_command->command_name); - if(this_command->command_line) - free(this_command->command_line); - free(this_command); - this_command=next_command; - } - - command_list=NULL; - - return; - } - - - -/* executes a system command via popen(), but protects against timeouts */ -int my_system(char *command,int timeout,int *early_timeout,char *output,int output_length){ - pid_t pid; - int status; - int result; - extern int errno; - char buffer[MAX_INPUT_BUFFER]; - int fd[2]; - FILE *fp; - int bytes_read=0; - time_t start_time,end_time; - - /* initialize return variables */ - if(output!=NULL) - strcpy(output,""); - *early_timeout=FALSE; - - /* if no command was passed, return with no error */ - if(command==NULL) - return STATE_OK; - - /* create a pipe */ - pipe(fd); - - /* make the pipe non-blocking */ - fcntl(fd[0],F_SETFL,O_NONBLOCK); - fcntl(fd[1],F_SETFL,O_NONBLOCK); - - /* get the command start time */ - time(&start_time); - - /* fork */ - pid=fork(); - - /* return an error if we couldn't fork */ - if(pid==-1){ - - snprintf(buffer,sizeof(buffer)-1,"NRPE: Call to fork() failed\n"); - buffer[sizeof(buffer)-1]='\x0'; - - if(output!=NULL){ - strncpy(output,buffer,output_length-1); - output[output_length-1]='\x0'; - } - - /* close both ends of the pipe */ - close(fd[0]); - close(fd[1]); - - return STATE_UNKNOWN; - } - - /* execute the command in the child process */ - if(pid==0){ - - /* close pipe for reading */ - close(fd[0]); - - /* become process group leader */ - setpgid(0,0); - - /* trap commands that timeout */ - signal(SIGALRM,my_system_sighandler); - alarm(timeout); - - /* run the command */ - fp=popen(command,"r"); - - /* report an error if we couldn't run the command */ - if(fp==NULL){ - - strncpy(buffer,"NRPE: Call to popen() failed\n",sizeof(buffer)-1); - buffer[sizeof(buffer)-1]='\x0'; - - /* write the error back to the parent process */ - write(fd[1],buffer,strlen(buffer)+1); - - result=STATE_CRITICAL; - } - else{ - - /* read all lines of output - supports Nagios 3.x multiline output */ - while((bytes_read=fread(buffer,1,sizeof(buffer)-1,fp))>0){ - - /* write the output back to the parent process */ - write(fd[1],buffer,bytes_read); - } - - /* close the command and get termination status */ - status=pclose(fp); - - /* report an error if we couldn't close the command */ - if(status==-1) - result=STATE_CRITICAL; - /* report an error if child died due to signal (Klas Lindfors) */ - else if(!WIFEXITED(status)) - result=STATE_CRITICAL; - else - result=WEXITSTATUS(status); - } - - /* close pipe for writing */ - close(fd[1]); - - /* reset the alarm */ - alarm(0); - - /* return plugin exit code to parent process */ - exit(result); - } - - /* parent waits for child to finish executing command */ - else{ - - /* close pipe for writing */ - close(fd[1]); - - /* wait for child to exit */ - waitpid(pid,&status,0); - - /* get the end time for running the command */ - time(&end_time); - - /* get the exit code returned from the program */ - result=WEXITSTATUS(status); - - /* because of my idiotic idea of having UNKNOWN states be equivalent to -1, I must hack things a bit... */ - if(result==255) - result=STATE_UNKNOWN; - - /* check bounds on the return value */ - if(result<0 || result>3) - result=STATE_UNKNOWN; - - /* try and read the results from the command output (retry if we encountered a signal) */ - if(output!=NULL){ - do{ - bytes_read=read(fd[0], output, output_length-1); - }while (bytes_read==-1 && errno==EINTR); - - if(bytes_read==-1) - *output='\0'; - else - output[bytes_read]='\0'; - } - - /* if there was a critical return code and no output AND the command time exceeded the timeout thresholds, assume a timeout */ - if(result==STATE_CRITICAL && bytes_read==-1 && (end_time-start_time)>=timeout){ - *early_timeout=TRUE; - - /* send termination signal to child process group */ - kill((pid_t)(-pid),SIGTERM); - kill((pid_t)(-pid),SIGKILL); - } - - /* close the pipe for reading */ - close(fd[0]); - } - -#ifdef DEBUG - printf("my_system() end\n"); -#endif - - return result; - } - - - -/* handle timeouts when executing commands via my_system() */ -void my_system_sighandler(int sig){ - - /* force the child process to exit... */ - exit(STATE_CRITICAL); - } - - -/* handle errors where connection takes too long */ -void my_connection_sighandler(int sig) { - - syslog(LOG_ERR,"Connection has taken too long to establish. Exiting..."); - - exit(STATE_CRITICAL); - } - - -/* drops privileges */ -int drop_privileges(char *user, char *group){ - uid_t uid=-1; - gid_t gid=-1; - struct group *grp; - struct passwd *pw; - - /* set effective group ID */ - if(group!=NULL){ - - /* see if this is a group name */ - if(strspn(group,"0123456789")gr_gid); - else - syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group); - endgrent(); - } - - /* else we were passed the GID */ - else - gid=(gid_t)atoi(group); - - /* set effective group ID if other than current EGID */ - if(gid!=getegid()){ - - if(setgid(gid)==-1) - syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid); - } - } - - - /* set effective user ID */ - if(user!=NULL){ - - /* see if this is a user name */ - if(strspn(user,"0123456789")pw_uid); - else - syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user); - endpwent(); - } - - /* else we were passed the UID */ - else - uid=(uid_t)atoi(user); - - /* set effective user ID if other than current EUID */ - if(uid!=geteuid()){ - -#ifdef HAVE_INITGROUPS - /* initialize supplementary groups */ - if(initgroups(user,gid)==-1){ - if(errno==EPERM) - syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()"); - else{ - syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()"); - return ERROR; - } - } -#endif - - if(setuid(uid)==-1) - syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid); - } - } - - return OK; - } - - -/* write an optional pid file */ -int write_pid_file(void){ - int fd; - int result=0; - pid_t pid=0; - char pbuf[16]; - - /* no pid file was specified */ - if(pid_file==NULL) - return OK; - - /* read existing pid file */ - if((fd=open(pid_file,O_RDONLY))>=0){ - - result=read(fd,pbuf,(sizeof pbuf)-1); - - close(fd); - - if(result>0){ - - pbuf[result]='\x0'; - pid=(pid_t)atoi(pbuf); - - /* if previous process is no longer running running, remove the old pid file */ - if(pid && (pid==getpid() || kill(pid,0)<0)) - unlink(pid_file); - - /* previous process is still running */ - else{ - syslog(LOG_ERR,"There's already an NRPE server running (PID %lu). Bailing out...",(unsigned long)pid); - return ERROR; - } - } - } - - /* write new pid file */ - if((fd=open(pid_file,O_WRONLY | O_CREAT,0644))>=0){ - sprintf(pbuf,"%d\n",(int)getpid()); - write(fd,pbuf,strlen(pbuf)); - close(fd); - wrote_pid_file=TRUE; - } - else{ - syslog(LOG_ERR,"Cannot write to pidfile '%s' - check your privileges.",pid_file); - } - - return OK; - } - - - -/* remove pid file */ -int remove_pid_file(void){ - - /* no pid file was specified */ - if(pid_file==NULL) - return OK; - - /* pid file was not written */ - if(wrote_pid_file==FALSE) - return OK; - - /* remove existing pid file */ - if(unlink(pid_file)==-1){ - syslog(LOG_ERR,"Cannot remove pidfile '%s' - check your privileges.",pid_file); - return ERROR; - } - - return OK; - } - - - -/* 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; - } - - - -/* handle signals (parent process) */ -void sighandler(int sig){ - static char *sigs[]={"EXIT","HUP","INT","QUIT","ILL","TRAP","ABRT","BUS","FPE","KILL","USR1","SEGV","USR2","PIPE","ALRM","TERM","STKFLT","CHLD","CONT","STOP","TSTP","TTIN","TTOU","URG","XCPU","XFSZ","VTALRM","PROF","WINCH","IO","PWR","UNUSED","ZERR","DEBUG",(char *)NULL}; - int i; - - if(sig<0) - sig=-sig; - - for(i=0;sigs[i]!=(char *)NULL;i++); - - sig%=i; - - /* we received a SIGHUP, so restart... */ - if(sig==SIGHUP){ - - sigrestart=TRUE; - - syslog(LOG_NOTICE,"Caught SIGHUP - restarting...\n"); - } - - /* else begin shutting down... */ - if(sig==SIGTERM){ - - /* if shutdown is already true, we're in a signal trap loop! */ - if(sigshutdown==TRUE) - exit(STATE_CRITICAL); - - sigshutdown=TRUE; - - syslog(LOG_NOTICE,"Caught SIG%s - shutting down...\n",sigs[sig]); - } - - return; - } - - - -/* handle signals (child processes) */ -void child_sighandler(int sig){ - - /* free all memory we allocated */ - free_memory(); - - /* terminate */ - exit(0); - - /* so the compiler doesn't complain... */ - return; - } - - - -/* tests whether or not a client request is valid */ -int validate_request(packet *pkt){ - u_int32_t packet_crc32; - u_int32_t calculated_crc32; - char *ptr; -#ifdef ENABLE_COMMAND_ARGUMENTS - int x; -#endif - - - /***** DECRYPT REQUEST ******/ - - - /* check the crc 32 value */ - packet_crc32=ntohl(pkt->crc32_value); - pkt->crc32_value=0L; - calculated_crc32=calculate_crc32((char *)pkt,sizeof(packet)); - if(packet_crc32!=calculated_crc32){ - syslog(LOG_ERR,"Error: Request packet had invalid CRC32."); - return ERROR; - } - - /* make sure this is the right type of packet */ - if(ntohs(pkt->packet_type)!=QUERY_PACKET || ntohs(pkt->packet_version)!=NRPE_PACKET_VERSION_2){ - syslog(LOG_ERR,"Error: Request packet type/version was invalid!"); - return ERROR; - } - - /* make sure buffer is terminated */ - pkt->buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0'; - - /* client must send some kind of request */ - if(!strcmp(pkt->buffer,"")){ - syslog(LOG_ERR,"Error: Request contained no query!"); - return ERROR; - } - - /* make sure request doesn't contain nasties */ - if(contains_nasty_metachars(pkt->buffer)==TRUE){ - syslog(LOG_ERR,"Error: Request contained illegal metachars!"); - return ERROR; - } - - /* make sure the request doesn't contain arguments */ - if(strchr(pkt->buffer,'!')){ -#ifdef ENABLE_COMMAND_ARGUMENTS - if(allow_arguments==FALSE){ - syslog(LOG_ERR,"Error: Request contained command arguments, but argument option is not enabled!"); - return ERROR; - } -#else - syslog(LOG_ERR,"Error: Request contained command arguments!"); - return ERROR; -#endif - } - - /* get command name */ -#ifdef ENABLE_COMMAND_ARGUMENTS - ptr=strtok(pkt->buffer,"!"); -#else - ptr=pkt->buffer; -#endif - command_name=strdup(ptr); - if(command_name==NULL){ - syslog(LOG_ERR,"Error: Memory allocation failed"); - return ERROR; - } - -#ifdef ENABLE_COMMAND_ARGUMENTS - /* get command arguments */ - if(allow_arguments==TRUE){ - - for(x=0;x=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){ - char optchars[MAX_INPUT_BUFFER]; - int c=1; - int have_mode=FALSE; - -#ifdef HAVE_GETOPT_LONG - int option_index=0; - static struct option long_options[]={ - {"config", required_argument, 0, 'c'}, - {"inetd", no_argument, 0, 'i'}, - {"daemon", no_argument, 0, 'd'}, - {"no-ssl", no_argument, 0, 'n'}, - {"help", no_argument, 0, 'h'}, - {"license", no_argument, 0, 'l'}, - {0, 0, 0, 0} - }; -#endif - - /* no options were supplied */ - if(argc<2) - return ERROR; - - snprintf(optchars,MAX_INPUT_BUFFER,"c:hVldin"); - - while(1){ -#ifdef HAVE_GETOPT_LONG - c=getopt_long(argc,argv,optchars,long_options,&option_index); -#else - c=getopt(argc,argv,optchars); -#endif - if(c==-1 || c==EOF) - break; - - /* process all arguments */ - switch(c){ - - case '?': - case 'h': - show_help=TRUE; - break; - case 'V': - show_version=TRUE; - break; - case 'l': - show_license=TRUE; - break; - case 'c': - strncpy(config_file,optarg,sizeof(config_file)); - config_file[sizeof(config_file)-1]='\x0'; - break; - case 'd': - use_inetd=FALSE; - have_mode=TRUE; - break; - case 'i': - use_inetd=TRUE; - have_mode=TRUE; - break; - case 'n': - use_ssl=FALSE; - break; - default: - return ERROR; - break; - } - } - - /* bail if we didn't get required args */ - if(have_mode==FALSE) - return ERROR; - - return OK; - } - +/******************************************************************************* + * + * NRPE.C - Nagios Remote Plugin Executor + * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org) + * License: GPL + * + * Last Modified: 09-06-2013 + * + * Command line: nrpe -c [--inetd | --daemon] + * + * Description: + * + * This program is designed to run as a background process and + * handle incoming requests (from the host running Nagios) for + * plugin execution. It is useful for running "local" plugins + * such as check_users, check_load, check_disk, etc. without + * having to use rsh or ssh. + * + ******************************************************************************/ + +/* + * 08-10-2011 IPv4 subnetworks support added. + * Main change in nrpe.c is that is_an_allowed_host() moved to acl.c. + * now allowed_hosts is parsed by parse_allowed_hosts() from acl.c. + */ + +#include "config.h" +#include "common.h" +#include "nrpe.h" +#include "utils.h" +#include "acl.h" + +#ifdef HAVE_SSL +#include "../include/dh.h" +#endif + +#ifdef HAVE_LIBWRAP +int allow_severity=LOG_INFO; +int deny_severity=LOG_WARNING; +#endif + +#ifdef HAVE_SSL +#ifdef __sun +SSL_METHOD *meth; +#else +const SSL_METHOD *meth; +#endif +SSL_CTX *ctx; +int use_ssl=TRUE; +#else +int use_ssl=FALSE; +#endif + +#define DEFAULT_COMMAND_TIMEOUT 60 /* default timeout for execution of plugins */ +#define MAXFD 64 +#define NASTY_METACHARS "|`&><'\"\\[]{};" +#define howmany(x,y) (((x)+((y)-1))/(y)) +#define MAX_LISTEN_SOCKS 16 + + +char *command_name=NULL; +char *macro_argv[MAX_COMMAND_ARGUMENTS]; + +char config_file[MAX_INPUT_BUFFER]="nrpe.cfg"; +int log_facility=LOG_DAEMON; +int server_port=DEFAULT_SERVER_PORT; +char server_address[NI_MAXHOST]=""; +struct addrinfo *listen_addrs=NULL; +int listen_socks[MAX_LISTEN_SOCKS]; +int num_listen_socks = 0; +int address_family=AF_UNSPEC; +int socket_timeout=DEFAULT_SOCKET_TIMEOUT; +int command_timeout=DEFAULT_COMMAND_TIMEOUT; +int connection_timeout=DEFAULT_CONNECTION_TIMEOUT; +char *command_prefix=NULL; + +command *command_list=NULL; + +char *nrpe_user=NULL; +char *nrpe_group=NULL; + +char *allowed_hosts=NULL; + +char *pid_file=NULL; +int wrote_pid_file=FALSE; + +int allow_arguments=FALSE; +int allow_bash_command_substitution=FALSE; + +int allow_weak_random_seed=FALSE; + +int sigrestart=FALSE; +int sigshutdown=FALSE; + +int show_help=FALSE; +int show_license=FALSE; +int show_version=FALSE; +int use_inetd=TRUE; +int debug=FALSE; +int use_src=FALSE; /* Define parameter for SRC option */ + + +void complete_SSL_shutdown( SSL *); + + +int main(int argc, char **argv){ + int result=OK; + int x; + char buffer[MAX_INPUT_BUFFER]; + char *env_string=NULL; +#ifdef HAVE_SSL + DH *dh; + char seedfile[FILENAME_MAX]; + int i,c; +#endif + + /* set some environment variables */ + asprintf(&env_string,"NRPE_MULTILINESUPPORT=1"); + putenv(env_string); + asprintf(&env_string,"NRPE_PROGRAMVERSION=%s",PROGRAM_VERSION); + putenv(env_string); + + /* process command-line args */ + result=process_arguments(argc,argv); + + if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){ + + printf("\n"); + printf("NRPE - Nagios Remote Plugin Executor\n"); + printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n"); + printf("Version: %s\n",PROGRAM_VERSION); + printf("Last Modified: %s\n",MODIFICATION_DATE); + printf("License: GPL v2 with exemptions (-l for more info)\n"); +#ifdef HAVE_SSL + printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); +#endif +#ifdef HAVE_LIBWRAP + printf("TCP Wrappers Available\n"); +#endif + 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 +#ifndef HAVE_LIBWRAP + printf("***************************************************************\n"); + printf("** POSSIBLE SECURITY RISK - TCP WRAPPERS ARE NOT AVAILABLE! **\n"); + printf("** Read the NRPE SECURITY file for more information **\n"); + printf("***************************************************************\n"); + printf("\n"); +#endif + } + + if(show_license==TRUE) + display_license(); + + else if(result!=OK || show_help==TRUE){ + + printf("Usage: nrpe [-n] -c [-4|-6] \n"); + printf("\n"); + printf("Options:\n"); + printf(" -n = Do not use SSL\n"); + printf(" = Name of config file to use\n"); + printf(" -4 = use ipv4 only\n"); + printf(" -6 = use ipv6 only\n"); + printf(" = One of the following operating modes:\n"); + printf(" -i = Run as a service under inetd or xinetd\n"); + printf(" -d = Run as a standalone daemon\n"); + /* Updates help section to indicate how to start under SRC on AIX */ + printf(" -d -s = Run as a subsystem under AIX\n"); + printf("\n"); + printf("Notes:\n"); + printf("This program is designed to process requests from the check_nrpe\n"); + printf("plugin on the host(s) running Nagios. It can run as a service\n"); + printf("under inetd or xinetd (read the docs for info on this), or as a\n"); + printf("standalone daemon. Once a request is received from an authorized\n"); + printf("host, NRPE will execute the command/plugin (as defined in the\n"); + printf("config file) and return the plugin output and return code to the\n"); + printf("check_nrpe plugin.\n"); + printf("\n"); + } + + if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE) + exit(STATE_UNKNOWN); + + + /* open a connection to the syslog facility */ + /* facility name may be overridden later */ + get_log_facility(NRPE_LOG_FACILITY); + openlog("nrpe",LOG_PID,log_facility); + + /* make sure the config file uses an absolute path */ + if(config_file[0]!='/'){ + + /* save the name of the config file */ + strncpy(buffer,config_file,sizeof(buffer)); + buffer[sizeof(buffer)-1]='\x0'; + + /* get absolute path of current working directory */ + strcpy(config_file,""); + getcwd(config_file,sizeof(config_file)); + + /* append a forward slash */ + strncat(config_file,"/",sizeof(config_file)-2); + config_file[sizeof(config_file)-1]='\x0'; + + /* append the config file to the path */ + strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1); + config_file[sizeof(config_file)-1]='\x0'; + } + + /* read the config file */ + result=read_config_file(config_file); + + /* exit if there are errors... */ + if(result==ERROR){ + syslog(LOG_ERR,"Config file '%s' contained errors, aborting...",config_file); + return STATE_CRITICAL; + } + + /* generate the CRC 32 table */ + generate_crc32_table(); + + /* initialize macros */ + for(x=0;x=0;x--){ + if(isspace(input_line[x])) + input_line[x]='\x0'; + else + break; + } + + /* skip comments and blank lines */ + if(input_line[0]=='#') + continue; + if(input_line[0]=='\x0') + continue; + if(input_line[0]=='\n') + continue; + + /* get the variable name */ + varname=strtok(input_line,"="); + if(varname==NULL){ + syslog(LOG_ERR,"No variable name specified in config file '%s' - Line %d\n",filename,line); + return ERROR; + } + + /* get the variable value */ + varvalue=strtok(NULL,"\n"); + if(varvalue==NULL){ + syslog(LOG_ERR,"No variable value specified in config file '%s' - Line %d\n",filename,line); + return ERROR; + } + + /* allow users to specify directories to recurse into for config files */ + else if(!strcmp(varname,"include_dir")){ + + strncpy(config_file,varvalue,sizeof(config_file)-1); + config_file[sizeof(config_file)-1]='\x0'; + + /* strip trailing / if necessary */ + if(config_file[strlen(config_file)-1]=='/') + config_file[strlen(config_file)-1]='\x0'; + + /* process the config directory... */ + if(read_config_dir(config_file)==ERROR) + syslog(LOG_ERR,"Continuing with errors..."); + } + + /* allow users to specify individual config files to include */ + else if(!strcmp(varname,"include") || !strcmp(varname,"include_file")){ + + /* process the config file... */ + if(read_config_file(varvalue)==ERROR) + syslog(LOG_ERR,"Continuing with errors..."); + } + + else if(!strcmp(varname,"server_port")){ + server_port=atoi(varvalue); + if(server_port<1024){ + syslog(LOG_ERR,"Invalid port number specified in config file '%s' - Line %d\n",filename,line); + return ERROR; + } + } + else if(!strcmp(varname,"command_prefix")) + command_prefix=strdup(varvalue); + + else if(!strcmp(varname,"server_address")){ + strncpy(server_address,varvalue,sizeof(server_address) - 1); + server_address[sizeof(server_address)-1]='\0'; + } + else if(!strcmp(varname,"allowed_hosts")) { + allowed_hosts=strdup(varvalue); + parse_allowed_hosts(allowed_hosts); + } + else if(strstr(input_line,"command[")){ + temp_buffer=strtok(varname,"["); + temp_buffer=strtok(NULL,"]"); + if(temp_buffer==NULL){ + syslog(LOG_ERR,"Invalid command specified in config file '%s' - Line %d\n",filename,line); + return ERROR; + } + add_command(temp_buffer,varvalue); + } + + else if(strstr(input_buffer,"debug")){ + debug=atoi(varvalue); + if(debug>0) + debug=TRUE; + else + debug=FALSE; + } + + else if(!strcmp(varname,"nrpe_user")) + nrpe_user=strdup(varvalue); + + else if(!strcmp(varname,"nrpe_group")) + nrpe_group=strdup(varvalue); + + else if(!strcmp(varname,"dont_blame_nrpe")) + allow_arguments=(atoi(varvalue)==1)?TRUE:FALSE; + + else if(!strcmp(varname,"allow_bash_command_substitution")) + allow_bash_command_substitution=(atoi(varvalue)==1)?TRUE:FALSE; + + else if(!strcmp(varname,"command_timeout")){ + command_timeout=atoi(varvalue); + if(command_timeout<1){ + syslog(LOG_ERR,"Invalid command_timeout specified in config file '%s' - Line %d\n",filename,line); + return ERROR; + } + } + + else if(!strcmp(varname,"connection_timeout")){ + connection_timeout=atoi(varvalue); + if(connection_timeout<1){ + syslog(LOG_ERR,"Invalid connection_timeout specified in config file '%s' - Line %d\n",filename,line); + return ERROR; + } + } + + else if(!strcmp(varname,"allow_weak_random_seed")) + allow_weak_random_seed=(atoi(varvalue)==1)?TRUE:FALSE; + + else if(!strcmp(varname,"pid_file")) + pid_file=strdup(varvalue); + + else if(!strcmp(varname,"log_facility")){ + if((get_log_facility(varvalue))==OK){ + /* re-open log using new facility */ + closelog(); + openlog("nrpe",LOG_PID,log_facility); + } + else + syslog(LOG_WARNING,"Invalid log_facility specified in config file '%s' - Line %d\n",filename,line); + } + + else{ + syslog(LOG_WARNING,"Unknown option specified in config file '%s' - Line %d\n",filename,line); + continue; + } + + } + + + /* close the config file */ + fclose(fp); + + return OK; + } + + +/* process all config files in a specific config directory (with directory recursion) */ +int read_config_dir(char *dirname){ + char config_file[MAX_FILENAME_LENGTH]; + DIR *dirp; + struct dirent *dirfile; + struct stat buf; + int result=OK; + int x; + + /* open the directory for reading */ + dirp=opendir(dirname); + if(dirp==NULL){ + syslog(LOG_ERR,"Could not open config directory '%s' for reading.\n",dirname); + return ERROR; + } + + /* process all files in the directory... */ + while((dirfile=readdir(dirp))!=NULL){ + + /* create the full path to the config file or subdirectory */ + snprintf(config_file,sizeof(config_file)-1,"%s/%s",dirname,dirfile->d_name); + config_file[sizeof(config_file)-1]='\x0'; + stat(config_file, &buf); + + /* process this if it's a config file... */ + x=strlen(dirfile->d_name); + if(x>4 && !strcmp(dirfile->d_name+(x-4),".cfg")){ + + /* only process normal files */ + if(!S_ISREG(buf.st_mode)) + continue; + + /* process the config file */ + result=read_config_file(config_file); + + /* break out if we encountered an error */ + if(result==ERROR) + break; + } + + /* recurse into subdirectories... */ + if(S_ISDIR(buf.st_mode)){ + + /* ignore current, parent and hidden directory entries */ + if(dirfile->d_name[0]=='.') + continue; + + /* process the config directory */ + result=read_config_dir(config_file); + + /* break out if we encountered an error */ + if(result==ERROR) + break; + } + } + + closedir(dirp); + + return result; + } + + + +/* determines facility to use with syslog */ +int get_log_facility(char *varvalue){ + + if(!strcmp(varvalue,"kern")) + log_facility=LOG_KERN; + else if(!strcmp(varvalue,"user")) + log_facility=LOG_USER; + else if(!strcmp(varvalue,"mail")) + log_facility=LOG_MAIL; + else if(!strcmp(varvalue,"daemon")) + log_facility=LOG_DAEMON; + else if(!strcmp(varvalue,"auth")) + log_facility=LOG_AUTH; + else if(!strcmp(varvalue,"syslog")) + log_facility=LOG_SYSLOG; + else if(!strcmp(varvalue,"lrp")) + log_facility=LOG_LPR; + else if(!strcmp(varvalue,"news")) + log_facility=LOG_NEWS; + else if(!strcmp(varvalue,"uucp")) + log_facility=LOG_UUCP; + else if(!strcmp(varvalue,"cron")) + log_facility=LOG_CRON; + else if(!strcmp(varvalue,"authpriv")) + log_facility=LOG_AUTHPRIV; + else if(!strcmp(varvalue,"ftp")) + log_facility=LOG_FTP; + else if(!strcmp(varvalue,"local0")) + log_facility=LOG_LOCAL0; + else if(!strcmp(varvalue,"local1")) + log_facility=LOG_LOCAL1; + else if(!strcmp(varvalue,"local2")) + log_facility=LOG_LOCAL2; + else if(!strcmp(varvalue,"local3")) + log_facility=LOG_LOCAL3; + else if(!strcmp(varvalue,"local4")) + log_facility=LOG_LOCAL4; + else if(!strcmp(varvalue,"local5")) + log_facility=LOG_LOCAL5; + else if(!strcmp(varvalue,"local6")) + log_facility=LOG_LOCAL6; + else if(!strcmp(varvalue,"local7")) + log_facility=LOG_LOCAL7; + else{ + log_facility=LOG_DAEMON; + return ERROR; + } + + return OK; + } + + + +/* adds a new command definition from the config file to the list in memory */ +int add_command(char *command_name, char *command_line){ + command *new_command; + + if(command_name==NULL || command_line==NULL) + return ERROR; + + /* allocate memory for the new command */ + new_command=(command *)malloc(sizeof(command)); + if(new_command==NULL) + return ERROR; + + new_command->command_name=strdup(command_name); + if(new_command->command_name==NULL){ + free(new_command); + return ERROR; + } + new_command->command_line=strdup(command_line); + if(new_command->command_line==NULL){ + free(new_command->command_name); + free(new_command); + return ERROR; + } + + /* add new command to head of list in memory */ + new_command->next=command_list; + command_list=new_command; + + if(debug==TRUE) + syslog(LOG_DEBUG,"Added command[%s]=%s\n",command_name,command_line); + + return OK; + } + + + +/* given a command name, find the structure in memory */ +command *find_command(char *command_name){ + command *temp_command; + + for(temp_command=command_list;temp_command!=NULL;temp_command=temp_command->next) + if(!strcmp(command_name,temp_command->command_name)) + return temp_command; + + return NULL; + } + + +/* + * Close all listening sockets + */ +static void close_listen_socks(void) { + int i; + + for (i = 0; i <= num_listen_socks; i++) { + close(listen_socks[i]); + num_listen_socks--; + } + } + +/* Start listen on a particular port */ +void create_listener(struct addrinfo *ai) { + + int ret; + char ntop[NI_MAXHOST], strport[NI_MAXSERV]; + int listen_sock; + int flag=1; + + if(ai->ai_family != AF_INET && ai->ai_family != AF_INET6) return; + + if(num_listen_socks >= MAX_LISTEN_SOCKS) { + syslog(LOG_ERR, "Too many listen sockets. Enlarge MAX_LISTEN_SOCKS"); + exit(1); + } + + if((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), + strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { + syslog(LOG_ERR, "getnameinfo failed: %.100s", gai_strerror(ret)); + return; + } + + /* Create socket for listening. */ + listen_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (listen_sock < 0) { + /* kernel may not support ipv6 */ + syslog(LOG_ERR, "socket: %.100s", strerror(errno)); + return; + } + + /* socket should be non-blocking */ + fcntl(listen_sock,F_SETFL,O_NONBLOCK); + + /* set the reuse address flag so we don't get errors when + restarting */ + if(setsockopt(listen_sock, SOL_SOCKET,SO_REUSEADDR, &flag, + sizeof(flag)) < 0) { + syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %s", strerror(errno)); + return; + } + +#ifdef IPV6_V6ONLY + /* Only communicate in IPv6 over AF_INET6 sockets. */ + if (ai->ai_family == AF_INET6) { + if (setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &flag, + sizeof(flag)) == -1) { + fprintf(stderr, "setsockopt IPV6_V6ONLY: %s", strerror(errno)); + } + } +#endif + + /* Bind the socket to the desired port. */ + if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { + syslog(LOG_ERR, "Bind to port %s on %s failed: %.200s.", strport, + ntop, strerror(errno)); close(listen_sock); + return; + } + listen_socks[num_listen_socks] = listen_sock; + num_listen_socks++; + + /* Start listening on the port. */ + if (listen(listen_sock, 5) < 0) { + syslog(LOG_ERR, "listen on [%s]:%s: %.100s", ntop, strport, + strerror(errno)); + exit(1); + } + + syslog(LOG_INFO, "Server listening on %s port %s.", ntop, strport); + } + +/* wait for incoming connection requests */ +void wait_for_connections(void){ + struct addrinfo *ai; + fd_set *fdset=NULL; + int maxfd=0; + struct sockaddr_storage from; + socklen_t fromlen; + char ipstr[INET6_ADDRSTRLEN]; + int i; + int r; + + struct sockaddr_in myname; + struct sockaddr_in *nptr; + struct sockaddr_in6 *nptr6; + struct sockaddr_storage addr; + int rc; + int sock, new_sd; + socklen_t addrlen; + pid_t pid; + fd_set fdread; + struct timeval timeout; + int retval; +#ifdef HAVE_LIBWRAP + struct request_info req; +#endif + + add_listen_addr(&listen_addrs, address_family, + (strcmp(server_address, "") == 0) ? NULL : server_address, + server_port); + + for(ai = listen_addrs; ai; ai = ai->ai_next) { + create_listener(ai); + } + + if (!num_listen_socks) { + syslog(LOG_ERR, "Cannot bind to any address."); + exit(1); + } + + /* 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!"); +#ifdef ENABLE_BASH_COMMAND_SUBSTITUTION + if(TRUE==allow_bash_command_substitution) { + if(TRUE==allow_arguments) + syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments with bash command substitutions!"); + else + syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments with bash command substitutions, but is not configured to accept command argements from clients. Enable command arguments if you wish to allow command arguments with bash command substitutions."); + } +#endif +#endif + + syslog(LOG_INFO,"Listening for connections on port %d\n",htons(myname.sin_port)); + + if(allowed_hosts) + syslog(LOG_INFO,"Allowing connections from: %s\n",allowed_hosts); + + /* listen for connection requests - fork() if we get one */ + while(1){ + + /* bail out if necessary */ + if(sigrestart==TRUE || sigshutdown==TRUE) break; + + for(i = 0; i < num_listen_socks; i++) { + if (listen_socks[i] > maxfd) maxfd = listen_socks[i]; + } + + if(fdset != NULL) free(fdset); + fdset = (fd_set *)calloc(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask)); + + for (i = 0; i < num_listen_socks; i++) FD_SET(listen_socks[i], fdset); + + /* Wait in select until there is a connection. */ + retval = select(maxfd+1, fdset, NULL, NULL, NULL); + + /* bail out if necessary */ + if(sigrestart==TRUE || sigshutdown==TRUE) break; + + /* error */ + if(retval<0) continue; + + for (i = 0; i < num_listen_socks; i++) { + if (!FD_ISSET(listen_socks[i], fdset)) continue; + fromlen = sizeof(from); + + /* accept a new connection request */ + new_sd = accept(listen_socks[i], (struct sockaddr *)&from, &fromlen); + + /* some kind of error occurred... */ + if(new_sd<0){ + + /* bail out if necessary */ + if(sigrestart==TRUE || sigshutdown==TRUE) + break; + + /* retry */ + if(errno==EWOULDBLOCK || errno==EINTR) + continue; + + /* socket is nonblocking and we don't have a connection yet */ + if(errno==EAGAIN) + continue; + + /* fix for HP-UX 11.0 - just retry */ + if(errno==ENOBUFS) + continue; + + /* else handle the error later */ + break; + } + + /* child process should handle the connection */ + pid=fork(); + if(pid==0) { + + /* fork again so we don't create zombies */ + pid=fork(); + if(pid==0) { + + /* hey, there was an error... */ + if(new_sd<0) { + + /* log error to syslog facility */ + syslog(LOG_ERR, "Network server accept failure (%d: %s)", + errno, strerror(errno)); + + /* close socket prioer to exiting */ + close(sock); + + return; + } + + /* handle signals */ + signal(SIGQUIT,child_sighandler); + signal(SIGTERM,child_sighandler); + signal(SIGHUP,child_sighandler); + + /* grandchild does not need to listen for connections */ + close_listen_socks(); + + /* find out who just connected... */ + addrlen=sizeof(addr); + rc=getpeername(new_sd, (struct sockaddr *)&addr, &addrlen); + + if(rc<0) { + + /* log error to syslog facility */ + syslog(LOG_ERR, "Error: Network server getpeername() failure (%d: %s)", + errno, strerror(errno)); + + /* close socket prior to exiting */ + close(new_sd); + + return; + } + + /* is this is a blessed machine? */ + if(allowed_hosts) { + switch(addr.ss_family) { + case AF_INET: + nptr = (struct sockaddr_in *)&addr; + + /* log info to syslog facility */ + if(debug==TRUE) { + syslog(LOG_DEBUG, "Connection from %s port %d", + inet_ntoa(nptr->sin_addr), + nptr->sin_port); + } + if(!is_an_allowed_host(AF_INET, + (void *)&(nptr->sin_addr))) { + /* log error to syslog facility */ + syslog(LOG_ERR, + "Host %s is not allowed to talk to us!", + inet_ntoa(nptr->sin_addr)); + + /* log info to syslog facility */ + if ( debug==TRUE ) { + syslog(LOG_DEBUG, + "Connection from %s closed.", + inet_ntoa(nptr->sin_addr)); + } + + /* close socket prior to exiting */ + close(new_sd); + exit(STATE_OK); + } + else { + /* log info to syslog facility */ + if(debug==TRUE) { + syslog(LOG_DEBUG, + "Host address is in allowed_hosts"); + } + + } + break; + case AF_INET6: + nptr6 = (struct sockaddr_in6 *)&addr; + if(inet_ntop(AF_INET6, + (const void *)&(nptr6->sin6_addr), ipstr, + sizeof(ipstr)) == NULL) { + strncpy(ipstr, "Unknown", sizeof(ipstr)); + } + + /* log info to syslog facility */ + if(debug==TRUE) { + syslog(LOG_DEBUG, "Connection from %s port %d", + ipstr, nptr6->sin6_port); + } + if(!is_an_allowed_host(AF_INET6, + (void *)&(nptr6->sin6_addr))) { + /* log error to syslog facility */ + syslog(LOG_ERR, + "Host %s is not allowed to talk to us!", + ipstr); + + /* log info to syslog facility */ + if ( debug==TRUE ) { + syslog(LOG_DEBUG, + "Connection from %s closed.", + ipstr); + } + + /* close socket prior to exiting */ + close(new_sd); + exit(STATE_OK); + } + else { + /* log info to syslog facility */ + if(debug==TRUE) { + syslog(LOG_DEBUG, + "Host address is in allowed_hosts"); + } + + } + break; + } + } + +#ifdef HAVE_LIBWRAP + /* Check whether or not connections are allowed from this host */ + request_init(&req,RQ_DAEMON,"nrpe",RQ_FILE,new_sd,0); + fromhost(&req); + + if(!hosts_access(&req)){ + + syslog(LOG_DEBUG,"Connection refused by TCP wrapper"); + + /* refuse the connection */ + refuse(&req); + close(new_sd); + + /* should not be reached */ + syslog(LOG_ERR,"libwrap refuse() returns!"); + exit(STATE_CRITICAL); + } +#endif + + /* handle the client connection */ + handle_connection(new_sd); + + /* log info to syslog facility */ + if(debug==TRUE) { + syslog(LOG_DEBUG,"Connection from %s closed.",ipstr); + } + + /* close socket prior to exiting */ + close(new_sd); + + exit(STATE_OK); + } + + /* first child returns immediately, grandchild is inherited by + INIT process -> no zombies... */ + else + exit(STATE_OK); + } + + /* parent ... */ + else { + /* parent doesn't need the new connection */ + close(new_sd); + + /* parent waits for first child to exit */ + waitpid(pid,NULL,0); + } + } + } + + /* close the sockets we're listening on */ + close_listen_socks(); + freeaddrinfo(listen_addrs); + listen_addrs=NULL; + + return; + } + + +/* 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; +#ifdef DEBUG + FILE *errfp; +#endif +#ifdef HAVE_SSL + SSL *ssl=NULL; +#endif + + + /* log info to syslog facility */ + if(debug==TRUE) + syslog(LOG_DEBUG,"Handling the connection..."); + +#ifdef OLDSTUFF + /* socket should be non-blocking */ + fcntl(sock,F_SETFL,O_NONBLOCK); +#endif + + /* set connection handler */ + signal(SIGALRM,my_connection_sighandler); + alarm(connection_timeout); + +#ifdef HAVE_SSL + /* do SSL handshake */ + if(result==STATE_OK && use_ssl==TRUE){ + if((ssl=SSL_new(ctx))!=NULL){ + SSL_set_fd(ssl,sock); + + /* keep attempting the request if needed */ + while(((rc=SSL_accept(ssl))!=1) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); + + if(rc!=1){ + syslog(LOG_ERR,"Error: Could not complete SSL handshake. %d\n",SSL_get_error(ssl,rc)); +#ifdef DEBUG + errfp=fopen("/tmp/err.log","w"); + ERR_print_errors_fp(errfp); + fclose(errfp); +#endif + return; + } + } + else{ + syslog(LOG_ERR,"Error: Could not create SSL connection structure.\n"); +#ifdef DEBUG + errfp=fopen("/tmp/err.log","w"); + ERR_print_errors_fp(errfp); + fclose(errfp); +#endif + return; + } + } +#endif + + bytes_to_recv=sizeof(receive_packet); + if(use_ssl==FALSE) + rc=recvall(sock,(char *)&receive_packet,&bytes_to_recv,socket_timeout); +#ifdef HAVE_SSL + else{ + while(((rc=SSL_read(ssl,&receive_packet,bytes_to_recv))<=0) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); + } +#endif + + /* recv() error or client disconnect */ + if(rc<=0){ + + /* log error to syslog facility */ + syslog(LOG_ERR,"Could not read request from client, bailing out..."); + +#ifdef HAVE_SSL + if(ssl){ + complete_SSL_shutdown( ssl); + SSL_free(ssl); + syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n"); + } +#endif + + return; + } + + /* we couldn't read the correct amount of data, so bail out */ + else if(bytes_to_recv!=sizeof(receive_packet)){ + + /* log error to syslog facility */ + syslog(LOG_ERR,"Data packet from client was too short, bailing out..."); + +#ifdef HAVE_SSL + if(ssl){ + complete_SSL_shutdown( ssl); + SSL_free(ssl); + } +#endif + + return; + } + +#ifdef DEBUG + fp=fopen("/tmp/packet","w"); + if(fp){ + fwrite(&receive_packet,1,sizeof(receive_packet),fp); + fclose(fp); + } +#endif + + /* make sure the request is valid */ + if(validate_request(&receive_packet)==ERROR){ + + /* log an error */ + syslog(LOG_ERR,"Client request was invalid, bailing out..."); + + /* free memory */ + free(command_name); + command_name=NULL; + for(x=0;xcommand_line,sizeof(raw_command)-1); + else + snprintf(raw_command,sizeof(raw_command)-1,"%s %s",command_prefix,temp_command->command_line); + raw_command[sizeof(raw_command)-1]='\x0'; + process_macros(raw_command,processed_command,sizeof(processed_command)); + + /* log info to syslog facility */ + if(debug==TRUE) + syslog(LOG_DEBUG,"Running command: %s",processed_command); + + /* run the command */ + strcpy(buffer,""); + result=my_system(processed_command,command_timeout,&early_timeout,buffer,sizeof(buffer)); + + /* log debug info */ + if(debug==TRUE) + syslog(LOG_DEBUG,"Command completed with return code %d and output: %s",result,buffer); + + /* see if the command timed out */ + if(early_timeout==TRUE) + snprintf(buffer,sizeof(buffer)-1,"NRPE: Command timed out after %d seconds\n",command_timeout); + else if(!strcmp(buffer,"")) + snprintf(buffer,sizeof(buffer)-1,"NRPE: Unable to read output\n"); + + buffer[sizeof(buffer)-1]='\x0'; + + /* check return code bounds */ + if((result<0) || (result>3)){ + + /* log error to syslog facility */ + syslog(LOG_ERR,"Bad return code for [%s]: %d", buffer,result); + + result=STATE_UNKNOWN; + } + } + } + + /* free memory */ + free(command_name); + command_name=NULL; + for(x=0;xnext; + if(this_command->command_name) + free(this_command->command_name); + if(this_command->command_line) + free(this_command->command_line); + free(this_command); + this_command=next_command; + } + + command_list=NULL; + + return; + } + + + +/* executes a system command via popen(), but protects against timeouts */ +int my_system(char *command,int timeout,int *early_timeout,char *output,int output_length){ + pid_t pid; + int status; + int result; + extern int errno; + char buffer[MAX_INPUT_BUFFER]; + int fd[2]; + FILE *fp; + int bytes_read=0; + time_t start_time,end_time; + + /* initialize return variables */ + if(output!=NULL) + strcpy(output,""); + *early_timeout=FALSE; + + /* if no command was passed, return with no error */ + if(command==NULL) + return STATE_OK; + + /* create a pipe */ + pipe(fd); + + /* make the pipe non-blocking */ + fcntl(fd[0],F_SETFL,O_NONBLOCK); + fcntl(fd[1],F_SETFL,O_NONBLOCK); + + /* get the command start time */ + time(&start_time); + + /* fork */ + pid=fork(); + + /* return an error if we couldn't fork */ + if(pid==-1){ + + snprintf(buffer,sizeof(buffer)-1,"NRPE: Call to fork() failed\n"); + buffer[sizeof(buffer)-1]='\x0'; + + if(output!=NULL){ + strncpy(output,buffer,output_length-1); + output[output_length-1]='\x0'; + } + + /* close both ends of the pipe */ + close(fd[0]); + close(fd[1]); + + return STATE_UNKNOWN; + } + + /* execute the command in the child process */ + if(pid==0){ + + /* close pipe for reading */ + close(fd[0]); + + /* become process group leader */ + setpgid(0,0); + + /* trap commands that timeout */ + signal(SIGALRM,my_system_sighandler); + alarm(timeout); + + /* run the command */ + fp=popen(command,"r"); + + /* report an error if we couldn't run the command */ + if(fp==NULL){ + + strncpy(buffer,"NRPE: Call to popen() failed\n",sizeof(buffer)-1); + buffer[sizeof(buffer)-1]='\x0'; + + /* write the error back to the parent process */ + write(fd[1],buffer,strlen(buffer)+1); + + result=STATE_CRITICAL; + } + else{ + + /* read all lines of output - supports Nagios 3.x multiline output */ + while((bytes_read=fread(buffer,1,sizeof(buffer)-1,fp))>0){ + + /* write the output back to the parent process */ + write(fd[1],buffer,bytes_read); + } + + /* close the command and get termination status */ + status=pclose(fp); + + /* report an error if we couldn't close the command */ + if(status==-1) + result=STATE_CRITICAL; + /* report an error if child died due to signal (Klas Lindfors) */ + else if(!WIFEXITED(status)) + result=STATE_CRITICAL; + else + result=WEXITSTATUS(status); + } + + /* close pipe for writing */ + close(fd[1]); + + /* reset the alarm */ + alarm(0); + + /* return plugin exit code to parent process */ + exit(result); + } + + /* parent waits for child to finish executing command */ + else{ + + /* close pipe for writing */ + close(fd[1]); + + /* wait for child to exit */ + waitpid(pid,&status,0); + + /* get the end time for running the command */ + time(&end_time); + + /* get the exit code returned from the program */ + result=WEXITSTATUS(status); + + /* because of my idiotic idea of having UNKNOWN states be equivalent to -1, I must hack things a bit... */ + if(result==255) + result=STATE_UNKNOWN; + + /* check bounds on the return value */ + if(result<0 || result>3) + result=STATE_UNKNOWN; + + /* try and read the results from the command output (retry if we encountered a signal) */ + if(output!=NULL){ + do{ + bytes_read=read(fd[0], output, output_length-1); + }while (bytes_read==-1 && errno==EINTR); + + if(bytes_read==-1) + *output='\0'; + else + output[bytes_read]='\0'; + } + + /* if there was a critical return code and no output AND the command time exceeded the timeout thresholds, assume a timeout */ + if(result==STATE_CRITICAL && bytes_read==-1 && (end_time-start_time)>=timeout){ + *early_timeout=TRUE; + + /* send termination signal to child process group */ + kill((pid_t)(-pid),SIGTERM); + kill((pid_t)(-pid),SIGKILL); + } + + /* close the pipe for reading */ + close(fd[0]); + } + +#ifdef DEBUG + printf("my_system() end\n"); +#endif + + return result; + } + + + +/* handle timeouts when executing commands via my_system() */ +void my_system_sighandler(int sig){ + + /* force the child process to exit... */ + exit(STATE_CRITICAL); + } + + +/* handle errors where connection takes too long */ +void my_connection_sighandler(int sig) { + + syslog(LOG_ERR,"Connection has taken too long to establish. Exiting..."); + + exit(STATE_CRITICAL); + } + + +/* drops privileges */ +int drop_privileges(char *user, char *group){ + uid_t uid=-1; + gid_t gid=-1; + struct group *grp; + struct passwd *pw; + + /* set effective group ID */ + if(group!=NULL){ + + /* see if this is a group name */ + if(strspn(group,"0123456789")gr_gid); + else + syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group); + endgrent(); + } + + /* else we were passed the GID */ + else + gid=(gid_t)atoi(group); + + /* set effective group ID if other than current EGID */ + if(gid!=getegid()){ + + if(setgid(gid)==-1) + syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid); + } + } + + + /* set effective user ID */ + if(user!=NULL){ + + /* see if this is a user name */ + if(strspn(user,"0123456789")pw_uid); + else + syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user); + endpwent(); + } + + /* else we were passed the UID */ + else + uid=(uid_t)atoi(user); + + /* set effective user ID if other than current EUID */ + if(uid!=geteuid()){ + +#ifdef HAVE_INITGROUPS + /* initialize supplementary groups */ + if(initgroups(user,gid)==-1){ + if(errno==EPERM) + syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()"); + else{ + syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()"); + return ERROR; + } + } +#endif + + if(setuid(uid)==-1) + syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid); + } + } + + return OK; + } + + +/* write an optional pid file */ +int write_pid_file(void){ + int fd; + int result=0; + pid_t pid=0; + char pbuf[16]; + + /* no pid file was specified */ + if(pid_file==NULL) + return OK; + + /* read existing pid file */ + if((fd=open(pid_file,O_RDONLY))>=0){ + + result=read(fd,pbuf,(sizeof pbuf)-1); + + close(fd); + + if(result>0){ + + pbuf[result]='\x0'; + pid=(pid_t)atoi(pbuf); + + /* if previous process is no longer running running, remove the old pid file */ + if(pid && (pid==getpid() || kill(pid,0)<0)) + unlink(pid_file); + + /* previous process is still running */ + else{ + syslog(LOG_ERR,"There's already an NRPE server running (PID %lu). Bailing out...",(unsigned long)pid); + return ERROR; + } + } + } + + /* write new pid file */ + if((fd=open(pid_file,O_WRONLY | O_CREAT,0644))>=0){ + sprintf(pbuf,"%d\n",(int)getpid()); + write(fd,pbuf,strlen(pbuf)); + close(fd); + wrote_pid_file=TRUE; + } + else{ + syslog(LOG_ERR,"Cannot write to pidfile '%s' - check your privileges.",pid_file); + } + + return OK; + } + + + +/* remove pid file */ +int remove_pid_file(void){ + + /* no pid file was specified */ + if(pid_file==NULL) + return OK; + + /* pid file was not written */ + if(wrote_pid_file==FALSE) + return OK; + + /* remove existing pid file */ + if(unlink(pid_file)==-1){ + syslog(LOG_ERR,"Cannot remove pidfile '%s' - check your privileges.",pid_file); + return ERROR; + } + + return OK; + } + +void complete_SSL_shutdown( SSL *ssl) { + + /* + Thanks to Jari Takkala (jtakkala@gmail.com) for the following information. + + We need to call SSL_shutdown() at least twice, otherwise we'll + be left with data in the socket receive buffer, and the + subsequent process termination will cause TCP RST's to be sent + to the client. + + See http://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/32219/diff + for more information. + */ + + int x; + + for( x = 0; x < 4; x++) { + if( SSL_shutdown( ssl)) break; + } +} + +/* 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; + } + + + +/* handle signals (parent process) */ +void sighandler(int sig){ + static char *sigs[]={"EXIT","HUP","INT","QUIT","ILL","TRAP","ABRT","BUS","FPE","KILL","USR1","SEGV","USR2","PIPE","ALRM","TERM","STKFLT","CHLD","CONT","STOP","TSTP","TTIN","TTOU","URG","XCPU","XFSZ","VTALRM","PROF","WINCH","IO","PWR","UNUSED","ZERR","DEBUG",(char *)NULL}; + int i; + + if(sig<0) + sig=-sig; + + for(i=0;sigs[i]!=(char *)NULL;i++); + + sig%=i; + + /* we received a SIGHUP, so restart... */ + if(sig==SIGHUP){ + + sigrestart=TRUE; + + syslog(LOG_NOTICE,"Caught SIGHUP - restarting...\n"); + } + + /* else begin shutting down... */ + if(sig==SIGTERM){ + + /* if shutdown is already true, we're in a signal trap loop! */ + if(sigshutdown==TRUE) + exit(STATE_CRITICAL); + + sigshutdown=TRUE; + + syslog(LOG_NOTICE,"Caught SIG%s - shutting down...\n",sigs[sig]); + } + + return; + } + + + +/* handle signals (child processes) */ +void child_sighandler(int sig){ + + /* free all memory we allocated */ + free_memory(); + + /* terminate */ + exit(0); + + /* so the compiler doesn't complain... */ + return; + } + + + +/* tests whether or not a client request is valid */ +int validate_request(packet *pkt){ + u_int32_t packet_crc32; + u_int32_t calculated_crc32; + char *ptr; +#ifdef ENABLE_COMMAND_ARGUMENTS + int x; +#endif + + + /***** DECRYPT REQUEST ******/ + + + /* check the crc 32 value */ + packet_crc32=ntohl(pkt->crc32_value); + pkt->crc32_value=0L; + calculated_crc32=calculate_crc32((char *)pkt,sizeof(packet)); + if(packet_crc32!=calculated_crc32){ + syslog(LOG_ERR,"Error: Request packet had invalid CRC32."); + return ERROR; + } + + /* make sure this is the right type of packet */ + if(ntohs(pkt->packet_type)!=QUERY_PACKET || ntohs(pkt->packet_version)!=NRPE_PACKET_VERSION_2){ + syslog(LOG_ERR,"Error: Request packet type/version was invalid!"); + return ERROR; + } + + /* make sure buffer is terminated */ + pkt->buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0'; + + /* client must send some kind of request */ + if(!strcmp(pkt->buffer,"")){ + syslog(LOG_ERR,"Error: Request contained no query!"); + return ERROR; + } + + /* make sure request doesn't contain nasties */ + if(contains_nasty_metachars(pkt->buffer)==TRUE){ + syslog(LOG_ERR,"Error: Request contained illegal metachars!"); + return ERROR; + } + + /* make sure the request doesn't contain arguments */ + if(strchr(pkt->buffer,'!')){ +#ifdef ENABLE_COMMAND_ARGUMENTS + if(allow_arguments==FALSE){ + syslog(LOG_ERR,"Error: Request contained command arguments, but argument option is not enabled!"); + return ERROR; + } +#else + syslog(LOG_ERR,"Error: Request contained command arguments!"); + return ERROR; +#endif + } + + /* get command name */ +#ifdef ENABLE_COMMAND_ARGUMENTS + ptr=strtok(pkt->buffer,"!"); +#else + ptr=pkt->buffer; +#endif + command_name=strdup(ptr); + if(command_name==NULL){ + syslog(LOG_ERR,"Error: Memory allocation failed"); + return ERROR; + } + +#ifdef ENABLE_COMMAND_ARGUMENTS + /* get command arguments */ + if(allow_arguments==TRUE){ + + for(x=0;x=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){ + char optchars[MAX_INPUT_BUFFER]; + int c=1; + int have_mode=FALSE; + +#ifdef HAVE_GETOPT_LONG + int option_index=0; + static struct option long_options[]={ + {"config", required_argument, 0, 'c'}, + {"inetd", no_argument, 0, 'i'}, + /* To compatibility between short and long options but not used on AIX */ + {"src", no_argument, 0, 's'}, + {"4", no_argument, 0, '4'}, + {"6", no_argument, 0, '4'}, + {"daemon", no_argument, 0, 'd'}, + {"no-ssl", no_argument, 0, 'n'}, + {"help", no_argument, 0, 'h'}, + {"license", no_argument, 0, 'l'}, + {0, 0, 0, 0} + }; +#endif + + /* no options were supplied */ + if(argc<2) + return ERROR; + + snprintf(optchars,MAX_INPUT_BUFFER,"c:hVldi46n"); + + while(1){ +#ifdef HAVE_GETOPT_LONG + c=getopt_long(argc,argv,optchars,long_options,&option_index); +#else + c=getopt(argc,argv,optchars); +#endif + if(c==-1 || c==EOF) + break; + + /* process all arguments */ + switch(c){ + + case '?': + case 'h': + show_help=TRUE; + break; + case 'V': + show_version=TRUE; + break; + case 'l': + show_license=TRUE; + break; + case 'c': + strncpy(config_file,optarg,sizeof(config_file)); + config_file[sizeof(config_file)-1]='\x0'; + break; + case 'd': + use_inetd=FALSE; + have_mode=TRUE; + break; + case 'i': + use_inetd=TRUE; + have_mode=TRUE; + break; + case '4': + address_family=AF_INET; + break; + case '6': + address_family=AF_INET6; + break; + case 'n': + use_ssl=FALSE; + break; + case 's': /* Argument s to indicate SRC option*/ + use_src=TRUE; + break; + default: + return ERROR; + break; + } + } + + /* bail if we didn't get required args */ + if(have_mode==FALSE) + return ERROR; + + return OK; + } + diff -Nru nagios-nrpe-2.13/src/snprintf.c nagios-nrpe-2.15/src/snprintf.c --- nagios-nrpe-2.13/src/snprintf.c 2007-08-13 17:10:08.000000000 +0000 +++ nagios-nrpe-2.15/src/snprintf.c 2013-09-06 15:27:13.000000000 +0000 @@ -1,1452 +1,1452 @@ -/* - * NOTE: If you change this file, please merge it into rsync, samba, etc. - */ - -/* - * Copyright Patrick Powell 1995 - * This code is based on code written by Patrick Powell (papowell@astart.com) - * It may be used for any purpose as long as this notice remains intact - * on all source code distributions - */ - -/************************************************************** - * Original: - * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 - * A bombproof version of doprnt (dopr) included. - * Sigh. This sort of thing is always nasty do deal with. Note that - * the version here does not include floating point... - * - * snprintf() is used instead of sprintf() as it does limit checks - * for string length. This covers a nasty loophole. - * - * The other functions are there to prevent NULL pointers from - * causing nast effects. - * - * More Recently: - * Brandon Long 9/15/96 for mutt 0.43 - * This was ugly. It is still ugly. I opted out of floating point - * numbers, but the formatter understands just about everything - * from the normal C string format, at least as far as I can tell from - * the Solaris 2.5 printf(3S) man page. - * - * Brandon Long 10/22/97 for mutt 0.87.1 - * Ok, added some minimal floating point support, which means this - * probably requires libm on most operating systems. Don't yet - * support the exponent (e,E) and sigfig (g,G). Also, fmtint() - * was pretty badly broken, it just wasn't being exercised in ways - * which showed it, so that's been fixed. Also, formated the code - * to mutt conventions, and removed dead code left over from the - * original. Also, there is now a builtin-test, just compile with: - * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm - * and run snprintf for results. - * - * Thomas Roessler 01/27/98 for mutt 0.89i - * The PGP code was using unsigned hexadecimal formats. - * Unfortunately, unsigned formats simply didn't work. - * - * Michael Elkins 03/05/98 for mutt 0.90.8 - * The original code assumed that both snprintf() and vsnprintf() were - * missing. Some systems only have snprintf() but not vsnprintf(), so - * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. - * - * Andrew Tridgell (tridge@samba.org) Oct 1998 - * fixed handling of %.0f - * added test for HAVE_LONG_DOUBLE - * - * tridge@samba.org, idra@samba.org, April 2001 - * got rid of fcvt code (twas buggy and made testing harder) - * added C99 semantics - * - * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 - * actually print args for %g and %e - * - * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 - * Since includes.h isn't included here, VA_COPY has to be defined here. I don't - * see any include file that is guaranteed to be here, so I'm defining it - * locally. Fixes AIX and Solaris builds. - * - * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 - * put the ifdef for HAVE_VA_COPY in one place rather than in lots of - * functions - * - * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 - * Fix usage of va_list passed as an arg. Use __va_copy before using it - * when it exists. - * - * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 - * Fix incorrect zpadlen handling in fmtfp. - * Thanks to Ollie Oldham for spotting it. - * few mods to make it easier to compile the tests. - * addedd the "Ollie" test to the floating point ones. - * - * Martin Pool (mbp@samba.org) April 2003 - * Remove NO_CONFIG_H so that the test case can be built within a source - * tree with less trouble. - * Remove unnecessary SAFE_FREE() definition. - * - * Martin Pool (mbp@samba.org) May 2003 - * Put in a prototype for dummy_snprintf() to quiet compiler warnings. - * - * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even - * if the C library has some snprintf functions already. - * - * Darren Tucker (dtucker@zip.com.au) 2005 - * Fix bug allowing read overruns of the source string with "%.*s" - * Usually harmless unless the read runs outside the process' allocation - * (eg if your malloc does guard pages) in which case it will segfault. - * From OpenSSH. Also added test for same. - * - * Simo Sorce (idra@samba.org) Jan 2006 - * - * Add support for position independent parameters - * fix fmtstr now it conforms to sprintf wrt min.max - * - **************************************************************/ - -#ifndef NO_CONFIG_H -/* 08/13/2007 EG changed path to config.h to match NRPE distro */ -#include "../include/config.h" -#else -#define NULL 0 -#endif - -#ifdef TEST_SNPRINTF /* need math library headers for testing */ - -/* In test mode, we pretend that this system doesn't have any snprintf - * functions, regardless of what config.h says. */ -# undef HAVE_SNPRINTF -# undef HAVE_VSNPRINTF -# undef HAVE_C99_VSNPRINTF -# undef HAVE_ASPRINTF -# undef HAVE_VASPRINTF -# include -#endif /* TEST_SNPRINTF */ - -#ifdef HAVE_STRING_H -#include -#endif - -#ifdef HAVE_STRINGS_H -#include -#endif -#ifdef HAVE_CTYPE_H -#include -#endif -#include -#include -#ifdef HAVE_STDLIB_H -#include -#endif - -#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) -/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ -#include - /* make the compiler happy with an empty file */ - void dummy_snprintf(void); - void dummy_snprintf(void) {} -#endif /* HAVE_SNPRINTF, etc */ - -#ifdef HAVE_LONG_DOUBLE -#define LDOUBLE long double -#else -#define LDOUBLE double -#endif - -#ifdef HAVE_LONG_LONG -#define LLONG long long -#else -#define LLONG long -#endif - -#ifndef VA_COPY -#ifdef HAVE_VA_COPY -#define VA_COPY(dest, src) va_copy(dest, src) -#else -#ifdef HAVE___VA_COPY -#define VA_COPY(dest, src) __va_copy(dest, src) -#else -#define VA_COPY(dest, src) (dest) = (src) -#endif -#endif - -/* - * dopr(): poor man's version of doprintf - */ - -/* format read states */ -#define DP_S_DEFAULT 0 -#define DP_S_FLAGS 1 -#define DP_S_MIN 2 -#define DP_S_DOT 3 -#define DP_S_MAX 4 -#define DP_S_MOD 5 -#define DP_S_CONV 6 -#define DP_S_DONE 7 - -/* format flags - Bits */ -#define DP_F_MINUS (1 << 0) -#define DP_F_PLUS (1 << 1) -#define DP_F_SPACE (1 << 2) -#define DP_F_NUM (1 << 3) -#define DP_F_ZERO (1 << 4) -#define DP_F_UP (1 << 5) -#define DP_F_UNSIGNED (1 << 6) - -/* Conversion Flags */ -#define DP_C_CHAR 1 -#define DP_C_SHORT 2 -#define DP_C_LONG 3 -#define DP_C_LDOUBLE 4 -#define DP_C_LLONG 5 - -/* Chunk types */ -#define CNK_FMT_STR 0 -#define CNK_INT 1 -#define CNK_OCTAL 2 -#define CNK_UINT 3 -#define CNK_HEX 4 -#define CNK_FLOAT 5 -#define CNK_CHAR 6 -#define CNK_STRING 7 -#define CNK_PTR 8 -#define CNK_NUM 9 -#define CNK_PRCNT 10 - -#define char_to_int(p) ((p)- '0') -#ifndef MAX -#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) -#endif - -/* yes this really must be a ||. Don't muck with this (tridge) */ -#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) - -struct pr_chunk { - int type; /* chunk type */ - int num; /* parameter number */ - int min; - int max; - int flags; - int cflags; - int start; - int len; - LLONG value; - LDOUBLE fvalue; - char *strvalue; - void *pnum; - struct pr_chunk *min_star; - struct pr_chunk *max_star; - struct pr_chunk *next; -}; - -struct pr_chunk_x { - struct pr_chunk **chunks; - int num; -}; - -static size_t dopr(char *buffer, size_t maxlen, const char *format, - va_list args_in); -static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max); -static void fmtint(char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags); -static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags); -static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); -static struct pr_chunk *new_chunk(void); -static int add_cnk_list_entry(struct pr_chunk_x **list, - int max_num, struct pr_chunk *chunk); - -static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) -{ - char ch; - int state; - int pflag; - int pnum; - int pfirst; - size_t currlen; - va_list args; - const char *base; - struct pr_chunk *chunks = NULL; - struct pr_chunk *cnk = NULL; - struct pr_chunk_x *clist = NULL; - int max_pos; - size_t ret = -1; - - VA_COPY(args, args_in); - - state = DP_S_DEFAULT; - pfirst = 1; - pflag = 0; - pnum = 0; - - max_pos = 0; - base = format; - ch = *format++; - - /* retrieve the string structure as chunks */ - while (state != DP_S_DONE) { - if (ch == '\0') - state = DP_S_DONE; - - switch(state) { - case DP_S_DEFAULT: - - if (cnk) { - cnk->next = new_chunk(); - cnk = cnk->next; - } else { - cnk = new_chunk(); - } - if (!cnk) goto done; - if (!chunks) chunks = cnk; - - if (ch == '%') { - state = DP_S_FLAGS; - ch = *format++; - } else { - cnk->type = CNK_FMT_STR; - cnk->start = format - base -1; - while ((ch != '\0') && (ch != '%')) ch = *format++; - cnk->len = format - base - cnk->start -1; - } - break; - case DP_S_FLAGS: - switch (ch) { - case '-': - cnk->flags |= DP_F_MINUS; - ch = *format++; - break; - case '+': - cnk->flags |= DP_F_PLUS; - ch = *format++; - break; - case ' ': - cnk->flags |= DP_F_SPACE; - ch = *format++; - break; - case '#': - cnk->flags |= DP_F_NUM; - ch = *format++; - break; - case '0': - cnk->flags |= DP_F_ZERO; - ch = *format++; - break; - case 'I': - /* internationalization not supported yet */ - ch = *format++; - break; - default: - state = DP_S_MIN; - break; - } - break; - case DP_S_MIN: - if (isdigit((unsigned char)ch)) { - cnk->min = 10 * cnk->min + char_to_int (ch); - ch = *format++; - } else if (ch == '$') { - if (!pfirst && !pflag) { - /* parameters must be all positioned or none */ - goto done; - } - if (pfirst) { - pfirst = 0; - pflag = 1; - } - if (cnk->min == 0) /* what ?? */ - goto done; - cnk->num = cnk->min; - cnk->min = 0; - ch = *format++; - } else if (ch == '*') { - if (pfirst) pfirst = 0; - cnk->min_star = new_chunk(); - if (!cnk->min_star) /* out of memory :-( */ - goto done; - cnk->min_star->type = CNK_INT; - if (pflag) { - int num; - ch = *format++; - if (!isdigit((unsigned char)ch)) { - /* parameters must be all positioned or none */ - goto done; - } - for (num = 0; isdigit((unsigned char)ch); ch = *format++) { - num = 10 * num + char_to_int(ch); - } - cnk->min_star->num = num; - if (ch != '$') /* what ?? */ - goto done; - } else { - cnk->min_star->num = ++pnum; - } - max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star); - if (max_pos == 0) /* out of memory :-( */ - goto done; - ch = *format++; - state = DP_S_DOT; - } else { - if (pfirst) pfirst = 0; - state = DP_S_DOT; - } - break; - case DP_S_DOT: - if (ch == '.') { - state = DP_S_MAX; - ch = *format++; - } else { - state = DP_S_MOD; - } - break; - case DP_S_MAX: - if (isdigit((unsigned char)ch)) { - if (cnk->max < 0) - cnk->max = 0; - cnk->max = 10 * cnk->max + char_to_int (ch); - ch = *format++; - } else if (ch == '$') { - if (!pfirst && !pflag) { - /* parameters must be all positioned or none */ - goto done; - } - if (cnk->max <= 0) /* what ?? */ - goto done; - cnk->num = cnk->max; - cnk->max = -1; - ch = *format++; - } else if (ch == '*') { - cnk->max_star = new_chunk(); - if (!cnk->max_star) /* out of memory :-( */ - goto done; - cnk->max_star->type = CNK_INT; - if (pflag) { - int num; - ch = *format++; - if (!isdigit((unsigned char)ch)) { - /* parameters must be all positioned or none */ - goto done; - } - for (num = 0; isdigit((unsigned char)ch); ch = *format++) { - num = 10 * num + char_to_int(ch); - } - cnk->max_star->num = num; - if (ch != '$') /* what ?? */ - goto done; - } else { - cnk->max_star->num = ++pnum; - } - max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star); - if (max_pos == 0) /* out of memory :-( */ - goto done; - - ch = *format++; - state = DP_S_MOD; - } else { - state = DP_S_MOD; - } - break; - case DP_S_MOD: - switch (ch) { - case 'h': - cnk->cflags = DP_C_SHORT; - ch = *format++; - if (ch == 'h') { - cnk->cflags = DP_C_CHAR; - ch = *format++; - } - break; - case 'l': - cnk->cflags = DP_C_LONG; - ch = *format++; - if (ch == 'l') { /* It's a long long */ - cnk->cflags = DP_C_LLONG; - ch = *format++; - } - break; - case 'L': - cnk->cflags = DP_C_LDOUBLE; - ch = *format++; - break; - default: - break; - } - state = DP_S_CONV; - break; - case DP_S_CONV: - if (cnk->num == 0) cnk->num = ++pnum; - max_pos = add_cnk_list_entry(&clist, max_pos, cnk); - if (max_pos == 0) /* out of memory :-( */ - goto done; - - switch (ch) { - case 'd': - case 'i': - cnk->type = CNK_INT; - break; - case 'o': - cnk->type = CNK_OCTAL; - cnk->flags |= DP_F_UNSIGNED; - break; - case 'u': - cnk->type = CNK_UINT; - cnk->flags |= DP_F_UNSIGNED; - break; - case 'X': - cnk->flags |= DP_F_UP; - case 'x': - cnk->type = CNK_HEX; - cnk->flags |= DP_F_UNSIGNED; - break; - case 'A': - /* hex float not supported yet */ - case 'E': - case 'G': - case 'F': - cnk->flags |= DP_F_UP; - case 'a': - /* hex float not supported yet */ - case 'e': - case 'f': - case 'g': - cnk->type = CNK_FLOAT; - break; - case 'c': - cnk->type = CNK_CHAR; - break; - case 's': - cnk->type = CNK_STRING; - break; - case 'p': - cnk->type = CNK_PTR; - break; - case 'n': - cnk->type = CNK_NUM; - break; - case '%': - cnk->type = CNK_PRCNT; - break; - default: - /* Unknown, bail out*/ - goto done; - } - ch = *format++; - state = DP_S_DEFAULT; - break; - case DP_S_DONE: - break; - default: - /* hmm? */ - break; /* some picky compilers need this */ - } - } - - /* retieve the format arguments */ - for (pnum = 0; pnum < max_pos; pnum++) { - int i; - - if (clist[pnum].num == 0) { - /* ignoring a parameter should not be permitted - * all parameters must be matched at least once - * BUT seem some system ignore this rule ... - * at least my glibc based system does --SSS - */ -#ifdef DEBUG_SNPRINTF - printf("parameter at position %d not used\n", pnum+1); -#endif - /* eat the parameter */ - va_arg (args, int); - continue; - } - for (i = 1; i < clist[pnum].num; i++) { - if (clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) { - /* nooo noo no! - * all the references to a parameter - * must be of the same type - */ - goto done; - } - } - cnk = clist[pnum].chunks[0]; - switch (cnk->type) { - case CNK_INT: - if (cnk->cflags == DP_C_SHORT) - cnk->value = va_arg (args, int); - else if (cnk->cflags == DP_C_LONG) - cnk->value = va_arg (args, long int); - else if (cnk->cflags == DP_C_LLONG) - cnk->value = va_arg (args, LLONG); - else - cnk->value = va_arg (args, int); - - for (i = 1; i < clist[pnum].num; i++) { - clist[pnum].chunks[i]->value = cnk->value; - } - break; - - case CNK_OCTAL: - case CNK_UINT: - case CNK_HEX: - if (cnk->cflags == DP_C_SHORT) - cnk->value = va_arg (args, unsigned int); - else if (cnk->cflags == DP_C_LONG) - cnk->value = (long)va_arg (args, unsigned long int); - else if (cnk->cflags == DP_C_LLONG) - cnk->value = (LLONG)va_arg (args, unsigned LLONG); - else - cnk->value = (long)va_arg (args, unsigned int); - - for (i = 1; i < clist[pnum].num; i++) { - clist[pnum].chunks[i]->value = cnk->value; - } - break; - - case CNK_FLOAT: - if (cnk->cflags == DP_C_LDOUBLE) - cnk->fvalue = va_arg (args, LDOUBLE); - else - cnk->fvalue = va_arg (args, double); - - for (i = 1; i < clist[pnum].num; i++) { - clist[pnum].chunks[i]->fvalue = cnk->fvalue; - } - break; - - case CNK_CHAR: - cnk->value = va_arg (args, int); - - for (i = 1; i < clist[pnum].num; i++) { - clist[pnum].chunks[i]->value = cnk->value; - } - break; - - case CNK_STRING: - cnk->strvalue = va_arg (args, char *); - if (!cnk->strvalue) cnk->strvalue = "(NULL)"; - - for (i = 1; i < clist[pnum].num; i++) { - clist[pnum].chunks[i]->strvalue = cnk->strvalue; - } - break; - - case CNK_PTR: - cnk->strvalue = va_arg (args, void *); - for (i = 1; i < clist[pnum].num; i++) { - clist[pnum].chunks[i]->strvalue = cnk->strvalue; - } - break; - - case CNK_NUM: - if (cnk->cflags == DP_C_CHAR) - cnk->pnum = va_arg (args, char *); - else if (cnk->cflags == DP_C_SHORT) - cnk->pnum = va_arg (args, short int *); - else if (cnk->cflags == DP_C_LONG) - cnk->pnum = va_arg (args, long int *); - else if (cnk->cflags == DP_C_LLONG) - cnk->pnum = va_arg (args, LLONG *); - else - cnk->pnum = va_arg (args, int *); - - for (i = 1; i < clist[pnum].num; i++) { - clist[pnum].chunks[i]->pnum = cnk->pnum; - } - break; - - case CNK_PRCNT: - break; - - default: - /* what ?? */ - goto done; - } - } - /* print out the actual string from chunks */ - currlen = 0; - cnk = chunks; - while (cnk) { - int len, min, max; - - if (cnk->min_star) min = cnk->min_star->value; - else min = cnk->min; - if (cnk->max_star) max = cnk->max_star->value; - else max = cnk->max; - - switch (cnk->type) { - - case CNK_FMT_STR: - if (maxlen != 0 && maxlen > currlen) { - if (maxlen > (currlen + cnk->len)) len = cnk->len; - else len = maxlen - currlen; - - memcpy(&(buffer[currlen]), &(base[cnk->start]), len); - } - currlen += cnk->len; - - break; - - case CNK_INT: - case CNK_UINT: - fmtint (buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags); - break; - - case CNK_OCTAL: - fmtint (buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags); - break; - - case CNK_HEX: - fmtint (buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags); - break; - - case CNK_FLOAT: - fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags); - break; - - case CNK_CHAR: - dopr_outch (buffer, &currlen, maxlen, cnk->value); - break; - - case CNK_STRING: - if (max == -1) { - max = strlen(cnk->strvalue); - } - fmtstr (buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max); - break; - - case CNK_PTR: - fmtint (buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags); - break; - - case CNK_NUM: - if (cnk->cflags == DP_C_CHAR) - *((char *)(cnk->pnum)) = (char)currlen; - else if (cnk->cflags == DP_C_SHORT) - *((short int *)(cnk->pnum)) = (short int)currlen; - else if (cnk->cflags == DP_C_LONG) - *((long int *)(cnk->pnum)) = (long int)currlen; - else if (cnk->cflags == DP_C_LLONG) - *((LLONG *)(cnk->pnum)) = (LLONG)currlen; - else - *((int *)(cnk->pnum)) = (int)currlen; - break; - - case CNK_PRCNT: - dopr_outch (buffer, &currlen, maxlen, '%'); - break; - - default: - /* what ?? */ - goto done; - } - cnk = cnk->next; - } - if (maxlen != 0) { - if (currlen < maxlen - 1) - buffer[currlen] = '\0'; - else if (maxlen > 0) - buffer[maxlen - 1] = '\0'; - } - ret = currlen; - -done: - while (chunks) { - cnk = chunks->next; - free(chunks); - chunks = cnk; - } - if (clist) { - for (pnum = 0; pnum < max_pos; pnum++) { - if (clist[pnum].chunks) free(clist[pnum].chunks); - } - free(clist); - } - return ret; -} - -static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max) -{ - int padlen, strln; /* amount to pad */ - int cnt = 0; - -#ifdef DEBUG_SNPRINTF - printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); -#endif - if (value == 0) { - value = ""; - } - - for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */ - padlen = min - strln; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justify */ - - while (padlen > 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - } - while (*value && (cnt < max)) { - dopr_outch (buffer, currlen, maxlen, *value++); - ++cnt; - } - while (padlen < 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - } -} - -/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ - -static void fmtint(char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags) -{ - int signvalue = 0; - unsigned long uvalue; - char convert[20]; - int place = 0; - int spadlen = 0; /* amount to space pad */ - int zpadlen = 0; /* amount to zero pad */ - int caps = 0; - - if (max < 0) - max = 0; - - uvalue = value; - - if(!(flags & DP_F_UNSIGNED)) { - if( value < 0 ) { - signvalue = '-'; - uvalue = -value; - } else { - if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else if (flags & DP_F_SPACE) - signvalue = ' '; - } - } - - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ - - do { - convert[place++] = - (caps? "0123456789ABCDEF":"0123456789abcdef") - [uvalue % (unsigned)base ]; - uvalue = (uvalue / (unsigned)base ); - } while(uvalue && (place < 20)); - if (place == 20) place--; - convert[place] = 0; - - zpadlen = max - place; - spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); - if (zpadlen < 0) zpadlen = 0; - if (spadlen < 0) spadlen = 0; - if (flags & DP_F_ZERO) { - zpadlen = MAX(zpadlen, spadlen); - spadlen = 0; - } - if (flags & DP_F_MINUS) - spadlen = -spadlen; /* Left Justifty */ - -#ifdef DEBUG_SNPRINTF - printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", - zpadlen, spadlen, min, max, place); -#endif - - /* Spaces */ - while (spadlen > 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - --spadlen; - } - - /* Sign */ - if (signvalue) - dopr_outch (buffer, currlen, maxlen, signvalue); - - /* Zeros */ - if (zpadlen > 0) { - while (zpadlen > 0) { - dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - } - - /* Digits */ - while (place > 0) - dopr_outch (buffer, currlen, maxlen, convert[--place]); - - /* Left Justified spaces */ - while (spadlen < 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++spadlen; - } -} - -static LDOUBLE abs_val(LDOUBLE value) -{ - LDOUBLE result = value; - - if (value < 0) - result = -value; - - return result; -} - -static LDOUBLE POW10(int exp) -{ - LDOUBLE result = 1; - - while (exp) { - result *= 10; - exp--; - } - - return result; -} - -static LLONG ROUND(LDOUBLE value) -{ - LLONG intpart; - - intpart = (LLONG)value; - value = value - intpart; - if (value >= 0.5) intpart++; - - return intpart; -} - -/* a replacement for modf that doesn't need the math library. Should - be portable, but slow */ -static double my_modf(double x0, double *iptr) -{ - int i; - long l; - double x = x0; - double f = 1.0; - - for (i=0;i<100;i++) { - l = (long)x; - if (l <= (x+1) && l >= (x-1)) break; - x *= 0.1; - f *= 10.0; - } - - if (i == 100) { - /* yikes! the number is beyond what we can handle. What do we do? */ - (*iptr) = 0; - return 0; - } - - if (i != 0) { - double i2; - double ret; - - ret = my_modf(x0-l*f, &i2); - (*iptr) = l*f + i2; - return ret; - } - - (*iptr) = l; - return x - (*iptr); -} - - -static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags) -{ - int signvalue = 0; - double ufvalue; - char iconvert[311]; - char fconvert[311]; - int iplace = 0; - int fplace = 0; - int padlen = 0; /* amount to pad */ - int zpadlen = 0; - int caps = 0; - int idx; - double intpart; - double fracpart; - double temp; - - /* - * AIX manpage says the default is 0, but Solaris says the default - * is 6, and sprintf on AIX defaults to 6 - */ - if (max < 0) - max = 6; - - ufvalue = abs_val (fvalue); - - if (fvalue < 0) { - signvalue = '-'; - } else { - if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ - signvalue = '+'; - } else { - if (flags & DP_F_SPACE) - signvalue = ' '; - } - } - -#if 0 - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ -#endif - -#if 0 - if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ -#endif - - /* - * Sorry, we only support 9 digits past the decimal because of our - * conversion method - */ - if (max > 9) - max = 9; - - /* We "cheat" by converting the fractional part to integer by - * multiplying by a factor of 10 - */ - - temp = ufvalue; - my_modf(temp, &intpart); - - fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); - - if (fracpart >= POW10(max)) { - intpart++; - fracpart -= POW10(max); - } - - - /* Convert integer part */ - do { - temp = intpart*0.1; - my_modf(temp, &intpart); - idx = (int) ((temp -intpart +0.05)* 10.0); - /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ - /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ - iconvert[iplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; - } while (intpart && (iplace < 311)); - if (iplace == 311) iplace--; - iconvert[iplace] = 0; - - /* Convert fractional part */ - if (fracpart) - { - do { - temp = fracpart*0.1; - my_modf(temp, &fracpart); - idx = (int) ((temp -fracpart +0.05)* 10.0); - /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ - /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ - fconvert[fplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; - } while(fracpart && (fplace < 311)); - if (fplace == 311) fplace--; - } - fconvert[fplace] = 0; - - /* -1 for decimal point, another -1 if we are printing a sign */ - padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); - zpadlen = max - fplace; - if (zpadlen < 0) zpadlen = 0; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justifty */ - - if ((flags & DP_F_ZERO) && (padlen > 0)) { - if (signvalue) { - dopr_outch (buffer, currlen, maxlen, signvalue); - --padlen; - signvalue = 0; - } - while (padlen > 0) { - dopr_outch (buffer, currlen, maxlen, '0'); - --padlen; - } - } - while (padlen > 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - } - if (signvalue) - dopr_outch (buffer, currlen, maxlen, signvalue); - - while (iplace > 0) - dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); - -#ifdef DEBUG_SNPRINTF - printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); -#endif - - /* - * Decimal point. This should probably use locale to find the correct - * char to print out. - */ - if (max > 0) { - dopr_outch (buffer, currlen, maxlen, '.'); - - while (zpadlen > 0) { - dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - - while (fplace > 0) - dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); - } - - while (padlen < 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - } -} - -static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) -{ - if (*currlen < maxlen) { - buffer[(*currlen)] = c; - } - (*currlen)++; -} - -static struct pr_chunk *new_chunk(void) { - struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk)); - - if ( !new_c ) - return NULL; - - new_c->type = 0; - new_c->num = 0; - new_c->min = 0; - new_c->min_star = NULL; - new_c->max = -1; - new_c->max_star = NULL; - new_c->flags = 0; - new_c->cflags = 0; - new_c->start = 0; - new_c->len = 0; - new_c->value = 0; - new_c->fvalue = 0; - new_c->strvalue = NULL; - new_c->pnum = NULL; - new_c->next = NULL; - - return new_c; -} - -static int add_cnk_list_entry(struct pr_chunk_x **list, - int max_num, struct pr_chunk *chunk) { - struct pr_chunk_x *l; - struct pr_chunk **c; - int max; - int cnum; - int i, pos; - - if (chunk->num > max_num) { - max = chunk->num; - - if (*list == NULL) { - l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max); - pos = 0; - } else { - l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max); - pos = max_num; - } - if (l == NULL) { - for (i = 0; i < max; i++) { - if ((*list)[i].chunks) free((*list)[i].chunks); - } - return 0; - } - for (i = pos; i < max; i++) { - l[i].chunks = NULL; - l[i].num = 0; - } - } else { - l = *list; - max = max_num; - } - - i = chunk->num - 1; - cnum = l[i].num + 1; - if (l[i].chunks == NULL) { - c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum); - } else { - c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum); - } - if (c == NULL) { - for (i = 0; i < max; i++) { - if (l[i].chunks) free(l[i].chunks); - } - return 0; - } - c[l[i].num] = chunk; - l[i].chunks = c; - l[i].num = cnum; - - *list = l; - return max; -} - - int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args) -{ - return dopr(str, count, fmt, args); -} -#define vsnprintf smb_vsnprintf -#endif - -/* yes this really must be a ||. Don't muck with this (tridge) - * - * The logic for these two is that we need our own definition if the - * OS *either* has no definition of *sprintf, or if it does have one - * that doesn't work properly according to the autoconf test. - */ -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) -int smb_snprintf(char *str,size_t count,const char *fmt,...) -{ - size_t ret; - va_list ap; - - va_start(ap, fmt); - ret = vsnprintf(str, count, fmt, ap); - va_end(ap); - return ret; -} -#define snprintf smb_snprintf -#endif - -#endif - -#ifndef HAVE_VASPRINTF - int vasprintf(char **ptr, const char *format, va_list ap) -{ - int ret; - va_list ap2; - - VA_COPY(ap2, ap); - - ret = vsnprintf(NULL, 0, format, ap2); - if (ret <= 0) return ret; - - (*ptr) = (char *)malloc(ret+1); - if (!*ptr) return -1; - - VA_COPY(ap2, ap); - - ret = vsnprintf(*ptr, ret+1, format, ap2); - - return ret; -} -#endif - - -#ifndef HAVE_ASPRINTF - int asprintf(char **ptr, const char *format, ...) -{ - va_list ap; - int ret; - - *ptr = NULL; - va_start(ap, format); - ret = vasprintf(ptr, format, ap); - va_end(ap); - - return ret; -} -#endif - -#ifdef TEST_SNPRINTF - - int sprintf(char *str,const char *fmt,...); - - int main (void) -{ - char buf1[1024]; - char buf2[1024]; - char *buf3; - char *fp_fmt[] = { - "%1.1f", - "%-1.5f", - "%1.5f", - "%123.9f", - "%10.5f", - "% 10.5f", - "%+22.9f", - "%+4.9f", - "%01.3f", - "%4f", - "%3.1f", - "%3.2f", - "%.0f", - "%f", - "%-8.8f", - "%-9.9f", - NULL - }; - double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, - 0.9996, 1.996, 4.136, 5.030201, 0.00205, - /* END LIST */ 0}; - char *int_fmt[] = { - "%-1.5d", - "%1.5d", - "%123.9d", - "%5.5d", - "%10.5d", - "% 10.5d", - "%+22.33d", - "%01.3d", - "%4d", - "%d", - NULL - }; - long int_nums[] = { -1, 134, 91340, 341, 0203, 0, 1234567890}; - char *str_fmt[] = { - "%10.5s", - "%-10.5s", - "%5.10s", - "%-5.10s", - "%10.1s", - "%0.10s", - "%10.0s", - "%1.10s", - "%s", - "%.1s", - "%.10s", - "%10s", - NULL - }; - char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; - int x, y; - int fail = 0; - int num = 0; - int l1, l2; - - printf ("Testing snprintf format codes against system sprintf...\n"); - - for (x = 0; fp_fmt[x] ; x++) { - for (y = 0; fp_nums[y] != 0 ; y++) { - buf1[0] = buf2[0] = '\0'; - l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); - l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); - sprintf (buf2, fp_fmt[x], fp_nums[y]); - buf1[1023] = buf1[1023] = '\0'; - if (strcmp (buf1, buf2) || (l1 != l2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", - fp_fmt[x], l1, buf1, l2, buf2); - fail++; - } - num++; - } - } - - for (x = 0; int_fmt[x] ; x++) { - for (y = 0; int_nums[y] != 0 ; y++) { - buf1[0] = buf2[0] = '\0'; - l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); - l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); - sprintf (buf2, int_fmt[x], int_nums[y]); - buf1[1023] = buf1[1023] = '\0'; - if (strcmp (buf1, buf2) || (l1 != l2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", - int_fmt[x], l1, buf1, l2, buf2); - fail++; - } - num++; - } - } - - for (x = 0; str_fmt[x] ; x++) { - for (y = 0; str_vals[y] != 0 ; y++) { - buf1[0] = buf2[0] = '\0'; - l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); - l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); - sprintf (buf2, str_fmt[x], str_vals[y]); - buf1[1023] = buf1[1023] = '\0'; - if (strcmp (buf1, buf2) || (l1 != l2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", - str_fmt[x], l1, buf1, l2, buf2); - fail++; - } - num++; - } - } - -#define BUFSZ 2048 - - buf1[0] = buf2[0] = '\0'; - if ((buf3 = malloc(BUFSZ)) == NULL) { - fail++; - } else { - num++; - memset(buf3, 'a', BUFSZ); - snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3); - buf1[1023] = '\0'; - if (strcmp(buf1, "a") != 0) { - printf("length limit buf1 '%s' expected 'a'\n", buf1); - fail++; - } - } - - buf1[0] = buf2[0] = '\0'; - l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); - l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); - buf1[1023] = buf1[1023] = '\0'; - if (strcmp(buf1, buf2) || (l1 != l2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", - "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); - fail++; - } - - buf1[0] = buf2[0] = '\0'; - l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); - l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); - buf1[1023] = buf1[1023] = '\0'; - if (strcmp(buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", - "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); - fail++; - } -#if 0 - buf1[0] = buf2[0] = '\0'; - l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890); - l2 = sprintf(buf2, "%lld", (LLONG)1234567890); - buf1[1023] = buf1[1023] = '\0'; - if (strcmp(buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", - "%lld", l1, buf1, l2, buf2); - fail++; - } - - buf1[0] = buf2[0] = '\0'; - l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123); - l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123); - buf1[1023] = buf1[1023] = '\0'; - if (strcmp(buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", - "%Lf", l1, buf1, l2, buf2); - fail++; - } -#endif - printf ("%d tests failed out of %d.\n", fail, num); - - printf("seeing how many digits we support\n"); - { - double v0 = 0.12345678901234567890123456789012345678901; - for (x=0; x<100; x++) { - double p = pow(10, x); - double r = v0*p; - snprintf(buf1, sizeof(buf1), "%1.1f", r); - sprintf(buf2, "%1.1f", r); - if (strcmp(buf1, buf2)) { - printf("we seem to support %d digits\n", x-1); - break; - } - } - } - - return 0; -} -#endif /* TEST_SNPRINTF */ +/* + * NOTE: If you change this file, please merge it into rsync, samba, etc. + */ + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell (papowell@astart.com) + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions + */ + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Andrew Tridgell (tridge@samba.org) Oct 1998 + * fixed handling of %.0f + * added test for HAVE_LONG_DOUBLE + * + * tridge@samba.org, idra@samba.org, April 2001 + * got rid of fcvt code (twas buggy and made testing harder) + * added C99 semantics + * + * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 + * actually print args for %g and %e + * + * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 + * Since includes.h isn't included here, VA_COPY has to be defined here. I don't + * see any include file that is guaranteed to be here, so I'm defining it + * locally. Fixes AIX and Solaris builds. + * + * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 + * put the ifdef for HAVE_VA_COPY in one place rather than in lots of + * functions + * + * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 + * Fix usage of va_list passed as an arg. Use __va_copy before using it + * when it exists. + * + * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 + * Fix incorrect zpadlen handling in fmtfp. + * Thanks to Ollie Oldham for spotting it. + * few mods to make it easier to compile the tests. + * addedd the "Ollie" test to the floating point ones. + * + * Martin Pool (mbp@samba.org) April 2003 + * Remove NO_CONFIG_H so that the test case can be built within a source + * tree with less trouble. + * Remove unnecessary SAFE_FREE() definition. + * + * Martin Pool (mbp@samba.org) May 2003 + * Put in a prototype for dummy_snprintf() to quiet compiler warnings. + * + * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even + * if the C library has some snprintf functions already. + * + * Darren Tucker (dtucker@zip.com.au) 2005 + * Fix bug allowing read overruns of the source string with "%.*s" + * Usually harmless unless the read runs outside the process' allocation + * (eg if your malloc does guard pages) in which case it will segfault. + * From OpenSSH. Also added test for same. + * + * Simo Sorce (idra@samba.org) Jan 2006 + * + * Add support for position independent parameters + * fix fmtstr now it conforms to sprintf wrt min.max + * + **************************************************************/ + +#ifndef NO_CONFIG_H +/* 08/13/2007 EG changed path to config.h to match NRPE distro */ +#include "../include/config.h" +#else +#define NULL 0 +#endif + +#ifdef TEST_SNPRINTF /* need math library headers for testing */ + +/* In test mode, we pretend that this system doesn't have any snprintf + * functions, regardless of what config.h says. */ +# undef HAVE_SNPRINTF +# undef HAVE_VSNPRINTF +# undef HAVE_C99_VSNPRINTF +# undef HAVE_ASPRINTF +# undef HAVE_VASPRINTF +# include +#endif /* TEST_SNPRINTF */ + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) +/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ +#include + /* make the compiler happy with an empty file */ + void dummy_snprintf(void); + void dummy_snprintf(void) {} +#endif /* HAVE_SNPRINTF, etc */ + +#ifdef HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +#ifdef HAVE_LONG_LONG +#define LLONG long long +#else +#define LLONG long +#endif + +#ifndef VA_COPY +#ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#else +#ifdef HAVE___VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#else +#define VA_COPY(dest, src) (dest) = (src) +#endif +#endif + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_CHAR 1 +#define DP_C_SHORT 2 +#define DP_C_LONG 3 +#define DP_C_LDOUBLE 4 +#define DP_C_LLONG 5 + +/* Chunk types */ +#define CNK_FMT_STR 0 +#define CNK_INT 1 +#define CNK_OCTAL 2 +#define CNK_UINT 3 +#define CNK_HEX 4 +#define CNK_FLOAT 5 +#define CNK_CHAR 6 +#define CNK_STRING 7 +#define CNK_PTR 8 +#define CNK_NUM 9 +#define CNK_PRCNT 10 + +#define char_to_int(p) ((p)- '0') +#ifndef MAX +#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) +#endif + +/* yes this really must be a ||. Don't muck with this (tridge) */ +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + +struct pr_chunk { + int type; /* chunk type */ + int num; /* parameter number */ + int min; + int max; + int flags; + int cflags; + int start; + int len; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + void *pnum; + struct pr_chunk *min_star; + struct pr_chunk *max_star; + struct pr_chunk *next; +}; + +struct pr_chunk_x { + struct pr_chunk **chunks; + int num; +}; + +static size_t dopr(char *buffer, size_t maxlen, const char *format, + va_list args_in); +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags); +static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags); +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); +static struct pr_chunk *new_chunk(void); +static int add_cnk_list_entry(struct pr_chunk_x **list, + int max_num, struct pr_chunk *chunk); + +static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) +{ + char ch; + int state; + int pflag; + int pnum; + int pfirst; + size_t currlen; + va_list args; + const char *base; + struct pr_chunk *chunks = NULL; + struct pr_chunk *cnk = NULL; + struct pr_chunk_x *clist = NULL; + int max_pos; + size_t ret = -1; + + VA_COPY(args, args_in); + + state = DP_S_DEFAULT; + pfirst = 1; + pflag = 0; + pnum = 0; + + max_pos = 0; + base = format; + ch = *format++; + + /* retrieve the string structure as chunks */ + while (state != DP_S_DONE) { + if (ch == '\0') + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + + if (cnk) { + cnk->next = new_chunk(); + cnk = cnk->next; + } else { + cnk = new_chunk(); + } + if (!cnk) goto done; + if (!chunks) chunks = cnk; + + if (ch == '%') { + state = DP_S_FLAGS; + ch = *format++; + } else { + cnk->type = CNK_FMT_STR; + cnk->start = format - base -1; + while ((ch != '\0') && (ch != '%')) ch = *format++; + cnk->len = format - base - cnk->start -1; + } + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + cnk->flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + cnk->flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + cnk->flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + cnk->flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + cnk->flags |= DP_F_ZERO; + ch = *format++; + break; + case 'I': + /* internationalization not supported yet */ + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + cnk->min = 10 * cnk->min + char_to_int (ch); + ch = *format++; + } else if (ch == '$') { + if (!pfirst && !pflag) { + /* parameters must be all positioned or none */ + goto done; + } + if (pfirst) { + pfirst = 0; + pflag = 1; + } + if (cnk->min == 0) /* what ?? */ + goto done; + cnk->num = cnk->min; + cnk->min = 0; + ch = *format++; + } else if (ch == '*') { + if (pfirst) pfirst = 0; + cnk->min_star = new_chunk(); + if (!cnk->min_star) /* out of memory :-( */ + goto done; + cnk->min_star->type = CNK_INT; + if (pflag) { + int num; + ch = *format++; + if (!isdigit((unsigned char)ch)) { + /* parameters must be all positioned or none */ + goto done; + } + for (num = 0; isdigit((unsigned char)ch); ch = *format++) { + num = 10 * num + char_to_int(ch); + } + cnk->min_star->num = num; + if (ch != '$') /* what ?? */ + goto done; + } else { + cnk->min_star->num = ++pnum; + } + max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star); + if (max_pos == 0) /* out of memory :-( */ + goto done; + ch = *format++; + state = DP_S_DOT; + } else { + if (pfirst) pfirst = 0; + state = DP_S_DOT; + } + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (cnk->max < 0) + cnk->max = 0; + cnk->max = 10 * cnk->max + char_to_int (ch); + ch = *format++; + } else if (ch == '$') { + if (!pfirst && !pflag) { + /* parameters must be all positioned or none */ + goto done; + } + if (cnk->max <= 0) /* what ?? */ + goto done; + cnk->num = cnk->max; + cnk->max = -1; + ch = *format++; + } else if (ch == '*') { + cnk->max_star = new_chunk(); + if (!cnk->max_star) /* out of memory :-( */ + goto done; + cnk->max_star->type = CNK_INT; + if (pflag) { + int num; + ch = *format++; + if (!isdigit((unsigned char)ch)) { + /* parameters must be all positioned or none */ + goto done; + } + for (num = 0; isdigit((unsigned char)ch); ch = *format++) { + num = 10 * num + char_to_int(ch); + } + cnk->max_star->num = num; + if (ch != '$') /* what ?? */ + goto done; + } else { + cnk->max_star->num = ++pnum; + } + max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star); + if (max_pos == 0) /* out of memory :-( */ + goto done; + + ch = *format++; + state = DP_S_MOD; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cnk->cflags = DP_C_SHORT; + ch = *format++; + if (ch == 'h') { + cnk->cflags = DP_C_CHAR; + ch = *format++; + } + break; + case 'l': + cnk->cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { /* It's a long long */ + cnk->cflags = DP_C_LLONG; + ch = *format++; + } + break; + case 'L': + cnk->cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + if (cnk->num == 0) cnk->num = ++pnum; + max_pos = add_cnk_list_entry(&clist, max_pos, cnk); + if (max_pos == 0) /* out of memory :-( */ + goto done; + + switch (ch) { + case 'd': + case 'i': + cnk->type = CNK_INT; + break; + case 'o': + cnk->type = CNK_OCTAL; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'u': + cnk->type = CNK_UINT; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'X': + cnk->flags |= DP_F_UP; + case 'x': + cnk->type = CNK_HEX; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'A': + /* hex float not supported yet */ + case 'E': + case 'G': + case 'F': + cnk->flags |= DP_F_UP; + case 'a': + /* hex float not supported yet */ + case 'e': + case 'f': + case 'g': + cnk->type = CNK_FLOAT; + break; + case 'c': + cnk->type = CNK_CHAR; + break; + case 's': + cnk->type = CNK_STRING; + break; + case 'p': + cnk->type = CNK_PTR; + break; + case 'n': + cnk->type = CNK_NUM; + break; + case '%': + cnk->type = CNK_PRCNT; + break; + default: + /* Unknown, bail out*/ + goto done; + } + ch = *format++; + state = DP_S_DEFAULT; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + + /* retieve the format arguments */ + for (pnum = 0; pnum < max_pos; pnum++) { + int i; + + if (clist[pnum].num == 0) { + /* ignoring a parameter should not be permitted + * all parameters must be matched at least once + * BUT seem some system ignore this rule ... + * at least my glibc based system does --SSS + */ +#ifdef DEBUG_SNPRINTF + printf("parameter at position %d not used\n", pnum+1); +#endif + /* eat the parameter */ + va_arg (args, int); + continue; + } + for (i = 1; i < clist[pnum].num; i++) { + if (clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) { + /* nooo noo no! + * all the references to a parameter + * must be of the same type + */ + goto done; + } + } + cnk = clist[pnum].chunks[0]; + switch (cnk->type) { + case CNK_INT: + if (cnk->cflags == DP_C_SHORT) + cnk->value = va_arg (args, int); + else if (cnk->cflags == DP_C_LONG) + cnk->value = va_arg (args, long int); + else if (cnk->cflags == DP_C_LLONG) + cnk->value = va_arg (args, LLONG); + else + cnk->value = va_arg (args, int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_OCTAL: + case CNK_UINT: + case CNK_HEX: + if (cnk->cflags == DP_C_SHORT) + cnk->value = va_arg (args, unsigned int); + else if (cnk->cflags == DP_C_LONG) + cnk->value = (long)va_arg (args, unsigned long int); + else if (cnk->cflags == DP_C_LLONG) + cnk->value = (LLONG)va_arg (args, unsigned LLONG); + else + cnk->value = (long)va_arg (args, unsigned int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_FLOAT: + if (cnk->cflags == DP_C_LDOUBLE) + cnk->fvalue = va_arg (args, LDOUBLE); + else + cnk->fvalue = va_arg (args, double); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->fvalue = cnk->fvalue; + } + break; + + case CNK_CHAR: + cnk->value = va_arg (args, int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_STRING: + cnk->strvalue = va_arg (args, char *); + if (!cnk->strvalue) cnk->strvalue = "(NULL)"; + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->strvalue = cnk->strvalue; + } + break; + + case CNK_PTR: + cnk->strvalue = va_arg (args, void *); + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->strvalue = cnk->strvalue; + } + break; + + case CNK_NUM: + if (cnk->cflags == DP_C_CHAR) + cnk->pnum = va_arg (args, char *); + else if (cnk->cflags == DP_C_SHORT) + cnk->pnum = va_arg (args, short int *); + else if (cnk->cflags == DP_C_LONG) + cnk->pnum = va_arg (args, long int *); + else if (cnk->cflags == DP_C_LLONG) + cnk->pnum = va_arg (args, LLONG *); + else + cnk->pnum = va_arg (args, int *); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->pnum = cnk->pnum; + } + break; + + case CNK_PRCNT: + break; + + default: + /* what ?? */ + goto done; + } + } + /* print out the actual string from chunks */ + currlen = 0; + cnk = chunks; + while (cnk) { + int len, min, max; + + if (cnk->min_star) min = cnk->min_star->value; + else min = cnk->min; + if (cnk->max_star) max = cnk->max_star->value; + else max = cnk->max; + + switch (cnk->type) { + + case CNK_FMT_STR: + if (maxlen != 0 && maxlen > currlen) { + if (maxlen > (currlen + cnk->len)) len = cnk->len; + else len = maxlen - currlen; + + memcpy(&(buffer[currlen]), &(base[cnk->start]), len); + } + currlen += cnk->len; + + break; + + case CNK_INT: + case CNK_UINT: + fmtint (buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags); + break; + + case CNK_OCTAL: + fmtint (buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags); + break; + + case CNK_HEX: + fmtint (buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags); + break; + + case CNK_FLOAT: + fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags); + break; + + case CNK_CHAR: + dopr_outch (buffer, &currlen, maxlen, cnk->value); + break; + + case CNK_STRING: + if (max == -1) { + max = strlen(cnk->strvalue); + } + fmtstr (buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max); + break; + + case CNK_PTR: + fmtint (buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags); + break; + + case CNK_NUM: + if (cnk->cflags == DP_C_CHAR) + *((char *)(cnk->pnum)) = (char)currlen; + else if (cnk->cflags == DP_C_SHORT) + *((short int *)(cnk->pnum)) = (short int)currlen; + else if (cnk->cflags == DP_C_LONG) + *((long int *)(cnk->pnum)) = (long int)currlen; + else if (cnk->cflags == DP_C_LLONG) + *((LLONG *)(cnk->pnum)) = (LLONG)currlen; + else + *((int *)(cnk->pnum)) = (int)currlen; + break; + + case CNK_PRCNT: + dopr_outch (buffer, &currlen, maxlen, '%'); + break; + + default: + /* what ?? */ + goto done; + } + cnk = cnk->next; + } + if (maxlen != 0) { + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else if (maxlen > 0) + buffer[maxlen - 1] = '\0'; + } + ret = currlen; + +done: + while (chunks) { + cnk = chunks->next; + free(chunks); + chunks = cnk; + } + if (clist) { + for (pnum = 0; pnum < max_pos; pnum++) { + if (clist[pnum].chunks) free(clist[pnum].chunks); + } + free(clist); + } + return ret; +} + +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + +#ifdef DEBUG_SNPRINTF + printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); +#endif + if (value == 0) { + value = ""; + } + + for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + while (*value && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } else { + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place); +#endif + + /* Spaces */ + while (spadlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + + if (value < 0) + result = -value; + + return result; +} + +static LDOUBLE POW10(int exp) +{ + LDOUBLE result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static LLONG ROUND(LDOUBLE value) +{ + LLONG intpart; + + intpart = (LLONG)value; + value = value - intpart; + if (value >= 0.5) intpart++; + + return intpart; +} + +/* a replacement for modf that doesn't need the math library. Should + be portable, but slow */ +static double my_modf(double x0, double *iptr) +{ + int i; + long l; + double x = x0; + double f = 1.0; + + for (i=0;i<100;i++) { + l = (long)x; + if (l <= (x+1) && l >= (x-1)) break; + x *= 0.1; + f *= 10.0; + } + + if (i == 100) { + /* yikes! the number is beyond what we can handle. What do we do? */ + (*iptr) = 0; + return 0; + } + + if (i != 0) { + double i2; + double ret; + + ret = my_modf(x0-l*f, &i2); + (*iptr) = l*f + i2; + return ret; + } + + (*iptr) = l; + return x - (*iptr); +} + + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags) +{ + int signvalue = 0; + double ufvalue; + char iconvert[311]; + char fconvert[311]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + int idx; + double intpart; + double fracpart; + double temp; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) { + signvalue = '-'; + } else { + if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ + signvalue = '+'; + } else { + if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + +#if 0 + if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ +#endif + + /* + * Sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + + temp = ufvalue; + my_modf(temp, &intpart); + + fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); + + if (fracpart >= POW10(max)) { + intpart++; + fracpart -= POW10(max); + } + + + /* Convert integer part */ + do { + temp = intpart*0.1; + my_modf(temp, &intpart); + idx = (int) ((temp -intpart +0.05)* 10.0); + /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ + /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while (intpart && (iplace < 311)); + if (iplace == 311) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + if (fracpart) + { + do { + temp = fracpart*0.1; + my_modf(temp, &fracpart); + idx = (int) ((temp -fracpart +0.05)* 10.0); + /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ + /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while(fracpart && (fplace < 311)); + if (fplace == 311) fplace--; + } + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + +#ifdef DEBUG_SNPRINTF + printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); +#endif + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch (buffer, currlen, maxlen, '.'); + + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + } + + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) { + buffer[(*currlen)] = c; + } + (*currlen)++; +} + +static struct pr_chunk *new_chunk(void) { + struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk)); + + if ( !new_c ) + return NULL; + + new_c->type = 0; + new_c->num = 0; + new_c->min = 0; + new_c->min_star = NULL; + new_c->max = -1; + new_c->max_star = NULL; + new_c->flags = 0; + new_c->cflags = 0; + new_c->start = 0; + new_c->len = 0; + new_c->value = 0; + new_c->fvalue = 0; + new_c->strvalue = NULL; + new_c->pnum = NULL; + new_c->next = NULL; + + return new_c; +} + +static int add_cnk_list_entry(struct pr_chunk_x **list, + int max_num, struct pr_chunk *chunk) { + struct pr_chunk_x *l; + struct pr_chunk **c; + int max; + int cnum; + int i, pos; + + if (chunk->num > max_num) { + max = chunk->num; + + if (*list == NULL) { + l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max); + pos = 0; + } else { + l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max); + pos = max_num; + } + if (l == NULL) { + for (i = 0; i < max; i++) { + if ((*list)[i].chunks) free((*list)[i].chunks); + } + return 0; + } + for (i = pos; i < max; i++) { + l[i].chunks = NULL; + l[i].num = 0; + } + } else { + l = *list; + max = max_num; + } + + i = chunk->num - 1; + cnum = l[i].num + 1; + if (l[i].chunks == NULL) { + c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum); + } else { + c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum); + } + if (c == NULL) { + for (i = 0; i < max; i++) { + if (l[i].chunks) free(l[i].chunks); + } + return 0; + } + c[l[i].num] = chunk; + l[i].chunks = c; + l[i].num = cnum; + + *list = l; + return max; +} + + int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + return dopr(str, count, fmt, args); +} +#define vsnprintf smb_vsnprintf +#endif + +/* yes this really must be a ||. Don't muck with this (tridge) + * + * The logic for these two is that we need our own definition if the + * OS *either* has no definition of *sprintf, or if it does have one + * that doesn't work properly according to the autoconf test. + */ +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +int smb_snprintf(char *str,size_t count,const char *fmt,...) +{ + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} +#define snprintf smb_snprintf +#endif + +#endif + +#ifndef HAVE_VASPRINTF + int vasprintf(char **ptr, const char *format, va_list ap) +{ + int ret; + va_list ap2; + + VA_COPY(ap2, ap); + + ret = vsnprintf(NULL, 0, format, ap2); + if (ret <= 0) return ret; + + (*ptr) = (char *)malloc(ret+1); + if (!*ptr) return -1; + + VA_COPY(ap2, ap); + + ret = vsnprintf(*ptr, ret+1, format, ap2); + + return ret; +} +#endif + + +#ifndef HAVE_ASPRINTF + int asprintf(char **ptr, const char *format, ...) +{ + va_list ap; + int ret; + + *ptr = NULL; + va_start(ap, format); + ret = vasprintf(ptr, format, ap); + va_end(ap); + + return ret; +} +#endif + +#ifdef TEST_SNPRINTF + + int sprintf(char *str,const char *fmt,...); + + int main (void) +{ + char buf1[1024]; + char buf2[1024]; + char *buf3; + char *fp_fmt[] = { + "%1.1f", + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + "%.0f", + "%f", + "%-8.8f", + "%-9.9f", + NULL + }; + double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 5.030201, 0.00205, + /* END LIST */ 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + "%d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 0, 1234567890}; + char *str_fmt[] = { + "%10.5s", + "%-10.5s", + "%5.10s", + "%-5.10s", + "%10.1s", + "%0.10s", + "%10.0s", + "%1.10s", + "%s", + "%.1s", + "%.10s", + "%10s", + NULL + }; + char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; + int x, y; + int fail = 0; + int num = 0; + int l1, l2; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] ; x++) { + for (y = 0; fp_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); + l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + buf1[1023] = buf1[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + fp_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + + for (x = 0; int_fmt[x] ; x++) { + for (y = 0; int_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); + l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); + sprintf (buf2, int_fmt[x], int_nums[y]); + buf1[1023] = buf1[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + int_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + + for (x = 0; str_fmt[x] ; x++) { + for (y = 0; str_vals[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); + l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); + sprintf (buf2, str_fmt[x], str_vals[y]); + buf1[1023] = buf1[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + str_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + +#define BUFSZ 2048 + + buf1[0] = buf2[0] = '\0'; + if ((buf3 = malloc(BUFSZ)) == NULL) { + fail++; + } else { + num++; + memset(buf3, 'a', BUFSZ); + snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3); + buf1[1023] = '\0'; + if (strcmp(buf1, "a") != 0) { + printf("length limit buf1 '%s' expected 'a'\n", buf1); + fail++; + } + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); + l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); + buf1[1023] = buf1[1023] = '\0'; + if (strcmp(buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); + fail++; + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); + l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); + buf1[1023] = buf1[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); + fail++; + } +#if 0 + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890); + l2 = sprintf(buf2, "%lld", (LLONG)1234567890); + buf1[1023] = buf1[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%lld", l1, buf1, l2, buf2); + fail++; + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123); + l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123); + buf1[1023] = buf1[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%Lf", l1, buf1, l2, buf2); + fail++; + } +#endif + printf ("%d tests failed out of %d.\n", fail, num); + + printf("seeing how many digits we support\n"); + { + double v0 = 0.12345678901234567890123456789012345678901; + for (x=0; x<100; x++) { + double p = pow(10, x); + double r = v0*p; + snprintf(buf1, sizeof(buf1), "%1.1f", r); + sprintf(buf2, "%1.1f", r); + if (strcmp(buf1, buf2)) { + printf("we seem to support %d digits\n", x-1); + break; + } + } + } + + return 0; +} +#endif /* TEST_SNPRINTF */ diff -Nru nagios-nrpe-2.13/src/utils.c nagios-nrpe-2.15/src/utils.c --- nagios-nrpe-2.13/src/utils.c 2006-12-12 02:04:01.000000000 +0000 +++ nagios-nrpe-2.15/src/utils.c 2013-09-06 15:27:13.000000000 +0000 @@ -1,440 +1,390 @@ -/**************************************************************************** - * - * UTILS.C - NRPE Utility Functions - * - * License: GPL - * Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org) - * - * Last Modified: 12-11-2006 - * - * Description: - * - * This file contains common network functions used in nrpe and check_nrpe. - * - * License Information: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************************/ - -#include "../include/common.h" -#include "../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>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;xh_addr,hp->h_length); - } - - /* map transport protocol name to protocol number */ - if(((ptrp=getprotobyname(proto)))==NULL){ - printf("Cannot map \"%s\" to protocol number\n",proto); - return STATE_UNKNOWN; - } - - /* create a socket */ - *sd=socket(PF_INET,(!strcmp(proto,"udp"))?SOCK_DGRAM:SOCK_STREAM,ptrp->p_proto); - if(*sd<0){ - printf("Socket creation failed\n"); - return STATE_UNKNOWN; - } - - /* open a connection */ - result=connect(*sd,(struct sockaddr *)&servaddr,sizeof(servaddr)); - if(result<0){ - switch(errno){ - case ECONNREFUSED: - printf("Connection refused by host\n"); - break; - case ETIMEDOUT: - printf("Timeout while attempting connection\n"); - break; - case ENETUNREACH: - printf("Network is unreachable\n"); - break; - default: - printf("Connection refused or timed out\n"); - } - - return STATE_CRITICAL; - } - - return STATE_OK; - } - - - -/* This code was taken from Fyodor's nmap utility, which was originally taken from - the GLIBC 2.0.6 libraries because Solaris doesn't contain the inet_aton() funtion. */ -int my_inet_aton(register const char *cp, struct in_addr *addr){ - register unsigned int val; /* changed from u_long --david */ - register int base, n; - register char c; - u_int parts[4]; - register u_int *pp = parts; - - c=*cp; - - for(;;){ - - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, isdigit=decimal. - */ - if (!isdigit((int)c)) - return (0); - val=0; - base=10; - - if(c=='0'){ - c=*++cp; - if(c=='x'||c=='X') - base=16,c=*++cp; - else - base=8; - } - - for(;;){ - if(isascii((int)c) && isdigit((int)c)){ - val=(val*base)+(c -'0'); - c=*++cp; - } - else if(base==16 && isascii((int)c) && isxdigit((int)c)){ - val=(val<<4) | (c+10-(islower((int)c)?'a':'A')); - c = *++cp; - } - else - break; - } - - if(c=='.'){ - - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if(pp>=parts+3) - return (0); - *pp++=val; - c=*++cp; - } - else - break; - } - - /* Check for trailing characters */ - if(c!='\0' && (!isascii((int)c) || !isspace((int)c))) - return (0); - - /* Concoct the address according to the number of parts specified */ - n=pp-parts+1; - switch(n){ - - case 0: - return (0); /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if(val>0xffffff) - return (0); - val|=parts[0]<<24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if(val>0xffff) - return (0); - val|=(parts[0]<< 24) | (parts[1]<<16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if(val>0xff) - return (0); - val|=(parts[0]<<24) | (parts[1]<<16) | (parts[2]<<8); - break; - } - - if(addr) - addr->s_addr=htonl(val); - - return (1); - } - - -void strip(char *buffer){ - int x; - int index; - - for(x=strlen(buffer);x>=1;x--){ - index=x-1; - if(buffer[index]==' ' || buffer[index]=='\r' || buffer[index]=='\n' || buffer[index]=='\t') - buffer[index]='\x0'; - else - break; - } - - return; - } - - -/* sends all data - thanks to Beej's Guide to Network Programming */ -int sendall(int s, char *buf, int *len){ - int total=0; - int bytesleft=*len; - int n=0; - - /* send all the data */ - while(total<*len){ - - /* send some data */ - n=send(s,buf+total,bytesleft,0); - - /* break on error */ - if(n==-1) - break; - - /* apply bytes we sent */ - total+=n; - bytesleft-=n; - } - - /* return number of bytes actually send here */ - *len=total; - - /* return -1 on failure, 0 on success */ - return n==-1?-1:0; - } - - -/* receives all data - modelled after sendall() */ -int recvall(int s, char *buf, int *len, int timeout){ - int total=0; - int bytesleft=*len; - int n=0; - time_t start_time; - time_t current_time; - - /* clear the receive buffer */ - bzero(buf,*len); - - time(&start_time); - - /* receive all data */ - while(total<*len){ - - /* receive some data */ - n=recv(s,buf+total,bytesleft,0); - - /* no data has arrived yet (non-blocking socket) */ - if(n==-1 && errno==EAGAIN){ - time(¤t_time); - if(current_time-start_time>timeout) - break; - sleep(1); - continue; - } - - /* receive error or client disconnect */ - else if(n<=0) - break; - - /* apply bytes we received */ - total+=n; - bytesleft-=n; - } - - /* return number of bytes actually received here */ - *len=total; - - /* return <=0 on failure, bytes received on success */ - return (n<=0)?n:total; - } - - -/* fixes compiler problems under Solaris, since strsep() isn't included */ -/* this code is taken from the glibc source */ -char *my_strsep (char **stringp, const char *delim){ - char *begin, *end; - - begin = *stringp; - if (begin == NULL) - return NULL; - - /* A frequent case is when the delimiter string contains only one - character. Here we don't need to call the expensive `strpbrk' - function and instead work using `strchr'. */ - if(delim[0]=='\0' || delim[1]=='\0'){ - char ch = delim[0]; - - if(ch=='\0') - end=NULL; - else{ - if(*begin==ch) - end=begin; - else - end=strchr(begin+1,ch); - } - } - - else - /* Find the end of the token. */ - end = strpbrk (begin, delim); - - if(end){ - - /* Terminate the token and set *STRINGP past NUL character. */ - *end++='\0'; - *stringp=end; - } - else - /* No more delimiters; this is the last token. */ - *stringp=NULL; - - return begin; - } - - -/* show license */ -void display_license(void){ - - printf("This program is released under the GPL (see below) with the additional\n"); - printf("exemption that compiling, linking, and/or using OpenSSL is allowed.\n\n"); - - printf("This program is free software; you can redistribute it and/or modify\n"); - printf("it under the terms of the GNU General Public License as published by\n"); - printf("the Free Software Foundation; either version 2 of the License, or\n"); - printf("(at your option) any later version.\n\n"); - printf("This program is distributed in the hope that it will be useful,\n"); - printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); - printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); - printf("GNU General Public License for more details.\n\n"); - printf("You should have received a copy of the GNU General Public License\n"); - printf("along with this program; if not, write to the Free Software\n"); - printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"); - - return; - } - - - +/**************************************************************************** + * + * UTILS.C - NRPE Utility Functions + * + * License: GPL + * Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org) + * + * Last Modified: 12-11-2006 + * + * Description: + * + * This file contains common network functions used in nrpe and check_nrpe. + * + * License Information: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ****************************************************************************/ + +#include "../include/common.h" +#include "../include/utils.h" + +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + +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>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;xai_next) { + if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), + strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { + fprintf(stderr, "my_connect: getnameinfo failed\n"); + continue; + } + + /* Create a socket for connecting. */ + sock = my_create_socket(ai, bind_address); + if (sock < 0) { + /* Any error is already output */ + continue; + } + + if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { + /* Successful connection. */ + memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); + break; + } + else { + fprintf(stderr,"connect to address %s port %s: %s\n", ntop, strport, + strerror(errno)); + close(sock); + sock = -1; + } + } + + freeaddrinfo(aitop); + + /* Return failure if we didn't get a successful connection. */ + if (sock == -1) { + fprintf(stderr, "connect to host %s port %s: %s", host, strport, + strerror(errno)); + return -1; + } + return sock; + } + +/* Creates a socket for the connection. */ +int my_create_socket(struct addrinfo *ai, const char *bind_address) { + int sock, gaierr; + struct addrinfo hints, *res; + + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) fprintf(stderr,"socket: %.100s\n", strerror(errno)); + + /* Bind the socket to an alternative local IP address */ + if (bind_address == NULL) return sock; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = ai->ai_family; + hints.ai_socktype = ai->ai_socktype; + hints.ai_protocol = ai->ai_protocol; + hints.ai_flags = AI_PASSIVE; + gaierr = getaddrinfo(bind_address, NULL, &hints, &res); + if(gaierr) { + fprintf(stderr, "getaddrinfo: %s: %s\n", bind_address, + gai_strerror(gaierr)); + close(sock); + return -1; + } + if(bind(sock, res->ai_addr, res->ai_addrlen) < 0) { + fprintf(stderr, "bind: %s: %s\n", bind_address, strerror(errno)); + close(sock); + freeaddrinfo(res); + return -1; + } + freeaddrinfo(res); + return sock; +} + +void add_listen_addr(struct addrinfo **listen_addrs, int address_family, + char *addr, int port) { + struct addrinfo hints, *ai, *aitop; + char strport[NI_MAXSERV]; + int gaierr; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = address_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; + snprintf(strport, sizeof strport, "%d", port); + if((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { + syslog(LOG_ERR,"bad addr or host: %s (%s)\n", addr ? addr : "", + gai_strerror(gaierr)); + exit(1); + } + for(ai = aitop; ai->ai_next; ai = ai->ai_next); + ai->ai_next = *listen_addrs; + *listen_addrs = aitop; + } + +void strip(char *buffer){ + int x; + int index; + + for(x=strlen(buffer);x>=1;x--){ + index=x-1; + if(buffer[index]==' ' || buffer[index]=='\r' || buffer[index]=='\n' || buffer[index]=='\t') + buffer[index]='\x0'; + else + break; + } + + return; + } + + +/* sends all data - thanks to Beej's Guide to Network Programming */ +int sendall(int s, char *buf, int *len){ + int total=0; + int bytesleft=*len; + int n=0; + + /* send all the data */ + while(total<*len){ + + /* send some data */ + n=send(s,buf+total,bytesleft,0); + + /* break on error */ + if(n==-1) + break; + + /* apply bytes we sent */ + total+=n; + bytesleft-=n; + } + + /* return number of bytes actually send here */ + *len=total; + + /* return -1 on failure, 0 on success */ + return n==-1?-1:0; + } + + +/* receives all data - modelled after sendall() */ +int recvall(int s, char *buf, int *len, int timeout){ + int total=0; + int bytesleft=*len; + int n=0; + time_t start_time; + time_t current_time; + + /* clear the receive buffer */ + bzero(buf,*len); + + time(&start_time); + + /* receive all data */ + while(total<*len){ + + /* receive some data */ + n=recv(s,buf+total,bytesleft,0); + + /* no data has arrived yet (non-blocking socket) */ + if(n==-1 && errno==EAGAIN){ + time(¤t_time); + if(current_time-start_time>timeout) + break; + sleep(1); + continue; + } + + /* receive error or client disconnect */ + else if(n<=0) + break; + + /* apply bytes we received */ + total+=n; + bytesleft-=n; + } + + /* return number of bytes actually received here */ + *len=total; + + /* return <=0 on failure, bytes received on success */ + return (n<=0)?n:total; + } + + +/* fixes compiler problems under Solaris, since strsep() isn't included */ +/* this code is taken from the glibc source */ +char *my_strsep (char **stringp, const char *delim){ + char *begin, *end; + + begin = *stringp; + if (begin == NULL) + return NULL; + + /* A frequent case is when the delimiter string contains only one + character. Here we don't need to call the expensive `strpbrk' + function and instead work using `strchr'. */ + if(delim[0]=='\0' || delim[1]=='\0'){ + char ch = delim[0]; + + if(ch=='\0') + end=NULL; + else{ + if(*begin==ch) + end=begin; + else + end=strchr(begin+1,ch); + } + } + + else + /* Find the end of the token. */ + end = strpbrk (begin, delim); + + if(end){ + + /* Terminate the token and set *STRINGP past NUL character. */ + *end++='\0'; + *stringp=end; + } + else + /* No more delimiters; this is the last token. */ + *stringp=NULL; + + return begin; + } + + +/* show license */ +void display_license(void){ + + printf("This program is released under the GPL (see below) with the additional\n"); + printf("exemption that compiling, linking, and/or using OpenSSL is allowed.\n\n"); + + printf("This program is free software; you can redistribute it and/or modify\n"); + printf("it under the terms of the GNU General Public License as published by\n"); + printf("the Free Software Foundation; either version 2 of the License, or\n"); + printf("(at your option) any later version.\n\n"); + printf("This program is distributed in the hope that it will be useful,\n"); + printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + printf("GNU General Public License for more details.\n\n"); + printf("You should have received a copy of the GNU General Public License\n"); + printf("along with this program; if not, write to the Free Software\n"); + printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"); + + return; + } + + + diff -Nru nagios-nrpe-2.13/subst.in nagios-nrpe-2.15/subst.in --- nagios-nrpe-2.13/subst.in 2007-11-23 17:32:14.000000000 +0000 +++ nagios-nrpe-2.15/subst.in 2013-09-06 15:27:13.000000000 +0000 @@ -1,47 +1,61 @@ #!/usr/bin/perl -w -my ${exec_prefix}; -my ${prefix}; +# This script finishes the job started by config.status by replacing the variables +# of the form ${...} which were inserted into the file(s) by config.status. -${prefix}="@prefix@"; -${exec_prefix}="@exec_prefix@"; -while ($f = shift @ARGV) { +# Read all files with a single read statement +$/ = undef; - if (-x "/bin/mktemp") { - $TEMP = `/bin/mktemp $f.$$.XXXXXX`; - die 'Cannot make temporary file $TEMP' if($?); - chomp $TEMP; - } else { - $XXXXXX = rand; - $TEMP = "$f.$$.$XXXXXX"; +# List of variables to replace +my %configvars = ( + "prefix" => { "value" => '@prefix@'}, + "exec_prefix" => { "value" => '@exec_prefix@'}, +); + +sub replace_var { + my $filep = shift; + my $cvp = shift; + my $varname = shift; + + return if( $cvp->{ $varname}->{ "replaced"}); + if( defined( $cvp->{ $varname}->{ "dependency"})) { + if( !$cvp->{ $cvp->{ $varname}->{ "dependency"}}->{ "replaced"}) { + # If a dependency exists and it is not already replaced, replace it + replace_var( $filep, $cvp, $cvp->{ $varname}->{ "dependency"}); + } } + my $replacement = $cvp->{ $varname}->{ "value"}; + $$filep =~ s/\${$varname}/$replacement/g; + $cvp->{ $varname}->{ "replaced"} = 1; +} - open(IN,"<$f.in"); - open(OUT,">$TEMP") || die 'Cannot make temporary file $TEMP'; - - while () { - s|\@nrpe_user\@|@nrpe_user@|g; - s|\@nrpe_group\@|@nrpe_group@|g; - s|\@nrpe_port\@|@nrpe_port@|g; - s|\@log_facility\@|@log_facility@|g; - s|\@libexecdir\@|@libexecdir@|g; # put all --with-vars before directories - s|\@localstatedir\@|@localstatedir@|g; - s|\@sysconfdir\@|@sysconfdir@|g; - s|\@datadir\@|@datadir@|g; - s|\@sbindir\@|@sbindir@|g; - s|\@bindir\@|@bindir@|g; - s|\$\{exec_prefix\}|@exec_prefix@|g; # must be next to last - s|\$\{prefix\}|@prefix@|g; # must be last - print OUT $_; +# Figure out the dependencies. +foreach my $cv ( keys %configvars ) { + if( $configvars{ $cv}->{ "value"} =~ /\${([^}]+)}/) { + my $dependency = $1; + if( exists( $configvars{ $dependency})) { + $configvars{ $dependency}->{ "dependency"} = $cv; + } + $configvars{ $cv}->{ "replaced"} = 0; } +} - close IN; - close OUT; +# Process each file +while ($f = shift @ARGV) { - if ((! -e $f) || (`diff $f $TEMP`)) { - `mv $TEMP $f`; - } else { - unlink $TEMP; + # Read in the file + open( FILE, $f) || die "Unable to open $f for reading"; + my $file = ; + close( FILE) || die "Unable to close $f after reading"; + + # Replace each of the variables we know about + foreach $cv ( keys %configvars ) { + replace_var( \$file, \%configvars, $cv); } + # Write out the replacements + open( FILE, ">$f") || die "Unable to open $f for writing"; + print FILE $file; + close( FILE) || die "Unable to close $f after writing"; + } diff -Nru nagios-nrpe-2.13/update-version nagios-nrpe-2.15/update-version --- nagios-nrpe-2.13/update-version 2011-11-11 18:45:49.000000000 +0000 +++ nagios-nrpe-2.15/update-version 2013-09-06 15:27:13.000000000 +0000 @@ -1,5 +1,23 @@ #!/bin/sh +# Make sure autoconf is installed and is the correct version +min_autoconf_major=2 +min_autoconf_minor=59 +autoconf_error="Autoconf version $min_autoconf_major.$min_autoconf_minor or later must be installed to run this script." +autoconf_version=`(autoconf -V 2> /dev/null) |\ + grep "^autoconf (GNU Autoconf)" | gawk '{print $NF}'` +if [ "$autoconf_version" != "" ] ; then + autoconf_major=`echo $autoconf_version | gawk -F '.' '{print $1}'` + autoconf_minor=`echo $autoconf_version | gawk -F '.' '{print $2}'` + if [ $autoconf_major -lt $min_autoconf_major -o $autoconf_minor -lt $min_autoconf_minor ] ; then + echo $autoconf_error + exit 1 + fi +else + echo $autoconf_error + exit 1 +fi + # Get date (two formats) if [ -n "$2" ]; then LONGDATE=`date -d "$2" "+%B %d, %Y"` @@ -10,10 +28,10 @@ fi # Current version number -CURRENTVERSION=2.13 +CURRENTVERSION=2.15 # Last date -LASTDATE=11-11-2011 +LASTDATE=09-06-2013 if [ "x$1" = "x" ] then @@ -45,14 +63,18 @@ perl -i -p -e "s/Last Modified: [0-9].*/Last Modified: $SHORTDATE/;" src/nrpe.c perl -i -p -e "s/Last Modified: [0-9].*/Last Modified: $SHORTDATE/;" src/check_nrpe.c -# Update version number and release date in configure script and configure.in -perl -i -p -e "s/PKG_VERSION=.*/PKG_VERSION=\"$1\"/;" configure -perl -i -p -e "s/PKG_REL_DATE=.*\"/PKG_REL_DATE=\"$SHORTDATE\"/;" configure +# Update version number and release date in configure.in +perl -i -p -e "if( /^AC_INIT/) { s/$CURRENTVERSION/$1/; }" configure.in perl -i -p -e "s/PKG_VERSION=.*/PKG_VERSION=\"$1\"/;" configure.in perl -i -p -e "s/PKG_REL_DATE=.*\"/PKG_REL_DATE=\"$SHORTDATE\"/;" configure.in +# Run autoconf to update configure (this is easier than updating every instance +# of the version number in configure) +autoconf + # Update RPM spec file with version number perl -i -p -e "s/%define version .*/%define version $1/;" nrpe.spec +perl -i -p -e "if( /\%define _docdir/) { s/$CURRENTVERSION/$1/; }" nrpe.spec # Update this file with version number and last date perl -i -p -e "s/^CURRENTVERSION=.*/CURRENTVERSION=$newversion/;" update-version