diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/check_curl.c | 1162 |
1 files changed, 574 insertions, 588 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c index 8ef48d0c..8ed1aeeb 100644 --- a/plugins/check_curl.c +++ b/plugins/check_curl.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | * normal (http) and secure (https) servers, follow redirects, search for | 13 | * normal (http) and secure (https) servers, follow redirects, search for |
| 14 | * strings and regular expressions, check connection times, and report on | 14 | * strings and regular expressions, check connection times, and report on |
| 15 | * certificate expiration times. | 15 | * certificate expiration times. |
| 16 | * | 16 | * |
| 17 | * This plugin uses functions from the curl library, see | 17 | * This plugin uses functions from the curl library, see |
| 18 | * http://curl.haxx.se | 18 | * http://curl.haxx.se |
| 19 | * | 19 | * |
| @@ -40,20 +40,6 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 40 | #include "common.h" | 40 | #include "common.h" |
| 41 | #include "utils.h" | 41 | #include "utils.h" |
| 42 | 42 | ||
| 43 | #ifdef HAVE_SYS_TYPES_H | ||
| 44 | #include <sys/types.h> | ||
| 45 | #else | ||
| 46 | #define unsigned int size_t | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #ifdef HAVE_STRING_H | ||
| 50 | #include <string.h> | ||
| 51 | #endif | ||
| 52 | |||
| 53 | #ifdef HAVE_STDLIB_H | ||
| 54 | #include <stdlib.h> | ||
| 55 | #endif | ||
| 56 | |||
| 57 | #ifndef LIBCURL_PROTOCOL_HTTP | 43 | #ifndef LIBCURL_PROTOCOL_HTTP |
| 58 | #error libcurl compiled without HTTP support, compiling check_curl plugin makes not much sense | 44 | #error libcurl compiled without HTTP support, compiling check_curl plugin makes not much sense |
| 59 | #endif | 45 | #endif |
| @@ -69,21 +55,21 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 69 | 55 | ||
| 70 | /* for buffers for header and body */ | 56 | /* for buffers for header and body */ |
| 71 | typedef struct { | 57 | typedef struct { |
| 72 | char *buf; | 58 | char *buf; |
| 73 | size_t buflen; | 59 | size_t buflen; |
| 74 | size_t bufsize; | 60 | size_t bufsize; |
| 75 | } curlhelp_curlbuf; | 61 | } curlhelp_curlbuf; |
| 76 | 62 | ||
| 77 | /* for parsing the HTTP status line */ | 63 | /* for parsing the HTTP status line */ |
| 78 | typedef struct { | 64 | typedef struct { |
| 79 | int http_major; /* major version of the protocol, always 1 (HTTP/0.9 | 65 | int http_major; /* major version of the protocol, always 1 (HTTP/0.9 |
| 80 | * never reached the big internet most likely) */ | 66 | * never reached the big internet most likely) */ |
| 81 | int http_minor; /* minor version of the protocol, usually 0 or 1 */ | 67 | int http_minor; /* minor version of the protocol, usually 0 or 1 */ |
| 82 | int http_code; /* HTTP return code as in RFC 2145 */ | 68 | int http_code; /* HTTP return code as in RFC 2145 */ |
| 83 | int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see | 69 | int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see |
| 84 | * http://support.microsoft.com/kb/318380/en-us */ | 70 | * http://support.microsoft.com/kb/318380/en-us */ |
| 85 | char *msg; /* the human readable message */ | 71 | char *msg; /* the human readable message */ |
| 86 | char *first_line; /* a copy of the first line */ | 72 | char *first_line; /* a copy of the first line */ |
| 87 | } curlhelp_statusline; | 73 | } curlhelp_statusline; |
| 88 | 74 | ||
| 89 | char *server_address; | 75 | char *server_address; |
| @@ -137,587 +123,587 @@ void test_file (char *); | |||
| 137 | int | 123 | int |
| 138 | main (int argc, char **argv) | 124 | main (int argc, char **argv) |
| 139 | { | 125 | { |
| 140 | int result = STATE_OK; | 126 | int result = STATE_OK; |
| 141 | 127 | ||
| 142 | setlocale (LC_ALL, ""); | 128 | setlocale (LC_ALL, ""); |
| 143 | bindtextdomain (PACKAGE, LOCALEDIR); | 129 | bindtextdomain (PACKAGE, LOCALEDIR); |
| 144 | textdomain (PACKAGE); | 130 | textdomain (PACKAGE); |
| 145 | 131 | ||
| 146 | /* Parse extra opts if any */ | 132 | /* Parse extra opts if any */ |
| 147 | argv = np_extra_opts (&argc, argv, progname); | 133 | argv = np_extra_opts (&argc, argv, progname); |
| 148 | 134 | ||
| 149 | /* set defaults */ | 135 | /* set defaults */ |
| 150 | snprintf( user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s)", | 136 | snprintf( user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s)", |
| 151 | progname, NP_VERSION, VERSION); | 137 | progname, NP_VERSION, VERSION); |
| 152 | 138 | ||
| 153 | /* parse arguments */ | 139 | /* parse arguments */ |
| 154 | if (process_arguments (argc, argv) == ERROR) | 140 | if (process_arguments (argc, argv) == ERROR) |
| 155 | usage4 (_("Could not parse arguments")); | 141 | usage4 (_("Could not parse arguments")); |
| 156 | 142 | ||
| 157 | /* initialize curl */ | 143 | /* initialize curl */ |
| 158 | if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) | 144 | if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) |
| 159 | die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); | 145 | die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); |
| 160 | 146 | ||
| 161 | if ((curl = curl_easy_init()) == NULL) | 147 | if ((curl = curl_easy_init()) == NULL) |
| 162 | die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); | 148 | die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); |
| 163 | 149 | ||
| 164 | if (verbose >= 3) | 150 | if (verbose >= 3) |
| 165 | curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE); | 151 | curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE); |
| 166 | 152 | ||
| 167 | /* initialize buffer for body of the answer */ | 153 | /* initialize buffer for body of the answer */ |
| 168 | if (curlhelp_initbuffer(&body_buf) < 0) | 154 | if (curlhelp_initbuffer(&body_buf) < 0) |
| 169 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); | 155 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); |
| 170 | curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_callback); | 156 | curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_callback); |
| 171 | curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf); | 157 | curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf); |
| 172 | 158 | ||
| 173 | /* initialize buffer for header of the answer */ | 159 | /* initialize buffer for header of the answer */ |
| 174 | if (curlhelp_initbuffer( &header_buf ) < 0) | 160 | if (curlhelp_initbuffer( &header_buf ) < 0) |
| 175 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); | 161 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); |
| 176 | curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_callback); | 162 | curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_callback); |
| 177 | curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf); | 163 | curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf); |
| 178 | 164 | ||
| 179 | /* set the error buffer */ | 165 | /* set the error buffer */ |
| 180 | curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf); | 166 | curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf); |
| 181 | 167 | ||
| 182 | /* set timeouts */ | 168 | /* set timeouts */ |
| 183 | curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout); | 169 | curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout); |
| 184 | curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout); | 170 | curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout); |
| 185 | 171 | ||
| 186 | /* compose URL */ | 172 | /* compose URL */ |
| 187 | snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s%s", use_ssl ? "https" : "http", | 173 | snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s%s", use_ssl ? "https" : "http", |
| 188 | server_address, server_url); | 174 | server_address, server_url); |
| 189 | curl_easy_setopt (curl, CURLOPT_URL, url); | 175 | curl_easy_setopt (curl, CURLOPT_URL, url); |
| 190 | 176 | ||
| 191 | /* set port */ | 177 | /* set port */ |
| 192 | curl_easy_setopt (curl, CURLOPT_PORT, server_port); | 178 | curl_easy_setopt (curl, CURLOPT_PORT, server_port); |
| 193 | 179 | ||
| 194 | /* compose HTTP headers */ | 180 | /* compose HTTP headers */ |
| 195 | snprintf (http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); | 181 | snprintf (http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); |
| 196 | header_list = curl_slist_append (header_list, http_header); | 182 | header_list = curl_slist_append (header_list, http_header); |
| 197 | curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ); | 183 | curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ); |
| 198 | 184 | ||
| 199 | /* set SSL version, warn about unsecure or unsupported versions */ | 185 | /* set SSL version, warn about unsecure or unsupported versions */ |
| 200 | if (use_ssl) { | 186 | if (use_ssl) { |
| 201 | curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version); | 187 | curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version); |
| 202 | } | 188 | } |
| 203 | 189 | ||
| 204 | /* client certificate and key to present to server (SSL) */ | 190 | /* client certificate and key to present to server (SSL) */ |
| 205 | if (client_cert) | 191 | if (client_cert) |
| 206 | curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert); | 192 | curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert); |
| 207 | if (client_privkey) | 193 | if (client_privkey) |
| 208 | curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey); | 194 | curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey); |
| 209 | 195 | ||
| 210 | /* per default if we have a CA verify both the peer and the | 196 | /* per default if we have a CA verify both the peer and the |
| 211 | * hostname in the certificate, can be switched off later */ | 197 | * hostname in the certificate, can be switched off later */ |
| 212 | curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2); | 198 | curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2); |
| 213 | curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2); | 199 | curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2); |
| 214 | 200 | ||
| 215 | /* backward-compatible behaviour, be tolerant in checks */ | 201 | /* backward-compatible behaviour, be tolerant in checks */ |
| 216 | if (!check_cert) { | 202 | if (!check_cert) { |
| 217 | //TODO: depending on more options have aspects we want | 203 | //TODO: depending on more options have aspects we want |
| 218 | //to be tolerant about | 204 | //to be tolerant about |
| 219 | //curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1 ); | 205 | //curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1 ); |
| 220 | curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0); | 206 | curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0); |
| 221 | curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0); | 207 | curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0); |
| 222 | } | 208 | } |
| 223 | 209 | ||
| 224 | /* set default or user-given user agent identification */ | 210 | /* set default or user-given user agent identification */ |
| 225 | curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent); | 211 | curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent); |
| 226 | 212 | ||
| 227 | /* authentication */ | 213 | /* authentication */ |
| 228 | if (strcmp(user_auth, "")) | 214 | if (strcmp(user_auth, "")) |
| 229 | curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth); | 215 | curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth); |
| 230 | 216 | ||
| 231 | /* TODO: parameter auth method, bitfield of following methods: | 217 | /* TODO: parameter auth method, bitfield of following methods: |
| 232 | * CURLAUTH_BASIC (default) | 218 | * CURLAUTH_BASIC (default) |
| 233 | * CURLAUTH_DIGEST | 219 | * CURLAUTH_DIGEST |
| 234 | * CURLAUTH_DIGEST_IE | 220 | * CURLAUTH_DIGEST_IE |
| 235 | * CURLAUTH_NEGOTIATE | 221 | * CURLAUTH_NEGOTIATE |
| 236 | * CURLAUTH_NTLM | 222 | * CURLAUTH_NTLM |
| 237 | * CURLAUTH_NTLM_WB | 223 | * CURLAUTH_NTLM_WB |
| 238 | * | 224 | * |
| 239 | * convenience tokens for typical sets of methods: | 225 | * convenience tokens for typical sets of methods: |
| 240 | * CURLAUTH_ANYSAFE: most secure, without BASIC | 226 | * CURLAUTH_ANYSAFE: most secure, without BASIC |
| 241 | * or CURLAUTH_ANY: most secure, even BASIC if necessary | 227 | * or CURLAUTH_ANY: most secure, even BASIC if necessary |
| 242 | * | 228 | * |
| 243 | * curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ); | 229 | * curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ); |
| 244 | */ | 230 | */ |
| 245 | 231 | ||
| 246 | /* TODO: --cacert: CA certificate file to verify SSL connection against (SSL) */ | 232 | /* TODO: --cacert: CA certificate file to verify SSL connection against (SSL) */ |
| 247 | //~ if( args_info.cacert_given ) { | 233 | //~ if( args_info.cacert_given ) { |
| 248 | //~ curl_easy_setopt( curl, CURLOPT_CAINFO, args_info.cacert_arg ); | 234 | //~ curl_easy_setopt( curl, CURLOPT_CAINFO, args_info.cacert_arg ); |
| 249 | //~ } | 235 | //~ } |
| 250 | 236 | ||
| 251 | /* handle redirections */ | 237 | /* handle redirections */ |
| 252 | if (onredirect == STATE_DEPENDENT) { | 238 | if (onredirect == STATE_DEPENDENT) { |
| 253 | curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); | 239 | curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); |
| 254 | /* TODO: handle the following aspects of redirection | 240 | /* TODO: handle the following aspects of redirection |
| 255 | CURLOPT_POSTREDIR: method switch | 241 | CURLOPT_POSTREDIR: method switch |
| 256 | CURLINFO_REDIRECT_URL: custom redirect option | 242 | CURLINFO_REDIRECT_URL: custom redirect option |
| 257 | CURLOPT_REDIRECT_PROTOCOLS | 243 | CURLOPT_REDIRECT_PROTOCOLS |
| 258 | CURLINFO_REDIRECT_COUNT | 244 | CURLINFO_REDIRECT_COUNT |
| 259 | */ | 245 | */ |
| 260 | } | 246 | } |
| 261 | 247 | ||
| 262 | /* do the request */ | 248 | /* do the request */ |
| 263 | res = curl_easy_perform(curl); | 249 | res = curl_easy_perform(curl); |
| 264 | 250 | ||
| 265 | /* free header list, we don't need it anymore */ | 251 | /* free header list, we don't need it anymore */ |
| 266 | curl_slist_free_all (header_list); | 252 | curl_slist_free_all (header_list); |
| 267 | 253 | ||
| 268 | /* Curl errors, result in critical Nagios state */ | 254 | /* Curl errors, result in critical Nagios state */ |
| 269 | if (res != CURLE_OK) { | 255 | if (res != CURLE_OK) { |
| 270 | remove_newlines (errbuf); | 256 | remove_newlines (errbuf); |
| 271 | snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s\n"), | 257 | snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s\n"), |
| 272 | server_port, res, curl_easy_strerror(res)); | 258 | server_port, res, curl_easy_strerror(res)); |
| 273 | die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | 259 | die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); |
| 274 | } | 260 | } |
| 275 | 261 | ||
| 276 | /* we got the data and we executed the request in a given time, so we can append | 262 | /* we got the data and we executed the request in a given time, so we can append |
| 277 | * performance data to the answer always | 263 | * performance data to the answer always |
| 278 | */ | 264 | */ |
| 279 | curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time); | 265 | curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time); |
| 280 | snprintf (perfstring, DEFAULT_BUFFER_SIZE, "time=%.6gs;%.6g;%.6g;%.6g size=%dB;;;0", | 266 | snprintf (perfstring, DEFAULT_BUFFER_SIZE, "time=%.6gs;%.6g;%.6g;%.6g size=%dB;;;0", |
| 281 | total_time, | 267 | total_time, |
| 282 | 0.0, 0.0, | 268 | 0.0, 0.0, |
| 283 | //~ args_info.warning_given ? args_info.warning_arg : 0.0, | 269 | //~ args_info.warning_given ? args_info.warning_arg : 0.0, |
| 284 | //~ args_info.critical_given ? args_info.critical_arg : 0.0, | 270 | //~ args_info.critical_given ? args_info.critical_arg : 0.0, |
| 285 | 0.0, | 271 | 0.0, |
| 286 | (int)body_buf.buflen); | 272 | (int)body_buf.buflen); |
| 287 | 273 | ||
| 288 | /* return a CRITICAL status if we couldn't read any data */ | 274 | /* return a CRITICAL status if we couldn't read any data */ |
| 289 | if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0) | 275 | if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0) |
| 290 | die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n")); | 276 | die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n")); |
| 291 | 277 | ||
| 292 | /* get status line of answer, check sanity of HTTP code */ | 278 | /* get status line of answer, check sanity of HTTP code */ |
| 293 | if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) { | 279 | if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) { |
| 294 | snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparseable status line in %.3g seconds response time|%s\n", | 280 | snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparseable status line in %.3g seconds response time|%s\n", |
| 295 | code, total_time, perfstring); | 281 | code, total_time, perfstring); |
| 296 | die (STATE_CRITICAL, "HTTP CRITICAL HTTP/1.x %d unknown - %s", code, msg); | 282 | die (STATE_CRITICAL, "HTTP CRITICAL HTTP/1.x %d unknown - %s", code, msg); |
| 297 | } | 283 | } |
| 298 | 284 | ||
| 299 | /* get result code from cURL */ | 285 | /* get result code from cURL */ |
| 300 | curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code); | 286 | curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code); |
| 301 | if (verbose>=2) | 287 | if (verbose>=2) |
| 302 | printf ("* curl CURLINFO_RESPONSE_CODE is %d\n", code); | 288 | printf ("* curl CURLINFO_RESPONSE_CODE is %d\n", code); |
| 303 | 289 | ||
| 304 | /* print status line, header, body if verbose */ | 290 | /* print status line, header, body if verbose */ |
| 305 | if (verbose >= 2) { | 291 | if (verbose >= 2) { |
| 306 | puts ("--- HEADER ---"); | 292 | puts ("--- HEADER ---"); |
| 307 | puts (header_buf.buf); | 293 | puts (header_buf.buf); |
| 308 | puts ("--- BODY ---"); | 294 | puts ("--- BODY ---"); |
| 309 | puts (body_buf.buf); | 295 | puts (body_buf.buf); |
| 310 | } | 296 | } |
| 311 | 297 | ||
| 312 | /* illegal return codes result in a critical state */ | 298 | /* illegal return codes result in a critical state */ |
| 313 | if (code >= 600 || code < 100) { | 299 | if (code >= 600 || code < 100) { |
| 314 | die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg); | 300 | die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg); |
| 315 | /* server errors result in a critical state */ | 301 | /* server errors result in a critical state */ |
| 316 | } else if (code >= 500) { | 302 | } else if (code >= 500) { |
| 317 | result = STATE_CRITICAL; | 303 | result = STATE_CRITICAL; |
| 318 | /* client errors result in a warning state */ | 304 | /* client errors result in a warning state */ |
| 319 | } else if (code >= 400) { | 305 | } else if (code >= 400) { |
| 320 | result = STATE_WARNING; | 306 | result = STATE_WARNING; |
| 321 | /* check redirected page if specified */ | 307 | /* check redirected page if specified */ |
| 322 | } else if (code >= 300) { | 308 | } else if (code >= 300) { |
| 323 | if (onredirect == STATE_DEPENDENT) { | 309 | if (onredirect == STATE_DEPENDENT) { |
| 324 | code = status_line.http_code; | 310 | code = status_line.http_code; |
| 325 | } | 311 | } |
| 326 | result = max_state_alt (onredirect, result); | 312 | result = max_state_alt (onredirect, result); |
| 327 | /* TODO: make sure the last status line has been | 313 | /* TODO: make sure the last status line has been |
| 328 | parsed into the status_line structure | 314 | parsed into the status_line structure |
| 329 | */ | 315 | */ |
| 330 | /* all other codes are considered ok */ | 316 | /* all other codes are considered ok */ |
| 331 | } else { | 317 | } else { |
| 332 | result = STATE_OK; | 318 | result = STATE_OK; |
| 333 | } | 319 | } |
| 334 | 320 | ||
| 335 | /* check status codes, set exit status accordingly */ | 321 | /* check status codes, set exit status accordingly */ |
| 336 | if( status_line.http_code != code ) { | 322 | if( status_line.http_code != code ) { |
| 337 | die (STATE_CRITICAL, _("HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld)\n"), | 323 | die (STATE_CRITICAL, _("HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld)\n"), |
| 338 | status_line.http_major, status_line.http_minor, | 324 | status_line.http_major, status_line.http_minor, |
| 339 | status_line.http_code, status_line.msg, code); | 325 | status_line.http_code, status_line.msg, code); |
| 340 | } | 326 | } |
| 341 | 327 | ||
| 342 | /* Page and Header content checks go here */ | 328 | /* Page and Header content checks go here */ |
| 343 | if (strlen (string_expect)) { | 329 | if (strlen (string_expect)) { |
| 344 | if (!strstr (body_buf.buf, string_expect)) { | 330 | if (!strstr (body_buf.buf, string_expect)) { |
| 345 | strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); | 331 | strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); |
| 346 | if(output_string_search[sizeof(output_string_search)-1]!='\0') { | 332 | if(output_string_search[sizeof(output_string_search)-1]!='\0') { |
| 347 | bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); | 333 | bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); |
| 348 | } | 334 | } |
| 349 | snprintf (msg, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); | 335 | snprintf (msg, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); |
| 350 | result = STATE_CRITICAL; | 336 | result = STATE_CRITICAL; |
| 351 | } | 337 | } |
| 352 | } | 338 | } |
| 353 | 339 | ||
| 354 | /* -w, -c: check warning and critical level */ | 340 | /* -w, -c: check warning and critical level */ |
| 355 | result = max_state_alt(get_status(total_time, thlds), result); | 341 | result = max_state_alt(get_status(total_time, thlds), result); |
| 356 | 342 | ||
| 357 | //~ die (result, "HTTP %s: %s\n", state_text(result), msg); | 343 | //~ die (result, "HTTP %s: %s\n", state_text(result), msg); |
| 358 | die (result, "HTTP %s HTTP/%d.%d %d %s - %s - %.3g seconds response time|%s\n", | 344 | die (result, "HTTP %s HTTP/%d.%d %d %s - %s - %.3g seconds response time|%s\n", |
| 359 | state_text(result), status_line.http_major, status_line.http_minor, | 345 | state_text(result), status_line.http_major, status_line.http_minor, |
| 360 | status_line.http_code, status_line.msg, msg, | 346 | status_line.http_code, status_line.msg, msg, |
| 361 | total_time, perfstring); | 347 | total_time, perfstring); |
| 362 | 348 | ||
| 363 | /* proper cleanup after die? */ | 349 | /* proper cleanup after die? */ |
| 364 | curlhelp_free_statusline(&status_line); | 350 | curlhelp_free_statusline(&status_line); |
| 365 | curl_easy_cleanup (curl); | 351 | curl_easy_cleanup (curl); |
| 366 | curl_global_cleanup (); | 352 | curl_global_cleanup (); |
| 367 | curlhelp_freebuffer(&body_buf); | 353 | curlhelp_freebuffer(&body_buf); |
| 368 | curlhelp_freebuffer(&header_buf); | 354 | curlhelp_freebuffer(&header_buf); |
| 369 | 355 | ||
| 370 | return result; | 356 | return result; |
| 371 | } | 357 | } |
| 372 | 358 | ||
| 373 | /* check whether a file exists */ | 359 | /* check whether a file exists */ |
| 374 | void | 360 | void |
| 375 | test_file (char *path) | 361 | test_file (char *path) |
| 376 | { | 362 | { |
| 377 | if (access(path, R_OK) == 0) | 363 | if (access(path, R_OK) == 0) |
| 378 | return; | 364 | return; |
| 379 | usage2 (_("file does not exist or is not readable"), path); | 365 | usage2 (_("file does not exist or is not readable"), path); |
| 380 | } | 366 | } |
| 381 | 367 | ||
| 382 | int | 368 | int |
| 383 | process_arguments (int argc, char **argv) | 369 | process_arguments (int argc, char **argv) |
| 384 | { | 370 | { |
| 385 | int c; | 371 | int c; |
| 386 | 372 | ||
| 387 | enum { | 373 | enum { |
| 388 | SNI_OPTION | 374 | SNI_OPTION |
| 389 | }; | 375 | }; |
| 390 | 376 | ||
| 391 | int option=0; | 377 | int option=0; |
| 392 | static struct option longopts[] = { | 378 | static struct option longopts[] = { |
| 393 | {"ssl", optional_argument, 0, 'S'}, | 379 | {"ssl", optional_argument, 0, 'S'}, |
| 394 | {"sni", no_argument, 0, SNI_OPTION}, | 380 | {"sni", no_argument, 0, SNI_OPTION}, |
| 395 | {"IP-address", required_argument, 0, 'I'}, | 381 | {"IP-address", required_argument, 0, 'I'}, |
| 396 | {"url", required_argument, 0, 'u'}, | 382 | {"url", required_argument, 0, 'u'}, |
| 397 | {"port", required_argument, 0, 'p'}, | 383 | {"port", required_argument, 0, 'p'}, |
| 398 | {"authorization", required_argument, 0, 'a'}, | 384 | {"authorization", required_argument, 0, 'a'}, |
| 399 | {"string", required_argument, 0, 's'}, | 385 | {"string", required_argument, 0, 's'}, |
| 400 | {"onredirect", required_argument, 0, 'f'}, | 386 | {"onredirect", required_argument, 0, 'f'}, |
| 401 | {"client-cert", required_argument, 0, 'J'}, | 387 | {"client-cert", required_argument, 0, 'J'}, |
| 402 | {"private-key", required_argument, 0, 'K'}, | 388 | {"private-key", required_argument, 0, 'K'}, |
| 403 | {"useragent", required_argument, 0, 'A'}, | 389 | {"useragent", required_argument, 0, 'A'}, |
| 404 | {"certificate", required_argument, 0, 'C'}, | 390 | {"certificate", required_argument, 0, 'C'}, |
| 405 | {0, 0, 0, 0} | 391 | {0, 0, 0, 0} |
| 406 | }; | 392 | }; |
| 407 | 393 | ||
| 408 | if (argc < 2) | 394 | if (argc < 2) |
| 409 | usage ("\n"); | 395 | usage ("\n"); |
| 410 | 396 | ||
| 411 | while (1) { | 397 | while (1) { |
| 412 | c = getopt_long (argc, argv, "Vvht:c:w:A:H:I:a:p:s:u:f:C:J:K:S::", longopts, &option); | 398 | c = getopt_long (argc, argv, "Vvht:c:w:A:H:I:a:p:s:u:f:C:J:K:S::", longopts, &option); |
| 413 | if (c == -1 || c == EOF || c == 1) | 399 | if (c == -1 || c == EOF || c == 1) |
| 414 | break; | 400 | break; |
| 415 | 401 | ||
| 416 | switch (c) { | 402 | switch (c) { |
| 417 | case 'h': | 403 | case 'h': |
| 418 | print_help(); | 404 | print_help(); |
| 419 | exit(STATE_UNKNOWN); | 405 | exit(STATE_UNKNOWN); |
| 420 | break; | 406 | break; |
| 421 | case 'V': | 407 | case 'V': |
| 422 | print_revision(progname, NP_VERSION); | 408 | print_revision(progname, NP_VERSION); |
| 423 | print_curl_version(); | 409 | print_curl_version(); |
| 424 | exit(STATE_UNKNOWN); | 410 | exit(STATE_UNKNOWN); |
| 425 | break; | 411 | break; |
| 426 | case 'v': | 412 | case 'v': |
| 427 | verbose++; | 413 | verbose++; |
| 428 | break; | 414 | break; |
| 429 | case 't': /* timeout period */ | 415 | case 't': /* timeout period */ |
| 430 | if (!is_intnonneg (optarg)) | 416 | if (!is_intnonneg (optarg)) |
| 431 | usage2 (_("Timeout interval must be a positive integer"), optarg); | 417 | usage2 (_("Timeout interval must be a positive integer"), optarg); |
| 432 | else | 418 | else |
| 433 | socket_timeout = (int)strtol (optarg, NULL, 10); | 419 | socket_timeout = (int)strtol (optarg, NULL, 10); |
| 434 | break; | 420 | break; |
| 435 | case 'c': /* critical time threshold */ | 421 | case 'c': /* critical time threshold */ |
| 436 | critical_thresholds = optarg; | 422 | critical_thresholds = optarg; |
| 437 | break; | 423 | break; |
| 438 | case 'w': /* warning time threshold */ | 424 | case 'w': /* warning time threshold */ |
| 439 | warning_thresholds = optarg; | 425 | warning_thresholds = optarg; |
| 440 | break; | 426 | break; |
| 441 | case 'H': /* virtual host */ | 427 | case 'H': /* virtual host */ |
| 442 | host_name = strdup (optarg); | 428 | host_name = strdup (optarg); |
| 443 | break; | 429 | break; |
| 444 | case 'I': /* internet address */ | 430 | case 'I': /* internet address */ |
| 445 | server_address = strdup (optarg); | 431 | server_address = strdup (optarg); |
| 446 | break; | 432 | break; |
| 447 | case 'u': /* URL path */ | 433 | case 'u': /* URL path */ |
| 448 | server_url = strdup (optarg); | 434 | server_url = strdup (optarg); |
| 449 | break; | 435 | break; |
| 450 | case 'p': /* Server port */ | 436 | case 'p': /* Server port */ |
| 451 | if (!is_intnonneg (optarg)) | 437 | if (!is_intnonneg (optarg)) |
| 452 | usage2 (_("Invalid port number, expecting a non-negative number"), optarg); | 438 | usage2 (_("Invalid port number, expecting a non-negative number"), optarg); |
| 453 | else { | 439 | else { |
| 454 | if( strtol(optarg, NULL, 10) > MAX_PORT) | 440 | if( strtol(optarg, NULL, 10) > MAX_PORT) |
| 455 | usage2 (_("Invalid port number, supplied port number is too big"), optarg); | 441 | usage2 (_("Invalid port number, supplied port number is too big"), optarg); |
| 456 | server_port = (unsigned short)strtol(optarg, NULL, 10); | 442 | server_port = (unsigned short)strtol(optarg, NULL, 10); |
| 457 | } | 443 | } |
| 458 | break; | 444 | break; |
| 459 | case 'a': /* authorization info */ | 445 | case 'a': /* authorization info */ |
| 460 | strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); | 446 | strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); |
| 461 | user_auth[MAX_INPUT_BUFFER - 1] = 0; | 447 | user_auth[MAX_INPUT_BUFFER - 1] = 0; |
| 462 | break; | 448 | break; |
| 463 | case 'A': /* useragent */ | 449 | case 'A': /* useragent */ |
| 464 | snprintf (user_agent, DEFAULT_BUFFER_SIZE, optarg); | 450 | snprintf (user_agent, DEFAULT_BUFFER_SIZE, optarg); |
| 465 | break; | 451 | break; |
| 466 | case 'C': /* Check SSL cert validity */ | 452 | case 'C': /* Check SSL cert validity */ |
| 467 | #ifdef LIBCURL_FEATURE_SSL | 453 | #ifdef LIBCURL_FEATURE_SSL |
| 468 | /* TODO: C:, check age of certificate for backward compatible | 454 | /* TODO: C:, check age of certificate for backward compatible |
| 469 | * behaviour, but we would later add more check conditions */ | 455 | * behaviour, but we would later add more check conditions */ |
| 470 | check_cert = TRUE; | 456 | check_cert = TRUE; |
| 471 | goto enable_ssl; | 457 | goto enable_ssl; |
| 472 | #endif | 458 | #endif |
| 473 | case 'J': /* use client certificate */ | 459 | case 'J': /* use client certificate */ |
| 474 | #ifdef LIBCURL_FEATURE_SSL | 460 | #ifdef LIBCURL_FEATURE_SSL |
| 475 | test_file(optarg); | 461 | test_file(optarg); |
| 476 | client_cert = optarg; | 462 | client_cert = optarg; |
| 477 | goto enable_ssl; | 463 | goto enable_ssl; |
| 478 | #endif | 464 | #endif |
| 479 | case 'K': /* use client private key */ | 465 | case 'K': /* use client private key */ |
| 480 | #ifdef LIBCURL_FEATURE_SSL | 466 | #ifdef LIBCURL_FEATURE_SSL |
| 481 | test_file(optarg); | 467 | test_file(optarg); |
| 482 | client_privkey = optarg; | 468 | client_privkey = optarg; |
| 483 | goto enable_ssl; | 469 | goto enable_ssl; |
| 484 | #endif | 470 | #endif |
| 485 | case 'S': /* use SSL */ | 471 | case 'S': /* use SSL */ |
| 486 | #ifdef LIBCURL_FEATURE_SSL | 472 | #ifdef LIBCURL_FEATURE_SSL |
| 487 | enable_ssl: | 473 | enable_ssl: |
| 488 | use_ssl = TRUE; | 474 | use_ssl = TRUE; |
| 489 | /* ssl_version initialized to CURL_SSLVERSION_TLSv1_0 as a default. Only set if it's non-zero. This helps when we include multiple | 475 | /* ssl_version initialized to CURL_SSLVERSION_TLSv1_0 as a default. Only set if it's non-zero. This helps when we include multiple |
| 490 | parameters, like -S and -C combinations */ | 476 | parameters, like -S and -C combinations */ |
| 491 | ssl_version = CURL_SSLVERSION_TLSv1_0; | 477 | ssl_version = CURL_SSLVERSION_TLSv1_0; |
| 492 | if (c=='S' && optarg != NULL) { | 478 | if (c=='S' && optarg != NULL) { |
| 493 | int got_plus = strchr(optarg, '+') != NULL; | 479 | int got_plus = strchr(optarg, '+') != NULL; |
| 494 | 480 | ||
| 495 | if (!strncmp (optarg, "1.2", 3)) | 481 | if (!strncmp (optarg, "1.2", 3)) |
| 496 | ssl_version = CURL_SSLVERSION_TLSv1_2; | 482 | ssl_version = CURL_SSLVERSION_TLSv1_2; |
| 497 | else if (!strncmp (optarg, "1.1", 3)) | 483 | else if (!strncmp (optarg, "1.1", 3)) |
| 498 | ssl_version = CURL_SSLVERSION_TLSv1_1; | 484 | ssl_version = CURL_SSLVERSION_TLSv1_1; |
| 499 | else if (optarg[0] == '1') | 485 | else if (optarg[0] == '1') |
| 500 | ssl_version = CURL_SSLVERSION_TLSv1_0; | 486 | ssl_version = CURL_SSLVERSION_TLSv1_0; |
| 501 | else if (optarg[0] == '3') | 487 | else if (optarg[0] == '3') |
| 502 | ssl_version = CURL_SSLVERSION_SSLv3; | 488 | ssl_version = CURL_SSLVERSION_SSLv3; |
| 503 | else if (optarg[0] == '2') | 489 | else if (optarg[0] == '2') |
| 504 | ssl_version = CURL_SSLVERSION_SSLv2; | 490 | ssl_version = CURL_SSLVERSION_SSLv2; |
| 505 | else | 491 | else |
| 506 | usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)")); | 492 | usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)")); |
| 507 | } | 493 | } |
| 508 | if (server_port == DEFAULT_HTTP_PORT) | 494 | if (server_port == DEFAULT_HTTP_PORT) |
| 509 | server_port = DEFAULT_HTTPS_PORT; | 495 | server_port = DEFAULT_HTTPS_PORT; |
| 510 | #else | 496 | #else |
| 511 | /* -C -J and -K fall through to here without SSL */ | 497 | /* -C -J and -K fall through to here without SSL */ |
| 512 | usage4 (_("Invalid option - SSL is not available")); | 498 | usage4 (_("Invalid option - SSL is not available")); |
| 513 | #endif | 499 | #endif |
| 514 | break; | 500 | break; |
| 515 | case SNI_OPTION: /* --sni is parsed, but ignored, the default is TRUE with libcurl */ | 501 | case SNI_OPTION: /* --sni is parsed, but ignored, the default is TRUE with libcurl */ |
| 516 | use_sni = TRUE; | 502 | use_sni = TRUE; |
| 517 | break; | 503 | break; |
| 518 | case 'f': /* onredirect */ | 504 | case 'f': /* onredirect */ |
| 519 | if (!strcmp (optarg, "ok")) | 505 | if (!strcmp (optarg, "ok")) |
| 520 | onredirect = STATE_OK; | 506 | onredirect = STATE_OK; |
| 521 | else if (!strcmp (optarg, "warning")) | 507 | else if (!strcmp (optarg, "warning")) |
| 522 | onredirect = STATE_WARNING; | 508 | onredirect = STATE_WARNING; |
| 523 | else if (!strcmp (optarg, "critical")) | 509 | else if (!strcmp (optarg, "critical")) |
| 524 | onredirect = STATE_CRITICAL; | 510 | onredirect = STATE_CRITICAL; |
| 525 | else if (!strcmp (optarg, "unknown")) | 511 | else if (!strcmp (optarg, "unknown")) |
| 526 | onredirect = STATE_UNKNOWN; | 512 | onredirect = STATE_UNKNOWN; |
| 527 | else if (!strcmp (optarg, "follow")) | 513 | else if (!strcmp (optarg, "follow")) |
| 528 | onredirect = STATE_DEPENDENT; | 514 | onredirect = STATE_DEPENDENT; |
| 529 | else usage2 (_("Invalid onredirect option"), optarg); | 515 | else usage2 (_("Invalid onredirect option"), optarg); |
| 530 | //~ if (!strcmp (optarg, "stickyport")) | 516 | //~ if (!strcmp (optarg, "stickyport")) |
| 531 | //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST|STICKY_PORT; | 517 | //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST|STICKY_PORT; |
| 532 | //~ else if (!strcmp (optarg, "sticky")) | 518 | //~ else if (!strcmp (optarg, "sticky")) |
| 533 | //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST; | 519 | //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST; |
| 534 | //~ else if (!strcmp (optarg, "follow")) | 520 | //~ else if (!strcmp (optarg, "follow")) |
| 535 | //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_NONE; | 521 | //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_NONE; |
| 536 | if (verbose >= 2) | 522 | if (verbose >= 2) |
| 537 | printf(_("* Following redirects set to %s\n"), state_text(onredirect)); | 523 | printf(_("* Following redirects set to %s\n"), state_text(onredirect)); |
| 538 | break; | 524 | break; |
| 539 | case 's': /* string or substring */ | 525 | case 's': /* string or substring */ |
| 540 | strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); | 526 | strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); |
| 541 | string_expect[MAX_INPUT_BUFFER - 1] = 0; | 527 | string_expect[MAX_INPUT_BUFFER - 1] = 0; |
| 542 | break; | 528 | break; |
| 543 | case '?': | 529 | case '?': |
| 544 | /* print short usage statement if args not parsable */ | 530 | /* print short usage statement if args not parsable */ |
| 545 | usage5 (); | 531 | usage5 (); |
| 546 | break; | 532 | break; |
| 547 | } | 533 | } |
| 548 | } | 534 | } |
| 549 | 535 | ||
| 550 | c = optind; | 536 | c = optind; |
| 551 | 537 | ||
| 552 | if (server_address == NULL && c < argc) | 538 | if (server_address == NULL && c < argc) |
| 553 | server_address = strdup (argv[c++]); | 539 | server_address = strdup (argv[c++]); |
| 554 | 540 | ||
| 555 | if (host_name == NULL && c < argc) | 541 | if (host_name == NULL && c < argc) |
| 556 | host_name = strdup (argv[c++]); | 542 | host_name = strdup (argv[c++]); |
| 557 | 543 | ||
| 558 | if (server_address == NULL) { | 544 | if (server_address == NULL) { |
| 559 | if (host_name == NULL) | 545 | if (host_name == NULL) |
| 560 | usage4 (_("You must specify a server address or host name")); | 546 | usage4 (_("You must specify a server address or host name")); |
| 561 | else | 547 | else |
| 562 | server_address = strdup (host_name); | 548 | server_address = strdup (host_name); |
| 563 | } | 549 | } |
| 564 | 550 | ||
| 565 | set_thresholds(&thlds, warning_thresholds, critical_thresholds); | 551 | set_thresholds(&thlds, warning_thresholds, critical_thresholds); |
| 566 | 552 | ||
| 567 | if (critical_thresholds && thlds->critical->end>(double)socket_timeout) | 553 | if (critical_thresholds && thlds->critical->end>(double)socket_timeout) |
| 568 | socket_timeout = (int)thlds->critical->end + 1; | 554 | socket_timeout = (int)thlds->critical->end + 1; |
| 569 | if (verbose >= 2) | 555 | if (verbose >= 2) |
| 570 | printf ("* Socket timeout set to %d seconds\n", socket_timeout); | 556 | printf ("* Socket timeout set to %d seconds\n", socket_timeout); |
| 571 | 557 | ||
| 572 | //~ if (http_method == NULL) | 558 | //~ if (http_method == NULL) |
| 573 | //~ http_method = strdup ("GET"); | 559 | //~ http_method = strdup ("GET"); |
| 574 | 560 | ||
| 575 | if (client_cert && !client_privkey) | 561 | if (client_cert && !client_privkey) |
| 576 | usage4 (_("If you use a client certificate you must also specify a private key file")); | 562 | usage4 (_("If you use a client certificate you must also specify a private key file")); |
| 577 | 563 | ||
| 578 | //~ if (virtual_port == 0) | 564 | //~ if (virtual_port == 0) |
| 579 | //~ virtual_port = server_port; | 565 | //~ virtual_port = server_port; |
| 580 | 566 | ||
| 581 | return TRUE; | 567 | return TRUE; |
| 582 | } | 568 | } |
| 583 | 569 | ||
| 584 | void | 570 | void |
| 585 | print_help (void) | 571 | print_help (void) |
| 586 | { | 572 | { |
| 587 | print_revision(progname, NP_VERSION); | 573 | print_revision(progname, NP_VERSION); |
| 574 | |||
| 575 | printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); | ||
| 576 | printf ("Copyright (c) 2017 Andreas Baumann <abaumann@yahoo.com>\n"); | ||
| 577 | printf (COPYRIGHT, copyright, email); | ||
| 588 | 578 | ||
| 589 | printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); | 579 | printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test")); |
| 590 | printf ("Copyright (c) 2017 Andreas Baumann <abaumann@yahoo.com>\n"); | 580 | printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for")); |
| 591 | printf (COPYRIGHT, copyright, email); | 581 | printf ("%s\n", _("strings and regular expressions, check connection times, and report on")); |
| 582 | printf ("%s\n", _("certificate expiration times.")); | ||
| 583 | printf ("\n"); | ||
| 584 | printf ("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http")); | ||
| 585 | printf ("%s\n", _("as possible.")); | ||
| 592 | 586 | ||
| 593 | printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test")); | 587 | printf ("\n\n"); |
| 594 | printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for")); | ||
| 595 | printf ("%s\n", _("strings and regular expressions, check connection times, and report on")); | ||
| 596 | printf ("%s\n", _("certificate expiration times.")); | ||
| 597 | printf ("\n"); | ||
| 598 | printf ("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http")); | ||
| 599 | printf ("%s\n", _("as possible.")); | ||
| 600 | 588 | ||
| 601 | printf ("\n\n"); | 589 | print_usage(); |
| 602 | 590 | ||
| 603 | print_usage(); | 591 | printf (_("NOTE: One or both of -H and -I must be specified")); |
| 604 | |||
| 605 | printf (_("NOTE: One or both of -H and -I must be specified")); | ||
| 606 | 592 | ||
| 607 | printf ("\n"); | 593 | printf ("\n"); |
| 608 | 594 | ||
| 609 | printf (UT_HELP_VRSN); | 595 | printf (UT_HELP_VRSN); |
| 610 | printf (UT_EXTRA_OPTS); | 596 | printf (UT_EXTRA_OPTS); |
| 611 | 597 | ||
| 612 | printf (" %s\n", "-H, --hostname=ADDRESS"); | 598 | printf (" %s\n", "-H, --hostname=ADDRESS"); |
| 613 | printf (" %s\n", _("Host name argument for servers using host headers (virtual host)")); | 599 | printf (" %s\n", _("Host name argument for servers using host headers (virtual host)")); |
| 614 | printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); | 600 | printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); |
| 615 | printf (" %s\n", "-I, --IP-address=ADDRESS"); | 601 | printf (" %s\n", "-I, --IP-address=ADDRESS"); |
| 616 | printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup).")); | 602 | printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup).")); |
| 617 | printf (" %s\n", "-p, --port=INTEGER"); | 603 | printf (" %s\n", "-p, --port=INTEGER"); |
| 618 | printf (" %s", _("Port number (default: ")); | 604 | printf (" %s", _("Port number (default: ")); |
| 619 | printf ("%d)\n", DEFAULT_HTTP_PORT); | 605 | printf ("%d)\n", DEFAULT_HTTP_PORT); |
| 620 | 606 | ||
| 621 | #ifdef LIBCURL_FEATURE_SSL | 607 | #ifdef LIBCURL_FEATURE_SSL |
| 622 | printf (" %s\n", "-S, --ssl=VERSION[+]"); | 608 | printf (" %s\n", "-S, --ssl=VERSION[+]"); |
| 623 | printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); | 609 | printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); |
| 624 | printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); | 610 | printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); |
| 625 | printf (" %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted.")); | 611 | printf (" %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted.")); |
| 626 | printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); | 612 | printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); |
| 627 | printf (" %s\n", "--sni"); | 613 | printf (" %s\n", "--sni"); |
| 628 | printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); | 614 | printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); |
| 629 | #if LIBCURL_VERSION_NUM >= 0x071801 | 615 | #if LIBCURL_VERSION_NUM >= 0x071801 |
| 630 | printf (" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and")); | 616 | printf (" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and")); |
| 631 | printf (" %s\n", _(" SNI only really works since TLSv1.0")); | 617 | printf (" %s\n", _(" SNI only really works since TLSv1.0")); |
| 632 | #else | 618 | #else |
| 633 | printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1")); | 619 | printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1")); |
| 634 | #endif | 620 | #endif |
| 635 | printf (" %s\n", "-C, --certificate"); | 621 | printf (" %s\n", "-C, --certificate"); |
| 636 | printf (" %s\n", _("Check validity of certificate")); | 622 | printf (" %s\n", _("Check validity of certificate")); |
| 637 | printf (" %s\n", "-J, --client-cert=FILE"); | 623 | printf (" %s\n", "-J, --client-cert=FILE"); |
| 638 | printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); | 624 | printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); |
| 639 | printf (" %s\n", _("to be used in establishing the SSL session")); | 625 | printf (" %s\n", _("to be used in establishing the SSL session")); |
| 640 | printf (" %s\n", "-K, --private-key=FILE"); | 626 | printf (" %s\n", "-K, --private-key=FILE"); |
| 641 | printf (" %s\n", _("Name of file containing the private key (PEM format)")); | 627 | printf (" %s\n", _("Name of file containing the private key (PEM format)")); |
| 642 | printf (" %s\n", _("matching the client certificate")); | 628 | printf (" %s\n", _("matching the client certificate")); |
| 643 | #endif | 629 | #endif |
| 644 | 630 | ||
| 645 | printf (" %s\n", "-s, --string=STRING"); | 631 | printf (" %s\n", "-s, --string=STRING"); |
| 646 | printf (" %s\n", _("String to expect in the content")); | 632 | printf (" %s\n", _("String to expect in the content")); |
| 647 | printf (" %s\n", "-u, --url=PATH"); | 633 | printf (" %s\n", "-u, --url=PATH"); |
| 648 | printf (" %s\n", _("URL to GET or POST (default: /)")); | 634 | printf (" %s\n", _("URL to GET or POST (default: /)")); |
| 649 | 635 | ||
| 650 | printf (" %s\n", "-a, --authorization=AUTH_PAIR"); | 636 | printf (" %s\n", "-a, --authorization=AUTH_PAIR"); |
| 651 | printf (" %s\n", _("Username:password on sites with basic authentication")); | 637 | printf (" %s\n", _("Username:password on sites with basic authentication")); |
| 652 | printf (" %s\n", "-A, --useragent=STRING"); | 638 | printf (" %s\n", "-A, --useragent=STRING"); |
| 653 | printf (" %s\n", _("String to be sent in http header as \"User Agent\"")); | 639 | printf (" %s\n", _("String to be sent in http header as \"User Agent\"")); |
| 654 | printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>"); | 640 | printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>"); |
| 655 | printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); | 641 | printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); |
| 656 | printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); | 642 | printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); |
| 657 | 643 | ||
| 658 | printf (UT_WARN_CRIT); | 644 | printf (UT_WARN_CRIT); |
| 659 | 645 | ||
| 660 | printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); | 646 | printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); |
| 661 | 647 | ||
| 662 | printf (UT_VERBOSE); | 648 | printf (UT_VERBOSE); |
| 663 | 649 | ||
| 664 | printf (UT_SUPPORT); | 650 | printf (UT_SUPPORT); |
| 665 | } | 651 | } |
| 666 | 652 | ||
| 667 | void | 653 | void |
| 668 | print_usage (void) | 654 | print_usage (void) |
| 669 | { | 655 | { |
| 670 | printf ("%s\n", _("Usage:")); | 656 | printf ("%s\n", _("Usage:")); |
| 671 | printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); | 657 | printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); |
| 672 | printf (" [-J <client certificate file>] [-K <private key>]\n"); | 658 | printf (" [-J <client certificate file>] [-K <private key>]\n"); |
| 673 | printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-a auth]\n"); | 659 | printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-a auth]\n"); |
| 674 | printf (" [-f <ok|warning|critcal|follow>]\n"); | 660 | printf (" [-f <ok|warning|critcal|follow>]\n"); |
| 675 | printf (" [-A string] [-S <version>] [-C]\n"); | 661 | printf (" [-A string] [-S <version>] [-C]\n"); |
| 676 | printf (" [-v verbose]\n", progname); | 662 | printf (" [-v verbose]\n", progname); |
| 677 | printf ("\n"); | 663 | printf ("\n"); |
| 678 | printf ("%s\n", _("WARNING: check_curl is experimental. Please use")); | 664 | printf ("%s\n", _("WARNING: check_curl is experimental. Please use")); |
| 679 | printf ("%s\n\n", _("check_http if you need a stable version.")); | 665 | printf ("%s\n\n", _("check_http if you need a stable version.")); |
| 680 | } | 666 | } |
| 681 | 667 | ||
| 682 | void | 668 | void |
| 683 | print_curl_version (void) | 669 | print_curl_version (void) |
| 684 | { | 670 | { |
| 685 | printf( "%s\n", curl_version()); | 671 | printf( "%s\n", curl_version()); |
| 686 | } | 672 | } |
| 687 | 673 | ||
| 688 | int | 674 | int |
| 689 | curlhelp_initbuffer (curlhelp_curlbuf *buf) | 675 | curlhelp_initbuffer (curlhelp_curlbuf *buf) |
| 690 | { | 676 | { |
| 691 | buf->bufsize = DEFAULT_BUFFER_SIZE; | 677 | buf->bufsize = DEFAULT_BUFFER_SIZE; |
| 692 | buf->buflen = 0; | 678 | buf->buflen = 0; |
| 693 | buf->buf = (char *)malloc ((size_t)buf->bufsize); | 679 | buf->buf = (char *)malloc ((size_t)buf->bufsize); |
| 694 | if (buf->buf == NULL) return -1; | 680 | if (buf->buf == NULL) return -1; |
| 695 | return 0; | 681 | return 0; |
| 696 | } | 682 | } |
| 697 | 683 | ||
| 698 | int | 684 | int |
| 699 | curlhelp_buffer_callback (void *buffer, size_t size, size_t nmemb, void *stream) | 685 | curlhelp_buffer_callback (void *buffer, size_t size, size_t nmemb, void *stream) |
| 700 | { | 686 | { |
| 701 | curlhelp_curlbuf *buf = (curlhelp_curlbuf *)stream; | 687 | curlhelp_curlbuf *buf = (curlhelp_curlbuf *)stream; |
| 702 | 688 | ||
| 703 | while (buf->bufsize < buf->buflen + size * nmemb + 1) { | 689 | while (buf->bufsize < buf->buflen + size * nmemb + 1) { |
| 704 | buf->bufsize *= buf->bufsize * 2; | 690 | buf->bufsize *= buf->bufsize * 2; |
| 705 | buf->buf = (char *)realloc (buf->buf, buf->bufsize); | 691 | buf->buf = (char *)realloc (buf->buf, buf->bufsize); |
| 706 | if (buf->buf == NULL) return -1; | 692 | if (buf->buf == NULL) return -1; |
| 707 | } | 693 | } |
| 708 | 694 | ||
| 709 | memcpy (buf->buf + buf->buflen, buffer, size * nmemb); | 695 | memcpy (buf->buf + buf->buflen, buffer, size * nmemb); |
| 710 | buf->buflen += size * nmemb; | 696 | buf->buflen += size * nmemb; |
| 711 | buf->buf[buf->buflen] = '\0'; | 697 | buf->buf[buf->buflen] = '\0'; |
| 712 | 698 | ||
| 713 | return (int)(size * nmemb); | 699 | return (int)(size * nmemb); |
| 714 | } | 700 | } |
| 715 | 701 | ||
| 716 | void | 702 | void |
| 717 | curlhelp_freebuffer (curlhelp_curlbuf *buf) | 703 | curlhelp_freebuffer (curlhelp_curlbuf *buf) |
| 718 | { | 704 | { |
| 719 | free (buf->buf); | 705 | free (buf->buf); |
| 720 | buf->buf = NULL; | 706 | buf->buf = NULL; |
| 721 | } | 707 | } |
| 722 | 708 | ||
| 723 | /* TODO: when redirecting we get more than one HTTP header, make sure | 709 | /* TODO: when redirecting we get more than one HTTP header, make sure |
| @@ -726,76 +712,76 @@ curlhelp_freebuffer (curlhelp_curlbuf *buf) | |||
| 726 | int | 712 | int |
| 727 | curlhelp_parse_statusline (char *buf, curlhelp_statusline *status_line) | 713 | curlhelp_parse_statusline (char *buf, curlhelp_statusline *status_line) |
| 728 | { | 714 | { |
| 729 | char *first_line_end; | 715 | char *first_line_end; |
| 730 | char *p; | 716 | char *p; |
| 731 | size_t first_line_len; | 717 | size_t first_line_len; |
| 732 | char *pp; | 718 | char *pp; |
| 733 | 719 | ||
| 734 | first_line_end = strstr(buf, "\r\n"); | 720 | first_line_end = strstr(buf, "\r\n"); |
| 735 | if (first_line_end == NULL) return -1; | 721 | if (first_line_end == NULL) return -1; |
| 736 | 722 | ||
| 737 | first_line_len = (size_t)(first_line_end - buf); | 723 | first_line_len = (size_t)(first_line_end - buf); |
| 738 | status_line->first_line = (char *)malloc (first_line_len + 1); | 724 | status_line->first_line = (char *)malloc (first_line_len + 1); |
| 739 | if (status_line->first_line == NULL) return -1; | 725 | if (status_line->first_line == NULL) return -1; |
| 740 | memcpy (status_line->first_line, buf, first_line_len); | 726 | memcpy (status_line->first_line, buf, first_line_len); |
| 741 | status_line->first_line[first_line_len] = '\0'; | 727 | status_line->first_line[first_line_len] = '\0'; |
| 742 | 728 | ||
| 743 | /* protocol and version: "HTTP/x.x" SP */ | 729 | /* protocol and version: "HTTP/x.x" SP */ |
| 744 | 730 | ||
| 745 | p = strtok(status_line->first_line, "/"); | 731 | p = strtok(status_line->first_line, "/"); |
| 746 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 732 | if( p == NULL ) { free( status_line->first_line ); return -1; } |
| 747 | if( strcmp( p, "HTTP" ) != 0 ) { free( status_line->first_line ); return -1; } | 733 | if( strcmp( p, "HTTP" ) != 0 ) { free( status_line->first_line ); return -1; } |
| 748 | 734 | ||
| 749 | p = strtok( NULL, "." ); | 735 | p = strtok( NULL, "." ); |
| 750 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 736 | if( p == NULL ) { free( status_line->first_line ); return -1; } |
| 751 | status_line->http_major = (int)strtol( p, &pp, 10 ); | 737 | status_line->http_major = (int)strtol( p, &pp, 10 ); |
| 752 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 738 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } |
| 753 | 739 | ||
| 754 | p = strtok( NULL, " " ); | 740 | p = strtok( NULL, " " ); |
| 755 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 741 | if( p == NULL ) { free( status_line->first_line ); return -1; } |
| 756 | status_line->http_minor = (int)strtol( p, &pp, 10 ); | 742 | status_line->http_minor = (int)strtol( p, &pp, 10 ); |
| 757 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 743 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } |
| 758 | 744 | ||
| 759 | /* status code: "404" or "404.1", then SP */ | 745 | /* status code: "404" or "404.1", then SP */ |
| 760 | 746 | ||
| 761 | p = strtok( NULL, " ." ); | 747 | p = strtok( NULL, " ." ); |
| 762 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 748 | if( p == NULL ) { free( status_line->first_line ); return -1; } |
| 763 | if( strchr( p, '.' ) != NULL ) { | 749 | if( strchr( p, '.' ) != NULL ) { |
| 764 | char *ppp; | 750 | char *ppp; |
| 765 | ppp = strtok( p, "." ); | 751 | ppp = strtok( p, "." ); |
| 766 | status_line->http_code = (int)strtol( ppp, &pp, 10 ); | 752 | status_line->http_code = (int)strtol( ppp, &pp, 10 ); |
| 767 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 753 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } |
| 768 | 754 | ||
| 769 | ppp = strtok( NULL, "" ); | 755 | ppp = strtok( NULL, "" ); |
| 770 | status_line->http_subcode = (int)strtol( ppp, &pp, 10 ); | 756 | status_line->http_subcode = (int)strtol( ppp, &pp, 10 ); |
| 771 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 757 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } |
| 772 | } else { | 758 | } else { |
| 773 | status_line->http_code = (int)strtol( p, &pp, 10 ); | 759 | status_line->http_code = (int)strtol( p, &pp, 10 ); |
| 774 | status_line->http_subcode = -1; | 760 | status_line->http_subcode = -1; |
| 775 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 761 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } |
| 776 | } | 762 | } |
| 777 | 763 | ||
| 778 | /* Human readable message: "Not Found" CRLF */ | 764 | /* Human readable message: "Not Found" CRLF */ |
| 779 | 765 | ||
| 780 | p = strtok( NULL, "" ); | 766 | p = strtok( NULL, "" ); |
| 781 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 767 | if( p == NULL ) { free( status_line->first_line ); return -1; } |
| 782 | status_line->msg = p; | 768 | status_line->msg = p; |
| 783 | 769 | ||
| 784 | return 0; | 770 | return 0; |
| 785 | } | 771 | } |
| 786 | 772 | ||
| 787 | void | 773 | void |
| 788 | curlhelp_free_statusline (curlhelp_statusline *status_line) | 774 | curlhelp_free_statusline (curlhelp_statusline *status_line) |
| 789 | { | 775 | { |
| 790 | free (status_line->first_line); | 776 | free (status_line->first_line); |
| 791 | } | 777 | } |
| 792 | 778 | ||
| 793 | void | 779 | void |
| 794 | remove_newlines (char *s) | 780 | remove_newlines (char *s) |
| 795 | { | 781 | { |
| 796 | char *p; | 782 | char *p; |
| 797 | 783 | ||
| 798 | for (p = s; *p != '\0'; p++) | 784 | for (p = s; *p != '\0'; p++) |
| 799 | if (*p == '\r' || *p == '\n') | 785 | if (*p == '\r' || *p == '\n') |
| 800 | *p = ' '; | 786 | *p = ' '; |
| 801 | } | 787 | } |
