--- 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 | -I ) [-u ] [-p ]\n\ + [-x ] [-y ]\n\ [-w ] [-c ] [-t ] [-L]\n\ [-a auth] [-f ] [-e ]\n\ [-s string] [-l] [-r | -R ]\n\