| 1023 | |
| 1024 | |
| 1025 | void LibeventSSLSocketImpl::peek_callback( |
| 1026 | evutil_socket_t fd, |
| 1027 | short what, |
| 1028 | void* arg) |
| 1029 | { |
| 1030 | CHECK(__in_event_loop__); |
| 1031 | |
| 1032 | CHECK(what & EV_READ); |
| 1033 | char data[6]; |
| 1034 | |
| 1035 | // Try to peek the first 6 bytes of the message. |
| 1036 | ssize_t size = ::recv(fd, data, 6, MSG_PEEK); |
| 1037 | |
| 1038 | // Based on the function 'ssl23_get_client_hello' in openssl, we |
| 1039 | // test whether to dispatch to the SSL or non-SSL based accept based |
| 1040 | // on the following rules: |
| 1041 | // 1. If there are fewer than 3 bytes: non-SSL. |
| 1042 | // 2. If the 1st bit of the 1st byte is set AND the 3rd byte is |
| 1043 | // equal to SSL2_MT_CLIENT_HELLO: SSL. |
| 1044 | // 3. If the 1st byte is equal to SSL3_RT_HANDSHAKE AND the 2nd |
| 1045 | // byte is equal to SSL3_VERSION_MAJOR and the 6th byte is |
| 1046 | // equal to SSL3_MT_CLIENT_HELLO: SSL. |
| 1047 | // 4. Otherwise: non-SSL. |
| 1048 | |
| 1049 | // For an ascii based protocol to falsely get dispatched to SSL it |
| 1050 | // needs to: |
| 1051 | // 1. Start with an invalid ascii character (0x80). |
| 1052 | // 2. OR have the first 2 characters be a SYN followed by ETX, and |
| 1053 | // then the 6th character be SOH. |
| 1054 | // These conditions clearly do not constitute valid HTTP requests, |
| 1055 | // and are unlikely to collide with other existing protocols. |
| 1056 | |
| 1057 | bool ssl = false; // Default to rule 4. |
| 1058 | |
| 1059 | if (size < 2) { // Rule 1. |
| 1060 | ssl = false; |
| 1061 | } else if ((data[0] & 0x80) && data[2] == SSL2_MT_CLIENT_HELLO) { // Rule 2. |
| 1062 | ssl = true; |
| 1063 | } else if (data[0] == SSL3_RT_HANDSHAKE && |
| 1064 | data[1] == SSL3_VERSION_MAJOR && |
| 1065 | data[5] == SSL3_MT_CLIENT_HELLO) { // Rule 3. |
| 1066 | ssl = true; |
| 1067 | } |
| 1068 | |
| 1069 | AcceptRequest* request = reinterpret_cast<AcceptRequest*>(arg); |
| 1070 | |
| 1071 | // We call 'event_free()' here because it ensures the event is made |
| 1072 | // non-pending and inactive before it gets deallocated. |
| 1073 | event_free(request->peek_event); |
| 1074 | request->peek_event = nullptr; |
| 1075 | |
| 1076 | if (ssl) { |
| 1077 | accept_SSL_callback(request); |
| 1078 | } else { |
| 1079 | // Downgrade to a non-SSL socket implementation. |
| 1080 | // |
| 1081 | // NOTE: The `int_fd` must be explicitly constructed to avoid the |
| 1082 | // `intptr_t` being casted to an `int`, resulting in a `HANDLE` |