Hi,

I am writing a specialized HTTPS server for Windows.  The server and
browser are on the same machine, with the browser requesting a resource via
localhost (e.g., "https://localhost:2649/someResource";).

When using Netscape 6.2 (a Mozilla 0.9.4 branch), the SSL_read in the
snippet below works fine.  When using IE 5.01 SP2, SSL_read returns 0, with
SSL_get_error returning SSL_ERR_SYSCALL (logic of SSL_get_error just falls
completely through to this default return value).

I'm at a complete loss on this one, so any help would be greatly
appreciated.  I have tried the following:

o  Using both the static and dynamic OpenSSL libraries
o  Identified the call stack:

   SSL_read
   ssl3_read
   ssl3_read_internal
   ssl3_read_bytes
   ssl3_get_record
   ssl3_read_n
   BIO_read
   sock_read  (pointed to by b->method->bread)
   readsocket (<-- failure point??: returns 0 bytes read, but why only for
IE?)

o  Tried using the BIO_new / BIO_new_socket approach instead
   of SSL_set_fd with the same result
o  Ensured non-SSL communications are ok by setting the
   do_ssl constant to false (see snippet below)
o  Tried the SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER option with no success

Here's my environment:

o  Windows NT 4, build 4.00.1381 (SP3?)
o  IE 5, build 5.00.3314.2101 (5.01 SP2)
o  Microsoft Visual C++ 6.0
o  Non-MFC console application, linked to multithreaded DLL runtime
o  128 MB RAM

Thanks,
Jim

Sample code:

#include <winsock2.h>
#include <string>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/crypto.h>

using namespace std;

int main()
{
     WSADATA d;
     int err = WSAStartup(0x0101, &d);

     const bool do_ssl = true;

     SOCKET     _sockfd;
     int        _port;
     SSL_CTX*   _ssl_ctx;
     SSL*       _ssl;
     int        rc;
     int        nrecv;

     if (err != 0)
          return err;

     if (do_ssl)
     {
          SSL_library_init();
          SSL_load_error_strings();

          _ssl_ctx = SSL_CTX_new( SSLv23_server_method() );

          if ( SSL_CTX_use_certificate_file( _ssl_ctx, ".\\localhost.crt",
SSL_FILETYPE_PEM ) == 0 )
               return -1;

          if ( SSL_CTX_use_PrivateKey_file( _ssl_ctx, ".\\localhost.key",
SSL_FILETYPE_PEM ) == 0 )
               return -1;

          if ( SSL_CTX_check_private_key( _ssl_ctx ) == 0 )
               return -1;
     }

     struct protoent   *ppe;
     struct sockaddr_in sin;

     int  type = SOCK_STREAM;

     memset(&sin, 0, sizeof(sin));

     sin.sin_family      = AF_INET;
     sin.sin_addr.s_addr = INADDR_ANY;

     _port = 2649;

     if ((sin.sin_port = htons((u_short)_port)) == 0)
          return -1;

     if ((ppe = getprotobyname("tcp")) == NULL)
          return -1;

     _sockfd = socket(PF_INET, type, ppe->p_proto);

     if (_sockfd < 0)
          return -1;

     if (bind(_sockfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
     {
          return -1;
     }

     if ((type = SOCK_STREAM) && (listen(_sockfd, 5) < 0))
     {
          return -1;
     }

     sockaddr cliaddr;

     int clilen = sizeof(cliaddr);

     fd_set fds;

     clilen = sizeof(cliaddr);
     FD_ZERO(&fds);

     FD_SET(_sockfd, &fds);
     SOCKET clisockfd;

     clisockfd = ::accept(_sockfd, &cliaddr, &clilen);

     if (clisockfd < 0)
          return -1;

     if (do_ssl)
     {
          _ssl = SSL_new(_ssl_ctx);
          SSL_set_options(_ssl, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
          SSL_set_fd(_ssl, clisockfd);

          while ( !SSL_is_init_finished(_ssl) )
          {
               if ( (rc = SSL_accept(_ssl)) <= 0 )
               {
                    if ( SSL_get_error(_ssl, rc) == SSL_ERROR_ZERO_RETURN )
                         return -1;
                    else if ( SSL_get_error(_ssl, rc) == SSL_ERROR_SYSCALL
)
                    {
                         if (errno == EINTR) continue;
                              return -1;
                    }
                    else
                         return -1;
               }
          }
     }

     /*
      *  Reading Request-Line from socket
      */

     static char prevChar = '\0';
     char        currChar = '\0';

     string      currLine;

     for ( ; ; )
     {
          if (do_ssl)
          {
               int ret = SSL_read( _ssl, &currChar, 1); // returns 0,
currChar is null string
               int wsaen = WSAGetLastError();
               int geno = SSL_get_error(_ssl, ret);     // returns
SSL_ERR_SYSCALL
               int egeno = ERR_get_error();

               if (ret == 0)
                    ERR_print_errors_fp(stdout);
          }
          else
          {
              nrecv = ::recv(clisockfd, &currChar, 1, 0); // Regular
sockets
              rc    = WSAGetLastError();
          }

          if (currChar == 0)
               break;

          // Ignore LF if it follows a CR, for CRLF end-of-line

          if ((currChar == '\n') && (prevChar == '\r'))
               continue;

          // Found end-of-line

          if ((currChar == '\r') || (currChar == '\n'))
               break;

          currLine = currLine + currChar;
     }

     strcpy(&prevChar, &currChar);

     /*
      *  Cleanup
      */

     if (do_ssl)
     {
          SSL_shutdown( _ssl );
          SSL_free( _ssl );
          SSL_CTX_free( _ssl_ctx );
     }

     ::shutdown(_sockfd, SD_SEND);

     char tmp;
     while( ::recv(_sockfd, &tmp, 1, 0) > 0 );

     if (::closesocket(_sockfd) != 0)
          return -1;

     _sockfd = 0;

     WSACleanup();

     return 0;
}

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

Reply via email to