1
/****************************************************************************
3
* Program: HTTP plugin for Nagios
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
* $Id: check_http.c,v 1.24.2.4 2003/06/21 05:31:23 kdebisschop Exp $
24
*****************************************************************************/
26
const char *progname = "check_http";
27
#define REVISION "$Revision: 1.24.2.4 $"
28
#define COPYRIGHT "1999-2001"
29
#define AUTHORS "Ethan Galstad/Karl DeBisschop"
30
#define EMAIL "kdebisschop@users.sourceforge.net"
38
This plugin tests the HTTP service on the specified host. It can test\n\
39
normal (http) and secure (https) servers, follow redirects, search for\n\
40
strings and regular expressions, check connection times, and report on\n\
41
certificate expiration times.\n"
44
(-H <vhost> | -I <IP-address>) [-u <uri>] [-p <port>]\n\
45
[-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n\
46
[-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n\
47
[-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n\
50
#define LONGOPTIONS "\
51
-H, --hostname=ADDRESS\n\
52
Host name argument for servers using host headers (virtual host)\n\
53
-I, --IP-address=ADDRESS\n\
54
IP address or name (use numeric address if possible to bypass DNS lookup).\n\
55
-e, --expect=STRING\n\
56
String to expect in first (status) line of server response (default: %s)\n\
57
If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)\n\
58
-s, --string=STRING\n\
59
String to expect in the content\n\
61
URL to GET or POST (default: /)\n\
63
Port number (default: %d)\n\
65
URL encoded http POST data\n\
66
-w, --warning=INTEGER\n\
67
Response time to result in warning status (seconds)\n\
68
-c, --critical=INTEGER\n\
69
Response time to result in critical status (seconds)\n\
70
-t, --timeout=INTEGER\n\
71
Seconds before connection times out (default: %d)\n\
72
-a, --authorization=AUTH_PAIR\n\
73
Username:password on sites with basic authentication\n\
75
Wrap output in HTML link (obsoleted by urlize)\n\
76
-f, --onredirect=<ok|warning|critical|follow>\n\
77
How to handle redirected pages\n%s%s\
79
Show details for command-line debugging (do not use with nagios server)\n\
81
Print detailed help screen\n\
83
Print version information\n"
89
-C, --certificate=INTEGER\n\
90
Minimum number of days a certificate has to be valid.\n\
91
(when this option is used the url is not checked.)\n"
99
Allow regex to span newlines (must precede -r or -R)\n\
100
-r, --regex, --ereg=STRING\n\
101
Search page for regex STRING\n\
102
-R, --eregi=STRING\n\
103
Search page for case-insensitive regex STRING\n"
105
#define REGOPTIONS ""
108
#define DESCRIPTION "\
109
This plugin will attempt to open an HTTP connection with the host. Successul\n\
110
connects return STATE_OK, refusals and timeouts return STATE_CRITICAL, other\n\
111
errors return STATE_UNKNOWN. Successful connects, but incorrect reponse\n\
112
messages from the host result in STATE_WARNING return values. If you are\n\
113
checking a virtual server that uses \"host headers\" you must supply the FQDN\n\
114
\(fully qualified domain name) as the [host_name] argument.\n"
116
#define SSLDESCRIPTION "\
117
This plugin can also check whether an SSL enabled web server is able to\n\
118
serve content (optionally within a specified time) or whether the X509 \n\
119
certificate is still valid for the specified number of days.\n\n\
120
CHECK CONTENT: check_http -w 5 -c 10 --ssl www.verisign.com\n\n\
121
When the 'www.verisign.com' server returns its content within 5 seconds, a\n\
122
STATE_OK will be returned. When the server returns its content but exceeds\n\
123
the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,\n\
124
a STATE_CRITICAL will be returned.\n\n\
125
CHECK CERTIFICATE: check_http www.verisign.com -C 14\n\n\
126
When the certificate of 'www.verisign.com' is valid for more than 14 days, a\n\
127
STATE_OK is returned. When the certificate is still valid, but for less than\n\
128
14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when\n\
129
the certificate is expired.\n"
141
#ifdef HAVE_OPENSSL_SSL_H
142
#include <openssl/rsa.h>
143
#include <openssl/crypto.h>
144
#include <openssl/x509.h>
145
#include <openssl/pem.h>
146
#include <openssl/ssl.h>
147
#include <openssl/err.h>
148
#include <openssl/rand.h>
152
int check_cert = FALSE;
158
int connect_SSL (void);
159
int check_certificate (X509 **);
169
regmatch_t pmatch[REGS];
170
char regexp[MAX_RE_SIZE];
171
char errbuf[MAX_INPUT_BUFFER];
172
int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
178
#define server_type_check(server_type) \
179
(strcmp (server_type, "https") ? FALSE : TRUE)
181
#define server_port_check(use_ssl) (use_ssl ? HTTPS_PORT : HTTP_PORT)
184
#define HDR_LOCATION "%*[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]: "
185
#define URI_HTTP "%[HTPShtps]://"
186
#define URI_HOST "%[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
187
#define URI_PORT ":%[0123456789]"
188
#define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
190
MAX_IPV4_HOSTLENGTH = 255,
195
#define HTTP_EXPECT "HTTP/1."
199
char timestamp[17] = "";
200
int specify_port = FALSE;
201
int server_port = HTTP_PORT;
202
char server_port_text[6] = "";
203
char server_type[6] = "http";
204
char *server_address = "";
205
char *host_name = "";
206
char *server_url = "";
207
int server_url_length;
208
int server_expect_yn = 0;
209
char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
210
char string_expect[MAX_INPUT_BUFFER] = "";
211
double warning_time = 0;
212
int check_warning_time = FALSE;
213
double critical_time = 0;
214
int check_critical_time = FALSE;
215
char user_auth[MAX_INPUT_BUFFER] = "";
216
int display_html = FALSE;
217
int onredirect = STATE_OK;
221
char *http_method = "GET";
222
char *http_post_data = "";
223
char buffer[MAX_INPUT_BUFFER];
225
void print_usage (void);
226
void print_help (void);
227
int process_arguments (int, char **);
228
static char *base64 (char *bin, int len);
229
int check_http (void);
234
main (int argc, char **argv)
236
int result = STATE_UNKNOWN;
238
/* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
239
asprintf (&server_url, "%s", HTTP_URL);
240
server_url_length = strlen(server_url);
242
if (process_arguments (argc, argv) == ERROR)
243
usage ("check_http: could not parse arguments\n");
245
if (strstr (timestamp, ":")) {
246
if (strstr (server_url, "?"))
247
asprintf (&server_url, "%s&%s", server_url, timestamp);
249
asprintf (&server_url, "%s?%s", server_url, timestamp);
252
if (display_html == TRUE)
253
printf ("<A HREF=\"http://%s:%d%s\" target=\"_blank\">",
254
host_name, server_port, server_url);
256
/* initialize alarm signal handling, set socket timeout, start timer */
257
(void) signal (SIGALRM, socket_timeout_alarm_handler);
258
(void) alarm (socket_timeout);
259
gettimeofday (&tv, NULL);
262
if (use_ssl && check_cert == TRUE) {
263
if (connect_SSL () != OK)
264
terminate (STATE_CRITICAL,
265
"HTTP CRITICAL - Could not make SSL connection\n");
266
if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
267
result = check_certificate (&server_cert);
268
X509_free (server_cert);
271
printf ("ERROR: Cannot retrieve server certificate.\n");
272
result = STATE_CRITICAL;
280
result = check_http ();
283
result = check_http ();
290
/* process command-line arguments */
292
process_arguments (int argc, char **argv)
297
int option_index = 0;
298
static struct option long_options[] = {
300
{"file",required_argument,0,'F'},
301
{"link", no_argument, 0, 'L'},
302
{"nohtml", no_argument, 0, 'n'},
303
{"ssl", no_argument, 0, 'S'},
304
{"verbose", no_argument, 0, 'v'},
305
{"post", required_argument, 0, 'P'},
306
{"IP-address", required_argument, 0, 'I'},
307
{"string", required_argument, 0, 's'},
308
{"regex", required_argument, 0, 'r'},
309
{"ereg", required_argument, 0, 'r'},
310
{"eregi", required_argument, 0, 'R'},
311
{"linespan", no_argument, 0, 'l'},
312
{"onredirect", required_argument, 0, 'f'},
313
{"certificate", required_argument, 0, 'C'},
321
for (c = 1; c < argc; c++) {
322
if (strcmp ("-to", argv[c]) == 0)
323
strcpy (argv[c], "-t");
324
if (strcmp ("-hn", argv[c]) == 0)
325
strcpy (argv[c], "-H");
326
if (strcmp ("-wt", argv[c]) == 0)
327
strcpy (argv[c], "-w");
328
if (strcmp ("-ct", argv[c]) == 0)
329
strcpy (argv[c], "-c");
330
if (strcmp ("-nohtml", argv[c]) == 0)
331
strcpy (argv[c], "-n");
334
#define OPTCHARS "Vvht:c:w:H:P:I:a:e:p:s:R:r:u:f:C:nlLS"
338
c = getopt_long (argc, argv, OPTCHARS, long_options, &option_index);
340
c = getopt (argc, argv, OPTCHARS);
342
if (c == -1 || c == EOF)
346
case '?': /* usage */
347
usage2 ("unknown argument", optarg);
353
case 'V': /* version */
354
print_revision (progname, REVISION);
357
case 't': /* timeout period */
358
if (!is_intnonneg (optarg))
359
usage2 ("timeout interval must be a non-negative integer", optarg);
360
socket_timeout = atoi (optarg);
362
case 'c': /* critical time threshold */
363
if (!is_intnonneg (optarg))
364
usage2 ("invalid critical threshold", optarg);
365
critical_time = strtod (optarg, NULL);
366
check_critical_time = TRUE;
368
case 'w': /* warning time threshold */
369
if (!is_intnonneg (optarg))
370
usage2 ("invalid warning threshold", optarg);
371
warning_time = strtod (optarg, NULL);
372
check_warning_time = TRUE;
374
case 'L': /* show html link */
377
case 'n': /* do not show html link */
378
display_html = FALSE;
380
case 'S': /* use SSL */
382
usage ("check_http: invalid option - SSL is not available\n");
385
if (specify_port == FALSE)
386
server_port = HTTPS_PORT;
388
case 'C': /* Check SSL cert validity */
390
if (!is_intnonneg (optarg))
391
usage2 ("invalid certificate expiration period", optarg);
392
days_till_exp = atoi (optarg);
395
usage ("check_http: invalid option - SSL is not available\n");
398
case 'f': /* onredirect */
399
if (!strcmp (optarg, "follow"))
400
onredirect = STATE_DEPENDENT;
401
if (!strcmp (optarg, "unknown"))
402
onredirect = STATE_UNKNOWN;
403
if (!strcmp (optarg, "ok"))
404
onredirect = STATE_OK;
405
if (!strcmp (optarg, "warning"))
406
onredirect = STATE_WARNING;
407
if (!strcmp (optarg, "critical"))
408
onredirect = STATE_CRITICAL;
410
printf("option f:%d \n", onredirect);
412
/* Note: H, I, and u must be malloc'd or will fail on redirects */
413
case 'H': /* Host Name (virtual host) */
414
asprintf (&host_name, "%s", optarg);
416
case 'I': /* Server IP-address */
417
asprintf (&server_address, "%s", optarg);
419
case 'u': /* Host or server */
420
asprintf (&server_url, "%s", optarg);
421
server_url_length = strlen (server_url);
423
case 'p': /* Host or server */
424
if (!is_intnonneg (optarg))
425
usage2 ("invalid port number", optarg);
426
server_port = atoi (optarg);
429
case 'a': /* authorization info */
430
strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
431
user_auth[MAX_INPUT_BUFFER - 1] = 0;
433
case 'P': /* HTTP POST data in URL encoded format */
434
asprintf (&http_method, "%s", "POST");
435
asprintf (&http_post_data, "%s", optarg);
437
case 's': /* string or substring */
438
strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
439
string_expect[MAX_INPUT_BUFFER - 1] = 0;
441
case 'e': /* string or substring */
442
strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1);
443
server_expect[MAX_INPUT_BUFFER - 1] = 0;
444
server_expect_yn = 1;
447
case 'l': /* linespan */
448
case 'r': /* linespan */
449
case 'R': /* linespan */
450
usage ("check_http: call for regex which was not a compiled option\n");
453
case 'l': /* linespan */
454
cflags &= ~REG_NEWLINE;
456
case 'R': /* regex */
458
case 'r': /* regex */
459
strncpy (regexp, optarg, MAX_RE_SIZE - 1);
460
regexp[MAX_RE_SIZE - 1] = 0;
461
errcode = regcomp (&preg, regexp, cflags);
463
(void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
464
printf ("Could Not Compile Regular Expression: %s", errbuf);
469
case 'v': /* verbose */
477
if (strcmp (server_address, "") == 0 && c < argc)
478
asprintf (&server_address, "%s", argv[c++]);
480
if (strcmp (host_name, "") == 0 && c < argc)
481
asprintf (&host_name, "%s", argv[c++]);
483
if (strcmp (server_address ,"") == 0) {
484
if (strcmp (host_name, "") == 0)
485
usage ("check_http: you must specify a server address or host name\n");
487
asprintf (&server_address, "%s", host_name);
495
/* written by lauri alanko */
497
base64 (char *bin, int len)
500
char *buf = (char *) malloc ((len + 2) / 3 * 4 + 1);
503
char BASE64_END = '=';
504
char base64_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
506
while (j < len - 2) {
507
buf[i++] = base64_table[bin[j] >> 2];
508
buf[i++] = base64_table[((bin[j] & 3) << 4) | (bin[j + 1] >> 4)];
509
buf[i++] = base64_table[((bin[j + 1] & 15) << 2) | (bin[j + 2] >> 6)];
510
buf[i++] = base64_table[bin[j + 2] & 63];
516
buf[i++] = base64_table[bin[j] >> 2];
517
buf[i++] = base64_table[(bin[j] & 3) << 4];
518
buf[i++] = BASE64_END;
519
buf[i++] = BASE64_END;
522
buf[i++] = base64_table[bin[j] >> 2];
523
buf[i++] = base64_table[((bin[j] & 3) << 4) | (bin[j + 1] >> 4)];
524
buf[i++] = base64_table[(bin[j + 1] & 15) << 2];
525
buf[i++] = BASE64_END;
541
char *status_line = "";
547
char *full_page = "";
551
char *orig_url = NULL;
557
/* try to connect to the host at the given port number */
559
if (use_ssl == TRUE) {
561
if (connect_SSL () != OK) {
562
terminate (STATE_CRITICAL, "Unable to open TCP socket");
565
if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
566
X509_free (server_cert);
569
printf ("ERROR: Cannot retrieve server certificate.\n");
570
return STATE_CRITICAL;
576
if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
577
terminate (STATE_CRITICAL, "Unable to open TCP socket");
582
asprintf (&buf, "%s %s HTTP/1.0\r\n", http_method, server_url);
584
/* optionally send the host header info (not clear if it's usable) */
585
if (strcmp (host_name, ""))
586
asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
588
/* send user agent */
589
asprintf (&buf, "%sUser-Agent: check_http/%s (nagios-plugins %s)\r\n",
590
buf, clean_revstring (REVISION), PACKAGE_VERSION);
592
/* optionally send the authentication info */
593
if (strcmp (user_auth, "")) {
594
auth = base64 (user_auth, strlen (user_auth));
595
asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
598
/* either send http POST data */
599
if (strlen (http_post_data)) {
600
asprintf (&buf, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf);
601
asprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, strlen (http_post_data));
602
asprintf (&buf, "%s%s%s", buf, http_post_data, CRLF);
605
/* or just a newline so the server knows we're done with the request */
606
asprintf (&buf, "%s%s", buf, CRLF);
610
if (use_ssl == TRUE) {
611
if (SSL_write (ssl, buf, strlen (buf)) == -1) {
612
ERR_print_errors_fp (stderr);
613
return STATE_CRITICAL;
618
send (sd, buf, strlen (buf), 0);
624
while ((i = my_recv ()) > 0) {
626
asprintf (&full_page, "%s%s", full_page, buffer);
630
if (i < 0 && errno != ECONNRESET) {
633
sslerr=SSL_get_error(ssl, i);
634
if ( sslerr == SSL_ERROR_SSL ) {
635
terminate (STATE_WARNING, "Client Certificate Required\n");
637
terminate (STATE_CRITICAL, "Error in recv()");
642
terminate (STATE_CRITICAL, "Error in recv()");
648
/* return a CRITICAL status if we couldn't read any data */
649
if (pagesize == (size_t) 0)
650
terminate (STATE_CRITICAL, "No data received %s", timestamp);
652
/* close the connection */
655
/* reset the alarm */
658
/* leave full_page untouched so we can free it later */
662
printf ("Page is %d characters\n", pagesize);
664
/* find status line and null-terminate it */
666
page += (size_t) strcspn (page, "\r\n");
668
page += (size_t) strspn (page, "\r\n");
669
status_line[strcspn(status_line, "\r\n")] = 0;
672
printf ("STATUS: %s\n", status_line);
674
/* find header info and null terminate it */
676
while (strcspn (page, "\r\n") > 0) {
677
page += (size_t) strcspn (page, "\r\n");
679
if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
680
(strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
685
page += (size_t) strspn (page, "\r\n");
686
header[pos - header] = 0;
688
printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header, page);
690
/* make sure the status line matches the response we are looking for */
691
if (!strstr (status_line, server_expect)) {
692
if (server_port == HTTP_PORT)
693
asprintf (&msg, "Invalid HTTP response received from host\n");
696
"Invalid HTTP response received from host on port %d\n",
698
terminate (STATE_CRITICAL, msg);
702
/* Exit here if server_expect was set by user and not default */
703
if ( server_expect_yn ) {
704
asprintf (&msg, "HTTP OK: Status line output matched \"%s\"\n",
713
/* check the return code */
714
/* server errors result in a critical state */
715
if (strstr (status_line, "500") ||
716
strstr (status_line, "501") ||
717
strstr (status_line, "502") ||
718
strstr (status_line, "503")) {
719
terminate (STATE_CRITICAL, "HTTP CRITICAL: %s\n", status_line);
722
/* client errors result in a warning state */
723
if (strstr (status_line, "400") ||
724
strstr (status_line, "401") ||
725
strstr (status_line, "402") ||
726
strstr (status_line, "403") ||
727
strstr (status_line, "404")) {
728
terminate (STATE_WARNING, "HTTP WARNING: %s\n", status_line);
731
/* check redirected page if specified */
732
if (strstr (status_line, "300") ||
733
strstr (status_line, "301") ||
734
strstr (status_line, "302") ||
735
strstr (status_line, "303") ||
736
strstr (status_line, "304")) {
737
if (onredirect == STATE_DEPENDENT) {
739
asprintf (&orig_url, "%s", server_url);
742
server_address = realloc (server_address, MAX_IPV4_HOSTLENGTH + 1);
743
if (server_address == NULL)
744
terminate (STATE_UNKNOWN,
745
"HTTP UNKNOWN: could not allocate server_address");
746
if (strcspn (pos, "\r\n") > server_url_length) {
747
server_url = realloc (server_url, strcspn (pos, "\r\n"));
748
if (server_url == NULL)
749
terminate (STATE_UNKNOWN,
750
"HTTP UNKNOWN: could not allocate server_url");
751
server_url_length = strcspn (pos, "\r\n");
753
if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST URI_PORT URI_PATH, server_type, server_address, server_port_text, server_url) == 4) {
754
asprintf (&host_name, "%s", server_address);
755
use_ssl = server_type_check (server_type);
756
server_port = atoi (server_port_text);
759
else if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST URI_PATH, server_type, server_address, server_url) == 3 ) {
760
asprintf (&host_name, "%s", server_address);
761
use_ssl = server_type_check (server_type);
762
server_port = server_port_check (use_ssl);
765
else if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST URI_PORT, server_type, server_address, server_port_text) == 3) {
766
asprintf (&host_name, "%s", server_address);
767
strcpy (server_url, "/");
768
use_ssl = server_type_check (server_type);
769
server_port = atoi (server_port_text);
772
else if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST, server_type, server_address) == 2) {
773
asprintf (&host_name, "%s", server_address);
774
strcpy (server_url, "/");
775
use_ssl = server_type_check (server_type);
776
server_port = server_port_check (use_ssl);
779
else if (sscanf (pos, HDR_LOCATION URI_PATH, server_url) == 1) {
780
if ((server_url[0] != '/') && (x = strrchr(orig_url, '/'))) {
782
asprintf (&server_url, "%s/%s", orig_url, server_url);
786
pos += (size_t) strcspn (pos, "\r\n");
787
pos += (size_t) strspn (pos, "\r\n");
788
} /* end while (pos) */
789
printf ("HTTP UNKNOWN: Could not find redirect location - %s%s",
790
status_line, (display_html ? "</A>" : ""));
791
exit (STATE_UNKNOWN);
792
} /* end if (onredirect == STATE_DEPENDENT) */
794
else if (onredirect == STATE_UNKNOWN)
795
printf ("HTTP UNKNOWN");
796
else if (onredirect == STATE_OK)
798
else if (onredirect == STATE_WARNING)
799
printf ("HTTP WARNING");
800
else if (onredirect == STATE_CRITICAL)
801
printf ("HTTP CRITICAL");
802
elapsed_time = delta_time (tv);
803
asprintf (&msg, ": %s - %7.3f second response time %s%s|time=%7.3f\n",
804
status_line, elapsed_time, timestamp,
805
(display_html ? "</A>" : ""), elapsed_time);
806
terminate (onredirect, msg);
807
} /* end if (strstr (status_line, "30[0-4]") */
810
} /* end else (server_expect_yn) */
813
/* check elapsed time */
814
elapsed_time = delta_time (tv);
815
asprintf (&msg, "HTTP problem: %s - %7.3f second response time %s%s|time=%7.3f\n",
816
status_line, elapsed_time, timestamp,
817
(display_html ? "</A>" : ""), elapsed_time);
818
if (check_critical_time == TRUE && elapsed_time > critical_time)
819
terminate (STATE_CRITICAL, msg);
820
if (check_warning_time == TRUE && elapsed_time > warning_time)
821
terminate (STATE_WARNING, msg);
823
/* Page and Header content checks go here */
824
/* these checks should be last */
826
if (strlen (string_expect)) {
827
if (strstr (page, string_expect)) {
828
printf ("HTTP ok: %s - %7.3f second response time %s%s|time=%7.3f\n",
829
status_line, elapsed_time,
830
timestamp, (display_html ? "</A>" : ""), elapsed_time);
834
printf ("HTTP CRITICAL: string not found%s|time=%7.3f\n",
835
(display_html ? "</A>" : ""), elapsed_time);
836
exit (STATE_CRITICAL);
840
if (strlen (regexp)) {
841
errcode = regexec (&preg, page, REGS, pmatch, 0);
843
printf ("HTTP ok: %s - %7.3f second response time %s%s|time=%7.3f\n",
844
status_line, elapsed_time,
845
timestamp, (display_html ? "</A>" : ""), elapsed_time);
849
if (errcode == REG_NOMATCH) {
850
printf ("HTTP CRITICAL: pattern not found%s|time=%7.3f\n",
851
(display_html ? "</A>" : ""), elapsed_time);
852
exit (STATE_CRITICAL);
855
regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
856
printf ("Execute Error: %s\n", errbuf);
857
exit (STATE_CRITICAL);
863
/* We only get here if all tests have been passed */
864
asprintf (&msg, "HTTP ok: %s - %7.3f second response time %s%s|time=%7.3f\n",
865
status_line, (float)elapsed_time,
866
timestamp, (display_html ? "</A>" : ""), elapsed_time);
867
terminate (STATE_OK, msg);
868
return STATE_UNKNOWN;
874
int connect_SSL (void)
878
asprintf (&randbuff, "%s", "qwertyuiopasdfghjklqwertyuiopasdfghjkl");
879
RAND_seed (randbuff, strlen (randbuff));
881
printf("SSL seeding: %s\n", (RAND_status()==1 ? "OK" : "Failed") );
883
/* Initialize SSL context */
884
SSLeay_add_ssl_algorithms ();
885
meth = SSLv23_client_method ();
886
SSL_load_error_strings ();
887
if ((ctx = SSL_CTX_new (meth)) == NULL) {
888
printf ("ERROR: Cannot create SSL context.\n");
889
return STATE_CRITICAL;
892
/* Initialize alarm signal handling */
893
signal (SIGALRM, socket_timeout_alarm_handler);
895
/* Set socket timeout */
896
alarm (socket_timeout);
898
/* Save start time */
899
gettimeofday (&tv, NULL);
901
/* Make TCP connection */
902
if (my_tcp_connect (server_address, server_port, &sd) == STATE_OK) {
903
/* Do the SSL handshake */
904
if ((ssl = SSL_new (ctx)) != NULL) {
905
SSL_set_cipher_list(ssl, "ALL");
906
SSL_set_fd (ssl, sd);
907
if (SSL_connect (ssl) != -1)
909
ERR_print_errors_fp (stderr);
912
printf ("ERROR: Cannot initiate SSL handshake.\n");
920
return STATE_CRITICAL;
926
check_certificate (X509 ** certificate)
934
/* Retrieve timestamp of certificate */
935
tm = X509_get_notAfter (*certificate);
937
/* Generate tm structure to process timestamp */
938
if (tm->type == V_ASN1_UTCTIME) {
939
if (tm->length < 10) {
940
printf ("ERROR: Wrong time format in certificate.\n");
941
return STATE_CRITICAL;
944
stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0');
945
if (stamp.tm_year < 50)
946
stamp.tm_year += 100;
951
if (tm->length < 12) {
952
printf ("ERROR: Wrong time format in certificate.\n");
953
return STATE_CRITICAL;
957
(tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
958
(tm->data[2] - '0') * 10 + (tm->data[3] - '0');
959
stamp.tm_year -= 1900;
964
(tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
966
(tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
968
(tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
970
(tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
974
days_left = (mktime (&stamp) - time (NULL)) / 86400;
976
(timestamp, 16, "%02d/%02d/%04d %02d:%02d",
978
stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min);
980
if (days_left > 0 && days_left <= days_till_exp) {
981
printf ("Certificate expires in %d day(s) (%s).\n", days_left, timestamp);
982
return STATE_WARNING;
985
printf ("Certificate expired on %s.\n", timestamp);
986
return STATE_CRITICAL;
989
if (days_left == 0) {
990
printf ("Certificate expires today (%s).\n", timestamp);
991
return STATE_WARNING;
994
printf ("Certificate will expire on %s.\n", timestamp);
1008
i = SSL_read (ssl, buffer, MAX_INPUT_BUFFER - 1);
1011
i = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
1014
i = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
1024
if (use_ssl == TRUE) {
1043
print_revision (progname, REVISION);
1045
("Copyright (c) %s %s <%s>\n\n%s\n",
1046
COPYRIGHT, AUTHORS, EMAIL, SUMMARY);
1048
printf ("NOTE: One or both of -H and -I must be specified\n");
1049
printf ("\nOptions:\n" LONGOPTIONS "\n", HTTP_EXPECT, HTTP_PORT,
1050
DEFAULT_SOCKET_TIMEOUT, SSLOPTIONS, REGOPTIONS);
1052
printf (SSLDESCRIPTION);
1060
printf ("Usage:\n" " %s %s\n"
1061
#ifdef HAVE_GETOPT_H
1062
" %s (-h | --help) for detailed help\n"
1063
" %s (-V | --version) for version information\n",
1065
" %s -h for detailed help\n"
1066
" %s -V for version information\n",
1068
progname, OPTIONS, progname, progname);