ws: add workaround for Komodia based LSPs that break SIO_BASE_HANDLE

This commit is contained in:
Bert Belder 2020-05-12 05:06:23 +02:00
parent 8223744d7b
commit 8dc6115127
No known key found for this signature in database
GPG Key ID: 7A77887B2E2ED461

View File

@ -1,9 +1,14 @@
#include <stdlib.h> #include <stdlib.h>
#include "error.h" #include "error.h"
#include "util.h"
#include "win.h" #include "win.h"
#include "ws.h" #include "ws.h"
#ifndef SIO_BSP_HANDLE_POLL
#define SIO_BSP_HANDLE_POLL 0x4800001D
#endif
#ifndef SIO_BASE_HANDLE #ifndef SIO_BASE_HANDLE
#define SIO_BASE_HANDLE 0x48000022 #define SIO_BASE_HANDLE 0x48000022
#endif #endif
@ -19,20 +24,54 @@ int ws_global_init(void) {
return 0; return 0;
} }
SOCKET ws_get_base_socket(SOCKET socket) { static inline SOCKET ws__ioctl_get_bsp_socket(SOCKET socket, DWORD ioctl) {
SOCKET base_socket; SOCKET bsp_socket;
DWORD bytes; DWORD bytes;
if (WSAIoctl(socket, if (WSAIoctl(socket,
SIO_BASE_HANDLE, ioctl,
NULL, NULL,
0, 0,
&base_socket, &bsp_socket,
sizeof base_socket, sizeof bsp_socket,
&bytes, &bytes,
NULL, NULL,
NULL) == SOCKET_ERROR) NULL) != SOCKET_ERROR)
return_map_error(INVALID_SOCKET); return bsp_socket;
else
return base_socket; return INVALID_SOCKET;
}
SOCKET ws_get_base_socket(SOCKET socket) {
SOCKET base_socket;
DWORD error;
for (;;) {
base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BASE_HANDLE);
if (base_socket != INVALID_SOCKET)
return base_socket;
error = GetLastError();
if (error == WSAENOTSOCK)
return_set_error(INVALID_SOCKET, error);
/* clang-format off */
/* Even though Microsoft documentation clearly states that LSPs should
* never intercept the `SIO_BASE_HANDLE` ioctl [1], Komodia based LSPs do
* so anyway, breaking it, with the apparent intention of preventing LSP
* bypass [2]. Fortunately they don't handle `SIO_BSP_HANDLE_POLL`, which
* we can use to obtain the socket associated with the next protocol chain
* entry. If this succeeds, loop around and call `SIO_BASE_HANDLE` again
* with the retrieved BSP socket to be sure that we actually got all the
* way to the base.
* [1] https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls
* [2] https://www.komodia.com/newwiki/index.php?title=Komodia%27s_Redirector_bug_fixes#Version_2.2.2.6
*/
/* clang-format on */
base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BSP_HANDLE_POLL);
if (base_socket != INVALID_SOCKET && base_socket != socket)
socket = base_socket;
else
return_set_error(INVALID_SOCKET, error);
}
} }