summaryrefslogtreecommitdiff
path: root/ace/SSL/SSL_Accept_Handler.cpp
blob: 84073dabb231ea5463371b1f8048bd52c4333e52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// -*- C++ -*-

#include "SSL_Accept_Handler.h"
#include "SSL_SOCK_Stream.h"

#include <openssl/err.h>

ACE_RCSID (ACE_SSL,
           SSL_Accept_Handler,
           "$Id$")


ACE_SSL_Accept_Handler::ACE_SSL_Accept_Handler (ACE_SSL_SOCK_Stream &s)
  : ssl_stream_ (s)
{
}

ACE_SSL_Accept_Handler::~ACE_SSL_Accept_Handler (void)
{
}

ACE_HANDLE
ACE_SSL_Accept_Handler::get_handle (void) const
{
  return this->ssl_stream_.get_handle ();
}

int
ACE_SSL_Accept_Handler::handle_input (ACE_HANDLE)
{
  return this->ssl_accept ();
}

int
ACE_SSL_Accept_Handler::handle_output (ACE_HANDLE)
{
  return this->ssl_accept ();
}

int
ACE_SSL_Accept_Handler::handle_close (ACE_HANDLE /* handle */,
                                      ACE_Reactor_Mask /* close_mask */)
{
  return this->ssl_stream_.close ();
}


int
ACE_SSL_Accept_Handler::ssl_accept (void)
{
  SSL *ssl = this->ssl_stream_.ssl ();

  // A race condition exists where data may be sent over an SSL
  // session after the SSL passive connection is completed but before
  // this event handler is deregistered from the Reactor.
  // Specifically data meant to be handled by SSL_read() could end up
  // being handled by the SSL_accept() call below, resulting in an SSL
  // protocol error (i.e. "SSL_ERROR_SSL" error status).  The
  // following check avoids the race condition.
  if (SSL_is_init_finished (ssl))
    return 0;

  int status = ::SSL_accept (ssl);

  switch (::SSL_get_error (ssl, status))
    {
    case SSL_ERROR_NONE:
      break;

    case SSL_ERROR_WANT_WRITE:
    case SSL_ERROR_WANT_READ:
      // If data is still buffered within OpenSSL's internal buffer,
      // then force the Reactor to invoke the SSL accept event handler
      // (with the appropriate mask) before waiting for more events
      // (e.g. blocking on select()).  All pending data must be
      // processed before waiting for more events to come in on the
      // SSL handle.
      if (::SSL_pending (ssl))
        return 1;

      break;

    case SSL_ERROR_ZERO_RETURN:
      // The peer has notified us that it is shutting down via
      // the SSL "close_notify" message so we need to
      // shutdown, too.
      //
      // Removing this event handler causes the SSL stream to be
      // shutdown.
      return -1;

    case SSL_ERROR_SYSCALL:
      // On some platforms (e.g. MS Windows) OpenSSL does not
      // store the last error in errno so explicitly do so.
      //
      // Explicitly check for EWOULDBLOCK since it doesn't get
      // converted to an SSL_ERROR_WANT_{READ,WRITE} on some
      // platforms, such as AIX.
      if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK)
        return 0;

    default:
      ACE_SSL_Context::report_error ();

      return -1;
    }

  return 0;
}