www.pudn.com > SSLjiamisuanfa.rar > wclient2.c, change:2002-10-28,size:3842b


/* A simple HTTPS client

   It connects to the server, makes an HTTP
   request and waits for the response
*/
#include "common.h"
#include "client.h"

static char *REQUEST_TEMPLATE=
   "GET / HTTP/1.0\r\nUser-Agent:"
   "EKRClient\r\nHost: %s:%d\r\n\r\n";

static char *host=HOST;
static int port=PORT;
static int require_server_auth=1;
static char *ciphers=0;
static int reconnect=0;

static int http_request(ssl)
  SSL *ssl;
  {
    char *request=0;
    char buf[BUFSIZZ];
    int r;
    int len, request_len;
    
    /* Now construct our HTTP request */
    request_len=strlen(REQUEST_TEMPLATE)+
      strlen(host)+6;
    if(!(request=(char *)malloc(request_len)))
      err_exit("Couldn't allocate request");
    snprintf(request,request_len,REQUEST_TEMPLATE,
      host,port);

    /* Find the exact request_len */
    request_len=strlen(request);

    r=SSL_write(ssl,request,request_len);
    switch(SSL_get_error(ssl,r)){      
      case SSL_ERROR_NONE:
        if(request_len!=r)
          err_exit("Incomplete write!");
        break;
        default:
          berr_exit("SSL write problem");
    }

    /* Now read the server's response, assuming
       that it's terminated by a close */
    while(1){
      r=SSL_read(ssl,buf,BUFSIZZ);
      switch(SSL_get_error(ssl,r)){
        case SSL_ERROR_NONE:
          len=r;
          break;
        case SSL_ERROR_WANT_READ:
          continue;
        case SSL_ERROR_ZERO_RETURN:
          goto shutdown;
        case SSL_ERROR_SYSCALL:
          fprintf(stderr,
            "SSL Error: Premature close\n");
          goto done;
        default:
          berr_exit("SSL read problem");
      }

      fwrite(buf,1,len,stdout);
    }
    
  shutdown:
    r=SSL_shutdown(ssl);
    switch(r){
      case 1:
        break; /* Success */
      case 0:
      case -1:
      default:
        berr_exit("Shutdown failed");
    }
    
  done:
    SSL_free(ssl);
    free(request);
    return(0);
  }
    
int main(argc,argv)
  int argc;
  char **argv;
  {
    SSL_CTX *ctx;
    SSL *ssl;
    BIO *sbio;
    int sock;
    extern char *optarg;
    int c;
    SSL_SESSION *sess;
    
    while((c=getopt(argc,argv,"h:p:ia:r"))!=-1){
      switch(c){
        case 'h':
          if(!(host=strdup(optarg)))
            err_exit("Out of memory");
          break;
        case 'p':
          if(!(port=atoi(optarg)))
            err_exit("Bogus port specified");
          break;
        case 'i':
          require_server_auth=0;
          break;
        case 'a':
          if(!(ciphers=strdup(optarg)))
            err_exit("Out of memory");
          break;
        case 'r':
          reconnect=1;
          break;
      }
    }

    /* Build our SSL context*/
    ctx=initialize_ctx(KEYFILE,PASSWORD);
    
    /* Set our cipher list */
    if(ciphers){
      SSL_CTX_set_cipher_list(ctx,ciphers);
    }

    /* Connect the TCP socket*/
    sock=tcp_connect(host,port);

    /* Connect the SSL socket */
    ssl=SSL_new(ctx);
    sbio=BIO_new_socket(sock,BIO_NOCLOSE);
    SSL_set_bio(ssl,sbio,sbio);

    if(SSL_connect(ssl)<=0)
      berr_exit("SSL connect error");
    if(require_server_auth)
      check_cert(ssl,host);

    /* Now hang up and reconnect, if requested */
    if(reconnect) {
      sess=SSL_get1_session(ssl); /*Collect the session*/
      SSL_shutdown(ssl);
      SSL_free(ssl);
      close(sock);
      
      sock=tcp_connect(host,port);
      ssl=SSL_new(ctx);
      sbio=BIO_new_socket(sock,BIO_NOCLOSE);
      SSL_set_bio(ssl,sbio,sbio);
      SSL_set_session(ssl,sess); /*And resume it*/
      if(SSL_connect(ssl)<=0)
        berr_exit("SSL connect error (second connect)");
      check_cert(ssl,host);
    }
    
    /* Now make our HTTP request */
    http_request(ssl);

    /* Shutdown the socket */
    destroy_ctx(ctx);
    close(sock);

    exit(0);
  }