[pkg-nagios-changes] [Git][nagios-team/pkg-nsca][master] 5 commits: New upstream version 2.10.1

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Sun Oct 31 12:24:02 GMT 2021



Bas Couwenberg pushed to branch master at Debian Nagios Maintainer Group / pkg-nsca


Commits:
b30e8d91 by Bas Couwenberg at 2021-10-31T13:11:18+01:00
New upstream version 2.10.1
- - - - -
919aeab6 by Bas Couwenberg at 2021-10-31T13:11:20+01:00
Update upstream source from tag 'upstream/2.10.1'

Update to upstream version '2.10.1'
with Debian dir 1b1c0c035109f980bc4474b6e9b6ee84c9132a6d
- - - - -
6abbff8f by Bas Couwenberg at 2021-10-31T13:11:43+01:00
New upstream release.

- - - - -
3df493dd by Bas Couwenberg at 2021-10-31T13:14:17+01:00
Close bug in changelog.

- - - - -
7e62cfcc by Bas Couwenberg at 2021-10-31T13:19:07+01:00
Set distribution to unstable.

- - - - -


10 changed files:

- CHANGELOG.md
- SECURITY.md
- configure
- configure.ac
- debian/changelog
- include/common.h
- nsca.spec
- src/nsca.c
- src/send_nsca.c
- update-version


Changes:

=====================================
CHANGELOG.md
=====================================
@@ -1,9 +1,16 @@
 NSCA Changelog
 ==============
 
