Bug 1180 - ACE_SSL_SOCK_Stream::close() can crash ACE_SSL server
Summary: ACE_SSL_SOCK_Stream::close() can crash ACE_SSL server
Status: NEW
Alias: None
Product: ACE
Classification: Unclassified
Component: SSL Wrappers (show other bugs)
Version: 5.2.2
Hardware: Alpha other
: P3 major
Assignee: DOC Center Support List (internal)
URL:
Depends on:
Blocks:
 
Reported: 2002-04-02 06:38 CST by Vladimir Chovanec
Modified: 2006-04-21 12:15 CDT (History)
1 user (show)

See Also:


Attachments
Suggested patch (5.36 KB, text/plain)
2002-10-22 09:23 CDT, Vladimir Chovanec
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimir Chovanec 2002-04-02 06:38:15 CST
DESCRIPTION:
    when handshake fails there is this in ACE_SSL_SOCK_Acceptor::accept()

  if (this->ssl_accept (new_stream, timeout) == -1)
    {
>>>   new_stream.close ();    //PROBLEM HERE!
      new_stream.set_handle (ACE_INVALID_HANDLE);
      return -1;
    }

    but when new_stream.close() fails with error EWOULDBLOCK, stream is not
    actually closed and when another connection comes to server, the same
    HANDLE is used for new_stream (at least on Alpha) and this can lead 
    to "Broken pipe" error and crash

    All this seems to be problem with integration of new implementation of 
    Connector and Acceptor. ACE_SSL_SOCK_Stream::close needs to be rewrited 
    too because it seem to depend on ACE_SSL_Accept_Handler which has been 
    removed. 

  REPEATED BY:
    I cant simlulate this error for sure but I have hacked win32 client
    (using WIN32 "feature": connect with timeout -10 :-))
    that can sometimes crash server running on Alpha 
    
    files attached :
      ssl_server.cpp should run on alpha
      ssl_win32_client.cpp should run on WINNT 
        (to have a "much better chance" to crash the server it should be
         compiled with version 1.36 of SSL_SOCK_Connector.cpp :-)

------------------------------------
attachments
ssl_server.cpp
---

#include <ace/OS.h>
#include <ace/Reactor.h>
#include <ace/Select_Reactor.h>
#include <ace/SSL/SSL_SOCK.h>
#include <ace/Acceptor.h>
#include <ace/SSL/SSL_SOCK_Acceptor.h>

#define SZ_SOCK_ACCEPTOR ACE_SSL_SOCK_ACCEPTOR
#define SZ_SOCK_STREAM ACE_SSL_SOCK_STREAM

typedef ACE_Svc_Handler<SZ_SOCK_STREAM, ACE_SYNCH> Handler_Base;

class Handler : public Handler_Base
{
public:
  
  Handler() { ACE_OS::printf("created\n"); }
  ~Handler() { ACE_OS::printf("destroyed\n"); }

  virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask mask);
};

typedef ACE_Acceptor<Handler, SZ_SOCK_ACCEPTOR> Acceptor;

int Handler::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask mask)
  {
    ACE_OS::printf("handle = %d, get_handle = %d\n", int(handle) + 1,
        this->get_handle() + 1);

    return Handler_Base::handle_close(handle, mask);
  }

void *svc(void *)
{
  ACE_SSL_Context *ctx = ACE_SSL_Context::instance();
  ctx->set_mode(ACE_SSL_Context::TLSv1_server);
  ctx->certificate("dummy.pem", SSL_FILETYPE_PEM);
  ctx->private_key("key.pem", SSL_FILETYPE_PEM);

  ACE_Select_Reactor select_reactor;
  ACE_Reactor reactor(&select_reactor);

  ACE_Acceptor<Handler, ACE_SSL_SOCK_ACCEPTOR> acceptor(&reactor);

  if (acceptor.open(ACE_INET_Addr(5050), &reactor) == -1)
    ACE_OS::exit(100);

  reactor.owner(ACE_Thread::self());  
  
  reactor.run_reactor_event_loop();
  return 0;
}

