Summary: | ACE_SSL_SOCK_Stream::close() can crash ACE_SSL server | ||
---|---|---|---|
Product: | ACE | Reporter: | Vladimir Chovanec <vladimir.chovanec> |
Component: | SSL Wrappers | Assignee: | DOC Center Support List (internal) <tao-support> |
Status: | NEW --- | ||
Severity: | major | CC: | Martin.Krumpolec |
Priority: | P3 | ||
Version: | 5.2.2 | ||
Hardware: | Alpha | ||
OS: | other | ||
Attachments: | Suggested patch |
Accepted. Created attachment 153 [details]
Suggested patch
|
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; }