[Nagiosplug-devel] check_http patch for proxy and SSL client_cert support
Jos Visser
josv at osp.nl
Wed Sep 15 04:17:01 CEST 2004
Hi all,
The accompanying patch adds support for HTTP proxies and SSL client
certificates to the check_http plug-in.
It adds four new command line options:
-i, --client_cert Filename of the client certificate (PEM)
-k, --private_key Filename of the private key file (PEM)
-x, --proxy-host HTTP proxy hostname or IP address
-y, --proxy-port port of the HTTP proxy
(proxying works for SSL and non-SSL; proxy authentication not yet
supported...)
Use of -i automatically enables -S (--use-ssl).
The patch is against the check_http.c that I checked out this very
morning...
Samples:
$ ./check_http -H www.josvisser.nl -x localhost -y 3128
HTTP OK HTTP/1.0 200 OK - 4887 bytes in 1.730 seconds |time=1.729544s;;;0.000000 size=4887B;;;0
$ ./check_http -H rours.org -i cert.pem -k key.pem -x localhost -y 3128
HTTP WARNING: HTTP/1.1 403 Forbidden
Share and enjoy!
++Jos.es
--
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 Wed Sep 15 13:04:21 2004
+++ check_http.c Wed Sep 15 13:04:21 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,6 +222,10 @@
{"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'},
@@ -233,7 +250,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, "Vvh46t: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 +314,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;
@@ -408,6 +454,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,13 +554,18 @@
}
else {
#endif
- if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
+ if (proxy_host && 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 %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)
@@ -918,6 +972,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 +1023,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 +1044,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 +1229,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 +1243,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 (_("\
@@ -1223,6 +1331,7 @@
{
printf (_("\
Usage: %s (-H <vhost> | -I <IP-address>) [-u <uri>] [-p <port>]\n\
+ [-x <proxy>] [-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\
More information about the Devel
mailing list