Quellcode durchsuchen

Merge branch 'master' into timeout_state

Spenser Reinhardt vor 11 Jahren
Ursprung
Commit
0ba816c9f8

+ 36 - 4
NEWS

@@ -1,5 +1,37 @@
 This file documents the major additions and syntax changes between releases.
 
+2.0.3 26th June 2014
+	SECURITY FIXES
+	parse_ini.c - Additional fixes for the SUID plugins vulnerabilities (sreinhardt) 
+	Added Gnulib module idpriv-droptemp (weiss) 
+
+	FIXES
+	check_dns.c - Resolved issues with reverse lookup (sreinhardt)
+	check_dns.c - Changed query types from ALL to ANY (sreinhardt)
+	common.h - Include fixes for esoteric AIX compile issues (emislivec)
+	negate.c - Small fixes from coverity (66479) (66480) (sreinhardt)
+	check_dhcp.c - Small fix from coverity (66488) (sreinhardt)
+	check_http.c - Potential memory leak and overflow fixed from coverity (66514) (sreinhardt)
+	check_ntp.c - Small fix from coverity (66524) (sreinhardt)
+	utils_cmd.c - Small file descriptor fix from coverity (66502) (sreinhardt)  	
+	check_apt.c - Small fix for from coverity (66531) (sreinhardt)	
+
+	REVERTS
+	check_mailq - Reverted autodetection commits to avoid awk parsing issues. Autodetection will return in version 2.1.0 as part of the changes in the FindBin branch (abrist) 
+
+2.0.2 20th May 2014
+	SECURITY FIXES
+	Fixed file access vulnerability with SUID binaries (check_icmp, check_dhcp) and extra-opts.  Fixes were applied globally, so the new resrictions on fopen should apply to all plugins. Special thanks to Dawid Golunski for the submission. More information: http://www.exploit-db.com/exploits/33387/  (sreinhardt) (emislivec)
+
+	ENHANCEMENTS
+	check_disk - Now compiles in cygwin on windows (Gunnar Beutner)
+	check_ping - Now compiles in cygwin on windows (Gunnar Beutner)
+	check_users - Now compiles in cygwin on windows (Gunnar Beutner)
+	netutils.c - Connection error verbosity increased. C plugins will now differentiate file socket errors from connection errors (Davide Madrisan)
+
+	FIXES
+	check_nt.c - Changed 'Mb' to 'MB' in MEMUSE output for clarity (abrist)
+
 2.0.1 15th April 2014
 	ENHANCMENTS
 	check_snmp.c - Added thresholds to performance data (jccomputing)
@@ -13,11 +45,11 @@ This file documents the major additions and syntax changes between releases.
 	check_uptime.c - Fixed timeout option (abrist)
 	check_uptime.c - Fixed help output and updated verbose usage (abrist)
 	check_uptime.c - Removed executable permissions on check_uptime.c (abrist)
-	check_uptime.c - Removed old code (madrisian)
+	check_uptime.c - Removed old code (Davide Madrisan)
 	check_pgsql.c - Fixed help output (weiss)
-	lib/Makefile.am - Avoid deprecated includes (madrasian)
-	lib/tests/Makefile.am - Avoid deprecated includes (madrasian)
-	plugins/Makefile.am - Avoid deprecated includes (madrasian)
+	lib/Makefile.am - Avoid deprecated includes (Davide Madrisan)
+	lib/tests/Makefile.am - Avoid deprecated includes (Davide Madrisan)
+	plugins/Makefile.am - Avoid deprecated includes (Davide Madrisan)
 	check_apt.c - Removed the verbose flag suggestion (skottler)
 	check_oracle.c - Changed regex to compensate for tns string match edge cases (waja)
 	check_snmp.c - Always privides the security name when noAuthPriv is specified (catharsis)

+ 1 - 1
NP-VERSION-GEN

@@ -6,7 +6,7 @@
 SRC_ROOT=`dirname $0`
 
 NPVF=NP-VERSION-FILE
-DEF_VER=2.0.1.git
+DEF_VER=2.0.3.git
 
 LF='
 '

+ 4 - 0
THANKS.in

@@ -318,3 +318,7 @@ Sam Kottler
 Frederic Krueger
 Anton Lofgren
 Evgeni Golov
+Davide Madrisan
+Dawid Golunski
+Gunnar Beutner
+Eric Mislivec

+ 45 - 25
configure.ac

@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.59)
-AC_INIT(nagios-plugins,2.0.1)
+AC_INIT(nagios-plugins,2.0.3)
 AC_CONFIG_SRCDIR(NPTest.pm)
 AC_CONFIG_FILES([gl/Makefile 
 	nagios-plugins.spec])
@@ -91,6 +91,7 @@ ac_cv_uname_m=`uname -m`
 ac_cv_uname_s=`uname -s`
 ac_cv_uname_r=`uname -r`
 ac_cv_uname_v=`uname -v`
+ac_cv_uname_o=`uname -o`
 
 PKG_ARCH=`uname -p`
 REV_DATESTAMP=`date '+%Y.%m.%d.%H.%M'`
@@ -242,7 +243,7 @@ if test "$ac_cv_lib_crypt_main" = "yes" -a "x$PGSQL" != "xno"; then
     else
       AC_SUBST(PGLIBS)
       AC_SUBST(PGINCLUDE)
-      EXTRAS="$EXTRAS check_pgsql"
+      EXTRAS="$EXTRAS check_pgsql\$(EXEEXT)"
     fi
   else
     AC_MSG_WARN([Skipping PostgreSQL plugin (check_pgsql)])
