Advertisement
Guest User

Alnitak

a guest
May 10th, 2009
362
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.69 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <limits.h>
  6. #include <sys/types.h>
  7. #include <sys/time.h>
  8. #include <sys/socket.h>
  9. #include <netdb.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12. #include <openssl/ssl.h>
  13. #include <openssl/err.h>
  14.  
  15. void usage()
  16. {
  17.         fprintf(stderr, "usage: httpsclient [-h] [-q] [-t] <uri>\n");
  18.         fprintf(stderr, "\t-h : send HEAD instead of GET request\n");
  19.         fprintf(stderr, "\t-q : don't print output\n");
  20.         fprintf(stderr, "\t-t : print milliseconds to complete request in MRTG format\n");
  21.         fprintf(stderr, "\t-d : print debugging information\n");
  22.         exit(EXIT_FAILURE);
  23. }
  24.  
  25. int main(int argc, char **argv)
  26. {
  27.         char                    *uri = 0;
  28.         char                    *host;
  29.         char                    *request;
  30.         char                    *port = 0;
  31.         const char              *proto = "tcp";
  32.         char                    *service;
  33.         char                    *randfile;
  34.         struct protoent         *pe;
  35.         struct hostent          *he;
  36.         struct sockaddr_in       addr;
  37.         struct timeval           t1, t2, t3;
  38.         unsigned long            td1, td2;
  39.         int                      s, n;
  40.         char                    *buffer;
  41.         const int                bufsize = 4096;
  42.         int                      opt_q = 0;
  43.         int                      opt_t = 0;
  44.         int                      opt_h = 0;
  45.         int                      opt_d = 0;
  46.         SSL_CTX                 *ctx;
  47.         SSL                     *ssl = 0;
  48.         int                      https = 0;
  49.  
  50.         /* skip argv[0] */
  51.         argv++;
  52.         argc--;
  53.  
  54.         while (*argv && **argv == '-') {
  55.                 char *opt = *argv + 1;
  56.  
  57.                 switch (*opt) {
  58.                         case 'h':
  59.                                 opt_h = 1; break;
  60.                         case 'q':
  61.                                 opt_q = 1; break;
  62.                         case 't':
  63.                                 opt_t = 1; break;
  64.                         case 'd':
  65.                                 opt_d = 1; break;
  66.                         default:
  67.                                 usage();
  68.                 }
  69.  
  70.                 argv++;
  71.                 argc--;
  72.         }
  73.  
  74.         if (argc == 1) {
  75.                 uri = *argv++; argc--;
  76.         } else {
  77.                 usage();
  78.         }
  79.  
  80.         /* parse the URI */
  81.         {
  82.                 if (strncmp(uri, "http://", 7) == 0) {
  83.                         host = uri + 7;
  84.                         uri[4] = '\0';
  85.                 } else if (strncmp(uri, "https://", 8) == 0) {
  86.                         host = uri + 8;
  87.                         uri[5] = '\0';
  88.                         https = 1;
  89.                 } else {
  90.                         fprintf(stderr, "error: invalid uri\n");
  91.                         return EXIT_FAILURE;
  92.                 }
  93.  
  94.                 service = uri;
  95.  
  96.                 request = strchr(host, '/');
  97.                 if (request) {
  98.                         *request++ = '\0';
  99.                 } else {
  100.                         request = "";
  101.                 }
  102.  
  103.                 /* look for a port number */
  104.                 port = strrchr(host, ':');
  105.                 if (port) {
  106.                         *port++ = '\0';
  107.  
  108.                         /* catch empty port specifiers */
  109.                         if (*port == '\0') {
  110.                                 port = 0;
  111.                         }
  112.                 }
  113.         }
  114.  
  115.         if ((buffer = malloc(bufsize)) == 0) {
  116.                 perror("malloc");
  117.                 return EXIT_FAILURE;
  118.         }
  119.  
  120.         if ((he = gethostbyname(host)) == 0) {
  121.                 if (h_errno == HOST_NOT_FOUND) {
  122.                         fprintf(stderr, "gethostbyname: host not found\n");
  123.                 } else if (h_errno == NO_DATA) {
  124.                         fprintf(stderr, "gethostbyname: no data for host\n");
  125.                 } else if (h_errno == TRY_AGAIN) {
  126.                         fprintf(stderr, "gethostbyname: host not found\n");
  127.                 } else {
  128.                         fprintf(stderr, "gethostbyname: error %d\n", h_errno);
  129.                 }
  130.                 return EXIT_FAILURE;
  131.         }
  132.  
  133.         if ((pe = getprotobyname(proto)) == 0) {
  134.                 perror("getprotobyname");
  135.                 return EXIT_FAILURE;
  136.         }
  137.  
  138.         memset(&addr, 0, sizeof(addr));
  139.         memcpy(&addr.sin_addr, he->h_addr, sizeof(addr.sin_addr));
  140.         addr.sin_family = AF_INET;
  141.  
  142.         if (port) {
  143.                 addr.sin_port = htons(atoi(port));
  144.         } else {
  145.                 struct servent          *se;
  146.                 if ((se = getservbyname(service, proto)) == 0) {
  147.                         perror("getservbyname");
  148.                         return EXIT_FAILURE;
  149.                 }
  150.                 addr.sin_port = se->s_port;
  151.         }
  152.  
  153.         /* create the socket */
  154.         if ((s = socket(PF_INET, SOCK_STREAM, pe->p_proto)) < 0) {
  155.                 perror("socket");
  156.                 return EXIT_FAILURE;
  157.         }
  158.  
  159.         /* first timing point here */
  160.         if (gettimeofday(&t1, NULL) < 0) {
  161.                 perror("gettimeofday(t1)");
  162.                 return EXIT_FAILURE;
  163.         }
  164.  
  165.         if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  166.                 perror("connect");
  167.                 return EXIT_FAILURE;
  168.         }
  169.  
  170.         /* create SSL connection if necessary */
  171.         if (https) {
  172.  
  173.                 SSL_load_error_strings();
  174.  
  175.                 randfile = (char *)malloc(_POSIX_PATH_MAX);
  176.                 RAND_file_name(randfile, _POSIX_PATH_MAX);
  177.                 RAND_load_file(randfile, -1);
  178.  
  179.                 SSL_library_init();
  180.                 ctx = SSL_CTX_new(SSLv23_client_method());
  181.                 ssl = SSL_new(ctx);
  182.                 SSL_set_fd(ssl, s);
  183.                 SSL_connect(ssl);
  184.  
  185.                 if (opt_d) {
  186.                         char buffer[128];
  187.                         SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
  188.                         SSL_CIPHER_description(cipher, buffer, sizeof(buffer));
  189.                         fputs(buffer, stderr);
  190.                 }
  191.         }
  192.  
  193.         /* second timing point here */
  194.         if (gettimeofday(&t2, NULL) < 0) {
  195.                 perror("gettimeofday(t2)");
  196.                 return EXIT_FAILURE;
  197.         }
  198.  
  199.         n = sprintf(buffer, "%s /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
  200.                 (opt_h ? "HEAD" : "GET"), request, host);
  201.  
  202.         if (n > bufsize) {
  203.                 fprintf(stderr, "buffer overflow");
  204.                 return EXIT_FAILURE;
  205.         }
  206.  
  207.         if (https) {
  208.                 if (SSL_write(ssl, buffer, n) <= 0) {
  209.                         fprintf(stderr, "SSL error 1\n");
  210.                         ERR_print_errors_fp(stderr);
  211.                         return EXIT_FAILURE;
  212.                 }
  213.  
  214.                 ERR_clear_error();
  215.                 while ((n = SSL_read(ssl, buffer, bufsize)) > 0) {
  216.                         if (opt_q) continue;
  217.                         fwrite(buffer, 1, n, stdout);
  218.                 }
  219.  
  220.                 if (n <= 0) {
  221.                         int error = SSL_get_error(ssl, n);
  222.                         if (error == SSL_ERROR_SYSCALL) {
  223.                                 if (errno != 0) {
  224.                                         perror("SSL_read");
  225.                                         ERR_print_errors_fp(stderr);
  226.                                 }
  227.                         } else if (error != SSL_ERROR_ZERO_RETURN &&
  228.                                    error != SSL_ERROR_NONE)
  229.                         {
  230.                                 ERR_print_errors_fp(stderr);
  231.                                 return EXIT_FAILURE;
  232.                         }
  233.                 }
  234.         } else {
  235.                 if (write(s, buffer, n) != n) {
  236.                         perror("write");
  237.                         return EXIT_FAILURE;
  238.                 }
  239.  
  240.                 while ((n = read(s, buffer, bufsize)) > 0) {
  241.                         if (opt_q) continue;
  242.                         fwrite(buffer, 1, n, stdout);
  243.                 }
  244.         }
  245.  
  246.         /* third timing point here */
  247.         if (gettimeofday(&t3, NULL) < 0) {
  248.                 perror("gettimeofday(t3)");
  249.                 return EXIT_FAILURE;
  250.         }
  251.  
  252.         /* calculate elapsed times */
  253.         td1 = (t3.tv_sec - t2.tv_sec) * 1000;
  254.         td1 += (t3.tv_usec - t2.tv_usec) / 1000;
  255.  
  256.         td2 = (t3.tv_sec - t1.tv_sec) * 1000;
  257.         td2 += (t3.tv_usec - t1.tv_usec) / 1000;
  258.  
  259.         if (opt_t) {
  260.                 fprintf(stdout, "%ld\n%ld\n", td1, td2);
  261.         }
  262.  
  263.         return EXIT_SUCCESS;
  264. }
  265.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement