Help,

It seems to me after looking throught the openSSL library code and most of
the examples provided(and the email archives), that most of the support in
this library is geared towards the server side of the SSL mechanism.  What I
need help in, seems to me to be a very simple yet common task. I need to
know 'how-to', say via a command line utility which takes as command line
arguments: a 'destination ip address', a 'certificate filename', a 'key
filename', a 'send data filename', and a 'response data filename'.  The
utility does no authentication of the server(speed issue), yet is able to
encrypt and send the 'send datafile' and decrypted the response into the
'response datafile'.  The reason for the command-line type utility, is that
I need a cross-platform means(without the need for a browser) to send a data
file via HTTPS/SSL from various clients(some of the are old legacy systems)
to various servers.

I guess the most frustrating issue is the lack of documentation on-line or
off-line (function name lists is of little help), and searching through
e-mail archives for tid-bits here and there is very tedious. Also the
returning of a value of '-1' for almost every error code does no help when
trying to figure out what your doing wrong(even the use of SSL_get_error
isn't much help when it reflects the most recent,outer-layer error).  I'm
including a couple portions of the code I have in my utility.  I'm trying to
add the client certificate and key portions to the utility, but it seems
that I' having little success.  Prior to adding the cert/key info,
everything seem to be working OK till the SSL_connect call when it started
to handshake with my test server to get the client cert/key info.  Any help
that anyone could provide would be greatly welcomed. Till then, I'll just
keep plodding along....


Doug Putz
John Deere Information Systems
(309) 765-2458
[EMAIL PROTECTED]



#ifdef _WIN32
  TOCON("Starting-up windows socket support\n");
  if (initWinsock(fLog)==0)
  {
    FULL("Unable to startup windows socket support\n");
  }
#endif
  /* --------------------------------------------------- */
  // begin
  /* --------------------------------------------------- */

  // Initialize the SSL environment
  SSL_load_error_strings();                     

  SSLeay_add_ssl_algorithms();  
  
  meth = SSLv23_client_method();
             
  ctx = SSL_CTX_new(meth);                        
  
  if (NULL == ctx)
  {
    // Log error and cleanup
    FULL("Unable to create SSL CTX\n");
    goto cleanup;
  }

  if
(!SSL_CTX_use_certificate_file(ctx,config.szCERTFilename,SSL_FILETYPE_PEM))
  {
    // Log error and cleanup
    FULL("Invalid CERT file\n");
    goto cleanup;
  }
  else if
(!SSL_CTX_use_PrivateKey_file(ctx,config.szKEYFilename,SSL_FILETYPE_PEM))
  {
    // Log error and cleanup
    FULL("Invalid KEY file\n");
    goto cleanup;
  }
  
  SSL_CTX_set_session_id_context(ctx, (const unsigned char
*)&session_id_context, sizeof session_id_context);

  /* --------------------------------------------------- */
  // Create a socket and connect to server using normal socket calls.
  /* --------------------------------------------------- */
  sd = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);

  if (INVALID_SOCKET == sd)
  {
    // log and clean up
    FULL("Unable to create socket\n");
    goto cleanup;
  }

  // Figure out what we are going to bind to
  memset(&myname, 0, sizeof(myname));
  myname.sin_family = AF_INET;

  // See if they actually want to bind to a specific IP
  if (strcmp(config.szLocalIP, "ADDR_ANY") == 0) 
  {
    myname.sin_addr.s_addr = ADDR_ANY;
  }
  else
  {
    myname.sin_addr.s_addr = inet_addr(config.szLocalIP);
  }

  myname.sin_port = htons((unsigned short)atoi(config.szLocalPort));

  if (bind(sd, (struct sockaddr *) &myname, sizeof(myname)) == -1) 
  {
    FULL("Unable to bind locally\n");
    goto cleanup;
  }

  memset (&sa, '\0', sizeof(sa));
  sa.sin_family      = AF_INET;
  sa.sin_addr.s_addr = inet_addr(config.szIP);                     /*
config-> Server IP */
  sa.sin_port        = htons((unsigned short)atoi(config.szPort)); /*
config-> Server Port number */
  
  err = connect(sd, (struct sockaddr*) &sa,     sizeof(sa));

  
  if (-1 == err)
  {
    // Log error and cleanup
    FULL("Unable to create connection\n");
    goto cleanup;
  }

  /* --------------------------------------------------- */
  // Send Proxy information if available
  /* --------------------------------------------------- */
  if (strlen(config.szProxy) > 0) 
  {
    // build proxy connection
    send (sd, config.szProxy, strlen(config.szProxy),0);

    // Perform the read
    int err =  recv(sd,buf,BLOCK_SIZE,0);
    buf[err] = '\0';
        
    if (buf[9]=='4' && buf[10]=='0' && buf[11]=='7') 
    {
      FULL("PROXY AUTH FAILED - 407\n");
      goto cleanup;
    }

    if (buf[9]!='2' || buf[10]!='0' || buf[11]!='0') 
    {
      FULL("PROXY CLEAR FAIL - 407\n");
      goto cleanup;
    }
  }

  /* --------------------------------------------------- */
  // Now we have TCP conncetion. Start SSL negotiation.
  /* --------------------------------------------------- */
  ssl = SSL_new (ctx);                         
  
  if (NULL == ssl)
  {
    // Log error and cleanup
    FULL("Unable to create SSL\n");
    goto cleanup;
  }

  SSL_set_fd (ssl, sd);

  err = SSL_connect(ssl);                     
  
  if (err < 0)
  {
    // Log error and cleanup
    code = SSL_get_error(ssl,err);
    sprintf(buf,"Unable to connect SSL[%d]\n",code);
    FULL(buf);
    goto cleanup;
  }

  /* --------------------------------------------------- */
  // We could do all sorts of certificate verification stuff here
  /* --------------------------------------------------- */
  
  /* --------------------------------------------------- */
  // DUMP sendfile into socket
  /* --------------------------------------------------- */
  ...
  I'm using SSL_write to send the file
  ...

  /* --------------------------------------------------- */
  // READ response from socket and WRITE to responsefile
  /* --------------------------------------------------- */
  ...
  I'm using SSL_read to get the response
  ...

  /* --------------------------------------------------- */
  SSL_shutdown (ssl);  /* send SSL/TLS close_notify */
  /* --------------------------------------------------- */
  // Clean up.
  /* --------------------------------------------------- */
cleanup:
  TOCON("Cleanning Up\n");
  if (sd != INVALID_SOCKET)
#ifdef _WIN32
    closesocket(sd);
#else
    close(sd);
#endif
  if (ssl != NULL)
    SSL_free(ssl);

  if (ctx != NULL)
    SSL_CTX_free(ctx);

  if (fLog != NULL)
    CLOSE(fLog);

  if (fSend != NULL)
    CLOSE(fSend);

  if (fResponse != NULL)
    CLOSE(fResponse);

#ifdef _WIN32
  TOCON("Shutting-down windows socket support\n");
  WSACleanup();
#endif


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to