@@ -262,7 +263,7 @@ AS_IF([test "x$with_dbi" != "xno"], [
   _SAVEDLIBS="$LIBS"
   AC_CHECK_LIB(dbi,dbi_initialize)
   if test "$ac_cv_lib_dbi_dbi_initialize" = "yes"; then
-    EXTRAS="$EXTRAS check_dbi"
+    EXTRAS="$EXTRAS check_dbi\$(EXEEXT)"
   	DBILIBS="-ldbi"
     AC_SUBST(DBILIBS)
   else
@@ -279,13 +280,13 @@ AS_IF([test "x$with_radius" != "xno"], [
   _SAVEDLIBS="$LIBS"
   AC_CHECK_LIB(radiusclient,rc_read_config)
   if test "$ac_cv_lib_radiusclient_rc_read_config" = "yes"; then
-    EXTRAS="$EXTRAS check_radius"
+    EXTRAS="$EXTRAS check_radius\$(EXEEXT)"
   	RADIUSLIBS="-lradiusclient"
     AC_SUBST(RADIUSLIBS)
   else
     AC_CHECK_LIB(radiusclient-ng,rc_read_config)
     if test "$ac_cv_lib_radiusclient_ng_rc_read_config" = "yes"; then
-      EXTRAS="$EXTRAS check_radius"
+      EXTRAS="$EXTRAS check_radius\$(EXEEXT)"
     	  RADIUSLIBS="-lradiusclient-ng"
       AC_SUBST(RADIUSLIBS)
     else
@@ -308,7 +309,7 @@ AS_IF([test "x$with_ldap" != "xno"], [
     AC_SUBST(LDAPLIBS)
     AC_SUBST(LDAPINCLUDE)
     AC_CHECK_FUNCS(ldap_set_option)
-    EXTRAS="$EXTRAS check_ldap"
+    EXTRAS="$EXTRAS check_ldap\$(EXEEXT)"
   	AC_CHECK_FUNCS(ldap_init ldap_set_option ldap_get_option ldap_start_tls_s)
   else
     AC_MSG_WARN([Skipping LDAP plugin])
@@ -345,7 +346,7 @@ case $host in
 esac
 
 if test "$FOUNDINCLUDE" = "yes" ; then
-	EXTRAS="$EXTRAS check_ide_smart"
+	EXTRAS="$EXTRAS check_ide_smart\$(EXEEXT)"
 fi
 
 dnl Check for headers used by check_uptime
@@ -370,7 +371,7 @@ if test $with_mysql = "no" ; then
   AC_MSG_WARN([Skipping mysql plugin])
   AC_MSG_WARN([install mysql client libs to compile this plugin (see REQUIREMENTS).])
 else
-  EXTRAS="$EXTRAS check_mysql check_mysql_query"
+  EXTRAS="$EXTRAS check_mysql\$(EXEEXT) check_mysql_query\$(EXEEXT)"
   MYSQLINCLUDE="$np_mysql_include"
   MYSQLLIBS="$np_mysql_libs"
   MYSQLCFLAGS="$np_mysql_cflags"
@@ -383,8 +384,16 @@ dnl Check for headers used by check_users
 AC_CHECK_HEADERS(utmpx.h)
 AM_CONDITIONAL([HAVE_UTMPX], [test "$ac_cv_header_utmpx_h" = "yes"])
 
+AC_CHECK_HEADERS(wtsapi32.h, [], [], [#include <windows.h>])
+AM_CONDITIONAL([HAVE_WTS32API], [test "$ac_cv_header_wtsapi32_h" = "yes"])
+
+if test "$ac_cv_header_wtsapi32_h" = "yes"; then
+  WTSAPI32LIBS="-lwtsapi32"
+  AC_SUBST(WTSAPI32LIBS)
+fi
+
 dnl Fallback to who(1) if the system doesn't provide an utmpx(5) interface
-if test "$ac_cv_header_utmpx_h" = "no"
+if test "$ac_cv_header_utmpx_h" = "no" -a "$ac_cv_header_wtsapi32_h" = "no"
 then
 	AC_PATH_PROG(PATH_TO_WHO,who)
 
@@ -672,7 +681,7 @@ elif test "$ac_cv_uname_s" = "SunOS"; then
 	else
 		AC_MSG_NOTICE([using 32bit pst3])
 	fi
-        EXTRAS_ROOT="$EXTRAS_ROOT pst3"
+        EXTRAS_ROOT="$EXTRAS_ROOT pst3\$(EXEEXT)"
 
 	if test "$pst3_use_64bit" = 1; then
 		dnl Test if we can actually compile code in 64bit
@@ -997,7 +1006,7 @@ if test -n "$ac_cv_ps_varlist" ; then
 		[Format string for scanning ps output in check_procs])
 	AC_DEFINE_UNQUOTED(PS_COLS,$ac_cv_ps_cols,
 		[Number of columns in ps command])
-	EXTRAS="$EXTRAS check_procs check_nagios"
+	EXTRAS="$EXTRAS check_procs check_nagios\$(EXEEXT)"
 	if echo "$ac_cv_ps_varlist" | grep "procetime" >/dev/null; then
 		AC_DEFINE(PS_USES_PROCETIME,"yes",
 		          [Whether the ps utility uses the "procetime" field])
@@ -1031,6 +1040,13 @@ then
 		ac_cv_ping_packets_first=yes
 	fi
 
+elif [[ "z$ac_cv_uname_o" = "zCygwin" ]]
+then
+	with_ping_command="$PATH_TO_PING -n %d -w %d000 %s"
+	ac_cv_ping_packets_first=yes
+	ac_cv_ping_has_timeout=yes
+	AC_MSG_RESULT([$with_ping_command])
+
 elif [[ "z$ac_cv_uname_s" = "zUnixWare" ]] && \
 	$PATH_TO_PING -n -s 127.0.0.1 56 1 2>/dev/null | \
 	egrep -i "^round-trip|^rtt" >/dev/null
@@ -1044,7 +1060,7 @@ elif $PATH_TO_PING -n -U -w 10 -c 1 127.0.0.1 2>/dev/null | \
 then
 	with_ping_command="$PATH_TO_PING -n -U -w %d -c %d %s"
 	ac_cv_ping_packets_first=yes
-  ac_cv_ping_has_timeout=yes
+	ac_cv_ping_has_timeout=yes
 	AC_MSG_RESULT([$with_ping_command])
 
 elif $PATH_TO_PING -n -U -c 1 127.0.0.1 2>/dev/null | \
@@ -1141,7 +1157,11 @@ then
 	then
 		ac_cv_ping6_packets_first=yes
 	fi
-
+elif [[ "z$ac_cv_uname_o" = "zCygwin" -a "x$PATH_TO_PING" != "x" ]]; then
+	with_ping6_command="$PATH_TO_PING -6 -n %d -w %d000 %s"
+	ac_cv_ping6_packets_first=yes
+	ac_cv_ping_has_timeout=yes
+	AC_MSG_RESULT([$with_ping6_command])
 elif test "x$PATH_TO_PING6" != "x"; then
 	if [[ "z$ac_cv_uname_s" = "zUnixWare" ]] && \
 		$PATH_TO_PING6 -n -s ::1 56 1 2>/dev/null | \
@@ -1319,7 +1339,7 @@ else
 fi
 
 if test -n "$ac_cv_nslookup_command"; then
-	EXTRAS="$EXTRAS check_dns"
+	EXTRAS="$EXTRAS check_dns\$(EXEEXT)"
 	AC_DEFINE_UNQUOTED(NSLOOKUP_COMMAND,"$ac_cv_nslookup_command", [path and args for nslookup])
 fi
 
@@ -1379,7 +1399,7 @@ AC_ARG_WITH(snmpget_command,
 if test -n "$PATH_TO_SNMPGET"
 then
 	AC_DEFINE_UNQUOTED(PATH_TO_SNMPGET,"$PATH_TO_SNMPGET",[path to snmpget binary])
-	EXTRAS="$EXTRAS check_hpjd check_snmp"
+	EXTRAS="$EXTRAS check_hpjd check_snmp\$(EXEEXT)"
 else
 	AC_MSG_WARN([Get snmpget from http://net-snmp.sourceforge.net to make check_hpjd and check_snmp plugins])
 fi
@@ -1411,12 +1431,12 @@ AC_ARG_WITH(qstat_command,
 if test -x "$PATH_TO_QUAKESTAT"
 then
 	ac_cv_path_to_qstat="$PATH_TO_QUAKESTAT"
-	EXTRAS="$EXTRAS check_game"
+	EXTRAS="$EXTRAS check_game\$(EXEEXT)"
 
 elif test -n "$PATH_TO_QSTAT"
 then
 	ac_cv_path_to_qstat="$PATH_TO_QSTAT"
-	EXTRAS="$EXTRAS check_game"
+	EXTRAS="$EXTRAS check_game\$(EXEEXT)"
 else
 	AC_MSG_WARN([Get qstat from http://www.activesw.com/people/steve/qstat.html in order to make check_game plugin])
 fi
@@ -1440,7 +1460,7 @@ AC_ARG_WITH(fping6_command,
 if test -n "$PATH_TO_FPING"
 then
 	AC_DEFINE_UNQUOTED(PATH_TO_FPING,"$PATH_TO_FPING",[path to fping])
-	EXTRAS="$EXTRAS check_fping"
+	EXTRAS="$EXTRAS check_fping\$(EXEEXT)"
 	if test x"$with_ipv6" != xno && test -n "$PATH_TO_FPING6"; then
 		AC_DEFINE_UNQUOTED(PATH_TO_FPING6,"$PATH_TO_FPING6",[path to fping6])
 	fi
@@ -1455,7 +1475,7 @@ AC_ARG_WITH(ssh_command,
 if test -n "$PATH_TO_SSH"
 then
 	AC_DEFINE_UNQUOTED(SSH_COMMAND,"$PATH_TO_SSH",[path to ssh binary])
-	EXTRAS="$EXTRAS check_by_ssh"
+	EXTRAS="$EXTRAS check_by_ssh\$(EXEEXT)"
 else
 	AC_MSG_WARN([Get ssh in order to make check_by_ssh plugin])
 fi
@@ -1594,7 +1614,7 @@ AC_CHECK_MEMBERS([struct swapent.se_nblks],,,[
 
 if test "$ac_cv_have_decl_swapctl" = "yes";
 then
-	EXTRAS="$EXTRAS check_swap"
+	EXTRAS="$EXTRAS check_swap\$(EXEEXT)"
 	AC_MSG_CHECKING([for 2-arg (SVR4) swapctl])
 	if test "$ac_cv_type_swaptbl_t" = "yes" -a \
 	        "$ac_cv_type_swapent_t" = "yes";
@@ -1650,7 +1670,7 @@ dnl
 if test "x$ac_cv_have_swap" != "x"
 then
 	AC_DEFINE(HAVE_SWAP,1,[Define if swap/swapinfo command is found])
-	EXTRAS="$EXTRAS check_swap"
+	EXTRAS="$EXTRAS check_swap\$(EXEEXT)"
 fi
 if test "x$ac_cv_swap_command" != "x"
 then
@@ -1682,7 +1702,7 @@ fi
 if test -n "$ac_cv_proc_meminfo"; then
 	AC_DEFINE(HAVE_PROC_MEMINFO,1,[Define if we have /proc/meminfo])
 	AC_DEFINE_UNQUOTED(PROC_MEMINFO,"$ac_cv_proc_meminfo",[path to /proc/meminfo if name changes])
-	EXTRAS="$EXTRAS check_swap"
+	EXTRAS="$EXTRAS check_swap\$(EXEEXT)"
 fi
 
 AC_PATH_PROG(PATH_TO_DIG,dig)
@@ -1690,7 +1710,7 @@ AC_ARG_WITH(dig_command,
             ACX_HELP_STRING([--with-dig-command=PATH],
                             [Path to dig command]), PATH_TO_DIG=$withval)
 if test -n "$PATH_TO_DIG"; then
-	EXTRAS="$EXTRAS check_dig"
+	EXTRAS="$EXTRAS check_dig\$(EXEEXT)"
 	AC_DEFINE_UNQUOTED(PATH_TO_DIG,"$PATH_TO_DIG",[Path to dig command, if present])
 fi
 
@@ -1702,12 +1722,12 @@ AC_ARG_WITH(apt-get_command,
                             with_apt_get_command=$PATH_TO_APTGET)
 AC_DEFINE_UNQUOTED(PATH_TO_APTGET,"$PATH_TO_APTGET",[Path to apt-get command, if present])
 if test -n "$PATH_TO_APTGET" ; then
-	EXTRAS="$EXTRAS check_apt"
+	EXTRAS="$EXTRAS check_apt\$(EXEEXT)"
 fi
 
 
 if test -f $srcdir/plugins/check_nt.c ; then
-  EXTRAS="$EXTRAS check_nt"
+  EXTRAS="$EXTRAS check_nt\$(EXEEXT)"
 fi
 
 

+ 9 - 1
gl/Makefile.am

@@ -21,7 +21,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext mountlist regex setenv strsep timegm unsetenv vasprintf vsnprintf
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext idpriv-droptemp mountlist regex setenv strsep timegm unsetenv vasprintf vsnprintf
 
 AUTOMAKE_OPTIONS = 1.9.6 gnits subdir-objects
 
@@ -402,6 +402,14 @@ EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath
 
 ## end   gnulib module havelib
 
+## begin gnulib module idpriv-droptemp
+
+libgnu_a_SOURCES += idpriv-droptemp.c
+
+EXTRA_DIST += idpriv.h
+
+## end   gnulib module idpriv-droptemp
+
 ## begin gnulib module inet_ntop
 
 

+ 8 - 0
gl/getopt.c

@@ -588,6 +588,14 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
           d->__nextchar += strlen (d->__nextchar);
           d->optind++;
           d->optopt = 0;
+
+          while (ambig_list != NULL)
+            {
+              struct option_list *pn = ambig_list->next;
+              free (ambig_list);
+              ambig_list = pn;
+            }
+
           return '?';
         }
 

+ 204 - 0
gl/idpriv-droptemp.c

@@ -0,0 +1,204 @@
+/* Dropping uid/gid privileges of the current process temporarily.
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "idpriv.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* The privileged uid and gid that the process had earlier.  */
+#if HAVE_GETUID
+static int saved_uid = -1;
+#endif
+#if HAVE_GETGID
+static int saved_gid = -1;
+#endif
+
+int
+idpriv_temp_drop (void)
+{
+#if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
+  int uid = getuid ();
+  int gid = getgid ();
+
+  /* Find out about the privileged uid and gid at the first call.  */
+  if (saved_uid == -1)
+    saved_uid = geteuid ();
+  if (saved_gid == -1)
+    saved_gid = getegid ();
+
+  /* Drop the gid privilege first, because in some cases the gid privilege
+     cannot be dropped after the uid privilege has been dropped.  */
+
+  /* This is for executables that have the setgid bit set.  */
+# if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  if (setresgid (-1, gid, saved_gid) < 0)
+    return -1;
+# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+  if (setregid (-1, gid) < 0)
+    return -1;
+# endif
+
+  /* This is for executables that have the setuid bit set.  */
+# if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  /* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
+     figure 14.  */
+  if (setresuid (-1, uid, saved_uid) < 0)
+    return -1;
+# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+  if (setreuid (-1, uid) < 0)
+    return -1;
+# endif
+
+  /* Verify that the privileges have really been dropped.
+     This verification is here for security reasons.  Doesn't matter if it
+     takes a couple of system calls.
+     When the verification fails, it indicates that we need to use different
+     API in the code above. Therefore 'abort ()', not 'return -1'.  */
+# if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  {
+    uid_t real;
+    uid_t effective;
+    uid_t saved;
+    if (getresuid (&real, &effective, &saved) < 0
+        || real != uid
+        || effective != uid
+        || saved != saved_uid)
+      abort ();
+  }
+# else
+#  if HAVE_GETEUID
+  if (geteuid () != uid)
+    abort ();
+#  endif
+  if (getuid () != uid)
+    abort ();
+# endif
+# if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  {
+    uid_t real;
+    uid_t effective;
+    uid_t saved;
+    if (getresgid (&real, &effective, &saved) < 0
+        || real != gid
+        || effective != gid
+        || saved != saved_gid)
+      abort ();
+  }
+# else
+#  if HAVE_GETEGID
+  if (getegid () != gid)
+    abort ();
+#  endif
+  if (getgid () != gid)
+    abort ();
+# endif
+
+  return 0;
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}
+
+int
+idpriv_temp_restore (void)
+{
+#if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
+  int uid = getuid ();
+  int gid = getgid ();
+
+  if (saved_uid == -1 || saved_gid == -1)
+    /* Caller error: idpriv_temp_drop was never invoked.  */
+    abort ();
+
+  /* Acquire the gid privilege last, because in some cases the gid privilege
+     cannot be acquired before the uid privilege has been acquired.  */
+
+  /* This is for executables that have the setuid bit set.  */
+# if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  /* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
+     figure 14.  */
+  if (setresuid (-1, saved_uid, -1) < 0)
+    return -1;
+# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+  if (setreuid (-1, saved_uid) < 0)
+    return -1;
+# endif
+
+  /* This is for executables that have the setgid bit set.  */
+# if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  if (setresgid (-1, saved_gid, -1) < 0)
+    return -1;
+# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+  if (setregid (-1, saved_gid) < 0)
+    return -1;
+# endif
+
+  /* Verify that the privileges have really been acquired.
+     This verification is here for security reasons.  Doesn't matter if it
+     takes a couple of system calls.
+     When the verification fails, it indicates that we need to use different
+     API in the code above. Therefore 'abort ()', not 'return -1'.  */
+# if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  {
+    uid_t real;
+    uid_t effective;
+    uid_t saved;
+    if (getresuid (&real, &effective, &saved) < 0
+        || real != uid
+        || effective != saved_uid
+        || saved != saved_uid)
+      abort ();
+  }
+# else
+#  if HAVE_GETEUID
+  if (geteuid () != saved_uid)
+    abort ();
+#  endif
+  if (getuid () != uid)
+    abort ();
+# endif
+# if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  {
+    uid_t real;
+    uid_t effective;
+    uid_t saved;
+    if (getresgid (&real, &effective, &saved) < 0
+        || real != gid
+        || effective != saved_gid
+        || saved != saved_gid)
+      abort ();
+  }
+# else
+#  if HAVE_GETEGID
+  if (getegid () != saved_gid)
+    abort ();
+#  endif
+  if (getgid () != gid)
+    abort ();
+# endif
+
+  return 0;
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}

+ 116 - 0
gl/idpriv.h

@@ -0,0 +1,116 @@
+/* Dropping uid/gid privileges of the current process.
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _IDPRIV_H
+#define _IDPRIV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This module allows programs which are installed with setuid or setgid bit
+   (and which therefore initially run with an effective user id or group id
+   different from the one of the current user) to drop their uid or gid
+   privilege, either permanently or temporarily.
+
+   It is absolutely necessary to minimize the amount of code that is running
+   with escalated privileges (e.g. with effective uid = root). The reason is
+   that any bug or exploit in a part of a program that is running with
+   escalated privileges is a security vulnerability that - upon discovery -
+   puts the users in danger and requires immediate fixing. Then consider that
+   there's a bug every 10 or 20 lines of code on average...
+
+   For programs that temporarily drop privileges but have the ability to
+   restore them later, there are additionally the dangers that
+     - Any bug in the non-privileged part of the program may be used to
+       create invalid data structures that will trigger security
+       vulnerabilities in the privileged part of the program.
+     - Code execution exploits in the non-privileged part of the program may
+       be used to invoke the function that restores high privileges and then
+       execute additional arbitrary code.
+
+   1) The usual, and reasonably safe, way to minimize the amount of code
+      running with privileges is to create a separate executable, with setuid
+      or setgid bit, that contains only code for the tasks that require
+      privileges (and,of course, strict checking of the arguments, so that the
+      program cannot be abused). The main program is installed without setuid
+      or setgid bit.
+
+   2) A less safe way is to do some privileged tasks at the beginning of the
+      program's run, and drop privileges permanently as soon as possible.
+
+      Note: There may still be security issues if the privileged task puts
+      sensitive data into the process memory or opens communication channels
+      to restricted facilities.
+
+   3) The most unsafe way is to drop privileges temporarily for most of the
+      main program but to re-enable them for the duration of privileged tasks.
+
+      As explained above, this approach has uncontrollable dangers for
+      security.
+
+      This approach is normally not usable in multithreaded programs, because
+      you cannot know what kind of system calls the other threads could be
+      doing during the time the privileges are enabled.
+
+   With approach 1, you don't need gnulib modules.
+   With approach 2, you need the gnulib module 'idpriv-drop'.
+   With approach 3, you need the gnulib module 'idpriv-droptemp'. But really,
+   you should better stay away from this approach.
+ */
+
+/* For more in-depth discussion of these topics, see the papers/articles
+   * Hao Chen, David Wagner, Drew Dean: Setuid Demystified
+     <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
+   * Dan Tsafrir, Dilma da Silva, David Wagner: The Murky Issue of Changing
+     Process Identity: Revising "Setuid Demystified"
+     <http://www.eecs.berkeley.edu/~daw/papers/setuid-login08b.pdf>
+     <http://code.google.com/p/change-process-identity/>
+   * Dhruv Mohindra: Observe correct revocation order while relinquishing
+     privileges
+     <https://www.securecoding.cert.org/confluence/display/seccode/POS36-C.+Observe+correct+revocation+order+while+relinquishing+privileges>
+ */
+
+
+/* For approach 2.  */
+
+/* Drop the uid and gid privileges of the current process.
+   Return 0 if successful, or -1 with errno set upon failure. The recommended
+   handling of failure is to terminate the process.  */
+extern int idpriv_drop (void);
+
+
+/* For approach 3.  */
+
+/* Drop the uid and gid privileges of the current process in a way that allows
+   them to be restored later.
+   Return 0 if successful, or -1 with errno set upon failure. The recommended
+   handling of failure is to terminate the process.  */
+extern int idpriv_temp_drop (void);
+
+/* Restore the uid and gid privileges of the current process.
+   Return 0 if successful, or -1 with errno set upon failure. The recommended
+   handling of failure is to not perform the actions that require the escalated
+   privileges.  */
+extern int idpriv_temp_restore (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _IDPRIV_H */

+ 2 - 1
gl/m4/gnulib-cache.m4

@@ -27,7 +27,7 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext mountlist regex setenv strsep timegm unsetenv vasprintf vsnprintf
+#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext idpriv-droptemp mountlist regex setenv strsep timegm unsetenv vasprintf vsnprintf
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
@@ -43,6 +43,7 @@ gl_MODULES([
   getloadavg
   getopt-gnu
   gettext
+  idpriv-droptemp
   mountlist
   regex
   setenv

+ 7 - 2
gl/m4/gnulib-comp.m4

@@ -28,7 +28,7 @@
 # other built files.
 
 
-# This macro should be invoked from ./configure.in, in the section
+# This macro should be invoked from ./configure.ac, in the section
 # "Checks for programs", right after AC_PROG_CC, and certainly before
 # any checks for libraries, header files, types and library functions.
 AC_DEFUN([gl_EARLY],
@@ -70,6 +70,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module gettext-h:
   # Code from module havelib:
   # Code from module hostent:
+  # Code from module idpriv-droptemp:
   # Code from module include_next:
   # Code from module inet_ntop:
   # Code from module intprops:
@@ -151,7 +152,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module xstrndup:
 ])
 
-# This macro should be invoked from ./configure.in, in the section
+# This macro should be invoked from ./configure.ac, in the section
 # "Check for header files, types and library functions".
 AC_DEFUN([gl_INIT],
 [
@@ -256,6 +257,7 @@ AC_DEFUN([gl_INIT],
   AC_SUBST([LIBINTL])
   AC_SUBST([LTLIBINTL])
   gl_HOSTENT
+  gl_IDPRIV
   gl_FUNC_INET_NTOP
   if test $HAVE_INET_NTOP = 0 || test $REPLACE_INET_NTOP = 1; then
     AC_LIBOBJ([inet_ntop])
@@ -646,6 +648,8 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/glthread/lock.c
   lib/glthread/lock.h
   lib/glthread/threadlib.c
+  lib/idpriv-droptemp.c
+  lib/idpriv.h
   lib/inet_ntop.c
   lib/intprops.h
   lib/itold.c
@@ -775,6 +779,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/gnulib-common.m4
   m4/hostent.m4
   m4/iconv.m4
+  m4/idpriv.m4
   m4/include_next.m4
   m4/inet_ntop.m4
   m4/intdiv0.m4

+ 14 - 0
gl/m4/idpriv.m4

@@ -0,0 +1,14 @@
+# idpriv.m4 serial 1
+dnl Copyright (C) 2009-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_IDPRIV],
+[
+  dnl Persuade glibc <unistd.h> to declare {get,set}res{uid,gid}.
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  AC_CHECK_FUNCS_ONCE([getuid geteuid getresuid getgid getegid getresgid])
+  AC_CHECK_FUNCS_ONCE([setresuid setreuid seteuid setresgid setregid setegid])
+])

+ 36 - 14
lib/parse_ini.c

@@ -92,23 +92,45 @@ np_arg_list* np_get_defaults(const char *locator, const char *default_section){
 	FILE *inifile=NULL;
 	np_arg_list *defaults=NULL;
 	np_ini_info i;
+	struct stat fstat;
+	bool is_suid_set = np_suid();
 
-	parse_locator(locator, default_section, &i);
-	/* if a file was specified or if we're using the default file */
-	if(i.file != NULL && strlen(i.file) > 0){
-		if(strcmp(i.file, "-")==0){
-			inifile=stdin;
-		} else {
-			inifile=fopen(i.file, "r");
-		}
-		if(inifile==NULL) die(STATE_UNKNOWN, "%s\n", _("Can't read config file"));
-		if(read_defaults(inifile, i.stanza, &defaults)==FALSE)
-			die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file);
+	if (is_suid_set && idpriv_temp_drop() == -1) 
+		die(STATE_UNKNOWN, "%s %s\n", _("Can't drop user permissions."), strerror(errno));
 
-		free(i.file);
-		if(inifile!=stdin) fclose(inifile);
-	}
+	parse_locator(locator, default_section, &i);
+	/* If a file was specified or if we're using the default file. */
+        if (i.file != NULL && strlen(i.file) > 0) {
+                if (strcmp(i.file, "-") == 0) {
+                        inifile = stdin;
+                } else {
+                        /* We must be able to stat() the thing. */
+                        if (lstat(i.file, &fstat) != 0)
+                                die(STATE_UNKNOWN, "%s %s\n", _("Can't read config file."), strerror(errno));
+                        /* The requested file must be a regular file. */
+                        if (!S_ISREG(fstat.st_mode))
+                                die(STATE_UNKNOWN, "%s\n", _("Can't read config file. Requested path is not a regular file."));
+                        /* We must be able to read the requested file. */
+                        if (access(i.file, R_OK|F_OK) != 0)
+                                die(STATE_UNKNOWN, "%s %s\n", _("Can't read config file."), strerror(errno));
+                        /* We need to successfully open the file for reading... */
+                        if ((inifile=fopen(i.file, "r")) == NULL)
+                                die(STATE_UNKNOWN, "%s %s\n", _("Can't read config file."), strerror(errno));
+                }
+
+                /* inifile points to an open FILE our ruid/rgid can access, parse its contents. */
+                if (read_defaults(inifile, i.stanza, &defaults) == FALSE)
+                        die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file);
+
+                if (inifile != stdin) fclose(inifile);
+        }
+
+	if (i.file != NULL) free(i.file);
 	free(i.stanza);
+
+	if (is_suid_set && idpriv_temp_restore() == -1) 
+		die(STATE_UNKNOWN, "%s %s\n", _("Can't restore user permissions."), strerror(errno));
+
 	return defaults;
 }
 

+ 4 - 1
lib/utils_cmd.c

@@ -387,9 +387,12 @@ cmd_file_read ( char *filename, output *out, int flags)
 	if ((fd = open(filename, O_RDONLY)) == -1) {
 		die( STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno) );
 	}
-	
+
 	if(out)
 		out->lines = _cmd_fetch_output (fd, out, flags);
+	
+	if (close(fd) == -1)
+		die( STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno) );
 
 	return 0;
 }

+ 1 - 1
plugins-root/check_dhcp.c

@@ -837,7 +837,7 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
 		return ERROR;
 
 	/* process all DHCP options present in the packet */
-	for(x=4;x<MAX_DHCP_OPTIONS_LENGTH;){
+	for(x=4;x<MAX_DHCP_OPTIONS_LENGTH-1;){
 
 		if((int)offer_packet->options[x]==-1)
 			break;

+ 19 - 44
plugins-scripts/check_mailq.pl

@@ -199,20 +199,20 @@ if ($mailq eq "sendmail") {
 	## now check the queue length(s)
 
 	if ($msg_q == 0) {
-		$msg = "OK: $mailq mailq is empty";
+		$msg = "OK: mailq is empty";
 		$state = $ERRORS{'OK'};
 	} else {
 		print "msg_q = $msg_q warn=$opt_w crit=$opt_c\n" if $verbose;
 	
 		# overall queue length
 		if ($msg_q < $opt_w) {
-			$msg = "OK: $mailq mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
+			$msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
 			$state = $ERRORS{'OK'};
 		}elsif ($msg_q >= $opt_w  && $msg_q < $opt_c) {
-			$msg = "WARNING: $mailq mailq is $msg_q (threshold w = $opt_w)";
+			$msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)";
 			$state = $ERRORS{'WARNING'};
 		}else {
-			$msg = "CRITICAL: $mailq mailq is $msg_q (threshold c = $opt_c)";
+			$msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)";
 			$state = $ERRORS{'CRITICAL'};
 		}
 
@@ -344,20 +344,20 @@ elsif ( $mailq eq "postfix" ) {
 
         # check queue length(s)
         if ($msg_q == 0){
-                $msg = "OK: $mailq mailq reports queue is empty";
+                $msg = "OK: mailq reports queue is empty";
                 $state = $ERRORS{'OK'};
         } else {
                 print "msg_q = $msg_q warn=$opt_w crit=$opt_c\n" if $verbose;
 
                 # overall queue length
                 if ($msg_q < $opt_w) {
-                        $msg = "OK: $mailq mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
+                        $msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
                         $state = $ERRORS{'OK'};
                 }elsif  ($msg_q >= $opt_w  && $msg_q < $opt_c) {
-                        $msg = "WARNING: $mailq mailq is $msg_q (threshold w = $opt_w)";
+                        $msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)";
                         $state = $ERRORS{'WARNING'};
                 }else {
-                        $msg = "CRITICAL: $mailq mailq is $msg_q (threshold c = $opt_c)";
+                        $msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)";
                         $state = $ERRORS{'CRITICAL'};
                 }
 
@@ -431,13 +431,13 @@ elsif ( $mailq eq "qmail" ) {
 		
 		# overall queue length
 		if ($msg_q < $opt_w) {
-			$msg = "OK: $mailq mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
+			$msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
 			$state = $ERRORS{'OK'};
 		}elsif ($msg_q >= $opt_w  && $msg_q < $opt_c) {
-			$msg = "WARNING: $mailq mailq is $msg_q (threshold w = $opt_w)";
+			$msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)";
 			$state = $ERRORS{'WARNING'};
 		}else {
-			$msg = "CRITICAL: $mailq mailq is $msg_q (threshold c = $opt_c)";
+			$msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)";
 			$state = $ERRORS{'CRITICAL'};
 		}
 
@@ -489,13 +489,13 @@ elsif ( $mailq eq "exim" ) {
 		exit $ERRORS{CRITICAL};
 	}
 	if ($msg_q < $opt_w) {
-		$msg = "OK: $mailq mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
+		$msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
 		$state = $ERRORS{'OK'};
 	}elsif ($msg_q >= $opt_w  && $msg_q < $opt_c) {
-		$msg = "WARNING: $mailq mailq is $msg_q (threshold w = $opt_w)";
+		$msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)";
 		$state = $ERRORS{'WARNING'};
 	}else {
-		$msg = "CRITICAL: $mailq mailq is $msg_q (threshold c = $opt_c)";
+		$msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)";
 		$state = $ERRORS{'CRITICAL'};
 	}
 } # end of ($mailq eq "exim")
@@ -526,13 +526,13 @@ elsif ( $mailq eq "nullmailer" ) {
 	}
 	close(MAILQ) ;
 	if ($msg_q < $opt_w) {
-		$msg = "OK: $mailq mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
+		$msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
 		$state = $ERRORS{'OK'};
 	}elsif ($msg_q >= $opt_w  && $msg_q < $opt_c) {
-		$msg = "WARNING: $mailq mailq is $msg_q (threshold w = $opt_w)";
+		$msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)";
 		$state = $ERRORS{'WARNING'};
 	}else {
-		$msg = "CRITICAL: $mailq mailq is $msg_q (threshold c = $opt_c)";
+		$msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)";
 		$state = $ERRORS{'CRITICAL'};
 	}
 } # end of ($mailq eq "nullmailer")
@@ -605,30 +605,7 @@ sub process_arguments(){
 			exit $ERRORS{'UNKNOWN'};
 		}
 	}else{
-		if (defined $utils::PATH_TO_QMAIL_QSTAT
-		    && -x $utils::PATH_TO_QMAIL_QSTAT)
-		{
-			$mailq = 'qmail';
-		}
-		elsif (-d '/var/lib/postfix' || -d '/var/local/lib/postfix'
-		       || -e '/usr/sbin/postfix' || -e '/usr/local/sbin/postfix')
-		{
-			$mailq = 'postfix';
-		}
-		elsif (-d '/usr/lib/exim4' || -d '/usr/local/lib/exim4'
-		       || -e '/usr/sbin/exim' || -e '/usr/local/sbin/exim')
-		{
-			$mailq = 'exim';
-		}
-		elsif (-d '/usr/lib/nullmailer' || -d '/usr/local/lib/nullmailer'
-		       || -e '/usr/sbin/nullmailer-send'
-		       || -e '/usr/local/sbin/nullmailer-send')
-		{
-			$mailq = 'nullmailer';
-		}
-		else {
-			$mailq = 'sendmail';
-		}
+		$mailq = 'sendmail' ;
 	}
 		
 	return $ERRORS{'OK'};
@@ -651,7 +628,7 @@ sub print_help () {
 	print "-W (--Warning)   = Min. number of messages for same domain in queue to generate warning\n";
 	print "-C (--Critical)  = Min. number of messages for same domain in queue to generate critical alert ( W < C )\n";
 	print "-t (--timeout)   = Plugin timeout in seconds (default = $utils::TIMEOUT)\n";
-	print "-M (--mailserver) = [ sendmail | qmail | postfix | exim | nullmailer ] (default = autodetect)\n";
+	print "-M (--mailserver) = [ sendmail | qmail | postfix | exim | nullmailer ] (default = sendmail)\n";
 	print "-h (--help)\n";
 	print "-V (--version)\n";
 	print "-v (--verbose)   = debugging output\n";
@@ -659,8 +636,6 @@ sub print_help () {
 	print "Note: -w and -c are required arguments.  -W and -C are optional.\n";
 	print " -W and -C are applied to domains listed on the queues - both FROM and TO. (sendmail)\n";
 	print " -W and -C are applied message not yet preproccessed. (qmail)\n";
-	print " This plugin tries to autodetect which mailserver you are running,\n";
-	print " you can override the autodetection with -M.\n";
 	print " This plugin uses the system mailq command (sendmail) or qmail-stat (qmail)\n";
 	print " to look at the queues. Mailq can usually only be accessed by root or \n";
 	print " a TrustedUser. You will have to set appropriate permissions for the plugin to work.\n";

+ 1 - 1
plugins/Makefile.am

@@ -107,7 +107,7 @@ check_tcp_LDADD = $(SSLOBJS)
 check_time_LDADD = $(NETLIBS)
 check_ntp_time_LDADD = $(NETLIBS) $(MATHLIBS)
 check_ups_LDADD = $(NETLIBS)
-check_users_LDADD = $(BASEOBJS)
+check_users_LDADD = $(BASEOBJS) $(WTSAPI32LIBS)
 check_uptime_LDADD = $(BASEOBJS) -lrt
 check_by_ssh_LDADD = $(NETLIBS)
 check_ide_smart_LDADD = $(BASEOBJS)

+ 3 - 0
plugins/check_apt.c

@@ -223,6 +223,9 @@ int run_upgrade(int *pkgcount, int *secpkgcount){
 	regex_t ireg, ereg, sreg;
 	char *cmdline=NULL, rerrbuf[64];
 
+	/* initialize ereg as it is possible it is printed while uninitialized */
+	memset(&ereg, "\0", sizeof(ereg.buffer));
+
 	if(upgrade==NO_UPGRADE) return STATE_OK;
 
 	/* compile the regexps */

+ 20 - 1
plugins/check_disk.c

@@ -52,6 +52,11 @@ const char *email = "devel@nagios-plugins.org";
 #endif
 #include "regex.h"
 
+#ifdef __CYGWIN__
+# include <windows.h>
+# undef ERROR
+# define ERROR -1
+#endif
 
 /* If nonzero, show inode information. */
 static int inode_format = 1;
@@ -176,6 +181,10 @@ main (int argc, char **argv)
   struct fs_usage fsp, tmpfsp;
   struct parameter_list *temp_list, *path;
 
+#ifdef __CYGWIN__
+  char mountdir[32];
+#endif
+
   preamble = strdup (" - free space:");
   output = strdup ("");
   details = strdup ("");
@@ -222,7 +231,6 @@ main (int argc, char **argv)
 
   /* Process for every path in list */
   for (path = path_select_list; path; path=path->name_next) {
-
     if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
       printf("Thresholds(pct) for %s warn: %f crit %f\n",path->name, path->freespace_percent->warning->end,
                                                          path->freespace_percent->critical->end);
@@ -235,6 +243,13 @@ main (int argc, char **argv)
 
     me = path->best_match;
 
+#ifdef __CYGWIN__
+    if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
+	    continue;
+    snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
+    if (GetDriveType(mountdir) != DRIVE_FIXED)
+	    me->me_remote = 1;
+#endif
     /* Filters */
 
     /* Remove filesystems already seen */
@@ -983,6 +998,10 @@ get_stats (struct parameter_list *p, struct fs_usage *fsp) {
   } else {
     /* find all group members */
     for (p_list = path_select_list; p_list; p_list=p_list->name_next) {
+#ifdef __CYGWIN__
+      if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
+        continue;
+#endif
       if (p_list->group && ! (strcmp(p_list->group, p->group))) {
         stat_path(p_list);
         get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);

+ 21 - 10
plugins/check_dns.c

@@ -50,6 +50,7 @@ char query_address[ADDRESS_LENGTH] = "";
 char dns_server[ADDRESS_LENGTH] = "";
 char ptr_server[ADDRESS_LENGTH] = "";
 char query_type[16] = "";
+int query_set = FALSE;
 int verbose = FALSE;
 char **expected_address = NULL;
 int expected_address_cnt = 0;
@@ -155,25 +156,25 @@ main (int argc, char **argv)
     if (strstr (chld_out.line[i], "Name:"))
       parse_address = TRUE;
     /* begin handling types of records */
-    if (strstr (chld_out.line[i], "AAAA address") && (strncmp(query_type, "-querytype=AAAA", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    if (strstr (chld_out.line[i], "AAAA address") && (strncmp(query_type, "-querytype=AAAA", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found AAAA record\n");
       temp_buffer = rindex (chld_out.line[i], ' ');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=AAAA", sizeof(query_found));
     }
-    else if (strstr (chld_out.line[i], "exchanger =") && (strncmp(query_type, "-querytype=MX", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "exchanger =") && (strncmp(query_type, "-querytype=MX", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found MX record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=MX", sizeof(query_found));
     }
-    else if (strstr (chld_out.line[i], "service =") && (strncmp(query_type, "-querytype=SRV", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "service =") && (strncmp(query_type, "-querytype=SRV", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found SRV record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=SRV", sizeof(query_found));
     }
-    else if (accept_cname && strstr (chld_out.line[i], "canonical name =") && (strncmp(query_type, "-querytype=CNAME", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (accept_cname && strstr (chld_out.line[i], "canonical name =") && (strncmp(query_type, "-querytype=CNAME", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found CNAME record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
@@ -186,45 +187,54 @@ main (int argc, char **argv)
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=A", sizeof(query_found));
     }
-    else if (strstr (chld_out.line[i], "nameserver =") && (strncmp(query_type, "-querytype=NS", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "nameserver =") && (strncmp(query_type, "-querytype=NS", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found NS record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=NS", sizeof(query_found));
     }
-    else if (strstr (chld_out.line[i], "dname =") && (strncmp(query_type, "-querytype=DNAME", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "dname =") && (strncmp(query_type, "-querytype=DNAME", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found DNAME record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=DNAME", sizeof(query_found));
     }
     /* must be after other records with "name" as an identifier, as ptr does not spefify */
-    else if (strstr (chld_out.line[i], "name =") && (strncmp(query_type, "-querytype=PTR", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "name =") && (strncmp(query_type, "-querytype=PTR", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found PTR record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=PTR", sizeof(query_found));
     }
-    else if (strstr (chld_out.line[i], "protocol =") && (strncmp(query_type, "-querytype=WKS", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "protocol =") && (strncmp(query_type, "-querytype=WKS", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found WKS record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=WKS", sizeof(query_found));
     }
     /* TODO: needs to be changed to handle txt output and max size of txt recrods */
-    else if (strstr (chld_out.line[i], "text =") && (strncmp(query_type, "-querytype=TXT", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "text =") && (strncmp(query_type, "-querytype=TXT", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found TXT record\n");
       temp_buffer = index (chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=TXT", sizeof(query_found));
     }
     /* only matching for origin records, if requested other fields could be included at a later date */
-    else if (strstr (chld_out.line[i], "origin =") && (strncmp(query_type, "-querytype=SOA", query_size) == 0 || strncmp(query_type, "-querytype=ALL", query_size) == 0)) {
+    else if (strstr (chld_out.line[i], "origin =") && (strncmp(query_type, "-querytype=SOA", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found SOA record\n");
       temp_buffer = index(chld_out.line[i], '=');
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=SOA", sizeof(query_found));
     }
+    /* needed for non-query ptr\reverse lookup checks */
+    else if (strstr(chld_out.line[i], ".in-addr.arpa") && !query_set) {
+      if ((temp_buffer = strstr(chld_out.line[i], "name = ")))
+        addresses[n_addresses++] = strdup(temp_buffer + 7);
+      else {
+        msg = (char *)_("Warning plugin error");
+        result = STATE_WARNING;
+      }
+    }
 
     if (strstr (chld_out.line[i], _("Non-authoritative answer:"))) {
       non_authoritative = TRUE;
@@ -499,6 +509,7 @@ process_arguments (int argc, char **argv)
       strntoupper(optarg, sizeof(optarg));
       strcpy(query_type, "-querytype=");
       strcat(query_type, optarg);
+      query_set = TRUE;
       break;
     case 'A': /* expect authority */
       expect_authority = TRUE;

+ 6 - 4
plugins/check_http.c

@@ -1246,6 +1246,7 @@ redir (char *pos, char *status_line)
   if (addr == NULL)
     die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n"));
 
+  memset(addr, 0, MAX_IPV4_HOSTLENGTH);
   url = malloc (strcspn (pos, "\r\n"));
   if (url == NULL)
     die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
@@ -1336,8 +1337,8 @@ redir (char *pos, char *status_line)
          max_depth, type, addr, i, url, (display_html ? "</A>" : ""));
 
   if (server_port==i &&
-      !strcmp(server_address, addr) &&
-      (host_name && !strcmp(host_name, addr)) &&
+      !strncmp(server_address, addr, MAX_IPV4_HOSTLENGTH) &&
+      (host_name && !strncmp(host_name, addr, MAX_IPV4_HOSTLENGTH)) &&
       !strcmp(server_url, url))
     die (STATE_WARNING,
          _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
@@ -1346,11 +1347,11 @@ redir (char *pos, char *status_line)
   strcpy (server_type, type);
 
   free (host_name);
-  host_name = strdup (addr);
+  host_name = strndup (addr, MAX_IPV4_HOSTLENGTH);
 
   if (!(followsticky & STICKY_HOST)) {
     free (server_address);
-    server_address = strdup (addr);
+    server_address = strndup (addr, MAX_IPV4_HOSTLENGTH);
   }
   if (!(followsticky & STICKY_PORT)) {
     server_port = i;
@@ -1369,6 +1370,7 @@ redir (char *pos, char *status_line)
     printf (_("Redirection to %s://%s:%d%s\n"), server_type,
             host_name ? host_name : server_address, server_port, server_url);
 
+  free(addr);
   check_http ();
 }
 

+ 2 - 2
plugins/check_nt.c

@@ -314,10 +314,10 @@ int main(int argc, char **argv){
 
 		/* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here,
 		which equals RAM + Pagefiles. */
-		xasprintf(&output_message,_("Memory usage: total:%.2f Mb - used: %.2f Mb (%.0f%%) - free: %.2f Mb (%.0f%%)"),
+		xasprintf(&output_message,_("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"),
 		  mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space,
 		  (mem_commitLimit - mem_commitByte) / 1048567, (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
-		xasprintf(&perfdata,_("'Memory usage'=%.2fMb;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567,
+		xasprintf(&perfdata,_("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567,
 		  warning_used_space / 1048567, critical_used_space / 1048567, mem_commitLimit / 1048567);
 
 		return_code=STATE_OK;

+ 11 - 2
plugins/check_ntp.c

@@ -517,13 +517,14 @@ setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){
 double jitter_request(const char *host, int *status){
 	int conn=-1, i, npeers=0, num_candidates=0, syncsource_found=0;
 	int run=0, min_peer_sel=PEER_INCLUDED, num_selected=0, num_valid=0;
-	int peers_size=0, peer_offset=0;
+	int peers_size=0, peer_offset=0, bytes_read=0;
 	ntp_assoc_status_pair *peers=NULL;
 	ntp_control_message req;
 	const char *getvar = "jitter";
 	double rval = 0.0, jitter = -1.0;
 	char *startofvalue=NULL, *nptr=NULL;
 	void *tmp;
+	int ntp_cm_ints = sizeof(uint16_t) * 5 + sizeof(uint8_t) * 2;
 
 	/* Long-winded explanation:
 	 * Getting the jitter requires a number of steps:
@@ -608,7 +609,15 @@ double jitter_request(const char *host, int *status){
 
 				req.count = htons(MAX_CM_SIZE);
 				DBG(printf("recieving READVAR response...\n"));
-				read(conn, &req, SIZEOF_NTPCM(req));
+
+				/* cov-66524 - req.data not null terminated before usage. Also covers verifying struct was returned correctly*/
+				if ((bytes_read = read(conn, &req, SIZEOF_NTPCM(req))) == -1)
+					die(STATE_UNKNOWN, _("Cannot read from socket: %s"), strerror(errno));
+				if (bytes_read != ntp_cm_ints + req.count)
+					die(STATE_UNKNOWN, _("Invalid NTP response: %d bytes read does not equal %d plus %d data segment"), bytes_read, ntp_cm_ints, req.count); 
+				/* else null terminate */
+				strncpy(req.data[req.count], "\0", 1);
+
 				DBG(print_ntp_control_message(&req));
 
 				if(req.op&REM_ERROR && strstr(getvar, "jitter")) {

+ 5 - 2
plugins/check_ping.c

@@ -458,7 +458,8 @@ run_ping (const char *cmd, const char *addr)
 			 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time%n",&pl,&match) && match) ||
 			 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time%n",&pl,&match) && match) ||
 			 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) ||
-			 (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match)
+			 (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) ||
+			 (sscanf(buf,"%*[^(](%d%% %*[^)])%n",&pl,&match) && match)
 			 )
 			continue;
 
@@ -471,7 +472,9 @@ run_ping (const char *cmd, const char *addr)
 				 (sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
 				 (sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) ||
 				 (sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
-				 (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match))
+				 (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match) ||
+				 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &rta, &match) && match)
+				 )
 			continue;
 	}
 

+ 1 - 0
plugins/check_real.c

@@ -178,6 +178,7 @@ main (int argc, char **argv)
 
 		/* watch for the REAL connection string */
 		result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
+		buffer[result] = "\0"; /* null terminate recieved buffer */
 
 		/* return a CRITICAL status if we couldn't read any data */
 		if (result == -1) {

+ 1 - 2
plugins/check_tcp.c

@@ -32,13 +32,12 @@ char *progname;
 const char *copyright = "1999-2014";
 const char *email = "devel@nagios-plugins.org";
 
-#include <ctype.h>
-
 #include "common.h"
 #include "netutils.h"
 #include "utils.h"
 #include "utils_tcp.h"
 
+#include <ctype.h>
 #include <sys/select.h>
 
 #ifdef HAVE_SSL

+ 41 - 3
plugins/check_users.c

@@ -37,7 +37,12 @@ const char *email = "devel@nagios-plugins.org";
 #include "common.h"
 #include "utils.h"
 
-#if HAVE_UTMPX_H
+#if HAVE_WTSAPI32_H
+# include <windows.h>
+# include <wtsapi32.h>
+# undef ERROR
+# define ERROR -1
+#elif HAVE_UTMPX_H
 # include <utmpx.h>
 #else
 # include "popen.h"
@@ -58,7 +63,11 @@ main (int argc, char **argv)
 	int users = -1;
 	int result = STATE_UNKNOWN;
 	char *perf;
-#if HAVE_UTMPX_H
+#if HAVE_WTSAPI32_H
+	WTS_SESSION_INFO *wtsinfo;
+	DWORD wtscount;
+	DWORD index;
+#elif HAVE_UTMPX_H
 	struct utmpx *putmpx;
 #else
 	char input_buffer[MAX_INPUT_BUFFER];
@@ -78,7 +87,36 @@ main (int argc, char **argv)
 
 	users = 0;
 
-#if HAVE_UTMPX_H
+#if HAVE_WTSAPI32_H
+	if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE,
+	  0, 1, &wtsinfo, &wtscount)) {
+		printf(_("Could not enumerate RD sessions: %d\n"), GetLastError());
+		return STATE_UNKNOWN;
+	}
+
+	for (index = 0; index < wtscount; index++) {
+		LPTSTR username;
+		DWORD size;
+		int len;
+
+		if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
+		  wtsinfo[index].SessionId, WTSUserName, &username, &size))
+			continue;
+
+		len = lstrlen(username);
+
+		WTSFreeMemory(username);
+
+		if (len == 0)
+			continue;
+
+		if (wtsinfo[index].State == WTSActive ||
+		  wtsinfo[index].State == WTSDisconnected)
+			users++;
+	}
+
+	WTSFreeMemory(wtsinfo);
+#elif HAVE_UTMPX_H
 	/* get currently logged users from utmpx */
 	setutxent ();
 

+ 5 - 6
plugins/negate.c

@@ -35,16 +35,16 @@ const char *email = "devel@nagios-plugins.org";
 
 #define DEFAULT_TIMEOUT 11
 
-#include <ctype.h>
-
 #include "common.h"
 #include "utils.h"
 #include "utils_cmd.h"
 
+#include <ctype.h>
+
 /* char *command_line; */
 
 static const char **process_arguments (int, char **);
-int validate_arguments (char **);
+void validate_arguments (char **);
 void print_help (void);
 void print_usage (void);
 int subst_text = FALSE;
@@ -98,8 +98,7 @@ main (int argc, char **argv)
 		die (max_state_alt (result, STATE_UNKNOWN), _("No data returned from command\n"));
 
 	for (i = 0; i < chld_out.lines; i++) {
-		if (subst_text && result != state[result] &&
-		    result >= 0 && result <= 4) {
+		if (subst_text && result >= 0 && result <= 4 && result != state[result])  {
 			/* Loop over each match found */
 			while ((sub = strstr (chld_out.line[i], state_text (result)))) {
 				/* Terminate the first part and skip over the string we'll substitute */
@@ -203,7 +202,7 @@ process_arguments (int argc, char **argv)
 }
 
 
-int
+void
 validate_arguments (char **command_line)
 {
 	if (command_line[0] == NULL)

+ 12 - 3
plugins/netutils.c

@@ -163,11 +163,12 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
 	char port_str[6], host[MAX_HOST_ADDRESS_LENGTH];
 	size_t len;
 	int socktype, result;
+	short is_socket = (host_name[0] == '/');
 
 	socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
 
 	/* as long as it doesn't start with a '/', it's assumed a host or ip */
-	if(host_name[0] != '/'){
+	if (!is_socket){
 		memset (&hints, 0, sizeof (hints));
 		hints.ai_family = address_family;
 		hints.ai_protocol = proto;
@@ -249,7 +250,11 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
 			return econn_refuse_state;
 			break;
 		case STATE_CRITICAL: /* user did not set econn_refuse_state */
-			printf ("%s\n", strerror(errno));
+			if (is_socket)
+				printf("connect to file socket %s: %s\n", host_name, strerror(errno));
+			else
+				printf("connect to address %s and port %d: %s\n",
+				       host_name, port, strerror(errno));
 			return econn_refuse_state;
 			break;
 		default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */
@@ -258,7 +263,11 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
 		}
 	}
 	else {
-		printf ("%s\n", strerror(errno));
+		if (is_socket)
+			printf("connect to file socket %s: %s\n", host_name, strerror(errno));
+		else
+			printf("connect to address %s and port %d: %s\n",
+			       host_name, port, strerror(errno));
 		return STATE_CRITICAL;
 	}
 }