diff --git a/libvncserver/cargs.c b/libvncserver/cargs.c index 27ceb97..b9eb02b 100644 --- a/libvncserver/cargs.c +++ b/libvncserver/cargs.c @@ -45,6 +45,9 @@ rfbUsage(void) "instead)\n"); fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n"); fprintf(stderr, "-httpport portnum use portnum for http connection\n"); +#ifdef LIBVNCSERVER_IPv6 + fprintf(stderr, "-httpportv6 portnum use portnum for IPv6 http connection\n"); +#endif fprintf(stderr, "-enablehttpproxy enable http proxy support\n"); fprintf(stderr, "-progressive height enable progressive updating for slow links\n"); fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n"); @@ -162,6 +165,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]) return FALSE; } rfbScreen->httpPort = atoi(argv[++i]); +#ifdef LIBVNCSERVER_IPv6 + } else if (strcmp(argv[i], "-httpportv6") == 0) { /* -httpportv6 portnum */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->http6Port = atoi(argv[++i]); +#endif } else if (strcmp(argv[i], "-enablehttpproxy") == 0) { rfbScreen->httpEnableProxyConnect = TRUE; } else if (strcmp(argv[i], "-progressive") == 0) { /* -httpport portnum */ diff --git a/libvncserver/httpd.c b/libvncserver/httpd.c index 3025aae..6e46b99 100644 --- a/libvncserver/httpd.c +++ b/libvncserver/httpd.c @@ -102,17 +102,27 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) rfbScreen->httpPort = rfbScreen->port-100; } - rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort); - - rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort); - if ((rfbScreen->httpListenSock = rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) { rfbLogPerror("ListenOnTCPPort"); return; } + rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort); + rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort); + +#ifdef LIBVNCSERVER_IPv6 + if (rfbScreen->http6Port == 0) { + rfbScreen->http6Port = rfbScreen->ipv6port-100; + } - /*AddEnabledDevice(httpListenSock);*/ + if ((rfbScreen->httpListen6Sock + = rfbListenOnTCP6Port(rfbScreen->http6Port, rfbScreen->listen6Interface)) < 0) { + /* ListenOnTCP6Port has its own detailed error printout */ + return; + } + rfbLog("Listening for HTTP connections on TCP6 port %d\n", rfbScreen->http6Port); + rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->http6Port); +#endif } void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { @@ -121,6 +131,18 @@ void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds); rfbScreen->httpSock=-1; } + + if(rfbScreen->httpListenSock>-1) { + close(rfbScreen->httpListenSock); + FD_CLR(rfbScreen->httpListenSock,&rfbScreen->allFds); + rfbScreen->httpListenSock=-1; + } + + if(rfbScreen->httpListen6Sock>-1) { + close(rfbScreen->httpListen6Sock); + FD_CLR(rfbScreen->httpListen6Sock,&rfbScreen->allFds); + rfbScreen->httpListen6Sock=-1; + } } /* @@ -134,7 +156,11 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) int nfds; fd_set fds; struct timeval tv; +#ifdef LIBVNCSERVER_IPv6 + struct sockaddr_storage addr; +#else struct sockaddr_in addr; +#endif socklen_t addrlen = sizeof(addr); if (!rfbScreen->httpDir) @@ -145,12 +171,15 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) FD_ZERO(&fds); FD_SET(rfbScreen->httpListenSock, &fds); + if (rfbScreen->httpListen6Sock >= 0) { + FD_SET(rfbScreen->httpListen6Sock, &fds); + } if (rfbScreen->httpSock >= 0) { FD_SET(rfbScreen->httpSock, &fds); } tv.tv_sec = 0; tv.tv_usec = 0; - nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv); + nfds = select(max(rfbScreen->httpListen6Sock, max(rfbScreen->httpSock,rfbScreen->httpListenSock)) + 1, &fds, NULL, NULL, &tv); if (nfds == 0) { return; } @@ -167,19 +196,36 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) httpProcessInput(rfbScreen); } - if (FD_ISSET(rfbScreen->httpListenSock, &fds)) { + if (FD_ISSET(rfbScreen->httpListenSock, &fds) || FD_ISSET(rfbScreen->httpListen6Sock, &fds)) { if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); - if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, - (struct sockaddr *)&addr, &addrlen)) < 0) { - rfbLogPerror("httpCheckFds: accept"); - return; + if(FD_ISSET(rfbScreen->httpListenSock, &fds)) { + if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { + rfbLogPerror("httpCheckFds: accept"); + return; + } } + else if(FD_ISSET(rfbScreen->httpListen6Sock, &fds)) { + if ((rfbScreen->httpSock = accept(rfbScreen->httpListen6Sock, (struct sockaddr *)&addr, &addrlen)) < 0) { + rfbLogPerror("httpCheckFds: accept"); + return; + } + } + #ifdef USE_LIBWRAP - if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), + char host[1024]; +#ifdef LIBVNCSERVER_IPv6 + if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { + rfbLogPerror("httpCheckFds: error in getnameinfo"); + host[0] = '\0'; + } +#else + memcpy(host, inet_ntoa(addr.sin_addr), sizeof(host)); +#endif + if(!hosts_ctl("vnc",STRING_UNKNOWN, host, STRING_UNKNOWN)) { rfbLog("Rejected HTTP connection from client %s\n", - inet_ntoa(addr.sin_addr)); + host); close(rfbScreen->httpSock); rfbScreen->httpSock=-1; return; @@ -212,7 +258,11 @@ static rfbClientRec cl; static void httpProcessInput(rfbScreenInfoPtr rfbScreen) { +#ifdef LIBVNCSERVER_IPv6 + struct sockaddr_storage addr; +#else struct sockaddr_in addr; +#endif socklen_t addrlen = sizeof(addr); char fullFname[512]; char params[1024]; @@ -335,8 +385,16 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen) getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen); +#ifdef LIBVNCSERVER_IPv6 + char host[1024]; + if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { + rfbLogPerror("httpProcessInput: error in getnameinfo"); + } + rfbLog("httpd: get '%s' for %s\n", fname+1, host); +#else rfbLog("httpd: get '%s' for %s\n", fname+1, inet_ntoa(addr.sin_addr)); +#endif /* Extract parameters from the URL string if necessary */ @@ -562,7 +620,8 @@ parseParams(const char *request, char *result, int max_bytes) /* * Check if the string consists only of alphanumeric characters, '+' - * signs, underscores, and dots. Replace all '+' signs with spaces. + * signs, underscores, dots, colons and square brackets. + * Replace all '+' signs with spaces. */ static rfbBool @@ -571,7 +630,8 @@ validateString(char *str) char *ptr; for (ptr = str; *ptr != '\0'; ptr++) { - if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { + if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.' + && *ptr != ':' && *ptr != '[' && *ptr != ']' ) { if (*ptr == '+') { *ptr = ' '; } else { diff --git a/libvncserver/main.c b/libvncserver/main.c index a045d4c..4cb18ac 100644 --- a/libvncserver/main.c +++ b/libvncserver/main.c @@ -843,8 +843,10 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, screen->httpInitDone=FALSE; screen->httpEnableProxyConnect=FALSE; screen->httpPort=0; + screen->http6Port=0; screen->httpDir=NULL; screen->httpListenSock=-1; + screen->httpListen6Sock=-1; screen->httpSock=-1; screen->desktopName = "LibVNCServer"; diff --git a/rfb/rfb.h b/rfb/rfb.h index 9e9fbfe..bf4e011 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -383,6 +383,8 @@ typedef struct _rfbScreenInfo don't support dual binding sockets under *any* circumstances, for instance OpenBSD */ SOCKET listen6Sock; + int http6Port; + SOCKET httpListen6Sock; } rfbScreenInfo, *rfbScreenInfoPtr;