summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/check_by_ssh.c32
-rw-r--r--plugins/check_curl.c48
-rw-r--r--plugins/check_disk.c8
-rw-r--r--plugins/check_fping.c37
-rw-r--r--plugins/check_http.c42
-rw-r--r--plugins/check_pgsql.c17
-rw-r--r--plugins/check_ping.c55
-rw-r--r--plugins/check_procs.c2
-rw-r--r--plugins/check_snmp.c32
-rw-r--r--plugins/check_swap.c24
-rw-r--r--plugins/picohttpparser/picohttpparser.c30
-rw-r--r--plugins/picohttpparser/picohttpparser.h4
-rw-r--r--plugins/sslutils.c2
-rw-r--r--plugins/t/check_curl.t7
-rw-r--r--plugins/t/check_http.t8
-rw-r--r--plugins/tests/certs/.gitignore2
-rw-r--r--plugins/tests/certs/client-cert.pem22
-rw-r--r--plugins/tests/certs/client-key.pem28
-rw-r--r--plugins/tests/certs/clientca-cert.pem25
-rw-r--r--plugins/tests/certs/clientca-key.pem28
-rw-r--r--plugins/tests/certs/clientchain-cert.pem45
-rw-r--r--plugins/tests/certs/clientchain-key.pem28
-rw-r--r--plugins/tests/certs/clientintermediate-cert.pem23
-rw-r--r--plugins/tests/certs/clientintermediate-key.pem28
-rw-r--r--plugins/tests/certs/expired-cert.pem32
-rw-r--r--plugins/tests/certs/expired-key.pem52
-rw-r--r--plugins/tests/certs/ext.cnf2
-rwxr-xr-xplugins/tests/certs/generate-certs.sh63
-rw-r--r--plugins/tests/certs/server-cert.pem44
-rw-r--r--plugins/tests/certs/server-key.pem52
-rwxr-xr-xplugins/tests/check_curl.t10
-rwxr-xr-xplugins/tests/check_http.t256
32 files changed, 779 insertions, 309 deletions
diff --git a/plugins/check_by_ssh.c b/plugins/check_by_ssh.c
index 485bf3be..1ad547ed 100644
--- a/plugins/check_by_ssh.c
+++ b/plugins/check_by_ssh.c
@@ -49,6 +49,8 @@ unsigned int commands = 0;
49unsigned int services = 0; 49unsigned int services = 0;
50int skip_stdout = 0; 50int skip_stdout = 0;
51int skip_stderr = 0; 51int skip_stderr = 0;
52int warn_on_stderr = 0;
53bool unknown_timeout = FALSE;
52char *remotecmd = NULL; 54char *remotecmd = NULL;
53char **commargv = NULL; 55char **commargv = NULL;
54int commargc = 0; 56int commargc = 0;
@@ -100,6 +102,13 @@ main (int argc, char **argv)
100 102
101 result = cmd_run_array (commargv, &chld_out, &chld_err, 0); 103 result = cmd_run_array (commargv, &chld_out, &chld_err, 0);
102 104
105 /* SSH returns 255 if connection attempt fails; include the first line of error output */
106 if (result == 255 && unknown_timeout) {
107 printf (_("SSH connection failed: %s\n"),
108 chld_err.lines > 0 ? chld_err.line[0] : "(no error output)");
109 return STATE_UNKNOWN;
110 }
111
103 if (verbose) { 112 if (verbose) {
104 for(i = 0; i < chld_out.lines; i++) 113 for(i = 0; i < chld_out.lines; i++)
105 printf("stdout: %s\n", chld_out.line[i]); 114 printf("stdout: %s\n", chld_out.line[i]);
@@ -116,7 +125,10 @@ main (int argc, char **argv)
116 if(chld_err.lines > skip_stderr) { 125 if(chld_err.lines > skip_stderr) {
117 printf (_("Remote command execution failed: %s\n"), 126 printf (_("Remote command execution failed: %s\n"),
118 chld_err.line[skip_stderr]); 127 chld_err.line[skip_stderr]);
119 return max_state_alt(result, STATE_UNKNOWN); 128 if ( warn_on_stderr )
129 return max_state_alt(result, STATE_WARNING);
130 else
131 return max_state_alt(result, STATE_UNKNOWN);
120 } 132 }
121 133
122 /* this is simple if we're not supposed to be passive. 134 /* this is simple if we're not supposed to be passive.
@@ -176,6 +188,7 @@ process_arguments (int argc, char **argv)
176 {"verbose", no_argument, 0, 'v'}, 188 {"verbose", no_argument, 0, 'v'},
177 {"fork", no_argument, 0, 'f'}, 189 {"fork", no_argument, 0, 'f'},
178 {"timeout", required_argument, 0, 't'}, 190 {"timeout", required_argument, 0, 't'},
191 {"unknown-timeout", no_argument, 0, 'U'},
179 {"host", required_argument, 0, 'H'}, /* backward compatibility */ 192 {"host", required_argument, 0, 'H'}, /* backward compatibility */
180 {"hostname", required_argument, 0, 'H'}, 193 {"hostname", required_argument, 0, 'H'},
181 {"port", required_argument,0,'p'}, 194 {"port", required_argument,0,'p'},
@@ -189,6 +202,7 @@ process_arguments (int argc, char **argv)
189 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ 202 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */
190 {"skip-stdout", optional_argument, 0, 'S'}, 203 {"skip-stdout", optional_argument, 0, 'S'},
191 {"skip-stderr", optional_argument, 0, 'E'}, 204 {"skip-stderr", optional_argument, 0, 'E'},
205 {"warn-on-stderr", no_argument, 0, 'W'},
192 {"proto1", no_argument, 0, '1'}, 206 {"proto1", no_argument, 0, '1'},
193 {"proto2", no_argument, 0, '2'}, 207 {"proto2", no_argument, 0, '2'},
194 {"use-ipv4", no_argument, 0, '4'}, 208 {"use-ipv4", no_argument, 0, '4'},
@@ -207,7 +221,7 @@ process_arguments (int argc, char **argv)
207 strcpy (argv[c], "-t"); 221 strcpy (argv[c], "-t");
208 222
209 while (1) { 223 while (1) {
210 c = getopt_long (argc, argv, "Vvh1246fqt:H:O:p:i:u:l:C:S::E::n:s:o:F:", longopts, 224 c = getopt_long (argc, argv, "Vvh1246fqt:UH:O:p:i:u:l:C:S::E::n:s:o:F:", longopts,
211 &option); 225 &option);
212 226
213 if (c == -1 || c == EOF) 227 if (c == -1 || c == EOF)
@@ -229,6 +243,9 @@ process_arguments (int argc, char **argv)
229 else 243 else
230 timeout_interval = atoi (optarg); 244 timeout_interval = atoi (optarg);
231 break; 245 break;
246 case 'U':
247 unknown_timeout = TRUE;
248 break;
232 case 'H': /* host */ 249 case 'H': /* host */
233 hostname = optarg; 250 hostname = optarg;
234 break; 251 break;
@@ -307,6 +324,9 @@ process_arguments (int argc, char **argv)
307 else 324 else
308 skip_stderr = atoi (optarg); 325 skip_stderr = atoi (optarg);
309 break; 326 break;
327 case 'W': /* exit with warning if there is an output on stderr */
328 warn_on_stderr = 1;
329 break;
310 case 'o': /* Extra options for the ssh command */ 330 case 'o': /* Extra options for the ssh command */
311 comm_append("-o"); 331 comm_append("-o");
312 comm_append(optarg); 332 comm_append(optarg);
@@ -413,6 +433,8 @@ print_help (void)
413 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]")); 433 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]"));
414 printf (" %s\n", "-E, --skip-stderr[=n]"); 434 printf (" %s\n", "-E, --skip-stderr[=n]");
415 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]")); 435 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]"));
436 printf (" %s\n", "-W, --warn-on-stderr]");
437 printf (" %s\n", _("Exit with an warning, if there is an output on STDERR"));
416 printf (" %s\n", "-f"); 438 printf (" %s\n", "-f");
417 printf (" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always return OK if ssh is executed")); 439 printf (" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always return OK if ssh is executed"));
418 printf (" %s\n","-C, --command='COMMAND STRING'"); 440 printf (" %s\n","-C, --command='COMMAND STRING'");
@@ -435,6 +457,8 @@ print_help (void)
435 printf (" %s\n", _("Tell ssh to suppress warning and diagnostic messages [optional]")); 457 printf (" %s\n", _("Tell ssh to suppress warning and diagnostic messages [optional]"));
436 printf (UT_WARN_CRIT); 458 printf (UT_WARN_CRIT);
437 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 459 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
460 printf (" %s\n","-U, --unknown-timeout");
461 printf (" %s\n", _("Make connection problems return UNKNOWN instead of CRITICAL"));
438 printf (UT_VERBOSE); 462 printf (UT_VERBOSE);
439 printf("\n"); 463 printf("\n");
440 printf (" %s\n", _("The most common mode of use is to refer to a local identity file with")); 464 printf (" %s\n", _("The most common mode of use is to refer to a local identity file with"));
@@ -464,8 +488,8 @@ void
464print_usage (void) 488print_usage (void)
465{ 489{
466 printf ("%s\n", _("Usage:")); 490 printf ("%s\n", _("Usage:"));
467 printf (" %s -H <host> -C <command> [-fqv] [-1|-2] [-4|-6]\n" 491 printf (" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n"
468 " [-S [lines]] [-E [lines]] [-t timeout] [-i identity]\n" 492 " [-S [lines]] [-E [lines]] [-W] [-t timeout] [-i identity]\n"
469 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n" 493 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n"
470 " [-p port] [-o ssh-option] [-F configfile]\n", 494 " [-p port] [-o ssh-option] [-F configfile]\n",
471 progname); 495 progname);
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 14cc8463..a69854a8 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -66,13 +66,13 @@ const char *email = "devel@monitoring-plugins.org";
66#define DEFAULT_BUFFER_SIZE 2048 66#define DEFAULT_BUFFER_SIZE 2048
67#define DEFAULT_SERVER_URL "/" 67#define DEFAULT_SERVER_URL "/"
68#define HTTP_EXPECT "HTTP/" 68#define HTTP_EXPECT "HTTP/"
69#define DEFAULT_MAX_REDIRS 15
70#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN 69#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN
71enum { 70enum {
72 MAX_IPV4_HOSTLENGTH = 255, 71 MAX_IPV4_HOSTLENGTH = 255,
73 HTTP_PORT = 80, 72 HTTP_PORT = 80,
74 HTTPS_PORT = 443, 73 HTTPS_PORT = 443,
75 MAX_PORT = 65535 74 MAX_PORT = 65535,
75 DEFAULT_MAX_REDIRS = 15
76}; 76};
77 77
78enum { 78enum {
@@ -193,6 +193,7 @@ int followsticky = STICKY_NONE;
193int use_ssl = FALSE; 193int use_ssl = FALSE;
194int use_sni = TRUE; 194int use_sni = TRUE;
195int check_cert = FALSE; 195int check_cert = FALSE;
196int continue_after_check_cert = FALSE;
196typedef union { 197typedef union {
197 struct curl_slist* to_info; 198 struct curl_slist* to_info;
198 struct curl_certinfo* to_certinfo; 199 struct curl_certinfo* to_certinfo;
@@ -754,7 +755,9 @@ check_http (void)
754 * and we actually have OpenSSL in the monitoring tools 755 * and we actually have OpenSSL in the monitoring tools
755 */ 756 */
756 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 757 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
757 return result; 758 if (continue_after_check_cert == FALSE) {
759 return result;
760 }
758#else /* USE_OPENSSL */ 761#else /* USE_OPENSSL */
759 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 762 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
760#endif /* USE_OPENSSL */ 763#endif /* USE_OPENSSL */
@@ -794,13 +797,17 @@ GOT_FIRST_CERT:
794 } 797 }
795 BIO_free (cert_BIO); 798 BIO_free (cert_BIO);
796 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 799 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
797 return result; 800 if (continue_after_check_cert == FALSE) {
801 return result;
802 }
798#else /* USE_OPENSSL */ 803#else /* USE_OPENSSL */
799 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 804 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
800 * so we use the libcurl CURLINFO data 805 * so we use the libcurl CURLINFO data
801 */ 806 */
802 result = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 807 result = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
803 return result; 808 if (continue_after_check_cert == FALSE) {
809 return result;
810 }
804#endif /* USE_OPENSSL */ 811#endif /* USE_OPENSSL */
805 } else { 812 } else {
806 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), 813 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"),
@@ -1054,7 +1061,7 @@ redir (curlhelp_write_curlbuf* header_buf)
1054 char *new_url; 1061 char *new_url;
1055 1062
1056 int res = phr_parse_response (header_buf->buf, header_buf->buflen, 1063 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
1057 &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 1064 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
1058 headers, &nof_headers, 0); 1065 headers, &nof_headers, 0);
1059 1066
1060 location = get_header_value (headers, nof_headers, "location"); 1067 location = get_header_value (headers, nof_headers, "location");
@@ -1210,6 +1217,8 @@ process_arguments (int argc, char **argv)
1210 enum { 1217 enum {
1211 INVERT_REGEX = CHAR_MAX + 1, 1218 INVERT_REGEX = CHAR_MAX + 1,
1212 SNI_OPTION, 1219 SNI_OPTION,
1220 MAX_REDIRS_OPTION,
1221 CONTINUE_AFTER_CHECK_CERT,
1213 CA_CERT_OPTION, 1222 CA_CERT_OPTION,
1214 HTTP_VERSION_OPTION, 1223 HTTP_VERSION_OPTION,
1215 AUTOMATIC_DECOMPRESSION 1224 AUTOMATIC_DECOMPRESSION
@@ -1243,6 +1252,7 @@ process_arguments (int argc, char **argv)
1243 {"private-key", required_argument, 0, 'K'}, 1252 {"private-key", required_argument, 0, 'K'},
1244 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1253 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1245 {"verify-cert", no_argument, 0, 'D'}, 1254 {"verify-cert", no_argument, 0, 'D'},
1255 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
1246 {"useragent", required_argument, 0, 'A'}, 1256 {"useragent", required_argument, 0, 'A'},
1247 {"header", required_argument, 0, 'k'}, 1257 {"header", required_argument, 0, 'k'},
1248 {"no-body", no_argument, 0, 'N'}, 1258 {"no-body", no_argument, 0, 'N'},
@@ -1254,6 +1264,7 @@ process_arguments (int argc, char **argv)
1254 {"use-ipv6", no_argument, 0, '6'}, 1264 {"use-ipv6", no_argument, 0, '6'},
1255 {"extended-perfdata", no_argument, 0, 'E'}, 1265 {"extended-perfdata", no_argument, 0, 'E'},
1256 {"show-body", no_argument, 0, 'B'}, 1266 {"show-body", no_argument, 0, 'B'},
1267 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
1257 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1268 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1258 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION}, 1269 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1259 {0, 0, 0, 0} 1270 {0, 0, 0, 0}
@@ -1401,6 +1412,11 @@ process_arguments (int argc, char **argv)
1401 check_cert = TRUE; 1412 check_cert = TRUE;
1402 goto enable_ssl; 1413 goto enable_ssl;
1403#endif 1414#endif
1415 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */
1416#ifdef HAVE_SSL
1417 continue_after_check_cert = TRUE;
1418 break;
1419#endif
1404 case 'J': /* use client certificate */ 1420 case 'J': /* use client certificate */
1405#ifdef LIBCURL_FEATURE_SSL 1421#ifdef LIBCURL_FEATURE_SSL
1406 test_file(optarg); 1422 test_file(optarg);
@@ -1512,6 +1528,13 @@ process_arguments (int argc, char **argv)
1512 use_sni = TRUE; 1528 use_sni = TRUE;
1513 break; 1529 break;
1514#endif /* LIBCURL_FEATURE_SSL */ 1530#endif /* LIBCURL_FEATURE_SSL */
1531 case MAX_REDIRS_OPTION:
1532 if (!is_intnonneg (optarg))
1533 usage2 (_("Invalid max_redirs count"), optarg);
1534 else {
1535 max_depth = atoi (optarg);
1536 }
1537 break;
1515 case 'f': /* onredirect */ 1538 case 'f': /* onredirect */
1516 if (!strcmp (optarg, "ok")) 1539 if (!strcmp (optarg, "ok"))
1517 onredirect = STATE_OK; 1540 onredirect = STATE_OK;
@@ -1791,7 +1814,11 @@ print_help (void)
1791#endif 1814#endif
1792 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1815 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
1793 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443")); 1816 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1794 printf (" %s\n", _("(when this option is used the URL is not checked.)")); 1817 printf (" %s\n", _("(when this option is used the URL is not checked by default. You can use"));
1818 printf (" %s\n", _(" --continue-after-certificate to override this behavior)"));
1819 printf (" %s\n", "--continue-after-certificate");
1820 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
1821 printf (" %s\n", _("Does nothing unless -C is used."));
1795 printf (" %s\n", "-J, --client-cert=FILE"); 1822 printf (" %s\n", "-J, --client-cert=FILE");
1796 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 1823 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)"));
1797 printf (" %s\n", _("to be used in establishing the SSL session")); 1824 printf (" %s\n", _("to be used in establishing the SSL session"));
@@ -1854,6 +1881,9 @@ print_help (void)
1854 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 1881 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
1855 printf (" %s\n", _("follow uses the old redirection algorithm of check_http.")); 1882 printf (" %s\n", _("follow uses the old redirection algorithm of check_http."));
1856 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl.")); 1883 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl."));
1884 printf (" %s\n", "--max-redirs=INTEGER");
1885 printf (" %s", _("Maximal number of redirects (default: "));
1886 printf ("%d)\n", DEFAULT_MAX_REDIRS);
1857 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 1887 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1858 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); 1888 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1859 printf ("\n"); 1889 printf ("\n");
@@ -2188,7 +2218,7 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2188 size_t msglen; 2218 size_t msglen;
2189 2219
2190 int res = phr_parse_response (header_buf->buf, header_buf->buflen, 2220 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2191 &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 2221 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2192 headers, &nof_headers, 0); 2222 headers, &nof_headers, 0);
2193 2223
2194 server_date = get_header_value (headers, nof_headers, "date"); 2224 server_date = get_header_value (headers, nof_headers, "date");
@@ -2246,7 +2276,7 @@ get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_wri
2246 curlhelp_statusline status_line; 2276 curlhelp_statusline status_line;
2247 2277
2248 int res = phr_parse_response (header_buf->buf, header_buf->buflen, 2278 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2249 &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 2279 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2250 headers, &nof_headers, 0); 2280 headers, &nof_headers, 0);
2251 2281
2252 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2282 content_length_s = get_header_value (headers, nof_headers, "content-length");
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 54befcad..66c5dd39 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -230,8 +230,10 @@ main (int argc, char **argv)
230 /* Process for every path in list */ 230 /* Process for every path in list */
231 for (path = path_select_list; path; path=path->name_next) { 231 for (path = path_select_list; path; path=path->name_next) {
232 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) 232 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
233 printf("Thresholds(pct) for %s warn: %f crit %f\n",path->name, path->freespace_percent->warning->end, 233 printf("Thresholds(pct) for %s warn: %f crit %f\n",
234 path->freespace_percent->critical->end); 234 path->name,
235 path->freespace_percent->warning->end,
236 path->freespace_percent->critical->end);
235 237
236 if (verbose >= 3 && path->group != NULL) 238 if (verbose >= 3 && path->group != NULL)
237 printf("Group of %s: %s\n",path->name,path->group); 239 printf("Group of %s: %s\n",path->name,path->group);
@@ -959,7 +961,7 @@ print_help (void)
959 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems")); 961 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
960 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)")); 962 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
961 printf (" %s\n", "-M, --mountpoint"); 963 printf (" %s\n", "-M, --mountpoint");
962 printf (" %s\n", _("Display the mountpoint instead of the partition")); 964 printf (" %s\n", _("Display the (block) device instead of the mount point"));
963 printf (" %s\n", "-m, --megabytes"); 965 printf (" %s\n", "-m, --megabytes");
964 printf (" %s\n", _("Same as '--units MB'")); 966 printf (" %s\n", _("Same as '--units MB'"));
965 printf (" %s\n", "-A, --all"); 967 printf (" %s\n", "-A, --all");
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 521d0fef..be9362ad 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -37,6 +37,7 @@ const char *email = "devel@monitoring-plugins.org";
37#include "popen.h" 37#include "popen.h"
38#include "netutils.h" 38#include "netutils.h"
39#include "utils.h" 39#include "utils.h"
40#include <stdbool.h>
40 41
41enum { 42enum {
42 PACKET_COUNT = 1, 43 PACKET_COUNT = 1,
@@ -65,6 +66,7 @@ double crta;
65double wrta; 66double wrta;
66int cpl_p = FALSE; 67int cpl_p = FALSE;
67int wpl_p = FALSE; 68int wpl_p = FALSE;
69bool alive_p = FALSE;
68int crta_p = FALSE; 70int crta_p = FALSE;
69int wrta_p = FALSE; 71int wrta_p = FALSE;
70 72
@@ -147,9 +149,11 @@ main (int argc, char **argv)
147 (void) fclose (child_stderr); 149 (void) fclose (child_stderr);
148 150
149 /* close the pipe */ 151 /* close the pipe */
150 if (result = spclose (child_process)) 152 result = spclose (child_process);
153 if (result) {
151 /* need to use max_state not max */ 154 /* need to use max_state not max */
152 status = max_state (status, STATE_WARNING); 155 status = max_state (status, STATE_WARNING);
156 }
153 157
154 if (result > 1 ) { 158 if (result > 1 ) {
155 status = max_state (status, STATE_UNKNOWN); 159 status = max_state (status, STATE_UNKNOWN);
@@ -171,10 +175,7 @@ main (int argc, char **argv)
171} 175}
172 176
173 177
174 178int textscan (char *buf) {
175int
176textscan (char *buf)
177{
178 char *rtastr = NULL; 179 char *rtastr = NULL;
179 char *losstr = NULL; 180 char *losstr = NULL;
180 char *xmtstr = NULL; 181 char *xmtstr = NULL;
@@ -183,6 +184,20 @@ textscan (char *buf)
183 double xmt; 184 double xmt;
184 int status = STATE_UNKNOWN; 185 int status = STATE_UNKNOWN;
185 186
187 /* stops testing after the first successful reply. */
188 if (alive_p && strstr(buf, "avg, 0% loss)")) {
189 rtastr = strstr (buf, "ms (");
190 rtastr = 1 + index(rtastr, '(');
191 rta = strtod(rtastr, NULL);
192 loss=strtod("0",NULL);
193 die (STATE_OK,
194 _("FPING %s - %s (rta=%f ms)|%s\n"),
195 state_text (STATE_OK), server_name,rta,
196 /* No loss since we only waited for the first reply
197 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, TRUE, 0, TRUE, 100), */
198 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, TRUE, 0, FALSE, 0));
199 }
200
186 if (strstr (buf, "not found")) { 201 if (strstr (buf, "not found")) {
187 die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); 202 die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name);
188 203
@@ -278,6 +293,7 @@ process_arguments (int argc, char **argv)
278 {"sourceif", required_argument, 0, 'I'}, 293 {"sourceif", required_argument, 0, 'I'},
279 {"critical", required_argument, 0, 'c'}, 294 {"critical", required_argument, 0, 'c'},
280 {"warning", required_argument, 0, 'w'}, 295 {"warning", required_argument, 0, 'w'},
296 {"alive", no_argument, 0, 'a'},
281 {"bytes", required_argument, 0, 'b'}, 297 {"bytes", required_argument, 0, 'b'},
282 {"number", required_argument, 0, 'n'}, 298 {"number", required_argument, 0, 'n'},
283 {"target-timeout", required_argument, 0, 'T'}, 299 {"target-timeout", required_argument, 0, 'T'},
@@ -304,7 +320,7 @@ process_arguments (int argc, char **argv)
304 } 320 }
305 321
306 while (1) { 322 while (1) {
307 c = getopt_long (argc, argv, "+hVvH:S:c:w:b:n:T:i:I:46", longopts, &option); 323 c = getopt_long (argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option);
308 324
309 if (c == -1 || c == EOF || c == 1) 325 if (c == -1 || c == EOF || c == 1)
310 break; 326 break;
@@ -312,6 +328,9 @@ process_arguments (int argc, char **argv)
312 switch (c) { 328 switch (c) {
313 case '?': /* print short usage statement if args not parsable */ 329 case '?': /* print short usage statement if args not parsable */
314 usage5 (); 330 usage5 ();
331 case 'a': /* host alive mode */
332 alive_p = TRUE;
333 break;
315 case 'h': /* help */ 334 case 'h': /* help */
316 print_help (); 335 print_help ();
317 exit (STATE_UNKNOWN); 336 exit (STATE_UNKNOWN);
@@ -446,9 +465,7 @@ get_threshold (char *arg, char *rv[2])
446} 465}
447 466
448 467
449void 468void print_help (void) {
450print_help (void)
451{
452 469
453 print_revision (progname, NP_VERSION); 470 print_revision (progname, NP_VERSION);
454 471
@@ -474,6 +491,8 @@ print_help (void)
474 printf (" %s\n", _("warning threshold pair")); 491 printf (" %s\n", _("warning threshold pair"));
475 printf (" %s\n", "-c, --critical=THRESHOLD"); 492 printf (" %s\n", "-c, --critical=THRESHOLD");
476 printf (" %s\n", _("critical threshold pair")); 493 printf (" %s\n", _("critical threshold pair"));
494 printf (" %s\n", "-a, --alive");
495 printf (" %s\n", _("Return OK after first successfull reply"));
477 printf (" %s\n", "-b, --bytes=INTEGER"); 496 printf (" %s\n", "-b, --bytes=INTEGER");
478 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE); 497 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE);
479 printf (" %s\n", "-n, --number=INTEGER"); 498 printf (" %s\n", "-n, --number=INTEGER");
diff --git a/plugins/check_http.c b/plugins/check_http.c
index 34fb4f01..f8ec853b 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -52,11 +52,13 @@ enum {
52 MAX_IPV4_HOSTLENGTH = 255, 52 MAX_IPV4_HOSTLENGTH = 255,
53 HTTP_PORT = 80, 53 HTTP_PORT = 80,
54 HTTPS_PORT = 443, 54 HTTPS_PORT = 443,
55 MAX_PORT = 65535 55 MAX_PORT = 65535,
56 DEFAULT_MAX_REDIRS = 15
56}; 57};
57 58
58#ifdef HAVE_SSL 59#ifdef HAVE_SSL
59int check_cert = FALSE; 60int check_cert = FALSE;
61int continue_after_check_cert = FALSE;
60int ssl_version = 0; 62int ssl_version = 0;
61int days_till_exp_warn, days_till_exp_crit; 63int days_till_exp_warn, days_till_exp_crit;
62char *randbuff; 64char *randbuff;
@@ -125,7 +127,7 @@ int sd;
125int min_page_len = 0; 127int min_page_len = 0;
126int max_page_len = 0; 128int max_page_len = 0;
127int redir_depth = 0; 129int redir_depth = 0;
128int max_depth = 15; 130int max_depth = DEFAULT_MAX_REDIRS;
129char *http_method; 131char *http_method;
130char *http_method_proxy; 132char *http_method_proxy;
131char *http_post_data; 133char *http_post_data;
@@ -203,7 +205,9 @@ process_arguments (int argc, char **argv)
203 205
204 enum { 206 enum {
205 INVERT_REGEX = CHAR_MAX + 1, 207 INVERT_REGEX = CHAR_MAX + 1,
206 SNI_OPTION 208 SNI_OPTION,
209 MAX_REDIRS_OPTION,
210 CONTINUE_AFTER_CHECK_CERT
207 }; 211 };
208 212
209 int option = 0; 213 int option = 0;
@@ -231,6 +235,7 @@ process_arguments (int argc, char **argv)
231 {"certificate", required_argument, 0, 'C'}, 235 {"certificate", required_argument, 0, 'C'},
232 {"client-cert", required_argument, 0, 'J'}, 236 {"client-cert", required_argument, 0, 'J'},
233 {"private-key", required_argument, 0, 'K'}, 237 {"private-key", required_argument, 0, 'K'},
238 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
234 {"useragent", required_argument, 0, 'A'}, 239 {"useragent", required_argument, 0, 'A'},
235 {"header", required_argument, 0, 'k'}, 240 {"header", required_argument, 0, 'k'},
236 {"no-body", no_argument, 0, 'N'}, 241 {"no-body", no_argument, 0, 'N'},
@@ -242,6 +247,7 @@ process_arguments (int argc, char **argv)
242 {"use-ipv6", no_argument, 0, '6'}, 247 {"use-ipv6", no_argument, 0, '6'},
243 {"extended-perfdata", no_argument, 0, 'E'}, 248 {"extended-perfdata", no_argument, 0, 'E'},
244 {"show-body", no_argument, 0, 'B'}, 249 {"show-body", no_argument, 0, 'B'},
250 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
245 {0, 0, 0, 0} 251 {0, 0, 0, 0}
246 }; 252 };
247 253
@@ -329,6 +335,11 @@ process_arguments (int argc, char **argv)
329 check_cert = TRUE; 335 check_cert = TRUE;
330 goto enable_ssl; 336 goto enable_ssl;
331#endif 337#endif
338 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */
339#ifdef HAVE_SSL
340 continue_after_check_cert = TRUE;
341 break;
342#endif
332 case 'J': /* use client certificate */ 343 case 'J': /* use client certificate */
333#ifdef HAVE_SSL 344#ifdef HAVE_SSL
334 test_file(optarg); 345 test_file(optarg);
@@ -373,6 +384,13 @@ process_arguments (int argc, char **argv)
373 case SNI_OPTION: 384 case SNI_OPTION:
374 use_sni = TRUE; 385 use_sni = TRUE;
375 break; 386 break;
387 case MAX_REDIRS_OPTION:
388 if (!is_intnonneg (optarg))
389 usage2 (_("Invalid max_redirs count"), optarg);
390 else {
391 max_depth = atoi (optarg);
392 }
393 break;
376 case 'f': /* onredirect */ 394 case 'f': /* onredirect */
377 if (!strcmp (optarg, "stickyport")) 395 if (!strcmp (optarg, "stickyport"))
378 onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST|STICKY_PORT; 396 onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST|STICKY_PORT;
@@ -971,9 +989,11 @@ check_http (void)
971 elapsed_time_ssl = (double)microsec_ssl / 1.0e6; 989 elapsed_time_ssl = (double)microsec_ssl / 1.0e6;
972 if (check_cert == TRUE) { 990 if (check_cert == TRUE) {
973 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); 991 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
974 if (sd) close(sd); 992 if (continue_after_check_cert == FALSE) {
975 np_net_ssl_cleanup(); 993 if (sd) close(sd);
976 return result; 994 np_net_ssl_cleanup();
995 return result;
996 }
977 } 997 }
978 } 998 }
979#endif /* HAVE_SSL */ 999#endif /* HAVE_SSL */
@@ -1598,7 +1618,11 @@ print_help (void)
1598 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1618 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
1599 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1619 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
1600 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443")); 1620 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1601 printf (" %s\n", _("(when this option is used the URL is not checked.)")); 1621 printf (" %s\n", _("(when this option is used the URL is not checked by default. You can use"));
1622 printf (" %s\n", _(" --continue-after-certificate to override this behavior)"));
1623 printf (" %s\n", "--continue-after-certificate");
1624 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
1625 printf (" %s\n", _("Does nothing unless -C is used."));
1602 printf (" %s\n", "-J, --client-cert=FILE"); 1626 printf (" %s\n", "-J, --client-cert=FILE");
1603 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 1627 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)"));
1604 printf (" %s\n", _("to be used in establishing the SSL session")); 1628 printf (" %s\n", _("to be used in establishing the SSL session"));
@@ -1657,9 +1681,11 @@ print_help (void)
1657 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>"); 1681 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>");
1658 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); 1682 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
1659 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 1683 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
1684 printf (" %s\n", "--max-redirs=INTEGER");
1685 printf (" %s", _("Maximal number of redirects (default: "));
1686 printf ("%d)\n", DEFAULT_MAX_REDIRS);
1660 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 1687 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1661 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); 1688 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1662
1663 printf (UT_WARN_CRIT); 1689 printf (UT_WARN_CRIT);
1664 1690
1665 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1691 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index b8fc5f1d..c893386c 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -85,6 +85,8 @@ char *pgparams = NULL;
85double twarn = (double)DEFAULT_WARN; 85double twarn = (double)DEFAULT_WARN;
86double tcrit = (double)DEFAULT_CRIT; 86double tcrit = (double)DEFAULT_CRIT;
87char *pgquery = NULL; 87char *pgquery = NULL;
88#define OPTID_QUERYNAME -1000
89char *pgqueryname = NULL;
88char *query_warning = NULL; 90char *query_warning = NULL;
89char *query_critical = NULL; 91char *query_critical = NULL;
90thresholds *qthresholds = NULL; 92thresholds *qthresholds = NULL;
@@ -285,6 +287,7 @@ process_arguments (int argc, char **argv)
285 {"database", required_argument, 0, 'd'}, 287 {"database", required_argument, 0, 'd'},
286 {"option", required_argument, 0, 'o'}, 288 {"option", required_argument, 0, 'o'},
287 {"query", required_argument, 0, 'q'}, 289 {"query", required_argument, 0, 'q'},
290 {"queryname", required_argument, 0, OPTID_QUERYNAME},
288 {"query_critical", required_argument, 0, 'C'}, 291 {"query_critical", required_argument, 0, 'C'},
289 {"query_warning", required_argument, 0, 'W'}, 292 {"query_warning", required_argument, 0, 'W'},
290 {"verbose", no_argument, 0, 'v'}, 293 {"verbose", no_argument, 0, 'v'},
@@ -368,6 +371,9 @@ process_arguments (int argc, char **argv)
368 case 'q': 371 case 'q':
369 pgquery = optarg; 372 pgquery = optarg;
370 break; 373 break;
374 case OPTID_QUERYNAME:
375 pgqueryname = optarg;
376 break;
371 case 'v': 377 case 'v':
372 verbose++; 378 verbose++;
373 break; 379 break;
@@ -529,6 +535,9 @@ print_help (void)
529 535
530 printf (" %s\n", "-q, --query=STRING"); 536 printf (" %s\n", "-q, --query=STRING");
531 printf (" %s\n", _("SQL query to run. Only first column in first row will be read")); 537 printf (" %s\n", _("SQL query to run. Only first column in first row will be read"));
538 printf (" %s\n", "--queryname=STRING");
539 printf (" %s\n", _("A name for the query, this string is used instead of the query"));
540 printf (" %s\n", _("in the long output of the plugin"));
532 printf (" %s\n", "-W, --query-warning=RANGE"); 541 printf (" %s\n", "-W, --query-warning=RANGE");
533 printf (" %s\n", _("SQL query value to result in warning status (double)")); 542 printf (" %s\n", _("SQL query value to result in warning status (double)"));
534 printf (" %s\n", "-C, --query-critical=RANGE"); 543 printf (" %s\n", "-C, --query-critical=RANGE");
@@ -642,7 +651,13 @@ do_query (PGconn *conn, char *query)
642 : (my_status == STATE_CRITICAL) 651 : (my_status == STATE_CRITICAL)
643 ? _("CRITICAL") 652 ? _("CRITICAL")
644 : _("UNKNOWN")); 653 : _("UNKNOWN"));
645 printf (_("'%s' returned %f"), query, value); 654 if(pgqueryname) {
655 printf (_("%s returned %f"), pgqueryname, value);
656 }
657 else {
658 printf (_("'%s' returned %f"), query, value);
659 }
660
646 printf ("|query=%f;%s;%s;;\n", value, 661 printf ("|query=%f;%s;%s;;\n", value,
647 query_warning ? query_warning : "", 662 query_warning ? query_warning : "",
648 query_critical ? query_critical : ""); 663 query_critical ? query_critical : "");
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index ba7af373..741f732e 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -140,7 +140,7 @@ main (int argc, char **argv)
140 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) { 140 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) {
141 printf ("%s\n", cmd); 141 printf ("%s\n", cmd);
142 die (STATE_UNKNOWN, 142 die (STATE_UNKNOWN,
143 _("CRITICAL - Could not interpret output from ping command\n")); 143 _("CRITICAL - Could not interpret output from ping command\n"));
144 } 144 }
145 145
146 if (pl >= cpl || rta >= crta || rta < 0) 146 if (pl >= cpl || rta >= crta || rta < 0)
@@ -527,12 +527,13 @@ int
527error_scan (char buf[MAX_INPUT_BUFFER], const char *addr) 527error_scan (char buf[MAX_INPUT_BUFFER], const char *addr)
528{ 528{
529 if (strstr (buf, "Network is unreachable") || 529 if (strstr (buf, "Network is unreachable") ||
530 strstr (buf, "Destination Net Unreachable") 530 strstr (buf, "Destination Net Unreachable") ||
531 strstr (buf, "No route")
531 ) 532 )
532 die (STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr); 533 die (STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
533 else if (strstr (buf, "Destination Host Unreachable")) 534 else if (strstr (buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable"))
534 die (STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr); 535 die (STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr);
535 else if (strstr (buf, "Destination Port Unreachable")) 536 else if (strstr (buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable"))
536 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr); 537 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr);
537 else if (strstr (buf, "Destination Protocol Unreachable")) 538 else if (strstr (buf, "Destination Protocol Unreachable"))
538 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr); 539 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr);
@@ -540,11 +541,11 @@ error_scan (char buf[MAX_INPUT_BUFFER], const char *addr)
540 die (STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr); 541 die (STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr);
541 else if (strstr (buf, "Destination Host Prohibited")) 542 else if (strstr (buf, "Destination Host Prohibited"))
542 die (STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr); 543 die (STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr);
543 else if (strstr (buf, "Packet filtered")) 544 else if (strstr (buf, "Packet filtered") || strstr(buf, "Administratively prohibited"))
544 die (STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr); 545 die (STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr);
545 else if (strstr (buf, "unknown host" )) 546 else if (strstr (buf, "unknown host" ))
546 die (STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr); 547 die (STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
547 else if (strstr (buf, "Time to live exceeded")) 548 else if (strstr (buf, "Time to live exceeded") || strstr(buf, "Time exceeded"))
548 die (STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr); 549 die (STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
549 else if (strstr (buf, "Destination unreachable: ")) 550 else if (strstr (buf, "Destination unreachable: "))
550 die (STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr); 551 die (STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
@@ -553,7 +554,7 @@ error_scan (char buf[MAX_INPUT_BUFFER], const char *addr)
553 if (warn_text == NULL) 554 if (warn_text == NULL)
554 warn_text = strdup (_(WARN_DUPLICATES)); 555 warn_text = strdup (_(WARN_DUPLICATES));
555 else if (! strstr (warn_text, _(WARN_DUPLICATES)) && 556 else if (! strstr (warn_text, _(WARN_DUPLICATES)) &&
556 xasprintf (&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) 557 xasprintf (&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1)
557 die (STATE_UNKNOWN, _("Unable to realloc warn_text\n")); 558 die (STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
558 return (STATE_WARNING); 559 return (STATE_WARNING);
559 } 560 }
@@ -573,7 +574,7 @@ print_help (void)
573 574
574 printf (_("Use ping to check connection statistics for a remote host.")); 575 printf (_("Use ping to check connection statistics for a remote host."));
575 576
576 printf ("\n\n"); 577 printf ("\n\n");
577 578
578 print_usage (); 579 print_usage ();
579 580
@@ -583,29 +584,29 @@ print_help (void)
583 printf (UT_IPv46); 584 printf (UT_IPv46);
584 585
585 printf (" %s\n", "-H, --hostname=HOST"); 586 printf (" %s\n", "-H, --hostname=HOST");
586 printf (" %s\n", _("host to ping")); 587 printf (" %s\n", _("host to ping"));
587 printf (" %s\n", "-w, --warning=THRESHOLD"); 588 printf (" %s\n", "-w, --warning=THRESHOLD");
588 printf (" %s\n", _("warning threshold pair")); 589 printf (" %s\n", _("warning threshold pair"));
589 printf (" %s\n", "-c, --critical=THRESHOLD"); 590 printf (" %s\n", "-c, --critical=THRESHOLD");
590 printf (" %s\n", _("critical threshold pair")); 591 printf (" %s\n", _("critical threshold pair"));
591 printf (" %s\n", "-p, --packets=INTEGER"); 592 printf (" %s\n", "-p, --packets=INTEGER");
592 printf (" %s ", _("number of ICMP ECHO packets to send")); 593 printf (" %s ", _("number of ICMP ECHO packets to send"));
593 printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS); 594 printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS);
594 printf (" %s\n", "-L, --link"); 595 printf (" %s\n", "-L, --link");
595 printf (" %s\n", _("show HTML in the plugin output (obsoleted by urlize)")); 596 printf (" %s\n", _("show HTML in the plugin output (obsoleted by urlize)"));
596 597
597 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 598 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
598 599
599 printf ("\n"); 600 printf ("\n");
600 printf ("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel")); 601 printf ("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel"));
601 printf ("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the")); 602 printf ("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the"));
602 printf ("%s\n", _("percentage of packet loss to trigger an alarm state.")); 603 printf ("%s\n", _("percentage of packet loss to trigger an alarm state."));
603 604
604 printf ("\n"); 605 printf ("\n");
605 printf ("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss")); 606 printf ("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss"));
606 printf ("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output")); 607 printf ("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output"));
607 printf ("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in")); 608 printf ("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in"));
608 printf ("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/")); 609 printf ("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/"));
609 610
610 printf (UT_SUPPORT); 611 printf (UT_SUPPORT);
611} 612}
@@ -613,7 +614,7 @@ print_help (void)
613void 614void
614print_usage (void) 615print_usage (void)
615{ 616{
616 printf ("%s\n", _("Usage:")); 617 printf ("%s\n", _("Usage:"));
617 printf ("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname); 618 printf ("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
618 printf (" [-p packets] [-t timeout] [-4|-6]\n"); 619 printf (" [-p packets] [-t timeout] [-4|-6]\n");
619} 620}
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index 48723404..a025ee89 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -775,7 +775,7 @@ be the total number of running processes\n\n"));
775 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ"); 775 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
776 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K")); 776 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
777 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU"); 777 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
778 printf (" %s\n", _("Alert if CPU of any processes over 10%% or 20%%")); 778 printf (" %s\n", _("Alert if CPU of any processes over 10\% or 20\%"));
779 779
780 printf (UT_SUPPORT); 780 printf (UT_SUPPORT);
781} 781}
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index abe54cfb..2601ccd8 100644
--- a/plugins/check_snmp.c
+++ b/plugins/check_snmp.c
@@ -113,6 +113,7 @@ char *authproto = NULL;
113char *privproto = NULL; 113char *privproto = NULL;
114char *authpasswd = NULL; 114char *authpasswd = NULL;
115char *privpasswd = NULL; 115char *privpasswd = NULL;
116int nulloid = STATE_UNKNOWN;
116char **oids = NULL; 117char **oids = NULL;
117size_t oids_size = 0; 118size_t oids_size = 0;
118char *label; 119char *label;
@@ -375,7 +376,7 @@ main (int argc, char **argv)
375 } 376 }
376 } 377 }
377 378
378 for (line=0, i=0; line < chld_out.lines; line++, i++) { 379 for (line=0, i=0; line < chld_out.lines && i < numoids ; line++, i++) {
379 if(calculate_rate) 380 if(calculate_rate)
380 conv = "%.10g"; 381 conv = "%.10g";
381 else 382 else
@@ -472,8 +473,16 @@ main (int argc, char **argv)
472 print_thresholds(" thresholds", thlds[i]); 473 print_thresholds(" thresholds", thlds[i]);
473 } 474 }
474 ptr = strpbrk (show, "-0123456789"); 475 ptr = strpbrk (show, "-0123456789");
475 if (ptr == NULL) 476 if (ptr == NULL){
476 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show); 477 if (nulloid == 3)
478 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show);
479 else if (nulloid == 0)
480 die (STATE_OK,_("No valid data returned (%s)\n"), show);
481 else if (nulloid == 1)
482 die (STATE_WARNING,_("No valid data returned (%s)\n"), show);
483 else if (nulloid == 2)
484 die (STATE_CRITICAL,_("No valid data returned (%s)\n"), show);
485 }
477 while (i >= response_size) { 486 while (i >= response_size) {
478 response_size += OID_COUNT_STEP; 487 response_size += OID_COUNT_STEP;
479 response_value = realloc(response_value, response_size * sizeof(*response_value)); 488 response_value = realloc(response_value, response_size * sizeof(*response_value));
@@ -661,6 +670,7 @@ process_arguments (int argc, char **argv)
661 {"oid", required_argument, 0, 'o'}, 670 {"oid", required_argument, 0, 'o'},
662 {"object", required_argument, 0, 'o'}, 671 {"object", required_argument, 0, 'o'},
663 {"delimiter", required_argument, 0, 'd'}, 672 {"delimiter", required_argument, 0, 'd'},
673 {"nulloid", required_argument, 0, 'z'},
664 {"output-delimiter", required_argument, 0, 'D'}, 674 {"output-delimiter", required_argument, 0, 'D'},
665 {"string", required_argument, 0, 's'}, 675 {"string", required_argument, 0, 's'},
666 {"timeout", required_argument, 0, 't'}, 676 {"timeout", required_argument, 0, 't'},
@@ -705,7 +715,7 @@ process_arguments (int argc, char **argv)
705 } 715 }
706 716
707 while (1) { 717 while (1) {
708 c = getopt_long (argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:", 718 c = getopt_long (argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:z:",
709 longopts, &option); 719 longopts, &option);
710 720
711 if (c == -1 || c == EOF) 721 if (c == -1 || c == EOF)
@@ -816,6 +826,12 @@ process_arguments (int argc, char **argv)
816 eval_method[j+1] |= CRIT_PRESENT; 826 eval_method[j+1] |= CRIT_PRESENT;
817 } 827 }
818 break; 828 break;
829 case 'z': /* Null OID Return Check */
830 if (!is_integer (optarg))
831 usage2 (_("Exit status must be a positive integer"), optarg);
832 else
833 nulloid = atoi(optarg);
834 break;
819 case 's': /* string or substring */ 835 case 's': /* string or substring */
820 strncpy (string_value, optarg, sizeof (string_value) - 1); 836 strncpy (string_value, optarg, sizeof (string_value) - 1);
821 string_value[sizeof (string_value) - 1] = 0; 837 string_value[sizeof (string_value) - 1] = 0;
@@ -1181,6 +1197,14 @@ print_help (void)
1181 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER); 1197 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
1182 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered")); 1198 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
1183 printf (" %s\n", _("to be the data that should be used in the evaluation.")); 1199 printf (" %s\n", _("to be the data that should be used in the evaluation."));
1200 printf (" %s\n", "-z, --nulloid=#");
1201 printf (" %s\n", _("If the check returns a 0 length string or NULL value"));
1202 printf (" %s\n", _("This option allows you to choose what status you want it to exit"));
1203 printf (" %s\n", _("Excluding this option renders the default exit of 3(STATE_UNKNOWN)"));
1204 printf (" %s\n", _("0 = OK"));
1205 printf (" %s\n", _("1 = WARNING"));
1206 printf (" %s\n", _("2 = CRITICAL"));
1207 printf (" %s\n", _("3 = UNKNOWN"));
1184 1208
1185 /* Tests Against Integers */ 1209 /* Tests Against Integers */
1186 printf (" %s\n", "-w, --warning=THRESHOLD(s)"); 1210 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
diff --git a/plugins/check_swap.c b/plugins/check_swap.c
index bb854beb..ff58b15f 100644
--- a/plugins/check_swap.c
+++ b/plugins/check_swap.c
@@ -1,30 +1,30 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2*
3* Monitoring check_swap plugin 3* Monitoring check_swap plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net) 6* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
7* Copyright (c) 2000-2007 Monitoring Plugins Development Team 7* Copyright (c) 2000-2007 Monitoring Plugins Development Team
8* 8*
9* Description: 9* Description:
10* 10*
11* This file contains the check_swap plugin 11* This file contains the check_swap plugin
12* 12*
13* 13*
14* This program is free software: you can redistribute it and/or modify 14* This program is free software: you can redistribute it and/or modify
15* it under the terms of the GNU General Public License as published by 15* it under the terms of the GNU General Public License as published by
16* the Free Software Foundation, either version 3 of the License, or 16* the Free Software Foundation, either version 3 of the License, or
17* (at your option) any later version. 17* (at your option) any later version.
18* 18*
19* This program is distributed in the hope that it will be useful, 19* This program is distributed in the hope that it will be useful,
20* but WITHOUT ANY WARRANTY; without even the implied warranty of 20* but WITHOUT ANY WARRANTY; without even the implied warranty of
21* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22* GNU General Public License for more details. 22* GNU General Public License for more details.
23* 23*
24* You should have received a copy of the GNU General Public License 24* You should have received a copy of the GNU General Public License
25* along with this program. If not, see <http://www.gnu.org/licenses/>. 25* along with this program. If not, see <http://www.gnu.org/licenses/>.
26* 26*
27* 27*
28*****************************************************************************/ 28*****************************************************************************/
29 29
30const char *progname = "check_swap"; 30const char *progname = "check_swap";
@@ -150,7 +150,7 @@ main (int argc, char **argv)
150 * The following sscanf call looks for lines looking like: "SwapTotal: 123" and "SwapFree: 123" 150 * The following sscanf call looks for lines looking like: "SwapTotal: 123" and "SwapFree: 123"
151 * This format exists at least on Debian Linux with a 5.* kernel 151 * This format exists at least on Debian Linux with a 5.* kernel
152 */ 152 */
153 else if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%[TotalFreCchd]%*[:] %f %*[k]%*[B]", str, &tmp_KB)) { 153 else if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%[TotalFreCchd]%*[:] %lu %*[k]%*[B]", str, &tmp_KB)) {
154 if (verbose >= 3) { 154 if (verbose >= 3) {
155 printf("Got %s with %lu\n", str, tmp_KB); 155 printf("Got %s with %lu\n", str, tmp_KB);
156 } 156 }
@@ -389,7 +389,7 @@ main (int argc, char **argv)
389 TRUE, warn_print, 389 TRUE, warn_print,
390 TRUE, crit_print, 390 TRUE, crit_print,
391 TRUE, 0, 391 TRUE, 0,
392 TRUE, (long) total_swap_mb)); 392 TRUE, (long) total_swap_mb * 1024 * 1024));
393 393
394 return result; 394 return result;
395} 395}
diff --git a/plugins/picohttpparser/picohttpparser.c b/plugins/picohttpparser/picohttpparser.c
index 74ccc3ef..d9680b79 100644
--- a/plugins/picohttpparser/picohttpparser.c
+++ b/plugins/picohttpparser/picohttpparser.c
@@ -242,7 +242,7 @@ static const char *is_complete(const char *buf, const char *buf_end, size_t last
242 } while (0) 242 } while (0)
243 243
244/* returned pointer is always within [buf, buf_end), or null */ 244/* returned pointer is always within [buf, buf_end), or null */
245static const char *parse_http_version(const char *buf, const char *buf_end, int *minor_version, int *ret) 245static const char *parse_http_version(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *ret)
246{ 246{
247 /* we want at least [HTTP/1.<two chars>] to try to parse */ 247 /* we want at least [HTTP/1.<two chars>] to try to parse */
248 if (buf_end - buf < 9) { 248 if (buf_end - buf < 9) {
@@ -254,9 +254,13 @@ static const char *parse_http_version(const char *buf, const char *buf_end, int
254 EXPECT_CHAR_NO_CHECK('T'); 254 EXPECT_CHAR_NO_CHECK('T');
255 EXPECT_CHAR_NO_CHECK('P'); 255 EXPECT_CHAR_NO_CHECK('P');
256 EXPECT_CHAR_NO_CHECK('/'); 256 EXPECT_CHAR_NO_CHECK('/');
257 EXPECT_CHAR_NO_CHECK('1'); 257 PARSE_INT(major_version, 1);
258 EXPECT_CHAR_NO_CHECK('.'); 258 if (*major_version == 1) {
259 PARSE_INT(minor_version, 1); 259 EXPECT_CHAR_NO_CHECK('.');
260 PARSE_INT(minor_version, 1);
261 } else {
262 *minor_version = 0;
263 }
260 return buf; 264 return buf;
261} 265}
262 266
@@ -339,7 +343,7 @@ static const char *parse_headers(const char *buf, const char *buf_end, struct ph
339} 343}
340 344
341static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path, 345static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path,
342 size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers, 346 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers,
343 size_t max_headers, int *ret) 347 size_t max_headers, int *ret)
344{ 348{
345 /* skip first empty line (some clients add CRLF after POST content) */ 349 /* skip first empty line (some clients add CRLF after POST content) */
@@ -364,7 +368,7 @@ static const char *parse_request(const char *buf, const char *buf_end, const cha
364 *ret = -1; 368 *ret = -1;
365 return NULL; 369 return NULL;
366 } 370 }
367 if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) { 371 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) {
368 return NULL; 372 return NULL;
369 } 373 }
370 if (*buf == '\015') { 374 if (*buf == '\015') {
@@ -381,7 +385,7 @@ static const char *parse_request(const char *buf, const char *buf_end, const cha
381} 385}
382 386
383int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, 387int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path,
384 size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len) 388 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len)
385{ 389{
386 const char *buf = buf_start, *buf_end = buf_start + len; 390 const char *buf = buf_start, *buf_end = buf_start + len;
387 size_t max_headers = *num_headers; 391 size_t max_headers = *num_headers;
@@ -391,6 +395,7 @@ int phr_parse_request(const char *buf_start, size_t len, const char **method, si
391 *method_len = 0; 395 *method_len = 0;
392 *path = NULL; 396 *path = NULL;
393 *path_len = 0; 397 *path_len = 0;
398 *major_version = -1;
394 *minor_version = -1; 399 *minor_version = -1;
395 *num_headers = 0; 400 *num_headers = 0;
396 401
@@ -400,7 +405,7 @@ int phr_parse_request(const char *buf_start, size_t len, const char **method, si
400 return r; 405 return r;
401 } 406 }
402 407
403 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, minor_version, headers, num_headers, max_headers, 408 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, major_version, minor_version, headers, num_headers, max_headers,
404 &r)) == NULL) { 409 &r)) == NULL) {
405 return r; 410 return r;
406 } 411 }
@@ -408,11 +413,11 @@ int phr_parse_request(const char *buf_start, size_t len, const char **method, si
408 return (int)(buf - buf_start); 413 return (int)(buf - buf_start);
409} 414}
410 415
411static const char *parse_response(const char *buf, const char *buf_end, int *minor_version, int *status, const char **msg, 416static const char *parse_response(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *status, const char **msg,
412 size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret) 417 size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret)
413{ 418{
414 /* parse "HTTP/1.x" */ 419 /* parse "HTTP/1.x" */
415 if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) { 420 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) {
416 return NULL; 421 return NULL;
417 } 422 }
418 /* skip space */ 423 /* skip space */
@@ -451,13 +456,14 @@ static const char *parse_response(const char *buf, const char *buf_end, int *min
451 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret); 456 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
452} 457}
453 458
454int phr_parse_response(const char *buf_start, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len, 459int phr_parse_response(const char *buf_start, size_t len, int *major_version, int *minor_version, int *status, const char **msg, size_t *msg_len,
455 struct phr_header *headers, size_t *num_headers, size_t last_len) 460 struct phr_header *headers, size_t *num_headers, size_t last_len)
456{ 461{
457 const char *buf = buf_start, *buf_end = buf + len; 462 const char *buf = buf_start, *buf_end = buf + len;
458 size_t max_headers = *num_headers; 463 size_t max_headers = *num_headers;
459 int r; 464 int r;
460 465
466 *major_version = -1;
461 *minor_version = -1; 467 *minor_version = -1;
462 *status = 0; 468 *status = 0;
463 *msg = NULL; 469 *msg = NULL;
@@ -470,7 +476,7 @@ int phr_parse_response(const char *buf_start, size_t len, int *minor_version, in
470 return r; 476 return r;
471 } 477 }
472 478
473 if ((buf = parse_response(buf, buf_end, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == NULL) { 479 if ((buf = parse_response(buf, buf_end, major_version, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == NULL) {
474 return r; 480 return r;
475 } 481 }
476 482
diff --git a/plugins/picohttpparser/picohttpparser.h b/plugins/picohttpparser/picohttpparser.h
index 0849f844..8f13b36f 100644
--- a/plugins/picohttpparser/picohttpparser.h
+++ b/plugins/picohttpparser/picohttpparser.h
@@ -49,10 +49,10 @@ struct phr_header {
49/* returns number of bytes consumed if successful, -2 if request is partial, 49/* returns number of bytes consumed if successful, -2 if request is partial,
50 * -1 if failed */ 50 * -1 if failed */
51int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len, 51int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
52 int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len); 52 int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len);
53 53
54/* ditto */ 54/* ditto */
55int phr_parse_response(const char *_buf, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len, 55int phr_parse_response(const char *_buf, size_t len, int *major_version, int *minor_version, int *status, const char **msg, size_t *msg_len,
56 struct phr_header *headers, size_t *num_headers, size_t last_len); 56 struct phr_header *headers, size_t *num_headers, size_t last_len);
57 57
58/* ditto */ 58/* ditto */
diff --git a/plugins/sslutils.c b/plugins/sslutils.c
index 14f6579d..286273f6 100644
--- a/plugins/sslutils.c
+++ b/plugins/sslutils.c
@@ -134,7 +134,7 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
134 return STATE_CRITICAL; 134 return STATE_CRITICAL;
135 } 135 }
136 if (cert && privkey) { 136 if (cert && privkey) {
137 SSL_CTX_use_certificate_file(c, cert, SSL_FILETYPE_PEM); 137 SSL_CTX_use_certificate_chain_file(c, cert);
138 SSL_CTX_use_PrivateKey_file(c, privkey, SSL_FILETYPE_PEM); 138 SSL_CTX_use_PrivateKey_file(c, privkey, SSL_FILETYPE_PEM);
139#ifdef USE_OPENSSL 139#ifdef USE_OPENSSL
140 if (!SSL_CTX_check_private_key(c)) { 140 if (!SSL_CTX_check_private_key(c)) {
diff --git a/plugins/t/check_curl.t b/plugins/t/check_curl.t
index ada6a045..693f4b25 100644
--- a/plugins/t/check_curl.t
+++ b/plugins/t/check_curl.t
@@ -9,7 +9,7 @@ use Test::More;
9use POSIX qw/mktime strftime/; 9use POSIX qw/mktime strftime/;
10use NPTest; 10use NPTest;
11 11
12plan tests => 58; 12plan tests => 57;
13 13
14my $successOutput = '/OK.*HTTP.*second/'; 14my $successOutput = '/OK.*HTTP.*second/';
15 15
@@ -188,11 +188,6 @@ SKIP: {
188 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' ); 188 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
189 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' ); 189 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
190 190
191 $res = NPTest->testCmd(
192 "./$plugin --ssl -H www.e-paycobalt.com"
193 );
194 cmp_ok( $res->return_code, "==", 0, "Can read https for www.e-paycobalt.com (uses AES certificate)" );
195
196 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f curl" ); 191 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f curl" );
197 is( $res->return_code, 0, "Redirection based on location is okay"); 192 is( $res->return_code, 0, "Redirection based on location is okay");
198 193
diff --git a/plugins/t/check_http.t b/plugins/t/check_http.t
index c137f7b4..0c866229 100644
--- a/plugins/t/check_http.t
+++ b/plugins/t/check_http.t
@@ -9,7 +9,7 @@ use Test::More;
9use POSIX qw/mktime strftime/; 9use POSIX qw/mktime strftime/;
10use NPTest; 10use NPTest;
11 11
12plan tests => 50; 12plan tests => 49;
13 13
14my $successOutput = '/OK.*HTTP.*second/'; 14my $successOutput = '/OK.*HTTP.*second/';
15 15
@@ -166,12 +166,6 @@ SKIP: {
166 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' ); 166 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
167 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' ); 167 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
168 168
169 $res = NPTest->testCmd(
170 "./$plugin --ssl -H www.e-paycobalt.com"
171 );
172 cmp_ok( $res->return_code, "==", 0, "Can read https for www.e-paycobalt.com (uses AES certificate)" );
173
174
175 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f follow" ); 169 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f follow" );
176 is( $res->return_code, 0, "Redirection based on location is okay"); 170 is( $res->return_code, 0, "Redirection based on location is okay");
177 171
diff --git a/plugins/tests/certs/.gitignore b/plugins/tests/certs/.gitignore
new file mode 100644
index 00000000..79acaaa5
--- /dev/null
+++ b/plugins/tests/certs/.gitignore
@@ -0,0 +1,2 @@
1/*.csr
2/*.srl
diff --git a/plugins/tests/certs/client-cert.pem b/plugins/tests/certs/client-cert.pem
new file mode 100644
index 00000000..5709750d
--- /dev/null
+++ b/plugins/tests/certs/client-cert.pem
@@ -0,0 +1,22 @@
1-----BEGIN CERTIFICATE-----
2MIIDtDCCApwCAQIwDQYJKoZIhvcNAQELBQAwgaAxCzAJBgNVBAYTAkRFMRAwDgYD
3VQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0b3Jp
4bmcgUGx1Z2luczEkMCIGA1UEAwwbTW9uaXRvcmluZyBQbHVnaW5zIENsaWVudENB
5MSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdpbnMub3JnMB4X
6DTIxMDIyODIxMDIxMloXDTMwMTEyODIxMDIxMlowgZ4xCzAJBgNVBAYTAkRFMRAw
7DgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0
8b3JpbmcgUGx1Z2luczEiMCAGA1UEAwwZTW9uaXRvcmluZyBQbHVnaW5zIENsaWVu
9dDErMCkGCSqGSIb3DQEJARYcZGV2ZWxAbW9uaXRvcmluZy1wbHVnaW5zLm9yZzCC
10ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM3EiqfFPomm5dZQPGYG5SrF
11rPvyqseXTzCkwUIUzGf+Sfm3s13zx7e3ije/04yKhTXgK59EQ793q7E2aWhSOz3s
12hwKKdylFkOIyc5jgbAfF1/pLZMK209rLt/mMRksXCRXYrHdTjRMx1ev4C2407+8Y
138qkf77DuYQmUqCQe7DPOvqLeagdw9JcLGmQNTKHg3fl6wyRl5K1Bsy+qXu2XvEjZ
140Ng7n8LHjOUkTqUEJndOxci9gL5cHU5ttul/GW34dKOtTuMU/pQX6/ywYusOGVOx
15RYI76OolRqj5BqbNctDIB/obe2RLo+UVx74/0jAxtH4XS23pYjO7NUpJcytsVG8C
16AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAYfaY5n4pCq0NWPCdeVVRr4nr+GAfv1TC
17/PKcGuEoJZKt7TQT+OOA5yeZMZb53OvtA49D1r9aoJzWe946KElWOEBqxDRi5Cdr
18wkqpwGcPT2RfAqA3/cvQZ1XsquboXrCf7ajdl5OC64bs2jkqCFh9gnxuI140g8Ar
19Njol8BFxRPaYWOnwuQwmh/2t0FJqr3WSD85HrNqtxUSNGbTdSsvCfgF0v7QVkvLG
203/cbx6z5hxzj2JUjhMnCvn+EbasoJt4xyBFvg67Q2229SMwu9YNqS63GVoKUqhCB
214Gl5v31qx8dAFKuRvnez3ze/6oohwmakZkst4hcQdgZocHhzesvKlg==
22-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/client-key.pem b/plugins/tests/certs/client-key.pem
new file mode 100644
index 00000000..09b6761d
--- /dev/null
+++ b/plugins/tests/certs/client-key.pem
@@ -0,0 +1,28 @@
1-----BEGIN PRIVATE KEY-----
2MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNxIqnxT6JpuXW
3UDxmBuUqxaz78qrHl08wpMFCFMxn/kn5t7Nd88e3t4o3v9OMioU14CufREO/d6ux
4NmloUjs97IcCincpRZDiMnOY4GwHxdf6S2TCttPay7f5jEZLFwkV2Kx3U40TMdXr
5+AtuNO/vGPKpH++w7mEJlKgkHuwzzr6i3moHcPSXCxpkDUyh4N35esMkZeStQbMv
6ql7tl7xI2dDYO5/Cx4zlJE6lBCZ3TsXIvYC+XB1Obbbpfxlt+HSjrU7jFP6UF+v8
7sGLrDhlTsUWCO+jqJUao+QamzXLQyAf6G3tkS6PlFce+P9IwMbR+F0tt6WIzuzVK
8SXMrbFRvAgMBAAECggEBALtc2pB3p0E6KpAiEU0pvCRdSO1FgsIpAd+eNadRPur2
9fi+XWQkUwGeGBaJL1npja3aqP65PP40pj7nWfNaUAgOZyznCEU0QXiPJor6yo0vU
10l5v+aKpwRao107i0RRF80TYGTMx+1LeEqnCqNOZN56gERHlBbkTiWpOZvBzf1143
11oegTcyM6+Ee6+FYNhHaDyIYD0md1S2wGR+IBPet6HwWiakLNKahFPa7lOLIKfmmD
12iTtifcbf4724wSe44a0uTeP4JrquZSeIKakm8MEmffmYqpycnaakYefd0Xc5UEsH
13+VbhKpOWGY3d8FKHqUsTa+6QyXb2uFPo6A+yWm0pdJECgYEA7Prd5sbWACvXOcHT
14ONDBAgyfAVDQwOXi3D4dk6D5mg+/jxl5ZQY5slszJrwsLFtoEzXtYpNfTy3cpNOp
15JLbBDZYnqty+5tD8t3/Zv2IBXCAgvuk5CgfJWP5FNAfiyUEE6Vbp6J/5/vAnODsa
16fxZryN5UsH0X8ew7AlbfcVNyj4kCgYEA3khetIgn+GR6sv9jFRdCT6aJbp0xMsms
176F4v3L5FG4Kp+SwDHL1bVOhieJ5g8odYp9hDbgTEEqbJfNmyCOu9+OQmZ/mztku7
186reU8HhYBIvi+hFeJmvqKpdIgU0Zveg4Bst5QordmhPk8AHjBC4xvQ++uh7rwYKd
19WVsS08bGDjcCgYEAlAuNARUKsASzakOqHv5a9VrJIttH7povBYRQmd+gzxwzgcRa
20UEB5XvEWnYZE2lkoRYgVCtYiXqa6BsasDmGVbVV25okNQckhd8mJUMR7MQBpNJsi
21pR+EK/J9bSnYBf52gQdpDYiTdy60ca6KuQZaw5wRsEgV426+1pFK+dM16HECgYBY
22cTsdYb9lmbUoW201CxgbUQwFsw3MQ2pE2pT4o8wjcg3nUpe6a61XT08+5uV0Gl4w
23CmBp+gN52Fr7DjNEUWg5C64sWLIkqmWOspTUSU3cITyiex6W8wEtCRyUNfU0Fp2U
24Nol87HvXvmqtBFMraqXnr8gXjg4H5MxurUoEcWaEaQKBgCT4iIGZwW0Qf2rkFC7B
25xObzVGefivVVbaf8/c/LRO8TMLdnExkShMOmCzHeHV4mMEZDLbMOusHCI7xm10EX
26l3L1I1Kyqnhm1RH3e7TVWgkTmIDW3V5Fgrhm1jx5Iz6et4sb4Uh+bZq9tTLyqfZY
278s0yJUrfpjRggfk7eUs5s7aY
28-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/clientca-cert.pem b/plugins/tests/certs/clientca-cert.pem
new file mode 100644
index 00000000..9ce7cd7d
--- /dev/null
+++ b/plugins/tests/certs/clientca-cert.pem
@@ -0,0 +1,25 @@
1-----BEGIN CERTIFICATE-----
2MIIEIzCCAwugAwIBAgIUL9Jfp5zv5B29NgDsNEFU2OM/UHswDQYJKoZIhvcNAQEL
3BQAwgaAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN
4dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEkMCIGA1UEAwwbTW9u
5aXRvcmluZyBQbHVnaW5zIENsaWVudENBMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBt
6b25pdG9yaW5nLXBsdWdpbnMub3JnMB4XDTIxMDIyODIxMDIxMVoXDTMwMTEyODIx
7MDIxMVowgaAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQH
8DAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEkMCIGA1UEAwwb
9TW9uaXRvcmluZyBQbHVnaW5zIENsaWVudENBMSswKQYJKoZIhvcNAQkBFhxkZXZl
10bEBtb25pdG9yaW5nLXBsdWdpbnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
11MIIBCgKCAQEAyxiWsGrsJFHw3VR0pqHviXUfbfKMw8LaCxI5EQZfInsMVkBIGWEW
12tFW6qDuAOsMdzsrKOnQRNNt852ts/0Uz++z8zysoauAGpc4JnCZuM5A1DU5CFXBx
13w6Ax+1ft3UsTt8C6kfLfs8mPCbtNVqAHrMrIqDxsNSRRxQSqkzp1vD8rwSKcbB1h
14u2+lut1bEqMe7dp89jKOtc6G/1tHUFQuLAGFoX/qk9yPscmQNzL6YbLP4m9r/416
15PsxWsAfyY97hmoYo6mSCue5LmeanOsjf4Kzq90hIJRwrpiUGmxGjW+tPLEhQBZw6
16C2wHyN74YIJYX2xREz2ijT0mgsqdhO5ZxwIDAQABo1MwUTAdBgNVHQ4EFgQUtsP9
17Z3fKkhmFp97Kh/cW/UqHMIMwHwYDVR0jBBgwFoAUtsP9Z3fKkhmFp97Kh/cW/UqH
18MIMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEApO5o+YECwTEv
19s+elDJZQ20UYwDSiU9Lpf4EcdnRv6FAb5UlhfRTH3ZdKCc/HX7kcKuy3PsF+b8Pw
20EusoKito9OlNEOF5HYAI9/J54/qceqn+SC0INsISeE19PvT0dma7lBSj4OvBv0IS
21GYbdztVaKLWqYgYs0mcEzteUc4MZcy1/C+Ru1i1Kp2s9/vIeAw2PV2+kpWtw88Pb
22FRJomGngP/hQdwniayCltG/Q1smS4iFEHNI5ayLZj1qJGMHwzqGiRr4KknJKfHzv
23fl4NQaFyMY31s1FRIS6QVIRFHVzUAlKZTdzwqEJygg3fUS9n9uDBnyDI/sW7DQuj
24yjSmYRS1hw==
25-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/clientca-key.pem b/plugins/tests/certs/clientca-key.pem
new file mode 100644
index 00000000..a939f035
--- /dev/null
+++ b/plugins/tests/certs/clientca-key.pem
@@ -0,0 +1,28 @@
1-----BEGIN PRIVATE KEY-----
2MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLGJawauwkUfDd
3VHSmoe+JdR9t8ozDwtoLEjkRBl8iewxWQEgZYRa0VbqoO4A6wx3Oyso6dBE023zn
4a2z/RTP77PzPKyhq4AalzgmcJm4zkDUNTkIVcHHDoDH7V+3dSxO3wLqR8t+zyY8J
5u01WoAesysioPGw1JFHFBKqTOnW8PyvBIpxsHWG7b6W63VsSox7t2nz2Mo61zob/
6W0dQVC4sAYWhf+qT3I+xyZA3Mvphss/ib2v/jXo+zFawB/Jj3uGahijqZIK57kuZ
75qc6yN/grOr3SEglHCumJQabEaNb608sSFAFnDoLbAfI3vhgglhfbFETPaKNPSaC
8yp2E7lnHAgMBAAECggEAJqAWiJbNMlsjI/Tb+pTxqYLM52wpuVFlhpWApOxBS517
9SywOikUcvE9RoI0wZfyVvq5yp4tLenID3z9fC21t5Yu8yOm8VhclLINy8G+epc/X
10RyCLEOjBuiLNXq/qXRvaNChDU16NjPPYcFFe9AqbaxFl+BkFu1Wc94tbpYSIv7Qt
11L6iBxUTXdgvLM5doa9AazIQzJx+jUsVCgRVQQf3zsLqtp9hH0Pfq+KWFIy5TA+bG
120NFmYyQndRjtT0ihWGuNU7D8AXa+z7abzk+HydIlx4D//vGgdNq92QYPdnu2BBya
135Fs6LkmkUonX/I8FbkLbRKkQWNPMt+Ks21t3xcVBgQKBgQDn4HuHVCPwxgU6Mv+5
140sHJXYBq1fDzrUt0+iTtYkRqViX+9Mp4sUpYgXext/wXFLcKzQQp5B0g1dLYLSRS
15KwhsdiN0J7ZcoP1GMStw8zsayRTf8C3WRU6aACqyFiylYbyh56XomfYgwhja/7l9
16pzpVJD9ecG+mLVAyAkJtK2JolQKBgQDgOZfvrQj0L4QG+9E5VmFc3PE+6k3g+zDO
17MWqTSh0fOHqdTEyet4bMC4DogXGVsvw0/UKwbrGHOk0+ltA5VyKUtK/whSutr/+S
18nhCHljhV0XUN/I3OFcvezFjM3g0oC4uy1cL30hoM4IfeHM1d3EYse9N1Y/Op+mR6
19Sx+fEku16wKBgQC0KQ7RjuZ95N2a4pUe5En9EtD8MU4Nhs/iC5k1d+yAUn8jIT9P
20lzCUo8NEKheMN2Qg2Dor8jlPkdNIc4qM7TKWUxQo49IlFlCzgPCnydRac3HsrMhw
21e1ke/pIt3FzEArR1d27I0xcRTL3TKm4M2ynPjWJPFj0peHue33KNL/A+IQKBgEpL
22awd0Sxo1wEZcG9gmwf32C01wbzuTn3lCsHB7Ryj4GtCR3nVclCJ50U24zjzu4Fhi
23bj1tgA8xhzSs3fOR5phlQkKsrWtQfJtFGm8CnEn7LBDlVMsrN7Dr/qRrEuro4HHy
24GDbq+8y2fO5glr955BqLMOadprf0imRnDeQ0OLffAoGBAJio+X+xpglgMOC4BeH9
259LcYi9nUEw8MDJNGo9/3e0XKA7spd3HShLDvt8YZhFJ2m168qBpGfezuw0+jpWxy
26PV9q0dokAgDx4pvCzIKaptZ1D30CWXJZHq25VK1tA41PCUIOh8JD5+R0MpxA5rn2
27DbqL4Vq7K7K0imGENYhHdyM+
28-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/clientchain-cert.pem b/plugins/tests/certs/clientchain-cert.pem
new file mode 100644
index 00000000..acd1e3e8
--- /dev/null
+++ b/plugins/tests/certs/clientchain-cert.pem
@@ -0,0 +1,45 @@
1-----BEGIN CERTIFICATE-----
2MIIDuTCCAqECAQQwDQYJKoZIhvcNAQELBQAwgaAxCzAJBgNVBAYTAkRFMRAwDgYD
3VQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0b3Jp
4bmcgUGx1Z2luczEkMCIGA1UEAwwbTW9uaXRvcmluZyBQbHVnaW5zIENsaWVudENB
5MSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdpbnMub3JnMB4X
6DTIxMDIyODIxMDIxMloXDTMwMTEyODIxMDIxMlowgaMxCzAJBgNVBAYTAkRFMRAw
7DgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0
8b3JpbmcgUGx1Z2luczEnMCUGA1UEAwweTW9uaXRvcmluZyBQbHVnaW5zIENsaWVu
9dENoYWluMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdpbnMu
10b3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAphvoJBbi/rDvm3+X
118xok0sLCJvCRuUpSbU5wEmREQlkoOGmWK4l6r1JyOphKRBo8+n2MxPiCMvAmTrqx
12VlBmkcmyrwWj392Nga+2SLWTziASk5nFrrhV6U79PkgXnETV2Wk1/FNVIFkB8N+B
13undsTce8LLiCs7hfA5CK7ctJg8fqsAsmgKBNGzBRWwkbvxZPd6xlY6foIJeD7PQ2
14elvTmrD6WXSZq7GshFpDEkL3AifqrPMdsTnbBpyGgJ/fBM1b2dx9k53e25mgEQmn
15iSuYQxn08BsUT0FOvav8ksZLBQz859fuqCtwhikpODO635fD9zK5YkBPlVl+/5xo
16SvKOywIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBh4zeSKjENfY+VDLtPssaNQz2a
17R1ioY40lZ0WoihDSrfG32dqTK/R2YsLKBABjJ7uRYS1NIBMrtS2OktK8BWD5IUTF
18FuGuWilu6IWiTKZrLiZh1rsilNDVqwhorRPxDnbF+qVt9EMIvzKnKdJLGF+CWHN9
19yYJDeTD8MK5uR7zUJR3PsgW4ve5pFTi7z2UJ/xRvgOds6bmeeQnvaWDEL7k2+hrr
200G899A086NL3htzaOnIllg0xo2D1o4ToncAJn+cUQVJmHZSg9HYiD4Lg3z8uXPAl
21rt/MX7dBm4dnImLXbSg7N3e8FdUtz+kZT9z+beKAeIe9JTbpxtsVUTzUZBBA
22-----END CERTIFICATE-----
23-----BEGIN CERTIFICATE-----
24MIID2jCCAsKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBoDELMAkGA1UEBhMCREUx
25EDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwSTW9u
26aXRvcmluZyBQbHVnaW5zMSQwIgYDVQQDDBtNb25pdG9yaW5nIFBsdWdpbnMgQ2xp
27ZW50Q0ExKzApBgkqhkiG9w0BCQEWHGRldmVsQG1vbml0b3JpbmctcGx1Z2lucy5v
28cmcwHhcNMjEwMjI4MjEwMjEyWhcNMzAxMTI4MjEwMjEyWjCBqjELMAkGA1UEBhMC
29REUxEDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwS
30TW9uaXRvcmluZyBQbHVnaW5zMS4wLAYDVQQDDCVNb25pdG9yaW5nIFBsdWdpbnMg
31Q2xpZW50SW50ZXJtZWRpYXRlMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9y
32aW5nLXBsdWdpbnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
336rUgOZ9pAOxrcgeeOT3Vmu1YmY2O/C9tXhpKzDzjTaWUzcdDg00KdsjXfgbDzSiV
34uvMzjX63aKpmqeFG+05D2VzQGit3knqerUgl10FnTotiJGF5CU5/gY1aPxTJ7rj2
35tD6LINBkJcPTyQ4MoJT19pssvCax9erY1RxoXxLblJ+31C+VvrftdmBP4nVKXK26
364anb1oUQhkgpXpJimJBmF+v7NbDs1Wh21Be80KXUh9SKgePhSQblr2QlRcA7jLgJ
374PMjZ+KYF+da+4RB7s+DvTXVDMn9AL84E1w5Ut1E8XZV+u4RjWPvNdhK/7GnuxOR
38C9SdxonqkPQ8hiI7thP9bQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
39SIb3DQEBCwUAA4IBAQDKQeiDbyr0/7sEhX33MmTDv84GeWgKl9qqHecx+d/0vImb
40c8XHK0PDa4lVqo/BW4P1hjKzpt2DW35kbOhuqGqM0lasIczef43aCDDEBLwstAe6
41qMoyWGVGoAQbpwT3li2pMrsIYoPwMvoSGNUphjrkdpviff2POkLly7a5RrR1X3qt
42Dai6eYbeMCr9NdgW7AZ5++/sKlFoe+zVk/Ed31s4D2lh3awrApZhVgcoquPmEwpt
43gm+OgRmHw50U4SF3ZaJPwDyLMbx+clH/bgUg0+Za9e53Br1NtGKmw7hh/7CG/hy0
44yxeLd930pH4vZu7s0XM56N/ckkfUzRkAH8dSmhH4
45-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/clientchain-key.pem b/plugins/tests/certs/clientchain-key.pem
new file mode 100644
index 00000000..0263604f
--- /dev/null
+++ b/plugins/tests/certs/clientchain-key.pem
@@ -0,0 +1,28 @@
1-----BEGIN PRIVATE KEY-----
2MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmG+gkFuL+sO+b
3f5fzGiTSwsIm8JG5SlJtTnASZERCWSg4aZYriXqvUnI6mEpEGjz6fYzE+IIy8CZO
4urFWUGaRybKvBaPf3Y2Br7ZItZPOIBKTmcWuuFXpTv0+SBecRNXZaTX8U1UgWQHw
534G6d2xNx7wsuIKzuF8DkIrty0mDx+qwCyaAoE0bMFFbCRu/Fk93rGVjp+ggl4Ps
69DZ6W9OasPpZdJmrsayEWkMSQvcCJ+qs8x2xOdsGnIaAn98EzVvZ3H2Tnd7bmaAR
7CaeJK5hDGfTwGxRPQU69q/ySxksFDPzn1+6oK3CGKSk4M7rfl8P3MrliQE+VWX7/
8nGhK8o7LAgMBAAECggEAAfTqMyKh4eYrrGVAYPi53lG0/8htrwUVG3yFDXJo628p
9biCwSCsCavZJqi8JEOxOM5UvB1L2FauGh/7i/+VKkAUUOcOTPpvZguGTACBDcXYn
10Qd3Z2kkJmgn4Kbenr4uQCVOX8zT4F710rGW1nYCyoefsa4pw37UYSW52dH6kiwzW
119k4X251nDMl/twBdOcjZbL768IEa5l4nySLpUNwfrVbSb1NzBoH0dVioh3DTLjt6
12gaShW4eIpaKczht1U97n6/7WNLl6vHX/mR99k/py8OhzhR1ccYpd2IfSHAWyQT0M
13K8BoNnkjICrr9oc0FCr2BVJa3IzKHlhukF4GTZiGYQKBgQDWCHTwAmwL4FFEBVhj
14pZne/sjaZc8TzPPxA8SkmxwDIZrM7tSu7qUuYgWTM432jZbLILWTyGfXf2PpqyF6
15wOpoBJj1ETkre8ZfRmYvsSvS5vtjF3Drszol+XvZnOclfB5VG3m5P2vYkQ8wI9OE
16Y5jUBgDj0RsCNd8QnrC1u54U/wKBgQDGrd5y8S9kUT0P0lkZit7bYjSPJExtClXt
17V7YNTjELrVCdc0jranxBWaub8NP3e6TGTi9HiQWvk2eOAS2qyccqlK4+YAK5XO3D
18EpFUNNcClq8CErw2POuCAKajrPuSp6vd6q8h4lTzDExVctQS4R9fRKKFBKkPUV5G
19UiKFllnKNQKBgQDBGIQXfLfpxwjKK2BhFihKDOc8UhmOrZtvV4zzTJTrJkg4l0f+
20QoN34ytQcHSleXwP6oSmvWkh/GYxjBj6XE2eZndwsYc4ecSwdB0A7gCxl345Gg7g
21NqRBWmGoJGxNXzsmYVFiFZvAmK5xKgFMMWbR8lCfOCn7xopmviSC8K9gFQKBgFRb
22KmH/SbH8VELNews/TVQ0pEBKlzCM/OLjJOcNVgGxOtM/Say677sHibeST0168AFK
233QQwh3t+yK8gjPVA6xGHQ1w0g7OUY1c6IP5x2QC+XdwxfDxDLXNrN1WzcrVX/78f
24j/CBGrR/ekGlmanSb/GRQLfdvLJGSBLveLzjk4gpAoGBANN9RUm/aRz3dDBWex46
25kJ15xKJfLZiUeyDvY5+5d7YF4/tw5LU4XmKQNhiojHecykrTzPUMaGyMrbMPNn32
26WFW9CKMjuBEwWpMDJJb1/5NLEvpwu++sr7bUPZkQl76ot6OqgNHodbP8ATqrNr80
275b8FrEN1LyfkTbabxNyAWcA0
28-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/clientintermediate-cert.pem b/plugins/tests/certs/clientintermediate-cert.pem
new file mode 100644
index 00000000..608a8fa2
--- /dev/null
+++ b/plugins/tests/certs/clientintermediate-cert.pem
@@ -0,0 +1,23 @@
1-----BEGIN CERTIFICATE-----
2MIID2jCCAsKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBoDELMAkGA1UEBhMCREUx
3EDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwSTW9u
4aXRvcmluZyBQbHVnaW5zMSQwIgYDVQQDDBtNb25pdG9yaW5nIFBsdWdpbnMgQ2xp
5ZW50Q0ExKzApBgkqhkiG9w0BCQEWHGRldmVsQG1vbml0b3JpbmctcGx1Z2lucy5v
6cmcwHhcNMjEwMjI4MjEwMjEyWhcNMzAxMTI4MjEwMjEyWjCBqjELMAkGA1UEBhMC
7REUxEDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwS
8TW9uaXRvcmluZyBQbHVnaW5zMS4wLAYDVQQDDCVNb25pdG9yaW5nIFBsdWdpbnMg
9Q2xpZW50SW50ZXJtZWRpYXRlMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9y
10aW5nLXBsdWdpbnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
116rUgOZ9pAOxrcgeeOT3Vmu1YmY2O/C9tXhpKzDzjTaWUzcdDg00KdsjXfgbDzSiV
12uvMzjX63aKpmqeFG+05D2VzQGit3knqerUgl10FnTotiJGF5CU5/gY1aPxTJ7rj2
13tD6LINBkJcPTyQ4MoJT19pssvCax9erY1RxoXxLblJ+31C+VvrftdmBP4nVKXK26
144anb1oUQhkgpXpJimJBmF+v7NbDs1Wh21Be80KXUh9SKgePhSQblr2QlRcA7jLgJ
154PMjZ+KYF+da+4RB7s+DvTXVDMn9AL84E1w5Ut1E8XZV+u4RjWPvNdhK/7GnuxOR
16C9SdxonqkPQ8hiI7thP9bQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
17SIb3DQEBCwUAA4IBAQDKQeiDbyr0/7sEhX33MmTDv84GeWgKl9qqHecx+d/0vImb
18c8XHK0PDa4lVqo/BW4P1hjKzpt2DW35kbOhuqGqM0lasIczef43aCDDEBLwstAe6
19qMoyWGVGoAQbpwT3li2pMrsIYoPwMvoSGNUphjrkdpviff2POkLly7a5RrR1X3qt
20Dai6eYbeMCr9NdgW7AZ5++/sKlFoe+zVk/Ed31s4D2lh3awrApZhVgcoquPmEwpt
21gm+OgRmHw50U4SF3ZaJPwDyLMbx+clH/bgUg0+Za9e53Br1NtGKmw7hh/7CG/hy0
22yxeLd930pH4vZu7s0XM56N/ckkfUzRkAH8dSmhH4
23-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/clientintermediate-key.pem b/plugins/tests/certs/clientintermediate-key.pem
new file mode 100644
index 00000000..13f68874
--- /dev/null
+++ b/plugins/tests/certs/clientintermediate-key.pem
@@ -0,0 +1,28 @@
1-----BEGIN PRIVATE KEY-----
2MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDqtSA5n2kA7Gty
3B545PdWa7ViZjY78L21eGkrMPONNpZTNx0ODTQp2yNd+BsPNKJW68zONfrdoqmap
44Ub7TkPZXNAaK3eSep6tSCXXQWdOi2IkYXkJTn+BjVo/FMnuuPa0Posg0GQlw9PJ
5DgyglPX2myy8JrH16tjVHGhfEtuUn7fUL5W+t+12YE/idUpcrbrhqdvWhRCGSCle
6kmKYkGYX6/s1sOzVaHbUF7zQpdSH1IqB4+FJBuWvZCVFwDuMuAng8yNn4pgX51r7
7hEHuz4O9NdUMyf0AvzgTXDlS3UTxdlX67hGNY+812Er/sae7E5EL1J3GieqQ9DyG
8Iju2E/1tAgMBAAECggEACyYJXtNUoIeaXvM/r8ZhJBfMEpcnyJDUKBklnmfyABky
9ZUfmzBDXw2as3b6ihFc+LYAp3bm8KouVjtI1lfBUxrli5StVZa7PZLm9mmjv6Eo0
10ojfDEQ8afWPieoaZRO6iQVOLNkbPyv9vSuiQ7vvEZy9dw54u69h47j6IMqPprDiG
11ropUNeGAvTnh1Vf9/8aCHEvHUNHcc4zjzGiQ+E60JgnbpGVeJKoeiMgrQE0yjweo
12KyKA47Y6vqP6+AxAaPplXtmrx2UCbMjktHNvLvg42+2UlLS5roiwmJYEN9c6iT6t
13y82MJrjEFGZyLG2u6ZQANSJiIWaCnOyT1o2deJ8NoQKBgQD7UxivDTuljQD0so+E
14JX9UaFZ9PgS+8LC9v56PciL4XQ7bcCVP5vVgZZPABiQ9i989Wq7qI042Jrfu5qtE
15SthlOAu80GvAQV+Oujwo7ZzM6ciQtjMsj63r2uayWXnmQ07QcIg7x7y161Pt9Bqr
16LIDrqHziIj/lzT7+6QKZaQwFaQKBgQDvEuSC14CBlMhy2jji71kB/3Ya3c+8dP+A
17kQZL9wEWK4a4dm8IaTS8jl1/luhQUzFRMyh2rWaTqqigSe3dvs5DRblhE5NPwTSI
189TO7t1EnzjW3R8LxZZsySyiSFnZ/8mR0empxq0Mov37OdXBj0tXuuzREf/hwijWh
19WuLxJUSjZQKBgAIDZ2Y3l+u6lnBfYdDwL/XwJAk6zvTsnq3WdCG4C1mr/St62YGr
20WvnbtnRKWE356d7m9BHCGKVMaBrM1EBmzRb6fPWVQde3blmJWmQFi0UE9mtaWkyY
21Fg+WoFR7bQOQNHhs/lpkPjnC2dhFJVWLtLiuj9mL5rEjlMab/T5XXhZJAoGBAMEP
22FZ8fXbPGrTQqSwPfWpZFcF9zvbynEmkFM/uGRMddcNZnNXSqWJ7nrFNLTuEGvW2g
23DU4A6zPV/YQrDz4hRjmHBZOCFlSyZbUvpY4yFAQ7/p66AY+kiHZNwT5vi1P5Luvs
24qyaNsZcnRMR+i7rg2EeHv0aNvNdMlNBvL5KikNINAoGAU2P/phdwJOUcqgHavQcQ
25ureTEyZ5i5AeNomNeHSj0slG24V9nxOqEL7D00JKln7oAPovYBUWocEnF39uBJe0
26p0Hy7fCCK6EI8/0QyiQuuZmJfDEEvjQqE6irONNH63r2UwDEpDNGFvGsZNuWHLZc
27SXADu5oSNu6o6IydiyOx528=
28-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/expired-cert.pem b/plugins/tests/certs/expired-cert.pem
index 77a9166e..87fc8e47 100644
--- a/plugins/tests/certs/expired-cert.pem
+++ b/plugins/tests/certs/expired-cert.pem
@@ -1,24 +1,24 @@
1-----BEGIN CERTIFICATE----- 1-----BEGIN CERTIFICATE-----
2MIIEETCCAvmgAwIBAgIUFDsP6WnV/uqeQMpD/DYSqouE13kwDQYJKoZIhvcNAQEL 2MIIEETCCAvmgAwIBAgIUVDKkhcUoYFnjYCw12tScPIqQzqIwDQYJKoZIhvcNAQEL
3BQAwgZcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN 3BQAwgZcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN
4dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9u 4dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9u
5aXRvcmluZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5n 5aXRvcmluZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5n
6LXBsdWdpbnMub3JnMB4XDTA4MDEwMTExMDAyNloXDTA4MDEwMjExMDAyNlowgZcx 6LXBsdWdpbnMub3JnMB4XDTA4MDEwMTEyMDAwMFoXDTA4MDEwMjEyMDAwMFowgZcx
7CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gx 7CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gx
8GzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9uaXRvcmlu 8GzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9uaXRvcmlu
9ZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdp 9ZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdp
10bnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyeHKwKFjJWUX 10bnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwg1dmGT3rVqM
11YHKsisypUf9dHlIPQAISyGP1BX6UL26ZLvE6kKbx3LFQ9W2POGoQWlzFiB1soGeV 11beVWWLy8EAiq9re07AF8sTERy9oIYF5EUq9f0xO53mwwqIWV77O9mF99/kDFGQuQ
12WDd0U0JtWdCKmOXWdcXpupQlTSUtRCMDQkfqLN8GR5TBTd73rezp5mz08nMfLwu0 12NOnICMSHXNtMXEXzfBaMighw0uyCh1o/VCejNQ5x/HU8aLh930g5DIcOJQ3fZ4v9
13p5VQ191Ui8JHFgrAOalAn8Uw5De8vj4VmTXmU5NJ2UFoC0ddU/Th/lwRCayHc1cn 138kBaie7+aPgRMVDM1vIrILfedq9Kt56zvPizkXhDeqxjKyIZdrdoBlX5zAfftWtY
14MVq2F7c/uhMUUQYNBmJy0pxoHawp+j9NKl/xIYsjgQNgahQyNuswuGHjaEwhPu+7 14HpQ+lkThSSXqQnchN6S2JFejmRtsNnceDVOBBdvlzmH0NlfwjynLK3/EJooTsINy
15G03XsW4ehu+H1898M/MkSln6LQAU1syoJ8ypPM8tV+zgx4uwj7udnZ2hceN95uW7 15i9dXD8/Oe8r+UA+nokWvnWC2IAUJjpxW+XAyTG/NofGwX+PwquT0YD5cSlODIwZA
160PWg5DQyUwIDAQABo1MwUTAdBgNVHQ4EFgQUt9ps3KJ1XiMuy/ijFBjMzf6jgwkw 16WAimygWLqQIDAQABo1MwUTAdBgNVHQ4EFgQUsKyJAwR9OXWEcSZMQz73GfpxCJIw
17HwYDVR0jBBgwFoAUt9ps3KJ1XiMuy/ijFBjMzf6jgwkwDwYDVR0TAQH/BAUwAwEB 17HwYDVR0jBBgwFoAUsKyJAwR9OXWEcSZMQz73GfpxCJIwDwYDVR0TAQH/BAUwAwEB
18/zANBgkqhkiG9w0BAQsFAAOCAQEAVPBZwMHbrnHFbmhbcPuvYd5cxk0uSVNAUzsl 18/zANBgkqhkiG9w0BAQsFAAOCAQEAYKFGX7J3Fc/T9s278w61E2dSsY4DS/mjSDik
192biCq5P+ZHo10VHGygXtdV4utqk/IrAt2u5qSxycWPStCtAgTd3Q8ncfjOkaHM4z 19fMWvod6eKw0fE3wJOnkWxjEH3VywTY6CmHd/oiJOaD8lr/Vk+BJfYNVBaVNmguyg
202bxTkhLyQeU8NWPuDBqDszo2GOaFTv+lm36LEKiAfqB1tjQVePSkycdrWIhkamBV 204LXoWz9Benx0bAIeuDbNAhOvA4H4aIz8UrD9lKFvKdRp42gPMLtMEbzbLcBdT95D
21EgMe6uHLdU7QQk1ajQfrBdakN1beqki/dKieA6gm+XF/QS4SSYINmsHB/2X5cT9U 216BX7EhYm7vTnpitLPgFxVCsJ1JFqv2AQfUm+IkqQkezPs5x0tWLyrvCDNRGJ0kfv
22b/KMB8xurCnuJQuk1P4VsSkJCOSeHjWZgK9pKNdsIJZr4wDVfhjQgU0XT6xakSf7 22UuowpUZXDOh3k1vB+xaSOFviieLaCW8TSdd5FZgI2HQj4e6vCKsMGuKKZXrMUTI/
23eCaHtO0VKsbLZoiTmpxidjsdYiXyeKYIQNtUpTjyJ5V/cZsq9w== 23qtrFlUfsOuwourfC5LMHtCyYo5B3uvAWT1eTXxhrGqyleSlxJQ==
24-----END CERTIFICATE----- 24-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/expired-key.pem b/plugins/tests/certs/expired-key.pem
index c1510b2d..c5bba569 100644
--- a/plugins/tests/certs/expired-key.pem
+++ b/plugins/tests/certs/expired-key.pem
@@ -1,28 +1,28 @@
1-----BEGIN PRIVATE KEY----- 1-----BEGIN PRIVATE KEY-----
2MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDJ4crAoWMlZRdg 2MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCDV2YZPetWoxt
3cqyKzKlR/10eUg9AAhLIY/UFfpQvbpku8TqQpvHcsVD1bY84ahBaXMWIHWygZ5VY 35VZYvLwQCKr2t7TsAXyxMRHL2ghgXkRSr1/TE7nebDCohZXvs72YX33+QMUZC5A0
4N3RTQm1Z0IqY5dZ1xem6lCVNJS1EIwNCR+os3wZHlMFN3vet7OnmbPTycx8vC7Sn 46cgIxIdc20xcRfN8FoyKCHDS7IKHWj9UJ6M1DnH8dTxouH3fSDkMhw4lDd9ni/3y
5lVDX3VSLwkcWCsA5qUCfxTDkN7y+PhWZNeZTk0nZQWgLR11T9OH+XBEJrIdzVycx 5QFqJ7v5o+BExUMzW8isgt952r0q3nrO8+LOReEN6rGMrIhl2t2gGVfnMB9+1a1ge
6WrYXtz+6ExRRBg0GYnLSnGgdrCn6P00qX/EhiyOBA2BqFDI26zC4YeNoTCE+77sb 6lD6WROFJJepCdyE3pLYkV6OZG2w2dx4NU4EF2+XOYfQ2V/CPKcsrf8QmihOwg3KL
7Tdexbh6G74fXz3wz8yRKWfotABTWzKgnzKk8zy1X7ODHi7CPu52dnaFx433m5bvQ 711cPz857yv5QD6eiRa+dYLYgBQmOnFb5cDJMb82h8bBf4/Cq5PRgPlxKU4MjBkBY
89aDkNDJTAgMBAAECggEACrLFfNnQmD24NGs/S4e2/VpsA9xTZI/3kNkDNgxULANP 8CKbKBYupAgMBAAECggEBAJ2mdCKJ7LoWdT4W8pZ3BqZUFGkKCF8wOhhOUDH3+ZQp
9aNZtxRajwI9A/BCXQ2UTgsZhzWnJxOJYXrlpl7PweY78mUesysb3MOUC6QisUm0M 9IYK3XbdDMF7mMIXIuW4a7W4sLlTwU/Ar98U1JMESwRIMS7YvUke+ngDKKLcDVGwY
10kimfdktHWOnAKLFFLNleN9DUVjjVkTeslijqhNX80f80py1grG2UuCLKCX4OqYIm 10Qpjg9vP0v2Al8qT1NbW/nDF0S2aJJbWfAvnblHK5ClFHL9iL107NQYJ8PqzXbnFL
11qACE8TMmSZLz42AO96TndNtKplQ8LuGLEmByW95wEfhx3Gm4ckkL7qII/U3DnQXr 11gCQRiZxVHlrbn/73ZUMHPGEoU0711U9hSjrsqrRuSAMC+V38s4HxOomZWutlVAHF
120T+3xLaj+eNJzYDpIFZiw4sNzOuAyCz+4Cc4sPDuMnzquXF+enpkemoycC1RmEpG 12HwClNZBqRO+a2njPyUuV9DM/rl5Tm9IQ89iFo3/QEORICK77HjJYhi+UzdfI5F35
13KIDTwmFsc8TrbGV0qifC6fsCrDivdYLqL7R/q3IBQQKBgQDmfvO3VYTEKY8NA+AT 13UntRJt+WLaiAP+K6Vt6oxHSm58qXnOkeLzaAunTTie0CgYEA6OLYfme8xe5zYXWX
145s6+7NTxRsXxJUCEhCNBWimSH3EzmBAvrodLY6A0oYg8i81bgNX1I9GPVXJZ/QA7 14rqmKNYdcVfMkvL+vUfVT475o/piRtE54JC1LYWEFAN8paxEWHD5HZMy0+ONNXfGm
15ukd84HUIQoGS5Usmo4rp+kz4P6KkLXDemZtWPU5GXxicfajHRQlkbW6St6SpV7IS 15zyNNTN/Lagz4WcpdFzKQmhfdro7DzRiDfdvwSLmaZDyE41PPPVVvfrI9IeDiUNY4
16ibJcDADeoiaPL1xvue1ToP/LoQKBgQDgOFHjYpep00gabvjXfYW7vhrg1vVwaKUM 16nWLSb3sWo96Iuns+RoMqeA9wkqsCgYEA1U/UqeVQVTPlrWyiB2VXoI1xvFCCJTf8
17rf0+UW8Exk4nbBw0eEC2YjxIwzdktlkdbzGaXYULnhg8GnfxYesMOpCLPw1JdB8o 174NC0gcisxLRrtINk0BwrUJrRy0x1OLpJWiKwUl/W1GgvPPfhbYcUOb669JNtTIjY
18ixETAFpW5bKrUsjEFRUGhzWnsCSFIQ4smpmtGLTxOQ8AkoDdORY5Z+Wv7JtFF6Do 18FeIZblCTjz9GzKKmXeDciXvccyEdCJVUlPO3/e2JiJ4mCDjULprifq0a2gcQevFS
19PSoblckZcwKBgB3TD3YJesRnHDty5OuuUdIikuslXTd2uoJrFqS+JeLibqNeabnB 19PfqVULhBOvsCgYB5KfS7J1vGmv36ucSWAe0/VlKLATqe3RfpCzt/JQTZWSWNaroF
20u3/lxDULMbWj4U6VvRmbKOKDC+jY887Gq7lc0cff0yROxwqY3sCnwo3crg7QUmp7 20EG/ElUaWIoUZCEW5oglg/0Q0rYYGF4DTCingkhrx7ReVF70BIbSsBzi15d8nKNbY
21Nb5S8G3qoCSfndcq96wm/Me/O28uCbycVJfUdchY8uRUHIHYbP0FOBQBAoGBAMgh 21t4I3RCF4fyggYe1TmsysXS2DH85/gkToVY7oo2CvF0uJwi8vXnTNDDNkiwKBgHKs
22fPX4imaKr1DovDObVkK87EDDnU84GBm5MtDs3qrkVd3aIVK0Aw7HoAdSN58tI12i 22mAc94BHt9GtnGzQepx0I7TvvjAe2MZwqlt+uojKdS8mfWXMHscGDeYVxdRMqEoUC
23YiPmVVqJQhhjh6tsOuAvZdTj8ngdrbICbrsHFZt6an+A5LIgHyQ0iy+hiPdLCdvG 23YQfnvfYyjDKaj/XxyE3C237gQsICTyh0hHdpmepIeidIyWdumyDOFZVPF+ylWvM4
24ImTeKKMmyr04Bs1upueWVO0xw2VoMbcY4Py+NUEBAoGASQqedfCSKGLT+5lLZrhP 24kpFQQb/QRWHmKyti2KCBLw5G/fUaBryLGfprE6ZBAoGBANy5rr41A679UQZ0abev
25CbFVMmswEPjBcRb1trcuA09vfExn9FfUNFnnw3i9miprED5kufvAjb+6nduXizKg 25bOZb7YWOHYp/wReJaQbvLAyR30os3aEY/0ht9S+OWdrgGMezPKvsx2Sqr/CwoFXI
267HQYHCwVvakgtXgbiDMaNgYZcjWm+MdnfiwLJjJTO3DfI1JF2PJ8y9R95DPlAkDm 26esiklpknr11maEPxnQJYi4FYiXS1a3NCg7yBvKzFEgx2XnMAC3s6zhuZXaFq4zNu
27xH3OV8KV4UiTEVxS7ksmGzY= 27pm5Btrq/NZqtVXovS+UhGLvJ
28-----END PRIVATE KEY----- 28-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/ext.cnf b/plugins/tests/certs/ext.cnf
new file mode 100644
index 00000000..d09cee13
--- /dev/null
+++ b/plugins/tests/certs/ext.cnf
@@ -0,0 +1,2 @@
1[ client_ca ]
2basicConstraints = critical, CA:true
diff --git a/plugins/tests/certs/generate-certs.sh b/plugins/tests/certs/generate-certs.sh
new file mode 100755
index 00000000..78660a26
--- /dev/null
+++ b/plugins/tests/certs/generate-certs.sh
@@ -0,0 +1,63 @@
1#!/bin/sh -e
2#
3# Recreates the https server certificates
4#
5# Set the GEN_EXPIRED environment variable to also regenerate
6# the expired certificate.
7
8cd "$(dirname "$0")"
9trap 'rm -f *.csr; rm -f clientca-cert.srl' EXIT
10
11subj() {
12 c="DE"
13 st="Bavaria"
14 l="Munich"
15 o="Monitoring Plugins"
16 cn="Monitoring Plugins"
17 emailAddress="devel@monitoring-plugins.org"
18
19 if [ -n "$1" ]; then
20 # Add to CN
21 cn="$cn $1"
22 fi
23
24 printf "/C=%s/ST=%s/L=%s/O=%s/CN=%s/emailAddress=%s" \
25 "$c" "$st" "$l" "$o" "$cn" "$emailAddress"
26}
27
28# server
29openssl req -new -x509 -days 3560 -nodes \
30 -keyout server-key.pem -out server-cert.pem \
31 -subj "$(subj)"
32# server, expired
33# there is generally no need to regenerate this, as it will stay epxired
34[ -n "$GEN_EXPIRED" ] && TZ=UTC faketime -f '2008-01-01 12:00:00' \
35 openssl req -new -x509 -days 1 -nodes \
36 -keyout expired-key.pem -out expired-cert.pem \
37 -subj "$(subj)"
38
39# client, ca
40openssl req -new -x509 -days 3560 -nodes \
41 -keyout clientca-key.pem -out clientca-cert.pem \
42 -subj "$(subj ClientCA)"
43echo "01" >clientca-cert.srl
44# client
45openssl req -new -nodes \
46 -keyout client-key.pem -out client-cert.csr \
47 -subj "$(subj Client)"
48openssl x509 -days 3560 -req -CA clientca-cert.pem -CAkey clientca-key.pem \
49 -in client-cert.csr -out client-cert.pem
50# client, intermediate
51openssl req -new -nodes \
52 -keyout clientintermediate-key.pem -out clientintermediate-cert.csr \
53 -subj "$(subj ClientIntermediate)"
54openssl x509 -days 3560 -req -CA clientca-cert.pem -CAkey clientca-key.pem \
55 -extfile ext.cnf -extensions client_ca \
56 -in clientintermediate-cert.csr -out clientintermediate-cert.pem
57# client, chain
58openssl req -new -nodes \
59 -keyout clientchain-key.pem -out clientchain-cert.csr \
60 -subj "$(subj ClientChain)"
61openssl x509 -days 3560 -req -CA clientca-cert.pem -CAkey clientca-key.pem \
62 -in clientchain-cert.csr -out clientchain-cert.pem
63cat clientintermediate-cert.pem >>clientchain-cert.pem
diff --git a/plugins/tests/certs/server-cert.pem b/plugins/tests/certs/server-cert.pem
index b84b91d2..d1249ef1 100644
--- a/plugins/tests/certs/server-cert.pem
+++ b/plugins/tests/certs/server-cert.pem
@@ -1,24 +1,24 @@
1-----BEGIN CERTIFICATE----- 1-----BEGIN CERTIFICATE-----
2MIIEBjCCAu6gAwIBAgIJANbQ5QQrKhUGMA0GCSqGSIb3DQEBCwUAMIGXMQswCQYD 2MIIEETCCAvmgAwIBAgIUZwOhY4myaCUaPek3NM+MxbLG9vwwDQYJKoZIhvcNAQEL
3VQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTEPMA0GA1UEBwwGTXVuaWNoMRswGQYD 3BQAwgZcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN
4VQQKDBJNb25pdG9yaW5nIFBsdWdpbnMxGzAZBgNVBAMMEk1vbml0b3JpbmcgUGx1 4dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9u
5Z2luczErMCkGCSqGSIb3DQEJARYcZGV2ZWxAbW9uaXRvcmluZy1wbHVnaW5zLm9y 5aXRvcmluZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5n
6ZzAeFw0xOTAyMTkxNTMxNDRaFw0yOTAyMTYxNTMxNDRaMIGXMQswCQYDVQQGEwJE 6LXBsdWdpbnMub3JnMB4XDTIxMDIyODIxMDIxMVoXDTMwMTEyODIxMDIxMVowgZcx
7RTEQMA4GA1UECAwHQmF2YXJpYTEPMA0GA1UEBwwGTXVuaWNoMRswGQYDVQQKDBJN 7CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gx
8b25pdG9yaW5nIFBsdWdpbnMxGzAZBgNVBAMMEk1vbml0b3JpbmcgUGx1Z2luczEr 8GzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9uaXRvcmlu
9MCkGCSqGSIb3DQEJARYcZGV2ZWxAbW9uaXRvcmluZy1wbHVnaW5zLm9yZzCCASIw 9ZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdp
10DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKgV2yp8pQvJuN+aJGdAe6Hd0tja 10bnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/3eBA4WG6xz
11uteCPcNIcM92WLOF69TLTSYon1XDon4tHTh4Z5d4lD8bfsGzFVBmDSgWidhAUf+v 11LfM6xcWywxThb1Rp7XAW3ewQd9/PdoWXEe8BJWlLfyYi1drLMcsDywhLkKmW4Vp9
12EqEXwbp293ej/Frc0pXCvmrz6kI1tWrLtQhL/VdbxFYxhV7JjKb+PY3SxGFpSLPe 121R4PAkiljjrB/ZaUMDLJ1ri3dwX4RvXG7crsU3QWFWCBOrf5V2FTRQ2m/H/KyB/6
13PQ/5SwVndv7rZIwcjseL22K5Uy2TIrkgzzm2pRs/IvoxRybYr/+LGoHyrtJC6AO8 13rVZANsU47HqTFSPiUm2j7P3wx/wtHeYC+qmNG7zZTjAYPYxfKiod0lytTSmb+h54
14ylp8A/etL0gwtUvRnrnZeTQ2pA1uZ5QN3anTL8JP/ZRZYNegIkaawqMtTKbhM6pi 146lxn3+VPEXZAQZlLvPnm/58JnXGrUv7B2yocf5MhKkLJOrGxH2hfwKISfaj2gpOV
15u3/4a3Uppvt0y7vmGfQlYejxCpICnMrvHMpw8L58zv/98AbCGjDU3UwCt6MCAwEA 15m4PUVYiDzCSpq1fPvwbUxIvdO27xprx+mrGOFM6f2UCEOc35w8FSmYiR2yQTnEJK
16AaNTMFEwHQYDVR0OBBYEFG/UH6nGYPlVcM75UXzXBF5GZyrcMB8GA1UdIwQYMBaA 16pbSQD6t1jQIDAQABo1MwUTAdBgNVHQ4EFgQUMeYgglT2aWDlF8KEeF2376AlTGYw
17FG/UH6nGYPlVcM75UXzXBF5GZyrcMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN 17HwYDVR0jBBgwFoAUMeYgglT2aWDlF8KEeF2376AlTGYwDwYDVR0TAQH/BAUwAwEB
18AQELBQADggEBAGwitJPOnlIKLndNf+iCLMIs0dxsl8kAaejFcjoT0n4ja7Y6Zrqz 18/zANBgkqhkiG9w0BAQsFAAOCAQEAFcEg83rTJdgkp7JLYqK0j8JogSHNlDYchr/r
19VSIidzz9vQWvy24xKJpAOdj/iLRHCUOG+Pf5fA6+/FiuqXr6gE2/lm0eC58BNONr 19VxKBgQwfnjSp5A8d5+uTQ9s3QDabw8v7YeSrzYXbbjuWZ61mnl84tzOQ8LMeESnC
20E5OzjQ/VoQ8RX4hDntgu6FYbaVa/vhwn16igt9qmdNGGZXf2/+DM3JADwyaA4EK8 20CBXRCxB8Ow22WsVTVJq279SGYT+cZrdsmqGVWDi1A0C5kH+XTLAioG5CZmmxemD/
21vm7KdofX9zkxXecHPNvf3jiVLPiDDt6tkGpHPEsyP/yc+RUdltUeZvHfliV0cCuC 21S92ZoRxGyYfg33r+3X6EMcEYtHKGxCUa3EPcPOL4dq2F3nOnyjiWPZm3786H3NY2
22jJX+Fm9ysjSpHIFFr+jUMuMHibWoOD8iy3eYxfCDoWsH488pCbj8MNuAq6vd6DBk 22nsYwrEhAdUFtbYSsV5O0c/Zlc33fmTfh654ab35io1DtwmFo7q8J532dUE007EN0
23bOZxDz43vjWuYMkwXJTxJQh7Pne6kK0vE1g= 23mIQmhdrjNJJHIftgSt0fuN5m48oLOnX7vvkz+X0WLWfVTtMr0w==
24-----END CERTIFICATE----- 24-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/server-key.pem b/plugins/tests/certs/server-key.pem
index 11947555..0de63f8f 100644
--- a/plugins/tests/certs/server-key.pem
+++ b/plugins/tests/certs/server-key.pem
@@ -1,28 +1,28 @@
1-----BEGIN PRIVATE KEY----- 1-----BEGIN PRIVATE KEY-----
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
27N0wdmCAqlQwHR13+F1zrAD7V 27nYGB5/QXYr5WGV9YhAkRsFJYgA==
28-----END PRIVATE KEY----- 28-----END PRIVATE KEY-----
diff --git a/plugins/tests/check_curl.t b/plugins/tests/check_curl.t
index 29cb03f2..aa72ef67 100755
--- a/plugins/tests/check_curl.t
+++ b/plugins/tests/check_curl.t
@@ -228,23 +228,25 @@ SKIP: {
228 skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https}; 228 skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https};
229 run_common_tests( { command => "$command -p $port_https", ssl => 1 } ); 229 run_common_tests( { command => "$command -p $port_https", ssl => 1 } );
230 230
231 my $expiry = "Thu Nov 28 21:02:11 2030 +0000";
232
231 $result = NPTest->testCmd( "$command -p $port_https -S -C 14" ); 233 $result = NPTest->testCmd( "$command -p $port_https -S -C 14" );
232 is( $result->return_code, 0, "$command -p $port_https -S -C 14" ); 234 is( $result->return_code, 0, "$command -p $port_https -S -C 14" );
233 is( $result->output, "OK - Certificate 'Monitoring Plugins' will expire on Fri Feb 16 15:31:44 2029 +0000.", "output ok" ); 235 is( $result->output, "OK - Certificate 'Monitoring Plugins' will expire on $expiry.", "output ok" );
234 236
235 $result = NPTest->testCmd( "$command -p $port_https -S -C 14000" ); 237 $result = NPTest->testCmd( "$command -p $port_https -S -C 14000" );
236 is( $result->return_code, 1, "$command -p $port_https -S -C 14000" ); 238 is( $result->return_code, 1, "$command -p $port_https -S -C 14000" );
237 like( $result->output, '/WARNING - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(Fri Feb 16 15:31:44 2029 \+0000\)./', "output ok" ); 239 like( $result->output, '/WARNING - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
238 240
239 # Expired cert tests 241 # Expired cert tests
240 $result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" ); 242 $result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" );
241 is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" ); 243 is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" );
242 like( $result->output, '/CRITICAL - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(Fri Feb 16 15:31:44 2029 \+0000\)./', "output ok" ); 244 like( $result->output, '/CRITICAL - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
243 245
244 $result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" ); 246 $result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" );
245 is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" ); 247 is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" );
246 is( $result->output, 248 is( $result->output,
247 'CRITICAL - Certificate \'Monitoring Plugins\' expired on Wed Jan 2 11:00:26 2008 +0000.', 249 'CRITICAL - Certificate \'Monitoring Plugins\' expired on Wed Jan 2 12:00:00 2008 +0000.',
248 "output ok" ); 250 "output ok" );
249 251
250} 252}
diff --git a/plugins/tests/check_http.t b/plugins/tests/check_http.t
index 188f5e75..ea11b2ac 100755
--- a/plugins/tests/check_http.t
+++ b/plugins/tests/check_http.t
@@ -3,16 +3,7 @@
3# Test check_http by having an actual HTTP server running 3# Test check_http by having an actual HTTP server running
4# 4#
5# To create the https server certificate: 5# To create the https server certificate:
6# openssl req -new -x509 -keyout server-key.pem -out server-cert.pem -days 3650 -nodes 6# ./certs/generate-certs.sh
7# to create a new expired certificate:
8# faketime '2008-01-01 12:00:00' openssl req -new -x509 -keyout expired-key.pem -out expired-cert.pem -days 1 -nodes
9# Country Name (2 letter code) [AU]:DE
10# State or Province Name (full name) [Some-State]:Bavaria
11# Locality Name (eg, city) []:Munich
12# Organization Name (eg, company) [Internet Widgits Pty Ltd]:Monitoring Plugins
13# Organizational Unit Name (eg, section) []:
14# Common Name (e.g. server FQDN or YOUR name) []:Monitoring Plugins
15# Email Address []:devel@monitoring-plugins.org
16 7
17use strict; 8use strict;
18use Test::More; 9use Test::More;
@@ -23,7 +14,7 @@ $ENV{'LC_TIME'} = "C";
23 14
24my $common_tests = 70; 15my $common_tests = 70;
25my $virtual_port_tests = 8; 16my $virtual_port_tests = 8;
26my $ssl_only_tests = 8; 17my $ssl_only_tests = 12;
27# Check that all dependent modules are available 18# Check that all dependent modules are available
28eval "use HTTP::Daemon 6.01;"; 19eval "use HTTP::Daemon 6.01;";
29plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@; 20plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@;
@@ -59,61 +50,87 @@ $HTTP::Daemon::VERSION = "1.00";
59my $port_http = 50000 + int(rand(1000)); 50my $port_http = 50000 + int(rand(1000));
60my $port_https = $port_http + 1; 51my $port_https = $port_http + 1;
61my $port_https_expired = $port_http + 2; 52my $port_https_expired = $port_http + 2;
53my $port_https_clientcert = $port_http + 3;
62 54
63# This array keeps sockets around for implementing timeouts 55# This array keeps sockets around for implementing timeouts
64my @persist; 56my @persist;
65 57
66# Start up all servers 58# Start up all servers
67my @pids; 59my @pids;
68my $pid = fork(); 60# Fork a HTTP server
69if ($pid) { 61my $pid = fork;
70 # Parent 62defined $pid or die "Failed to fork";
71 push @pids, $pid; 63if (!$pid) {
72 if (exists $servers->{https}) { 64 undef @pids;
73 # Fork a normal HTTPS server
74 $pid = fork();
75 if ($pid) {
76 # Parent
77 push @pids, $pid;
78 # Fork an expired cert server
79 $pid = fork();
80 if ($pid) {
81 push @pids, $pid;
82 } else {
83 my $d = HTTP::Daemon::SSL->new(
84 LocalPort => $port_https_expired,
85 LocalAddr => "127.0.0.1",
86 SSL_cert_file => "$Bin/certs/expired-cert.pem",
87 SSL_key_file => "$Bin/certs/expired-key.pem",
88 ) || die;
89 print "Please contact https expired at: <URL:", $d->url, ">\n";
90 run_server( $d );
91 exit;
92 }
93 } else {
94 # closing the connection after -C cert checks make the daemon exit with a sigpipe otherwise
95 local $SIG{'PIPE'} = 'IGNORE';
96 my $d = HTTP::Daemon::SSL->new(
97 LocalPort => $port_https,
98 LocalAddr => "127.0.0.1",
99 SSL_cert_file => "$Bin/certs/server-cert.pem",
100 SSL_key_file => "$Bin/certs/server-key.pem",
101 ) || die;
102 print "Please contact https at: <URL:", $d->url, ">\n";
103 run_server( $d );
104 exit;
105 }
106 }
107} else {
108 # Child
109 #print "child\n";
110 my $d = HTTP::Daemon->new( 65 my $d = HTTP::Daemon->new(
111 LocalPort => $port_http, 66 LocalPort => $port_http,
112 LocalAddr => "127.0.0.1", 67 LocalAddr => "127.0.0.1",
113 ) || die; 68 ) || die;
114 print "Please contact http at: <URL:", $d->url, ">\n"; 69 print "Please contact http at: <URL:", $d->url, ">\n";
115 run_server( $d ); 70 run_server( $d );
116 exit; 71 die "webserver stopped";
72}
73push @pids, $pid;
74
75if (exists $servers->{https}) {
76 # Fork a normal HTTPS server
77 $pid = fork;
78 defined $pid or die "Failed to fork";
79 if (!$pid) {
80 undef @pids;
81 # closing the connection after -C cert checks make the daemon exit with a sigpipe otherwise
82 local $SIG{'PIPE'} = 'IGNORE';
83 my $d = HTTP::Daemon::SSL->new(
84 LocalPort => $port_https,
85 LocalAddr => "127.0.0.1",
86 SSL_cert_file => "$Bin/certs/server-cert.pem",
87 SSL_key_file => "$Bin/certs/server-key.pem",
88 ) || die;
89 print "Please contact https at: <URL:", $d->url, ">\n";
90 run_server( $d );
91 die "webserver stopped";
92 }
93 push @pids, $pid;
94
95 # Fork an expired cert server
96 $pid = fork;
97 defined $pid or die "Failed to fork";
98 if (!$pid) {
99 undef @pids;
100 # closing the connection after -C cert checks make the daemon exit with a sigpipe otherwise
101 local $SIG{'PIPE'} = 'IGNORE';
102 my $d = HTTP::Daemon::SSL->new(
103 LocalPort => $port_https_expired,
104 LocalAddr => "127.0.0.1",
105 SSL_cert_file => "$Bin/certs/expired-cert.pem",
106 SSL_key_file => "$Bin/certs/expired-key.pem",
107 ) || die;
108 print "Please contact https expired at: <URL:", $d->url, ">\n";
109 run_server( $d );
110 die "webserver stopped";
111 }
112 push @pids, $pid;
113
114 # Fork an client cert expecting server
115 $pid = fork;
116 defined $pid or die "Failed to fork";
117 if (!$pid) {
118 undef @pids;
119 # closing the connection after -C cert checks make the daemon exit with a sigpipe otherwise
120 local $SIG{'PIPE'} = 'IGNORE';
121 my $d = HTTP::Daemon::SSL->new(
122 LocalPort => $port_https_clientcert,
123 LocalAddr => "127.0.0.1",
124 SSL_cert_file => "$Bin/certs/server-cert.pem",
125 SSL_key_file => "$Bin/certs/server-key.pem",
126 SSL_verify_mode => IO::Socket::SSL->SSL_VERIFY_PEER | IO::Socket::SSL->SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
127 SSL_ca_file => "$Bin/certs/clientca-cert.pem",
128 ) || die;
129 print "Please contact https client cert at: <URL:", $d->url, ">\n";
130 run_server( $d );
131 die "webserver stopped";
132 }
133 push @pids, $pid;
117} 134}
118 135
119# give our webservers some time to startup 136# give our webservers some time to startup
@@ -122,60 +139,62 @@ sleep(3);
122# Run the same server on http and https 139# Run the same server on http and https
123sub run_server { 140sub run_server {
124 my $d = shift; 141 my $d = shift;
125 MAINLOOP: while (my $c = $d->accept ) { 142 while (1) {
126 while (my $r = $c->get_request) { 143 MAINLOOP: while (my $c = $d->accept) {
127 if ($r->method eq "GET" and $r->url->path =~ m^/statuscode/(\d+)^) { 144 while (my $r = $c->get_request) {
128 $c->send_basic_header($1); 145 if ($r->method eq "GET" and $r->url->path =~ m^/statuscode/(\d+)^) {
129 $c->send_crlf; 146 $c->send_basic_header($1);
130 } elsif ($r->method eq "GET" and $r->url->path =~ m^/file/(.*)^) { 147 $c->send_crlf;
131 $c->send_basic_header; 148 } elsif ($r->method eq "GET" and $r->url->path =~ m^/file/(.*)^) {
132 $c->send_crlf; 149 $c->send_basic_header;
133 $c->send_file_response("$Bin/var/$1"); 150 $c->send_crlf;
134 } elsif ($r->method eq "GET" and $r->url->path eq "/slow") { 151 $c->send_file_response("$Bin/var/$1");
135 $c->send_basic_header; 152 } elsif ($r->method eq "GET" and $r->url->path eq "/slow") {
136 $c->send_crlf; 153 $c->send_basic_header;
137 sleep 1; 154 $c->send_crlf;
138 $c->send_response("slow"); 155 sleep 1;
139 } elsif ($r->url->path eq "/method") { 156 $c->send_response("slow");
140 if ($r->method eq "DELETE") { 157 } elsif ($r->url->path eq "/method") {
141 $c->send_error(HTTP::Status->RC_METHOD_NOT_ALLOWED); 158 if ($r->method eq "DELETE") {
142 } elsif ($r->method eq "foo") { 159 $c->send_error(HTTP::Status->RC_METHOD_NOT_ALLOWED);
143 $c->send_error(HTTP::Status->RC_NOT_IMPLEMENTED); 160 } elsif ($r->method eq "foo") {
161 $c->send_error(HTTP::Status->RC_NOT_IMPLEMENTED);
162 } else {
163 $c->send_status_line(200, $r->method);
164 }
165 } elsif ($r->url->path eq "/postdata") {
166 $c->send_basic_header;
167 $c->send_crlf;
168 $c->send_response($r->method.":".$r->content);
169 } elsif ($r->url->path eq "/redirect") {
170 $c->send_redirect( "/redirect2" );
171 } elsif ($r->url->path eq "/redir_external") {
172 $c->send_redirect(($d->isa('HTTP::Daemon::SSL') ? "https" : "http") . "://169.254.169.254/redirect2" );
173 } elsif ($r->url->path eq "/redirect2") {
174 $c->send_basic_header;
175 $c->send_crlf;
176 $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' ));
177 } elsif ($r->url->path eq "/redir_timeout") {
178 $c->send_redirect( "/timeout" );
179 } elsif ($r->url->path eq "/timeout") {
180 # Keep $c from being destroyed, but prevent severe leaks
181 unshift @persist, $c;
182 delete($persist[1000]);
183 next MAINLOOP;
184 } elsif ($r->url->path eq "/header_check") {
185 $c->send_basic_header;
186 $c->send_header('foo');
187 $c->send_crlf;
188 } elsif ($r->url->path eq "/virtual_port") {
189 # return sent Host header
190 $c->send_basic_header;
191 $c->send_crlf;
192 $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host')));
144 } else { 193 } else {
145 $c->send_status_line(200, $r->method); 194 $c->send_error(HTTP::Status->RC_FORBIDDEN);
146 } 195 }
147 } elsif ($r->url->path eq "/postdata") { 196 $c->close;
148 $c->send_basic_header;
149 $c->send_crlf;
150 $c->send_response($r->method.":".$r->content);
151 } elsif ($r->url->path eq "/redirect") {
152 $c->send_redirect( "/redirect2" );
153 } elsif ($r->url->path eq "/redir_external") {
154 $c->send_redirect(($d->isa('HTTP::Daemon::SSL') ? "https" : "http") . "://169.254.169.254/redirect2" );
155 } elsif ($r->url->path eq "/redirect2") {
156 $c->send_basic_header;
157 $c->send_crlf;
158 $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' ));
159 } elsif ($r->url->path eq "/redir_timeout") {
160 $c->send_redirect( "/timeout" );
161 } elsif ($r->url->path eq "/timeout") {
162 # Keep $c from being destroyed, but prevent severe leaks
163 unshift @persist, $c;
164 delete($persist[1000]);
165 next MAINLOOP;
166 } elsif ($r->url->path eq "/header_check") {
167 $c->send_basic_header;
168 $c->send_header('foo');
169 $c->send_crlf;
170 } elsif ($r->url->path eq "/virtual_port") {
171 # return sent Host header
172 $c->send_basic_header;
173 $c->send_crlf;
174 $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host')));
175 } else {
176 $c->send_error(HTTP::Status->RC_FORBIDDEN);
177 } 197 }
178 $c->close;
179 } 198 }
180 } 199 }
181} 200}
@@ -200,25 +219,44 @@ SKIP: {
200 skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https}; 219 skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https};
201 run_common_tests( { command => "$command -p $port_https", ssl => 1 } ); 220 run_common_tests( { command => "$command -p $port_https", ssl => 1 } );
202 221
222 my $expiry = "Thu Nov 28 21:02:11 2030 +0000";
223
203 $result = NPTest->testCmd( "$command -p $port_https -S -C 14" ); 224 $result = NPTest->testCmd( "$command -p $port_https -S -C 14" );
204 is( $result->return_code, 0, "$command -p $port_https -S -C 14" ); 225 is( $result->return_code, 0, "$command -p $port_https -S -C 14" );
205 is( $result->output, "OK - Certificate 'Monitoring Plugins' will expire on Fri Feb 16 15:31:44 2029 +0000.", "output ok" ); 226 is( $result->output, "OK - Certificate 'Monitoring Plugins' will expire on $expiry.", "output ok" );
206 227
207 $result = NPTest->testCmd( "$command -p $port_https -S -C 14000" ); 228 $result = NPTest->testCmd( "$command -p $port_https -S -C 14000" );
208 is( $result->return_code, 1, "$command -p $port_https -S -C 14000" ); 229 is( $result->return_code, 1, "$command -p $port_https -S -C 14000" );
209 like( $result->output, '/WARNING - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(Fri Feb 16 15:31:44 2029 \+0000\)./', "output ok" ); 230 like( $result->output, '/WARNING - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
210 231
211 # Expired cert tests 232 # Expired cert tests
212 $result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" ); 233 $result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" );
213 is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" ); 234 is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" );
214 like( $result->output, '/CRITICAL - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(Fri Feb 16 15:31:44 2029 \+0000\)./', "output ok" ); 235 like( $result->output, '/CRITICAL - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
215 236
216 $result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" ); 237 $result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" );
217 is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" ); 238 is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" );
218 is( $result->output, 239 is( $result->output,
219 'CRITICAL - Certificate \'Monitoring Plugins\' expired on Wed Jan 2 11:00:26 2008 +0000.', 240 'CRITICAL - Certificate \'Monitoring Plugins\' expired on Wed Jan 2 12:00:00 2008 +0000.',
220 "output ok" ); 241 "output ok" );
221 242
243 # client cert tests
244 my $cmd;
245 $cmd = "$command -p $port_https_clientcert"
246 . " -J \"$Bin/certs/client-cert.pem\""
247 . " -K \"$Bin/certs/client-key.pem\""
248 . " -u /statuscode/200";
249 $result = NPTest->testCmd($cmd);
250 is( $result->return_code, 0, $cmd);
251 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
252
253 $cmd = "$command -p $port_https_clientcert"
254 . " -J \"$Bin/certs/clientchain-cert.pem\""
255 . " -K \"$Bin/certs/clientchain-key.pem\""
256 . " -u /statuscode/200";
257 $result = NPTest->testCmd($cmd);
258 is( $result->return_code, 0, $cmd);
259 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
222} 260}
223 261
224my $cmd; 262my $cmd;