int Acceptor::accept_svc_handler(Handler *svc_handler)
{
  ACE_TRACE ("Acceptor::accept_svc_handler");

  // Try to find out if the implementation of the reactor that we are
  // using requires us to reset the event association for the newly
  // created handle. This is because the newly created handle will
  // inherit the properties of the listen handle, including its event
  // associations.
  int reset_new_handle = this->reactor ()->uses_event_associations ();

  ACE_Time_Value time(30);
  if (this->acceptor ().accept (svc_handler->peer (), // stream
                                0, // remote address
                                &time, // timeout
                                1, // restart
                                reset_new_handle  // reset new handler
                                ) == -1)
    {
      // Close down handler to avoid memory leaks.
      svc_handler->close (0);

      return -1;
    }
  else
    return 0;
}


int main(int argc, char *argv[])
{
  ACE_UNUSED_ARG(argc);
  ACE_UNUSED_ARG(argv);
  ACE_Select_Reactor select_reactor;
  ACE_Reactor reactor(&select_reactor);
  ACE_Reactor::instance(&reactor);

  ACE_Thread_Manager::instance()->spawn(svc);
  ACE_Reactor::instance()->owner(ACE_Thread::self());
  ACE_Reactor::run_event_loop();
  ACE_Thread_Manager::instance()->wait();
  return 0;
}

----------------------
ssl_win32_client.cpp
----------------------
#include <ace/OS.h>
#include <ace/Reactor.h>
#include <ace/Select_Reactor.h>
#include <ace/Connector.h>
#include <ace/SSL/SSL_SOCK_Connector.h>


  typedef ACE_SSL_SOCK_Connector SZ_SOCK_CONNECTOR;
  #define SZ_SOCK_STREAM_CTOR_ARGS \
       (ACE_SSL_Context::instance()->set_mode(ACE_SSL_Context::TLSv1), \
                ACE_SSL_Context::instance())


int main(int argc, char *argv[])
{

  ACE_UNUSED_ARG(argc);
  ACE_UNUSED_ARG(argv);
  ACE_SSL_SOCK_Stream *sock_stream_ = 0;
  ACE_INET_Addr addr;
  SZ_SOCK_CONNECTOR connector;

 int port = 5050;
 char *host = "xxx.xx.xx.xx";
 int timeout = -10;  //WIN 32 can handle even this :-(
 ACE_Time_Value timeout_(timeout);
 ACE_Time_Value timeout2_(timeout);

 if (addr.set((u_short) port, host) == -1)
    ACE_ERROR_RETURN((LM_ERROR,
      ACE_TEXT("can't cope with supplied address %s:%d (%m)\n"), host, port),
      -1);

  ACE_SSL_Context *context = ACE_SSL_Context::instance ();
  context->seed_file("random.dat", 1024);

  ACE_NEW_RETURN(sock_stream_, ACE_SSL_SOCK_Stream(SZ_SOCK_STREAM_CTOR_ARGS),
    -1);
    ACE_SSL_Context::instance()->seed_file("random.dat", 1024);
                          
  if (connector.connect(*sock_stream_, addr, &timeout_) == -1) {

    ACE_ERROR((LM_ERROR,
      ACE_TEXT("can't connect to remote host %s:%d (%m)\n"),
      addr.get_host_addr(), addr.get_port_number()));
  }

  delete sock_stream_;

  ACE_NEW_RETURN(sock_stream_, ACE_SSL_SOCK_Stream(SZ_SOCK_STREAM_CTOR_ARGS),
    -1);
    ACE_SSL_Context::instance()->seed_file("random.dat", 1024);
                          
  if (connector.connect(*sock_stream_, addr, &timeout2_) == -1) {

    ACE_ERROR((LM_ERROR,
      ACE_TEXT("can't connect to remote host %s:%d (%m)\n"),
      addr.get_host_addr(), addr.get_port_number()));
  }

  ACE_ERROR((LM_ERROR, ACE_TEXT("END\n")));

  return 0;
}
Comment 1 Ossama Othman 2002-04-10 12:22:59 CDT
Accepted.
Comment 2 Vladimir Chovanec 2002-10-22 09:23:22 CDT
Created attachment 153 [details]
Suggested patch