[Nagiosplug-devel] check_http patch
Jos Visser
josv at osp.nl
Wed Sep 22 08:06:07 CEST 2004
Included in this patch are:
- Support for checking through HTTP proxies (-x/-y)
- Support for SSL client certificates (-i/-k)
- Support for HTTP HEAD (-D)
- Patch to include the port number in the Host: header
++Jos.nl
--
Handle nur nach derjenigen Maxime, durch die du zugleich wollen kannst,
daß sie ein allgemeines Gesetz werde.
-- Immanuel Kant
-------------- next part --------------
--- check_http.c.orig Mon Mar 22 08:19:58 2004
+++ check_http.c Wed Sep 22 17:03:45 2004
@@ -113,6 +113,11 @@
char *http_post_data;
char *http_content_type;
char buffer[MAX_INPUT_BUFFER];
+char *client_cert;
+char *client_privkey;
+char *proxy_host;
+int proxy_port=8080;
+
int process_arguments (int, char **);
static char *base64 (const char *bin, size_t len);
@@ -184,6 +189,14 @@
}
+/* Check whether a file exists */
+void
+test_file(char *filename)
+{
+ if (access(filename,R_OK)==0)
+ return;
+ usage2 (_("file does not exist or is not readable"), optarg);
+}
/* process command-line arguments */
int
@@ -209,10 +222,15 @@
{"linespan", no_argument, 0, 'l'},
{"onredirect", required_argument, 0, 'f'},
{"certificate", required_argument, 0, 'C'},
+ {"client-cert", required_argument, 0, 'i'},
+ {"private-key", required_argument, 0, 'k'},
+ {"proxy", required_argument, 0, 'x'},
+ {"proxy-port", required_argument, 0, 'y'},
{"content-type", required_argument, 0, 'T'},
{"min", required_argument, 0, 'm'},
{"use-ipv4", no_argument, 0, '4'},
{"use-ipv6", no_argument, 0, '6'},
+ {"head", no_argument, 0, 'D'},
{0, 0, 0, 0}
};
@@ -233,7 +251,7 @@
}
while (1) {
- c = getopt_long (argc, argv, "Vvh46t:c:w:H:P:T:I:a:e:p:s:R:r:u:f:C:nlLSm:", longopts, &option);
+ c = getopt_long (argc, argv, "Vvh46Dt:c:w:H:P:T:I:a:e:p:s:R:r:u:f:C:nlLSm:i:k:x:y:", longopts, &option);
if (c == -1 || c == EOF)
break;
@@ -297,6 +315,35 @@
usage (_("check_http: invalid option - SSL is not available\n"));
#endif
break;
+ case 'i': /* Use SSL client certificate */
+#ifdef HAVE_SSL
+ use_ssl=TRUE;
+
+ if (specify_port == FALSE)
+ server_port = HTTPS_PORT;
+
+ client_cert=optarg;
+ test_file(client_cert);
+#else
+ usage (_("check_http: invalid option - SSL is not available\n"));
+#endif
+ break;
+ case 'k': /* SSL client certificate private key file*/
+#ifdef HAVE_SSL
+ client_privkey=optarg;
+ test_file(client_privkey);
+#else
+ usage (_("check_http: invalid option - SSL is not available\n"));
+#endif
+ break;
+ case 'x': /* Use proxy */
+ proxy_host=optarg;
+ break;
+ case 'y': /* Proxy port */
+ proxy_port=atoi(optarg);
+ if (proxy_port==0)
+ usage2(_("check_http: invalid proxy port number\n"), optarg);
+ break;
case 'f': /* onredirect */
if (!strcmp (optarg, "follow"))
onredirect = STATE_DEPENDENT;
@@ -339,6 +386,10 @@
http_method = strdup("POST");
http_post_data = strdup (optarg);
break;
+ case 'D': /* HTTP HEAD */
+ if (http_method) break;
+ http_method = strdup("HEAD");
+ break;
case 's': /* string or substring */
strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
string_expect[MAX_INPUT_BUFFER - 1] = 0;
@@ -408,6 +459,9 @@
server_address = strdup (host_name);
}
+ if (client_cert && !client_privkey)
+ usage (_("check_http: if you use a client certificate you must also specify a private key file\n"));
+
if (check_critical_time && critical_time>(double)socket_timeout)
socket_timeout = (int)critical_time + 1;
@@ -505,17 +559,23 @@
}
else {
#endif
- if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
+ if (proxy_host) {
+ if (my_tcp_connect (proxy_host, proxy_port, &sd) != STATE_OK)
+ die (STATE_CRITICAL, _("Unable to open TCP socket to proxy\n"));
+ } else if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
die (STATE_CRITICAL, _("Unable to open TCP socket\n"));
#ifdef HAVE_SSL
}
#endif
- asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
+ if (proxy_host && !use_ssl)
+ asprintf (&buf, "%s http://%s%s HTTP/1.0\r\n%s\r\n", http_method, server_address, server_url, user_agent);
+ else
+ asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
/* optionally send the host header info */
if (host_name)
- asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
+ asprintf (&buf, "%sHost: %s:%d\r\n", buf, host_name, server_port);
/* optionally send the authentication info */
if (strlen(user_auth)) {
@@ -918,6 +978,39 @@
#ifdef HAVE_SSL
+int proxy_connect()
+{
+ char *buf;
+ int n,i;
+
+ if (my_tcp_connect(proxy_host, proxy_port, &sd)!=STATE_OK)
+ return FALSE;
+
+ asprintf (&buf, "CONNECT %s:%d HTTP/1.0\r\n%s\r\n\r\n", server_address, server_port, user_agent);
+ send(sd,buf,strlen(buf),0);
+
+ use_ssl=FALSE; /* hack */
+ buf="";
+
+ while ((n=my_recv())>0) {
+ buffer[n]=0;
+ asprintf(&buf,"%s%s",buf,buffer);
+ i=strlen(buf);
+
+ if (strcmp(buf+i-4,"\r\n\r\n")==0)
+ break;
+ }
+
+ if (verbose)
+ printf("PROXY CONNECT: %s",buf);
+
+ if (!(strncmp(buf,"HTTP/1.",7)==0 & strncmp(buf+8," 200 ",5)==0))
+ return FALSE;
+
+ use_ssl=TRUE;
+ return 1;
+}
+
int connect_SSL (void)
{
SSL_METHOD *meth;
@@ -936,6 +1029,17 @@
return STATE_CRITICAL;
}
+ /* Set up the client certificate to be used (if so requested) */
+ if (client_cert) {
+ SSL_CTX_use_certificate_file(ctx,client_cert,SSL_FILETYPE_PEM);
+ SSL_CTX_use_PrivateKey_file(ctx,client_privkey,SSL_FILETYPE_PEM);
+
+ if (!SSL_CTX_check_private_key(ctx)) {
+ printf(_("CRITICAL - Private key does not seem to match certificate!\n"));
+ return STATE_CRITICAL;
+ }
+ }
+
/* Initialize alarm signal handling */
signal (SIGALRM, socket_timeout_alarm_handler);
@@ -946,7 +1050,7 @@
gettimeofday (&tv, NULL);
/* Make TCP connection */
- if (my_tcp_connect (server_address, server_port, &sd) == STATE_OK) {
+ if ((proxy_host && proxy_connect()) || my_tcp_connect (server_address, server_port, &sd) == STATE_OK) {
/* Do the SSL handshake */
if ((ssl = SSL_new (ctx)) != NULL) {
SSL_set_cipher_list(ssl, "ALL");
@@ -1131,7 +1235,11 @@
-I, --IP-address=ADDRESS\n\
IP address or name (use numeric address if possible to bypass DNS lookup).\n\
-p, --port=INTEGER\n\
- Port number (default: %d)\n"), HTTP_PORT);
+ Port number (default: %d)\n\
+ -x, --proxy-host=ADDRESS\n\
+ Host name or IP address of HTTP proxy to be used\n\
+ -y, --proxy-port=INTEGER\n\
+ Port number of the HTTP proxy service\n"), HTTP_PORT);
printf (_(UT_IPv46));
@@ -1141,7 +1249,13 @@
Connect via SSL\n\
-C, --certificate=INTEGER\n\
Minimum number of days a certificate has to be valid.\n\
- (when this option is used the url is not checked.)\n"));
+ (when this option is used the url is not checked.)\n\
+ -i, --client-cert=FILE\n\
+ Name of file that contains the client certificate (PEM
+ format) to be used in establishing the SSL session.\n\
+ -k, --private-key=FILE\n\
+ Name of file containing the private key (PEM format)
+ matching the client certificate\n"));
#endif
printf (_("\
@@ -1154,6 +1268,9 @@
URL to GET or POST (default: /)\n\
-P, --post=STRING\n\
URL encoded http POST data\n\
+ -D, --head\n\
+ Use an HTTP HEAD request (actual data not transferred; more efficient than a\n\
+ GET)\n\
-T, --content-type=STRING\n\
specify Content-Type header media type when POSTing\n"), HTTP_EXPECT);
@@ -1223,9 +1340,10 @@
{
printf (_("\
Usage: %s (-H <vhost> | -I <IP-address>) [-u <uri>] [-p <port>]\n\
+ [-x <proxy-host>] [-y <proxy-port>]\n\
[-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n\
[-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n\
[-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n\
- [-P string] [-m min_pg_size] [-4|-6]\n"), progname);
+ [-P string|-D] [-m min_pg_size] [-4|-6]\n"), progname);
printf (_(UT_HLP_VRS), progname, progname);
}
More information about the Devel
mailing list