Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,11 @@ if(WITH_LIBVNCSERVER)
cargstest
copyrecttest
)
if(UNIX)
list(APPEND SIMPLETESTS
unixsocktest
)
endif(UNIX)
endif(WITH_LIBVNCSERVER)


Expand Down Expand Up @@ -758,6 +763,9 @@ endif(LIBVNCSERVER_WITH_WEBSOCKETS AND WITH_LIBVNCSERVER)

if(WITH_LIBVNCSERVER)
add_test(NAME cargs COMMAND test_cargstest)
if(UNIX)
add_test(NAME unixsock COMMAND test_unixsocktest)
endif(UNIX)
endif(WITH_LIBVNCSERVER)
if(UNIX)
if(WITH_LIBVNCSERVER)
Expand Down
59 changes: 48 additions & 11 deletions src/libvncserver/rfbserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,14 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
rfbProtocolVersionMsg pv;
rfbClientIteratorPtr iterator;
rfbClientPtr cl,cl_;
#ifdef LIBVNCSERVER_IPv6
#if defined(LIBVNCSERVER_IPv6) || !defined(WIN32)
struct sockaddr_storage addr;
#else
struct sockaddr_in addr;
#endif
socklen_t addrlen = sizeof(addr);
rfbProtocolExtension* extension;
rfbBool isTcp = FALSE;

cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);

Expand Down Expand Up @@ -396,21 +397,57 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
} else {
#ifdef LIBVNCSERVER_IPv6
char host[1024];
#endif
#ifndef WIN32
struct sockaddr *sockAddr;
sockAddr = (struct sockaddr *)&addr;
#endif
int one=1;
size_t otherClientsCount = 0;

getpeername(sock, (struct sockaddr *)&addr, &addrlen);
if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) < 0) {
rfbLogPerror("rfbNewClient: error in getpeername");
cl->host = strdup("NON_SOCKET");
} else {
#ifndef WIN32
if (sockAddr->sa_family == AF_UNIX) {
struct sockaddr_un uaddr;
addrlen = sizeof(uaddr);
memset(&uaddr, 0, sizeof(uaddr));
if (getsockname(sock, (struct sockaddr *)&uaddr, &addrlen) < 0) {
rfbLogPerror("rfbNewClient: error in getsockname");
cl->host = strdup("NAMEFAIL_AF_UNIX");
} else if (uaddr.sun_path[0] == '\0') {
cl->host = strdup("UNNAMED_AF_UNIX");
} else {
cl->host = strdup(uaddr.sun_path);
}
} else
#endif
#ifdef LIBVNCSERVER_IPv6
if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
rfbLogPerror("rfbNewClient: error in getnameinfo");
cl->host = strdup("");
}
else
cl->host = strdup(host);
{
if (addr.ss_family == AF_INET || addr.ss_family == AF_INET6)
isTcp = TRUE;
if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
rfbLogPerror("rfbNewClient: error in getnameinfo");
cl->host = strdup("UNKNOWN_HOST");
}
else
cl->host = strdup(host);
}
#else
cl->host = strdup(inet_ntoa(addr.sin_addr));
{
struct sockaddr_in *inetAddr;
inetAddr = (struct sockaddr_in *)&addr;
if (inetAddr->sin_family == AF_INET) {
isTcp = TRUE;
cl->host = strdup(inet_ntoa(inetAddr->sin_addr));
} else {
cl->host = strdup("UNKNOWN_HOST");
}
}
#endif
}

cl->destPort = -1;

Expand All @@ -426,9 +463,9 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
return NULL;
}

if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
if (isTcp && setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
rfbLogPerror("setsockopt failed: can't set TCP_NODELAY flag, non TCP socket?");
rfbLogPerror("setsockopt failed: can't set TCP_NODELAY flag");
}

FD_SET(sock,&(rfbScreen->allFds));
Expand Down
67 changes: 67 additions & 0 deletions test/unixsocktest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <rfb/rfb.h>

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

static char observedHost[256];
static rfbBool hookWasCalled = FALSE;

static enum rfbNewClientAction
recordAndRefuseClient(rfbClientPtr cl)
{
hookWasCalled = TRUE;
if (cl->host)
snprintf(observedHost, sizeof(observedHost), "%s", cl->host);
else
observedHost[0] = '\0';
return RFB_CLIENT_REFUSE;
}

int
main(int argc, char **argv)
{
rfbScreenInfoPtr screen;
int fds[2];
rfbClientPtr client;
int failed;

failed = 0;
fds[0] = -1;
fds[1] = -1;

if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
perror("socketpair");
return 1;
}

screen = rfbGetScreen(&argc, argv, 8, 8, 8, 3, 4);
if (!screen) {
close(fds[0]);
close(fds[1]);
return 1;
}

screen->newClientHook = recordAndRefuseClient;
client = rfbNewClient(screen, fds[0]);
if (client != NULL) {
fprintf(stderr, "expected refused client to be cleaned up\n");
rfbCloseClient(client);
rfbClientConnectionGone(client);
failed = 1;
}

if (!hookWasCalled) {
fprintf(stderr, "newClientHook was not called\n");
failed = 1;
} else if (observedHost[0] == '\0') {
fprintf(stderr, "AF_UNIX client host must not be empty\n");
failed = 1;
}

rfbScreenCleanup(screen);
close(fds[1]);

return failed ? 1 : 0;
}
Loading