summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlvar Penning <post@0x21.biz>2025-09-15 22:20:08 +0200
committerAlvar Penning <post@0x21.biz>2025-09-15 22:20:08 +0200
commit4b3f684d33af7459024011a06704cf4ca85dd0a3 (patch)
tree6f0d05fb8c21e1a920a143732166977871322b54
parent601a48a63e745817cf2a4c7f3ca526e393dd3fb8 (diff)
downloadmonitoring-plugins-4b3f684d33af7459024011a06704cf4ca85dd0a3.tar.gz
check_by_ssh: Ignore output on stderr by default
check_by_ssh no longer returns UNKNOWN if ssh(1) returns data on stderr. But it can be enforced again by the new "--unknown-on-stderr" option. --- The default logic of check_by_ssh results in an UNKNOWN state if the ssh(1) process produces output on stderr. Using the "--skip-stderr=[n]" option allows ignoring a certain amount of lines or disabling this check altogether. Furthermore, passing the "--warn-on-stderr" option reduces the exit code to WARNING. The "--help" output does not document this behavior, only states that "--warn-on-stderr" will result in the WARNING, but does not mention the UNKNOWN by default. The man page of ssh(1) mentions that debug information is logged to stderr. This conflicts with the described logic, resulting in check_by_ssh to go UNKNOWN, unless additional options are set. Starting with OpenSSH version 10.1, ssh(1) will report warnings to stderr if the opposite server does not support post-quantum cryptography, <https://www.openssh.com/pq.html>. This change, slowly being rolled out throughout the next months/years, might result in mass-breakages of check_by_ssh. By introducing a new "--unknown-on-stderr" option, enforcing the prior default logic of an UNKNOWN state for data on stderr, and ignoring output on stderr by default, check_by_ssh will continue to work. One might even argue that this change converges actual implementation and the documented behavior, as argued above. --- $ ssh example '/usr/lib/nagios/plugins/check_dummy 0 demo' ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to "store now, decrypt later" attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html OK: demo $ echo $? 0 $ ./check_by_ssh -H example -C '/usr/lib/nagios/plugins/check_dummy 0 demo' OK: demo $ echo $? 0 $ ./check_by_ssh -H example -C '/usr/lib/nagios/plugins/check_dummy 0 demo' --warn-on-stderr Remote command execution failed: ** WARNING: connection is not using a post-quantum key exchange algorithm. $ echo $? 1 $ ./check_by_ssh -H example -C '/usr/lib/nagios/plugins/check_dummy 0 demo' --unknown-on-stderr Remote command execution failed: ** WARNING: connection is not using a post-quantum key exchange algorithm. $ echo $? 3 --- Fixes #2147.
-rw-r--r--plugins/check_by_ssh.c23
-rw-r--r--plugins/check_by_ssh.d/config.h2
2 files changed, 17 insertions, 8 deletions
diff --git a/plugins/check_by_ssh.c b/plugins/check_by_ssh.c
index 74b7a46f..a43c0d34 100644
--- a/plugins/check_by_ssh.c
+++ b/plugins/check_by_ssh.c
@@ -119,13 +119,14 @@ int main(int argc, char **argv) {
119 skip_stderr = config.skip_stderr; 119 skip_stderr = config.skip_stderr;
120 } 120 }
121 121
122 /* UNKNOWN or worse if (non-skipped) output found on stderr */ 122 /* Allow UNKNOWN or WARNING state for (non-skipped) output found on stderr */
123 if (chld_err.lines > (size_t)skip_stderr) { 123 if (chld_err.lines > (size_t)skip_stderr && (config.unknown_on_stderr || config.warn_on_stderr)) {
124 printf(_("Remote command execution failed: %s\n"), chld_err.line[skip_stderr]); 124 printf(_("Remote command execution failed: %s\n"), chld_err.line[skip_stderr]);
125 if (config.warn_on_stderr) { 125 if (config.unknown_on_stderr) {
126 return max_state_alt(result, STATE_UNKNOWN);
127 } else if (config.warn_on_stderr) {
126 return max_state_alt(result, STATE_WARNING); 128 return max_state_alt(result, STATE_WARNING);
127 } 129 }
128 return max_state_alt(result, STATE_UNKNOWN);
129 } 130 }
130 131
131 /* this is simple if we're not supposed to be passive. 132 /* this is simple if we're not supposed to be passive.
@@ -191,12 +192,13 @@ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) {
191 {"name", required_argument, 0, 'n'}, 192 {"name", required_argument, 0, 'n'},
192 {"services", required_argument, 0, 's'}, 193 {"services", required_argument, 0, 's'},
193 {"identity", required_argument, 0, 'i'}, 194 {"identity", required_argument, 0, 'i'},
194 {"user", required_argument, 0, 'u'}, 195 {"user", required_argument, 0, 'u'}, /* backwards compatibility */
195 {"logname", required_argument, 0, 'l'}, 196 {"logname", required_argument, 0, 'l'},
196 {"command", required_argument, 0, 'C'}, 197 {"command", required_argument, 0, 'C'},
197 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ 198 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */
198 {"skip-stdout", optional_argument, 0, 'S'}, 199 {"skip-stdout", optional_argument, 0, 'S'},
199 {"skip-stderr", optional_argument, 0, 'E'}, 200 {"skip-stderr", optional_argument, 0, 'E'},
201 {"unknown-on-stderr", no_argument, 0, 'e'},
200 {"warn-on-stderr", no_argument, 0, 'W'}, 202 {"warn-on-stderr", no_argument, 0, 'W'},
201 {"proto1", no_argument, 0, '1'}, 203 {"proto1", no_argument, 0, '1'},
202 {"proto2", no_argument, 0, '2'}, 204 {"proto2", no_argument, 0, '2'},
@@ -341,6 +343,9 @@ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) {
341 result.config.skip_stderr = atoi(optarg); 343 result.config.skip_stderr = atoi(optarg);
342 } 344 }
343 break; 345 break;
346 case 'e': /* exit with unknown if there is an output on stderr */
347 result.config.unknown_on_stderr = true;
348 break;
344 case 'W': /* exit with warning if there is an output on stderr */ 349 case 'W': /* exit with warning if there is an output on stderr */
345 result.config.warn_on_stderr = true; 350 result.config.warn_on_stderr = true;
346 break; 351 break;
@@ -468,8 +473,10 @@ void print_help(void) {
468 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]")); 473 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]"));
469 printf(" %s\n", "-E, --skip-stderr[=n]"); 474 printf(" %s\n", "-E, --skip-stderr[=n]");
470 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]")); 475 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]"));
471 printf(" %s\n", "-W, --warn-on-stderr]"); 476 printf(" %s\n", "-e, --unknown-on-stderr");
472 printf(" %s\n", _("Exit with an warning, if there is an output on STDERR")); 477 printf(" %s\n", _("Exit with UNKNOWN, if there is output on STDERR"));
478 printf(" %s\n", "-W, --warn-on-stderr");
479 printf(" %s\n", _("Exit with WARNING, if there is output on STDERR"));
473 printf(" %s\n", "-f"); 480 printf(" %s\n", "-f");
474 printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always " 481 printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always "
475 "return OK if ssh is executed")); 482 "return OK if ssh is executed"));
@@ -522,7 +529,7 @@ void print_help(void) {
522void print_usage(void) { 529void print_usage(void) {
523 printf("%s\n", _("Usage:")); 530 printf("%s\n", _("Usage:"));
524 printf(" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n" 531 printf(" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n"
525 " [-S [lines]] [-E [lines]] [-W] [-t timeout] [-i identity]\n" 532 " [-S [lines]] [-E [lines]] [-e|-W] [-t timeout] [-i identity]\n"
526 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n" 533 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n"
527 " [-p port] [-o ssh-option] [-F configfile]\n", 534 " [-p port] [-o ssh-option] [-F configfile]\n",
528 progname); 535 progname);
diff --git a/plugins/check_by_ssh.d/config.h b/plugins/check_by_ssh.d/config.h
index 05435def..0e4b56d4 100644
--- a/plugins/check_by_ssh.d/config.h
+++ b/plugins/check_by_ssh.d/config.h
@@ -21,6 +21,7 @@ typedef struct {
21 command_construct cmd; 21 command_construct cmd;
22 22
23 bool unknown_timeout; 23 bool unknown_timeout;
24 bool unknown_on_stderr;
24 bool warn_on_stderr; 25 bool warn_on_stderr;
25 int skip_stdout; 26 int skip_stdout;
26 int skip_stderr; 27 int skip_stderr;
@@ -46,6 +47,7 @@ check_by_ssh_config check_by_ssh_config_init() {
46 }, 47 },
47 48
48 .unknown_timeout = false, 49 .unknown_timeout = false,
50 .unknown_on_stderr = false,
49 .warn_on_stderr = false, 51 .warn_on_stderr = false,
50 .skip_stderr = 0, 52 .skip_stderr = 0,
51 .skip_stdout = 0, 53 .skip_stdout = 0,