+2.10.1 - 2021-10-27
+------------------
+ * Fixed backward compatibility issue with -d in send_nsca (#44)
+ * Restored and fixed newline escaping, which was removed in 2.10
+ * Added the strict_mode_spoofing directive. See SECURITY for details. 
+
 2.10 - 2020-04-02
 ------------------
  * Changed release date to ISO format (yyyy-mm-dd) (John Frickson)
+ * Add IPv6 support (Stuart D. Gathman, Miquel van Smoorenburg) 
  * Add --quiet mode to send_nsca (Timo Juhani Lindfors)
  * Add --ds to specify block delimiters (for sending multiple checks at once) in send_nsca (Nate Rini)
  * Add legacy_2_7_mode (for sending to nsca 2.7.x) to send_nsca (Adrian Freihofer, Xavier Bachelot)


=====================================
SECURITY.md
=====================================
@@ -150,7 +150,17 @@ sent to the client, it can verify that the data the client
 sends to it has been properly encrypted.  This provides
 a reasonable mechanism of preventing replay attacks.
 
-
+Strict Mode
+-----------
+
+As of NSCA 2.10.1, you can now specify the `strict_mode_spoofing`
+directive in nsca.cfg. This will cause the daemon to run DNS queries
+for the connecting send_nsca client and for the host_name that it submits. 
+If they do not have any IP addresses in common, the check result will
+be discarded. Note that this will have performance implications, as
+NSCA does not maintain its own DNS cache. However, if your host names
+in Nagios Core match their FQDNs or IP Addresses, this can help to
+prevent check spoofing.
 
 Caveats
 -------


=====================================
configure
=====================================
@@ -2367,9 +2367,9 @@ ac_config_files="$ac_config_files Makefile subst src/Makefile package/solaris/Ma
 
 
 PKG_NAME=nsca
-PKG_VERSION="2.10.0"
+PKG_VERSION="2.10.1"
 PKG_HOME_URL="http://www.nagios.org/"
-PKG_REL_DATE="2020-04-15"
+PKG_REL_DATE="2021-10-27"
 
 
 


=====================================
configure.ac
=====================================
@@ -4,7 +4,7 @@ dnl Disable caching
 define([AC_CACHE_LOAD],)
 define([AC_CACHE_SAVE],)
 
-AC_INIT([nsca],[2.10.0],[nagios-users at lists.sourceforge.net],[nsca],[http://www.nagios.org])
+AC_INIT([nsca],[2.10.1],[nagios-users at lists.sourceforge.net],[nsca],[http://www.nagios.org])
 AC_CONFIG_SRCDIR([src/nsca.c])
 AC_CONFIG_HEADER(include/config.h)
 AC_CONFIG_FILES([Makefile
@@ -18,9 +18,9 @@ AC_CONFIG_FILES([Makefile
 AC_PREFIX_DEFAULT(/usr/local/nagios)
 
 PKG_NAME=nsca
-PKG_VERSION="2.10.0"
+PKG_VERSION="2.10.1"
 PKG_HOME_URL="http://www.nagios.org/"
-PKG_REL_DATE="2020-04-15"
+PKG_REL_DATE="2021-10-27"
 AC_SUBST(PKG_NAME)
 AC_SUBST(PKG_VERSION)
 AC_SUBST(PKG_HOME_URL)


=====================================
debian/changelog
=====================================
@@ -1,7 +1,10 @@
-nsca (2.10.0-2) UNRELEASED; urgency=medium
+nsca (2.10.1-1) unstable; urgency=medium
 
-  [ Bas Couwenberg ]
   * Team upload.
+
+  [ Bas Couwenberg ]
+  * New upstream release.
+    (closes: #994435)
   * Bump watch file version to 4.
   * Bump Standards-Version to 4.6.0, no changes.
   * Update watch file for GitHub URL changes.
@@ -14,7 +17,7 @@ nsca (2.10.0-2) UNRELEASED; urgency=medium
     + nsca-client: Drop versioned constraint on nsca in Replaces.
     + nsca-client: Drop versioned constraint on nsca in Breaks.
 
- -- Bas Couwenberg <sebastic at debian.org>  Fri, 06 Nov 2020 20:07:28 +0100
+ -- Bas Couwenberg <sebastic at debian.org>  Sun, 31 Oct 2021 13:15:16 +0100
 
 nsca (2.10.0-1) unstable; urgency=medium
 


=====================================
include/common.h
=====================================
@@ -2,7 +2,7 @@
  *
  * COMMON.H - NSCA Common Include File
  * Copyright (c) 1999-2003 Ethan Galstad (nagios at nagios.org)
- * Last Modified: 2020-04-15
+ * Last Modified: 2021-10-27
  *
  * License:
  *
@@ -24,8 +24,8 @@
 #include "config.h"
 
 
-#define PROGRAM_VERSION "2.10.0"
-#define MODIFICATION_DATE "2020-04-15"
+#define PROGRAM_VERSION "2.10.1"
+#define MODIFICATION_DATE "2021-10-27"
 
 
 #define OK		0


=====================================
nsca.spec
=====================================
@@ -1,5 +1,5 @@
 %define name nsca
-%define version 2.10.0
+%define version 2.10.1
 %define release 1
 %define nsusr nagios
 %define nsgrp nagios


=====================================
src/nsca.c
=====================================
@@ -5,7 +5,7 @@
  * Copyright (c) 2000-2009 Ethan Galstad (egalstad at nagios.org)
  * License: GPL v2
  *
- * Last Modified: 2020-04-15
+ * Last Modified: 2021-10-27
  *
  * Command line: NSCA -c <config_file> [mode]
  *
@@ -37,6 +37,7 @@ static char password[MAX_INPUT_BUFFER]="";
 static enum { OPTIONS_ERROR, SINGLE_PROCESS_DAEMON, MULTI_PROCESS_DAEMON, INETD } mode=SINGLE_PROCESS_DAEMON;
 static int foreground=FALSE;
 static int debug=FALSE;
+static int strict_mode_spoofing=FALSE;
 static int aggregate_writes=FALSE;
 static int decryption_method=ENCRYPT_XOR;
 static int append_to_file=FALSE;
@@ -477,6 +478,14 @@ static int read_config_file(char *filename){
                         else
                                 debug=FALSE;
                         }
+        else if (strstr(input_buffer, "strict_mode_spoofing")) {
+                        if (atoi(varvalue) > 0) {
+                            strict_mode_spoofing = TRUE;
+                        }
+                        else {
+                            strict_mode_spoofing = FALSE;
+                        }
+        }
 		else if(strstr(input_buffer,"aggregate_writes")){
                         if(atoi(varvalue)>0)
                                 aggregate_writes=TRUE;
@@ -926,35 +935,38 @@ static void wait_for_connections(void) {
 
 
 
-static void accept_connection(int sock, void *unused){
-        int new_sd;
-        pid_t pid;
-        struct sockaddr_storage addr;
-        socklen_t addrlen;
-        char hostbuf[64], portbuf[16];
-        char *h;
-        int rc;
+static void accept_connection(int sock, void *unused) {
+    int new_sd;
+    pid_t pid;
+    struct sockaddr_storage addr;
+    socklen_t addrlen;
+    char hostbuf[64], portbuf[16];
+    char *h;
+    int rc;
 #ifdef HAVE_LIBWRAP
 	struct request_info req;
 #endif
 
 	/* DO NOT REMOVE! 01/29/2007 single process daemon will fail if this is removed */
-        if(mode==SINGLE_PROCESS_DAEMON)
-                register_read_handler(sock,accept_connection,NULL);
+    if(mode==SINGLE_PROCESS_DAEMON) {
+        register_read_handler(sock,accept_connection,NULL);
+    }
 
-        /* wait for a connection request */
-        while(1){
+    /* wait for a connection request */
+    while(1) {
 
-		/* we got a live one... */
-                if((new_sd=accept(sock,0,0))>=0)
-                        break;
+	/* we got a live one... */
+        if((new_sd=accept(sock,0,0))>=0) {
+            break;
+        }
 
-		/* handle the error */
-		else{
+	/* handle the error */
+	    else {
 
 			/* bail out if necessary */
-			if(sigrestart==TRUE || sigshutdown==TRUE)
+			if(sigrestart==TRUE || sigshutdown==TRUE) {
 				return;
+            }
 
 			/* try and handle temporary errors */
 			if(errno==EWOULDBLOCK || errno==EINTR || errno==ECHILD || errno==ECONNABORTED){
@@ -962,24 +974,26 @@ static void accept_connection(int sock, void *unused){
 					sleep(1);
 				else
 					return;
-				}
-			else
+		    }
+			else {
 				break;
-			}
-                }
+            }
+		}
+    }
 
-        /* hey, there was an error... */
-        if(new_sd<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));
+            /* log error to syslog facility */
+            syslog(LOG_ERR,"Network server accept failure (%d: %s)",errno,strerror(errno));
 
-                /* close socket prior to exiting */
-                close(sock);
-		if(mode==MULTI_PROCESS_DAEMON)
+            /* close socket prior to exiting */
+            close(sock);
+		if(mode==MULTI_PROCESS_DAEMON) {
 			do_exit(STATE_CRITICAL);
+        }
 		return;
-                }
+    }
 
 #ifdef HAVE_LIBWRAP
 
@@ -992,60 +1006,63 @@ static void accept_connection(int sock, void *unused){
 		syslog(LOG_ERR, "refused connect from %s", eval_client(&req));
 		close(new_sd);
 		return;
-		}
+	}
 #endif
 
 
-        /* fork() if we have to... */
-        if(mode==MULTI_PROCESS_DAEMON){
+    /* fork() if we have to... */
+    if(mode==MULTI_PROCESS_DAEMON){
 
-                pid=fork();
-                if(pid){
-                        /* parent doesn't need the new connection */
-                        close(new_sd);
-                        return;
-                        }
-		else{
-                        /* child does not need to listen for connections */
-                        close(sock);
-                        }
-                }
+        pid=fork();
+        if(pid) {
+            /* parent doesn't need the new connection */
+            close(new_sd);
+            return;
+        }
+        else{
+            /* child does not need to listen for connections */
+            close(sock);
+        }
+    }
 
-        /* find out who just connected... */
-        addrlen=sizeof(addr);
-        rc=getpeername(new_sd,(struct sockaddr *)&addr,&addrlen);
+    /* 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));
+    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);
-		if(mode==MULTI_PROCESS_DAEMON)
+        /* close socket prior to exiting */
+        close(new_sd);
+		if(mode==MULTI_PROCESS_DAEMON) {
 			do_exit(STATE_CRITICAL);
+        }
 		return;
-                }
-
-        /* log info to syslog facility */
-        if(debug==TRUE) {
-                getnameinfo((struct sockaddr *)&addr, addrlen,
-                        hostbuf, sizeof(hostbuf),
-                        portbuf, sizeof(portbuf),
-                        NI_NUMERICHOST|NI_NUMERICSERV);
-		h = strncmp(hostbuf, "::ffff:", 7) == 0 ? hostbuf + 7 : hostbuf;
-                syslog(LOG_DEBUG,"Connection from %s port %s",h,portbuf);
-                }
+    }
+
+    /* log info to syslog facility */
+    if(debug==TRUE) {
+        getnameinfo((struct sockaddr *)&addr, addrlen,
+                    hostbuf, sizeof(hostbuf),
+                    portbuf, sizeof(portbuf),
+                    NI_NUMERICHOST|NI_NUMERICSERV);
+	    h = strncmp(hostbuf, "::ffff:", 7) == 0 ? hostbuf + 7 : hostbuf;
+        syslog(LOG_DEBUG,"Connection from %s port %s",h,portbuf);
+    }
 
 	/* handle the connection */
-	if(mode==SINGLE_PROCESS_DAEMON)
+	if(mode==SINGLE_PROCESS_DAEMON) {
 		/* mark the connection as ready to be handled */
 		register_write_handler(new_sd, handle_connection, NULL);
-	else
+    }
+	else {
 		/* handle the client connection */
 		handle_connection(new_sd, NULL);
+    }
 
 	return;
-        }
+}
 
 
 
@@ -1124,7 +1141,146 @@ static void handle_connection(int sock, void *data){
 	return;
         }
 
+/* Takes the peer socket and the host_name that the peer is claiming for a check result.
+ * Returns TRUE iff the peer socket's address matches one of the host_name's addresses
+ * according to getaddrinfo().
+ */
+static int strict_mode_verify_spoofing(int sock, char *host_name)
+{
+
+    // Retrieve the address associated with the socket fd
+
+    /* Note: we did run getpeername() earlier in the program, but adding
+     * parameters and passing data around is difficult due to the event 
+     * processing code. (Search for 'rhand' to see the relevant code.)
+     */ 
+
+    struct sockaddr_storage peer_addr;
+    int peer_addr_len;
+    int status;
+    peer_addr_len = sizeof(peer_addr);
+    status = getpeername(sock, (struct sockaddr *)&peer_addr, &peer_addr_len);
+    if (status == -1) {
+        char *errmsg = strerror(errno);
+        syslog(LOG_ERR, "Strict mode returning early - getpeername() failed: %s", errmsg);
+        return FALSE;
+    }
+    // Network-order bytes are in addr.sin_addr
+
+    // Retrieve the address associated withe the host name we just read
+    struct addrinfo hints, *ai;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = peer_addr.ss_family;
+    hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    status = getaddrinfo(host_name, NULL, &hints, &ai);
+
+    // A hostname can have multiple addresses.
+    // We don't have port information, so we'll check all of them
+    for (; ai != NULL; ai = ai->ai_next) {
+        if (ai->ai_addr->sa_family != peer_addr.ss_family) {
+            // Should already be filtered, but we'll check for it anyways
+            continue;
+        }
 
+        if (ai->ai_addr->sa_family == AF_INET) {
+            struct sockaddr_in *peer_as_ipv4 = ((struct sockaddr_in *) &peer_addr);
+            struct sockaddr_in *claimed_as_ipv4 = ((struct sockaddr_in *) ai->ai_addr);
+            unsigned long peer_network_order = peer_as_ipv4->sin_addr.s_addr;
+            unsigned long claimed_network_order = claimed_as_ipv4->sin_addr.s_addr;
+
+            // Both addresses should be in network order, so just compare longs
+            if (peer_network_order == claimed_network_order) {
+                return TRUE;
+            }
+        }
+        else if (ai->ai_addr->sa_family == AF_INET6) {
+            struct sockaddr_in6 *peer_as_ipv6 = ((struct sockaddr_in6 *) &peer_addr);
+            struct sockaddr_in6 *claimed_as_ipv6 = ((struct sockaddr_in6 *) ai->ai_addr);
+            unsigned char *peer_network_order = peer_as_ipv6->sin6_addr.s6_addr;
+            unsigned char *claimed_network_order = claimed_as_ipv6->sin6_addr.s6_addr;
+
+            int ipv6_no_differences = TRUE;
+            int i;
+            for (i = 0; i < 16; ++i)
+            {
+                ipv6_no_differences &= peer_network_order[i] == claimed_network_order[i];
+            }
+
+            if (ipv6_no_differences) {
+                return TRUE;
+            }
+        }
+    }
+
+    return FALSE;
+} 
+
+/* Convert newlines into the literals '\' and 'n'. Nagios Core runs the inverse
+ * of this function in both check result files and in the external commands file.
+ */
+char *escape_newlines(const char *rawbuf) {
+    char *newbuf = NULL;
+    int x;
+    int y;
+
+    if (rawbuf == NULL)
+        return NULL;
+
+    /* Count the escapes we need to make. */
+    for (x = 0, y = 0; rawbuf[x]; x++) {
+        if (rawbuf[x] == '\\' || rawbuf[x] == '\n')
+            y++;
+        }
+
+    /* Just duplicate the string if we have nothing to escape. */
+    if (y == 0)
+        return strdup(rawbuf);
+
+    /* Allocate memory for the new string with escapes. */
+    if ((newbuf = malloc(x + y + 1)) == NULL)
+        return NULL;
+
+    for (x = 0, y = 0; rawbuf[x]; x++) {
+
+        /* Escape backslashes. */
+        if (rawbuf[x] == '\\') {
+            newbuf[y++] = '\\';
+            newbuf[y++] = '\\';
+            }
+
+        /* Escape newlines. */
+        else if (rawbuf[x] == '\n') {
+            newbuf[y++] = '\\';
+            newbuf[y++] = 'n';
+            }
+
+        else
+            newbuf[y++] = rawbuf[x];
+        }
+    newbuf[y] = '\0';
+
+    return newbuf;
+}
+
+/* If the condition in this loop is triggered, the input is already malformed 
+ * for the purposes of writing to the external commands file. Let's just get
+ * rid of whatever weird thing was happening there.
+ */
+static inline void truncate_newlines(char *to_strip, size_t maxlen)
+{
+    size_t i;
+    for (i = 0; i < maxlen && to_strip[i] != 0; ++i)
+    {
+        if (to_strip[i] == '\n')
+        {
+            to_strip[i] = 0;
+        }
+    }
+}
 
 /* handle reading from a client connection */
 static void handle_connection_read(int sock, void *data){
@@ -1250,6 +1406,18 @@ static void handle_connection_read(int sock, void *data){
 			syslog(LOG_NOTICE,"SERVICE CHECK -> Host Name: '%s', Service Description: '%s', Return Code: '%d', Output: '%s'",host_name,svc_description,return_code,plugin_output);
 	        }
 
+        if (strict_mode_spoofing) {
+
+            int found_match = strict_mode_verify_spoofing(sock, host_name);
+
+            // If they don't match, reject the message and log the interaction
+            if (found_match == FALSE) {
+                syslog(LOG_WARNING, "Strict mode - dropped check for %s due to non-matching host name.", host_name);
+                return;
+            }
+
+        }
+
         /* write the check result to the external command file.
          * Note: it's OK to hang at this point if the write doesn't succeed, as there's
          * no way we could handle any other connection properly anyway.  so we don't
@@ -1257,102 +1425,121 @@ static void handle_connection_read(int sock, void *data){
          * only ever write one command at a time into the pipe.
          */
         //syslog(LOG_ERR,"'%s' (%s) []",check_result_path, strlen(check_result_path));
+        truncate_newlines(host_name, MAX_HOSTNAME_LENGTH);
+        truncate_newlines(svc_description, MAX_DESCRIPTION_LENGTH);
+        char *plugin_output_escaped = escape_newlines(plugin_output);
+
+
         if (check_result_path==NULL){
-        write_check_result(host_name,svc_description,return_code,plugin_output,time(NULL));
+            write_check_result(host_name,svc_description,return_code,plugin_output_escaped,time(NULL));
         }else{
-                write_checkresult_file(host_name,svc_description,return_code,plugin_output,time(NULL));
+            write_checkresult_file(host_name,svc_description,return_code,plugin_output_escaped,time(NULL));
         }
 
+        free(plugin_output_escaped);
+
 	return;
-        }
+}
 
 
 
 /* writes service/host check results to the Nagios checkresult directory */
-static int write_checkresult_file(char *host_name, char *svc_description, int return_code, char *plugin_output, time_t check_time){
-	if(debug==TRUE)
-		syslog(LOG_ERR,"Attempting to write checkresult file");
-        mode_t new_umask=077;
-        mode_t old_umask;
-        time_t current_time;
-        int checkresult_file_fd=-1;
-        char *checkresult_file=NULL;
-        char *checkresult_ok_file=NULL;
-        FILE *checkresult_file_fp=NULL;
-        FILE *checkresult_ok_file_fp=NULL;
-        /* change and store umask */
-        old_umask=umask(new_umask);
-
-        /* create safe checkresult file */
-        asprintf(&checkresult_file,"%s/cXXXXXX",check_result_path);
-        checkresult_file_fd=mkstemp(checkresult_file);
-        if(checkresult_file_fd>0){
-                checkresult_file_fp=fdopen(checkresult_file_fd,"w");
-        } else {
-                syslog(LOG_ERR,"Unable to open and write checkresult file '%s', failing back to PIPE",checkresult_file);
-                return write_check_result(host_name,svc_description,return_code,plugin_output,check_time);
-                }
-
-	if(debug==TRUE)
-		syslog(LOG_ERR,"checkresult file '%s' open for write.",checkresult_file);
-
-        time(&current_time);
-        fprintf(checkresult_file_fp,"### NSCA Passive Check Result ###\n");
-        fprintf(checkresult_file_fp,"# Time: %s",ctime(&current_time));
-        fprintf(checkresult_file_fp,"file_time=%ld\n\n",current_time);
-        fprintf(checkresult_file_fp,"### %s Check Result ###\n",(!*svc_description)?"Host":"Service");
-        fprintf(checkresult_file_fp,"host_name=%s\n",host_name);
-        if(strcmp(svc_description,""))
-                fprintf(checkresult_file_fp,"service_description=%s\n",svc_description);
-        fprintf(checkresult_file_fp,"check_type=1\n");
-        fprintf(checkresult_file_fp,"scheduled_check=0\n");
-        fprintf(checkresult_file_fp,"reschedule_check=0\n");
-        /* We have no latency data at this point. */
-        fprintf(checkresult_file_fp,"latency=0\n");
-        fprintf(checkresult_file_fp,"start_time=%lu.%lu\n",check_time,0L);
-        fprintf(checkresult_file_fp,"finish_time=%lu.%lu\n",check_time,0L);
-        fprintf(checkresult_file_fp,"return_code=%d\n",return_code);
-        /* newlines in output are already escaped */
-        fprintf(checkresult_file_fp,"output=%s\n",(plugin_output==NULL)?"":plugin_output);
-        fprintf(checkresult_file_fp,"\n");
-
-        fclose(checkresult_file_fp);
-        /* create and close ok file */
-        asprintf(&checkresult_ok_file,"%s.ok",checkresult_file);
+static int write_checkresult_file(char *host_name, char *svc_description, int return_code, char *plugin_output, time_t check_time)
+{
+    if(debug==TRUE) {
+        syslog(LOG_ERR,"Attempting to write checkresult file");
+    }
+    mode_t new_umask=077;
+    mode_t old_umask;
+    time_t current_time;
+    int checkresult_file_fd=-1;
+    char *checkresult_file=NULL;
+    char *checkresult_ok_file=NULL;
+    FILE *checkresult_file_fp=NULL;
+    FILE *checkresult_ok_file_fp=NULL;
+    /* change and store umask */
+    old_umask=umask(new_umask);
+
+    /* create safe checkresult file */
+    asprintf(&checkresult_file,"%s/cXXXXXX",check_result_path);
+    checkresult_file_fd=mkstemp(checkresult_file);
+    if(checkresult_file_fd>0) {
+        checkresult_file_fp=fdopen(checkresult_file_fd,"w");
+    }
+    else {
+        syslog(LOG_ERR,"Unable to open and write checkresult file '%s', failing back to PIPE",checkresult_file);
+        return write_check_result(host_name,svc_description,return_code,plugin_output,check_time);
+    }
+
+    if(debug==TRUE) {
+        syslog(LOG_ERR,"checkresult file '%s' open for write.",checkresult_file);
+    }
+
+    time(&current_time);
+    fprintf(checkresult_file_fp,"### NSCA Passive Check Result ###\n");
+    fprintf(checkresult_file_fp,"# Time: %s",ctime(&current_time));
+    fprintf(checkresult_file_fp,"file_time=%ld\n\n",current_time);
+    fprintf(checkresult_file_fp,"### %s Check Result ###\n",(!*svc_description)?"Host":"Service");
+    fprintf(checkresult_file_fp,"host_name=%s\n",host_name);
+    if(strcmp(svc_description,"")) {
+        fprintf(checkresult_file_fp,"service_description=%s\n",svc_description);
+    }
+    fprintf(checkresult_file_fp,"check_type=1\n");
+    fprintf(checkresult_file_fp,"scheduled_check=0\n");
+    fprintf(checkresult_file_fp,"reschedule_check=0\n");
+    /* We have no latency data at this point. */
+    fprintf(checkresult_file_fp,"latency=0\n");
+    fprintf(checkresult_file_fp,"start_time=%lu.%lu\n",check_time,0L);
+    fprintf(checkresult_file_fp,"finish_time=%lu.%lu\n",check_time,0L);
+    fprintf(checkresult_file_fp,"return_code=%d\n",return_code);
+    /* newlines in output are already escaped */
+    fprintf(checkresult_file_fp,"output=%s\n",(plugin_output==NULL)?"":plugin_output);
+    fprintf(checkresult_file_fp,"\n");
+
+    fclose(checkresult_file_fp);
+    /* create and close ok file */
+    asprintf(&checkresult_ok_file,"%s.ok",checkresult_file);
+    if(debug==TRUE) {
         syslog(LOG_DEBUG,"checkresult completion file '%s' open.",checkresult_ok_file);
-        checkresult_ok_file_fp = fopen(checkresult_ok_file,"w");
-        fclose(checkresult_ok_file_fp);
-        /* reset umask */
-        umask(old_umask);
+    }
+    checkresult_ok_file_fp = fopen(checkresult_ok_file,"w");
+    fclose(checkresult_ok_file_fp);
+    /* reset umask */
+    umask(old_umask);
 
-        return OK;
-        }
+    return OK;
+}
 
 /* writes service/host check results to the Nagios command file */
-static int write_check_result(char *host_name, char *svc_description, int return_code, char *plugin_output, time_t check_time){
-	if(debug==TRUE)
+static int write_check_result(char *host_name, char *svc_description, int return_code, char *plugin_output, time_t check_time) {
+	if(debug==TRUE) {
 		syslog(LOG_ERR,"Attempting to write to nagios command pipe");
-        if(aggregate_writes==FALSE){
-                if(open_command_file()==ERROR)
-                        return ERROR;
-                }
+    }
+    if(aggregate_writes==FALSE){
+        if(open_command_file()==ERROR) {
+            return ERROR;
+        }
+    }
 
-	if(!strcmp(svc_description,""))
+	if(!strcmp(svc_description,"")) {
 		fprintf(command_file_fp,"[%lu] PROCESS_HOST_CHECK_RESULT;%s;%d;%s\n",(unsigned long)check_time,host_name,return_code,plugin_output);
+    }
 	else{
 		fprintf(command_file_fp,"[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",(unsigned long)check_time,host_name,svc_description,return_code,plugin_output);
-                }
-        if(aggregate_writes==FALSE)
-                close_command_file();
-        else
-                /* if we don't fflush() then we're writing in 4k non-CR-terminated blocks, and
-                 * anything else (eg. pscwatch) which writes to the file will be writing into
-                 * the middle of our commands.
-                 */
-                fflush(command_file_fp);
+    }
+    if(aggregate_writes==FALSE) {
+        close_command_file();
+    }
+    else {
+        /* if we don't fflush() then we're writing in 4k non-CR-terminated blocks, and
+         * anything else (eg. pscwatch) which writes to the file will be writing into
+         * the middle of our commands.
+         */
+        fflush(command_file_fp);
+    }
 
-        return OK;
-        }
+    return OK;
+}
 
 
 


=====================================
src/send_nsca.c
=====================================
@@ -4,7 +4,7 @@
  * License: GPL v2
  * Copyright (c) 2000-2007 Ethan Galstad (nagios at nagios.org)
  *
- * Last Modified: 2020-04-15
+ * Last Modified: 2021-10-27
  *
  * Command line: SEND_NSCA <host_address> [-p port] [-to to_sec] [-c config_file]
  *
@@ -411,7 +411,29 @@ int read_init_packet(int sock){
 	return OK;
 }
 
+/* 
+ * Reads command-line argument arg and converts into a delimiter string, stored in result.
+ * For any single-character argument, the literal character is used as the argument.
+ * Otherwise, if a number is given, the argument will be converted to a number, and the 
+ * corresponding ASCII code will be used.
+ * e.g. if "9" is given, "9" will be used as a separator, but if "0x9" is given, the tab
+ * character ("\t") will be used instead.
+ */
+int parse_delimiter(char *result, size_t result_size, const char *arg) {
+	if (strlen(arg) > 1 && ((arg[0] > 47 && arg[0] < 58) || arg[0] == 43 || arg[0] == 45)) {
+		/* arg starts with 0-9, +, or -, but isn't a single character */
+		result[0] = (char) strtol(arg, NULL, 0);
+		if (errno) {
+			return ERROR;
+		}
+	}
+	else {
+	    snprintf(result,result_size,"%s",arg);
+	    delimiter[result_size-1]='\x0';
+	}
 
+	return OK;
+}
 
 /* process command line arguments */
 int process_arguments(int argc, char **argv){
@@ -496,34 +518,18 @@ int process_arguments(int argc, char **argv){
 
 		/* delimiter to use when parsing input */
 		else if(!strcmp(argv[x-1],"-d")){
-			if(x<argc){
-				errno=0;
-				long int d = strtol(argv[x], NULL, 16);
-				if(errno){
-				    snprintf(delimiter,sizeof(delimiter),"%s",argv[x]);
-				    delimiter[sizeof(delimiter)-1]='\x0';
-			        }else delimiter[0]= (char) d;
-				x++;
-				}
-			else {
+			if (parse_delimiter(delimiter, sizeof(delimiter), argv[x])) {
 				return ERROR;
 			}
+			x++;
 		}
 
 		/* delimiter to use when parsing input set */
 		else if(!strcmp(argv[x-1],"-ds")){
-			if(x<argc){
-				errno=0;
-				long int d = strtol(argv[x], NULL, 16);
-				if(errno){
-				    snprintf(block_delimiter,sizeof(block_delimiter),"%s",argv[x]);
-				    block_delimiter[sizeof(block_delimiter)-1]='\x0';
-			        }else block_delimiter[0]= (char) d;
-				x++;
-				}
-			else {
+			if (parse_delimiter(block_delimiter, sizeof(block_delimiter), argv[x])) {
 				return ERROR;
 			}
+			x++;
 		}
 
 		else if(x>2)
@@ -540,7 +546,7 @@ void alarm_handler(int sig){
 	char *msg = NULL;
 	asprintf(&msg, "Error: Timeout after %d seconds\n",socket_timeout);
 	/* fprintf(stderr, "Error: Timeout after %d seconds\n",socket_timeout); */
-	write(STDERR_FILENO, msg, sizeof(msg) - 1);
+	write(STDERR_FILENO, msg, strlen(msg));
 
 	do_exit(STATE_CRITICAL);
 }


=====================================
update-version
=====================================
@@ -10,10 +10,10 @@ else
 fi
 
 # Current version number
-CURRENTVERSION=2.10.0
+CURRENTVERSION=2.10.1
 
 # Last date
-LASTDATE=2020-04-15
+LASTDATE=2021-10-27
 
 if [ "x$1" = "x" ]
 then



View it on GitLab: https://salsa.debian.org/nagios-team/pkg-nsca/-/compare/edeb6a9763e674145a3d4ce37d205020b479f2f8...7e62cfcca1cebb35256e636c1da3ccc5e0477d5c

-- 
View it on GitLab: https://salsa.debian.org/nagios-team/pkg-nsca/-/compare/edeb6a9763e674145a3d4ce37d205020b479f2f8...7e62cfcca1cebb35256e636c1da3ccc5e0477d5c
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-nagios-changes/attachments/20211031/da49967b/attachment-0001.htm>


More information about the pkg-nagios-changes mailing list