gio: tests AF_UNIX socket credentials on win32

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2022-01-19 20:39:59 +04:00
parent 95c3e28af5
commit e796124b31

View File

@ -2102,7 +2102,118 @@ client_setup_thread (gpointer user_data)
return NULL;
}
#ifdef G_OS_UNIX
#ifdef G_OS_WIN32
/*
* _g_win32_socketpair:
*
* Create a pair of connected sockets, similar to POSIX/BSD socketpair().
*
* Windows does not (yet) provide a socketpair() function. However, since the
* introduction of AF_UNIX sockets, it is possible to implement a fairly close
* function.
*/
static gint
_g_win32_socketpair (gint domain,
gint type,
gint protocol,
gint sv[2])
{
struct sockaddr_un addr = { 0, };
socklen_t socklen;
SOCKET listener = INVALID_SOCKET;
SOCKET client = INVALID_SOCKET;
SOCKET server = INVALID_SOCKET;
gchar *path = NULL;
int tmpfd, rv = -1;
u_long arg, br;
g_return_val_if_fail (sv != NULL, -1);
addr.sun_family = AF_UNIX;
socklen = sizeof (addr);
tmpfd = g_file_open_tmp (NULL, &path, NULL);
if (tmpfd == -1)
{
WSASetLastError (WSAEACCES);
goto out;
}
g_close (tmpfd, NULL);
if (strlen (path) >= sizeof (addr.sun_path))
{
WSASetLastError (WSAEACCES);
goto out;
}
strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
listener = socket (domain, type, protocol);
if (listener == INVALID_SOCKET)
goto out;
if (DeleteFile (path) == 0)
{
if (GetLastError () != ERROR_FILE_NOT_FOUND)
goto out;
}
if (bind (listener, (struct sockaddr *) &addr, socklen) == SOCKET_ERROR)
goto out;
if (listen (listener, 1) == SOCKET_ERROR)
goto out;
client = socket (domain, type, protocol);
if (client == INVALID_SOCKET)
goto out;
arg = 1;
if (ioctlsocket (client, FIONBIO, &arg) == SOCKET_ERROR)
goto out;
if (connect (client, (struct sockaddr *) &addr, socklen) == SOCKET_ERROR &&
WSAGetLastError () != WSAEWOULDBLOCK)
goto out;
server = accept (listener, NULL, NULL);
if (server == INVALID_SOCKET)
goto out;
arg = 0;
if (ioctlsocket (client, FIONBIO, &arg) == SOCKET_ERROR)
goto out;
if (WSAIoctl (server, SIO_AF_UNIX_GETPEERPID,
NULL, 0U,
&arg, sizeof (arg), &br,
NULL, NULL) == SOCKET_ERROR || arg != GetCurrentProcessId ())
{
WSASetLastError (WSAEACCES);
goto out;
}
sv[0] = server;
server = INVALID_SOCKET;
sv[1] = client;
client = INVALID_SOCKET;
rv = 0;
out:
if (listener != INVALID_SOCKET)
closesocket (listener);
if (client != INVALID_SOCKET)
closesocket (client);
if (server != INVALID_SOCKET)
closesocket (server);
DeleteFile (path);
g_free (path);
return rv;
}
#endif /* G_OS_WIN32 */
static void
test_credentials_unix_socketpair (void)
{
@ -2112,7 +2223,11 @@ test_credentials_unix_socketpair (void)
GError *error = NULL;
GCredentials *creds;
#ifdef G_OS_WIN32
status = _g_win32_socketpair (PF_UNIX, SOCK_STREAM, 0, fds);
#else
status = socketpair (PF_UNIX, SOCK_STREAM, 0, fds);
#endif
g_assert_cmpint (status, ==, 0);
sock = g_socket_new_from_fd (fds[0], &error);
@ -2133,10 +2248,9 @@ test_credentials_unix_socketpair (void)
}
g_object_unref (sock);
close (fds[1]);
g_close (fds[1], NULL);
}
#endif
#endif
int
main (int argc,
@ -2199,9 +2313,7 @@ main (int argc,
#if G_CREDENTIALS_SUPPORTED
g_test_add_func ("/socket/credentials/tcp_client", test_credentials_tcp_client);
g_test_add_func ("/socket/credentials/tcp_server", test_credentials_tcp_server);
#ifdef G_OS_UNIX
g_test_add_func ("/socket/credentials/unix_socketpair", test_credentials_unix_socketpair);
#endif
#endif
return g_test_run();