From a01a18df1d44ec875708d5fc9d6c4e0934535974 Mon Sep 17 00:00:00 2001 From: Balazs Ludmany Date: Tue, 21 Jun 2016 10:03:52 +0200 Subject: Add function pointers for every type of rectangle --- rfb/rfbclient.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'rfb') diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 4f6f4f4..d90342b 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -182,6 +182,9 @@ typedef void (*BellProc)(struct _rfbClient* client); */ typedef void (*GotCursorShapeProc)(struct _rfbClient* client, int xhot, int yhot, int width, int height, int bytesPerPixel); typedef void (*GotCopyRectProc)(struct _rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y); +typedef void (*GotFillRectProc)(struct _rfbClient* client, int x, int y, int w, int h, uint32_t colour); +typedef void (*GotBitmapProc)(struct _rfbClient* client, const uint8_t* buffer, int x, int y, int w, int h); +typedef rfbBool (*GotJpegProc)(struct _rfbClient* client, const uint8_t* buffer, int length, int x, int y, int w, int h); typedef rfbBool (*LockWriteToTLSProc)(struct _rfbClient* client); typedef rfbBool (*UnlockWriteToTLSProc)(struct _rfbClient* client); @@ -367,6 +370,18 @@ typedef struct _rfbClient { LockWriteToTLSProc LockWriteToTLS; UnlockWriteToTLSProc UnlockWriteToTLS; + /** Hooks for custom rendering + * + * VNC rendering boils down to 3 activities: + * - GotCopyRect: copy an area of the framebuffer + * - GotFillRect: fill an area of the framebuffer with a solid color + * - GotBitmap: copy the bitmap in the buffer into the framebuffer + * The client application should either set all three of these or none! + */ + GotFillRectProc GotFillRect; + GotBitmapProc GotBitmap; + /** Hook for custom JPEG decoding and rendering */ + GotJpegProc GotJpeg; } rfbClient; /* cursor.c */ -- cgit v1.2.3 From dede3aea22640d9b036f358b228aa611da6bc0d9 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sat, 28 Jan 2017 17:59:52 +0100 Subject: Fix LibVNCClient compilation with MSVC 2014 --- common/vncauth.c | 2 ++ libvncclient/listen.c | 4 ++++ libvncclient/sockets.c | 2 ++ rfb/rfbclient.h | 4 ++++ 4 files changed, 12 insertions(+) (limited to 'rfb') diff --git a/common/vncauth.c b/common/vncauth.c index 0b20f53..2a5d96f 100644 --- a/common/vncauth.c +++ b/common/vncauth.c @@ -31,7 +31,9 @@ #endif #include #include +#ifdef LIBVNCSERVER_HAVE_UNISTD_H #include +#endif #include #include "d3des.h" diff --git a/libvncclient/listen.c b/libvncclient/listen.c index e989d6a..8674b3f 100644 --- a/libvncclient/listen.c +++ b/libvncclient/listen.c @@ -25,7 +25,9 @@ #ifdef __STRICT_ANSI__ #define _BSD_SOURCE #endif +#if LIBVNCSERVER_HAVE_UNISTD_H #include +#endif #include #ifdef WIN32 #define close closesocket @@ -34,7 +36,9 @@ #include #include #endif +#if LIBVNCSERVER_HAVE_SYS_TIME_H #include +#endif #include /* diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c index 8ddfd9d..1019580 100644 --- a/libvncclient/sockets.c +++ b/libvncclient/sockets.c @@ -30,7 +30,9 @@ # define _POSIX_SOURCE #endif #endif +#if LIBVNCSERVER_HAVE_UNISTD_H #include +#endif #include #include #include diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 4f6f4f4..9fdb008 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -38,8 +38,12 @@ #include #include #include +#if LIBVNCSERVER_HAVE_SYS_TIME_H #include +#endif +#if LIBVNCSERVER_HAVE_UNISTD_H #include +#endif #include #include -- cgit v1.2.3 From cd5b38d742e011bc6fe9c231796348426910ed3f Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sat, 28 Jan 2017 20:43:13 +0100 Subject: CMake: add a HAVE_SYS_UIO_H flag to rfbconfig.h --- rfb/rfbconfig.h.cmake | 3 +++ 1 file changed, 3 insertions(+) (limited to 'rfb') diff --git a/rfb/rfbconfig.h.cmake b/rfb/rfbconfig.h.cmake index 5bd6569..86f7ae3 100644 --- a/rfb/rfbconfig.h.cmake +++ b/rfb/rfbconfig.h.cmake @@ -51,6 +51,9 @@ /* Define to 1 if you have that is POSIX.1 compatible. */ #cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1 +/* Define to 1 if you have */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_UIO_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1 -- cgit v1.2.3 From 73684172397d63c4274d7fbdf940f428cf31744c Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sat, 28 Jan 2017 21:02:11 +0100 Subject: Various #ifdef fixes to allow building with MSVC2014 --- common/md5.h | 6 +++++- libvncserver/httpd.c | 1 + libvncserver/rfbcrypto.h | 2 ++ libvncserver/rfbserver.c | 3 +++ libvncserver/tightvnc-filetransfer/filetransfermsg.c | 2 ++ .../handlefiletransferrequest.c | 2 ++ libvncserver/websockets.c | 20 +++++++++++++++++--- rfb/rfb.h | 1 + 8 files changed, 33 insertions(+), 4 deletions(-) (limited to 'rfb') diff --git a/common/md5.h b/common/md5.h index 0fb0a4a..b0daab1 100644 --- a/common/md5.h +++ b/common/md5.h @@ -88,7 +88,11 @@ struct md5_ctx md5_uint32 total[2]; md5_uint32 buflen; - char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); + char buffer[128] +#if __GNUC__ + __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))) +#endif + ; }; /* diff --git a/libvncserver/httpd.c b/libvncserver/httpd.c index 8634b15..26d49af 100644 --- a/libvncserver/httpd.c +++ b/libvncserver/httpd.c @@ -47,6 +47,7 @@ #include #include #define close closesocket +#define strcasecmp _stricmp #if defined(_MSC_VER) #include /* For the missing ssize_t */ #define ssize_t SSIZE_T diff --git a/libvncserver/rfbcrypto.h b/libvncserver/rfbcrypto.h index 9dc3e63..7853154 100644 --- a/libvncserver/rfbcrypto.h +++ b/libvncserver/rfbcrypto.h @@ -1,6 +1,7 @@ #ifndef _RFB_CRYPTO_H #define _RFB_CRYPTO_H 1 +#ifdef LIBVNCSERVER_HAVE_UIO_H #include #define SHA1_HASH_SIZE 20 @@ -8,5 +9,6 @@ void digestmd5(const struct iovec *iov, int iovcnt, void *dest); void digestsha1(const struct iovec *iov, int iovcnt, void *dest); +#endif #endif diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c index bc9cc11..040238d 100644 --- a/libvncserver/rfbserver.c +++ b/libvncserver/rfbserver.c @@ -37,6 +37,7 @@ #include #include #include "private.h" +#include "rfb/rfbconfig.h" #ifdef LIBVNCSERVER_HAVE_FCNTL_H #include @@ -74,7 +75,9 @@ /* stst() */ #include #include +#if LIBVNCSERVER_HAVE_UNISTD_H #include +#endif #ifndef WIN32 /* readdir() */ diff --git a/libvncserver/tightvnc-filetransfer/filetransfermsg.c b/libvncserver/tightvnc-filetransfer/filetransfermsg.c index 153f123..5f84e7f 100644 --- a/libvncserver/tightvnc-filetransfer/filetransfermsg.c +++ b/libvncserver/tightvnc-filetransfer/filetransfermsg.c @@ -56,7 +56,9 @@ #endif #include +#if LIBVNCSERVER_HAVE_UNISTD_H #include +#endif #include #include diff --git a/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c b/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c index b235fa0..c511eed 100644 --- a/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c +++ b/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c @@ -29,7 +29,9 @@ #include #include #include +#if LIBVNCSERVER_HAVE_UNISTD_H #include +#endif #ifndef _MSC_VER #include #include diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c index f596ab1..72396c2 100644 --- a/libvncserver/websockets.c +++ b/libvncserver/websockets.c @@ -49,7 +49,9 @@ #endif #include +#if LIBVNCSERVER_UNISTD_H #include +#endif #include "rfb/rfbconfig.h" #include "rfbssl.h" #include "rfbcrypto.h" @@ -116,15 +118,27 @@ typedef union ws_mask_s { * it from recognizing anonymous structs and unions. * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=4784 */ -typedef struct __attribute__ ((__packed__)) ws_header_s { +typedef struct +#if __GNUC__ +__attribute__ ((__packed__)) +#endif +ws_header_s { unsigned char b0; unsigned char b1; union { - struct __attribute__ ((__packed__)) { + struct +#if __GNUC__ + __attribute__ ((__packed__)) +#endif + { uint16_t l16; ws_mask_t m16; } s16; - struct __attribute__ ((__packed__)) { + struct +#if __GNUC__ +__attribute__ ((__packed__)) +#endif + { uint64_t l64; ws_mask_t m64; } s64; diff --git a/rfb/rfb.h b/rfb/rfb.h index c6edc11..f982b40 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -54,6 +54,7 @@ extern "C" #ifdef WIN32 #undef SOCKET +typedef UINT32 in_addr_t; #include #ifdef LIBVNCSERVER_HAVE_WS2TCPIP_H #undef socklen_t -- cgit v1.2.3 From 502e97df1aa74c35818e708188d3784124bcc7e7 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 31 Jan 2017 10:20:52 +0100 Subject: CMake: that file ain't used no more --- rfb/rfbint.h.cmake | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 rfb/rfbint.h.cmake (limited to 'rfb') diff --git a/rfb/rfbint.h.cmake b/rfb/rfbint.h.cmake deleted file mode 100644 index 17de6cd..0000000 --- a/rfb/rfbint.h.cmake +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _RFB_RFBINT_H -#define _RFB_RFBINT_H 1 -/* empty ... */ -#endif -- cgit v1.2.3 From dbf5f9d51476eb513e26559e78fc524a267504d7 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 21 Feb 2017 18:22:01 +0100 Subject: Fix "rfbBool's size is not 1" runtime error with MSVC --- rfb/rfbproto.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rfb') diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h index ba643b1..b680da4 100644 --- a/rfb/rfbproto.h +++ b/rfb/rfbproto.h @@ -64,7 +64,7 @@ #if defined(WIN32) && !defined(__MINGW32__) #define LIBVNCSERVER_WORDS_BIGENDIAN -#define rfbBool int +typedef int8_t rfbBool; #include #include #undef SOCKET -- cgit v1.2.3 From 7edd53ec277a6d4942caf315b1aba741d2cbc414 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 21 Feb 2017 19:35:47 +0100 Subject: rfbproto: remove SOCKET redefinitions --- rfb/rfbproto.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'rfb') diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h index b680da4..3216601 100644 --- a/rfb/rfbproto.h +++ b/rfb/rfbproto.h @@ -67,8 +67,6 @@ typedef int8_t rfbBool; #include #include -#undef SOCKET -#define SOCKET int #else #include #endif @@ -101,7 +99,6 @@ typedef int8_t rfbBool; #ifdef LIBVNCSERVER_HAVE_NETINET_IN_H #include #endif -#define SOCKET int typedef int8_t rfbBool; #undef FALSE #define FALSE 0 -- cgit v1.2.3 From b551e7017b1284361e2d29c7f2571c10f307cdef Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 21 Feb 2017 21:42:33 +0100 Subject: rfbproto: re-add erroneously removed SOCKET definition --- rfb/rfbproto.h | 1 + 1 file changed, 1 insertion(+) (limited to 'rfb') diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h index 3216601..f0d6ea1 100644 --- a/rfb/rfbproto.h +++ b/rfb/rfbproto.h @@ -99,6 +99,7 @@ typedef int8_t rfbBool; #ifdef LIBVNCSERVER_HAVE_NETINET_IN_H #include #endif +#define SOCKET int typedef int8_t rfbBool; #undef FALSE #define FALSE 0 -- cgit v1.2.3 From 80ad74f7613d7d790a5152ee377af361ecd3ff9b Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sun, 26 Mar 2017 16:11:16 +0200 Subject: Fix building for Android and add build instructions to README --- README | 11 +++++++++++ libvncclient/listen.c | 2 +- rfb/rfbclient.h | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'rfb') diff --git a/README b/README index 5a69f3e..6227069 100644 --- a/README +++ b/README @@ -81,6 +81,17 @@ LibVNCServer uses CMake, so you can build via: For some more comprehensive examples that include installation of dependencies, see the [Unix CI](.travis.yml) and [Windows CI](.appveyor.yml) build setups. +Crosscompiling involves some more advanced command line switches but is easily possible +as well. + +For instance, building for Android (see https://developer.android.com/ndk/guides/cmake.html as a reference): + + mkdir build + cd build + cmake .. -DANDROID_NDK= -DCMAKE_TOOLCHAIN_FILE= -DANDROID_NATIVE_API_LEVEL= -DWITH_PNG=OFF # NDK not shipping png per default + cmake --build . + + How to use ---------- diff --git a/libvncclient/listen.c b/libvncclient/listen.c index 8674b3f..4ecedff 100644 --- a/libvncclient/listen.c +++ b/libvncclient/listen.c @@ -89,7 +89,7 @@ listenForIncomingConnections(rfbClient* client) int r; /* reap any zombies */ int status, pid; - while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); + while ((pid= wait4(-1, &status, WNOHANG, (struct rusage *)0))>0); /* TODO: callback for discard any events (like X11 events) */ diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 505dd9c..72e7a5a 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -35,6 +35,11 @@ #define WIN32_LEAN_AND_MEAN /* Prevent loading any Winsock 1.x headers from windows.h */ #endif +#if defined(ANDROID) || defined(LIBVNCSERVER_HAVE_ANDROID) +#include +#include +#endif + #include #include #include -- cgit v1.2.3 From 6d4bb07ea6abf82231ccd3699357b13ae113bb18 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 18 Apr 2017 22:18:08 +0200 Subject: CMake: detect mmap() and write result to rfbconfig.h --- CMakeLists.txt | 1 + rfb/rfbconfig.h.cmake | 3 +++ 2 files changed, 4 insertions(+) (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index d39672e..1d00d5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,7 @@ check_include_file("sys/types.h" HAVE_SYS_TYPES_H) check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY) check_function_exists(vfork LIBVNCSERVER_HAVE_VFORK) check_function_exists(vprintf LIBVNCSERVER_HAVE_VPRINTF) +check_function_exists(mmap LIBVNCSERVER_HAVE_MMAP) # On systems such as GNU/Linux with glibc, __b64_ntop is defined in a diff --git a/rfb/rfbconfig.h.cmake b/rfb/rfbconfig.h.cmake index 86f7ae3..661583d 100644 --- a/rfb/rfbconfig.h.cmake +++ b/rfb/rfbconfig.h.cmake @@ -72,6 +72,9 @@ /* Define to 1 if `vfork' works. */ #cmakedefine LIBVNCSERVER_HAVE_WORKING_VFORK 1 +/* Define to 1 if `mmap' exists. */ +#cmakedefine LIBVNCSERVER_HAVE_MMAP 1 + /* Define to 1 if you have the header file. */ #cmakedefine LIBVNCSERVER_HAVE_WS2TCPIP_H 1 -- cgit v1.2.3 From 2197b415f264aa3acfcd70bee1bbac510e560270 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 18 Apr 2017 22:53:08 +0200 Subject: CMake: set LIBVNCSERVER_HAVE_LIBSSL in rfbconfig.h if OpenSSL found --- CMakeLists.txt | 3 +++ rfb/rfbconfig.h.cmake | 3 +++ 2 files changed, 6 insertions(+) (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d00d5c..410f059 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,9 @@ if(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${LIBGCRYPT_LIBRARIES}) endif(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES) +if(OPENSSL_FOUND) + set(LIBVNCSERVER_HAVE_LIBSSL 1) +endif(OPENSSL_FOUND) if(WITH_IPv6) if(WIN32 AND LIBVNCSERVER_HAVE_WS2TCPIP_H AND LIBVNCSERVER_HAVE_VPRINTF) diff --git a/rfb/rfbconfig.h.cmake b/rfb/rfbconfig.h.cmake index 661583d..58c9205 100644 --- a/rfb/rfbconfig.h.cmake +++ b/rfb/rfbconfig.h.cmake @@ -100,6 +100,9 @@ /* Define to 1 if GnuTLS is present */ #cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1 +/* Define to 1 if OpenSSL is present */ +#cmakedefine LIBVNCSERVER_HAVE_LIBSSL 1 + /* Define to 1 to build with websockets */ #cmakedefine LIBVNCSERVER_WITH_WEBSOCKETS 1 -- cgit v1.2.3 From fc2899af7a3b402d5c689b0cc8527f965875b9e0 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 18 Apr 2017 23:12:09 +0200 Subject: CMake: set LIBVNCSERVER_HAVE_FORK in rfbconfig.h if fork() found --- CMakeLists.txt | 1 + rfb/rfbconfig.h.cmake | 3 +++ 2 files changed, 4 insertions(+) (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index 410f059..a218222 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,7 @@ check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY) check_function_exists(vfork LIBVNCSERVER_HAVE_VFORK) check_function_exists(vprintf LIBVNCSERVER_HAVE_VPRINTF) check_function_exists(mmap LIBVNCSERVER_HAVE_MMAP) +check_function_exists(fork LIBVNCSERVER_HAVE_FORK) # On systems such as GNU/Linux with glibc, __b64_ntop is defined in a diff --git a/rfb/rfbconfig.h.cmake b/rfb/rfbconfig.h.cmake index 58c9205..f2c96ee 100644 --- a/rfb/rfbconfig.h.cmake +++ b/rfb/rfbconfig.h.cmake @@ -75,6 +75,9 @@ /* Define to 1 if `mmap' exists. */ #cmakedefine LIBVNCSERVER_HAVE_MMAP 1 +/* Define to 1 if `fork' exists. */ +#cmakedefine LIBVNCSERVER_HAVE_FORK 1 + /* Define to 1 if you have the header file. */ #cmakedefine LIBVNCSERVER_HAVE_WS2TCPIP_H 1 -- cgit v1.2.3 From 81d5b844ed59593877a8b46518394af79570417f Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 21 Apr 2017 16:04:25 +0200 Subject: CMake: properly name rfbconfig.h cmake template --- CMakeLists.txt | 2 +- rfb/rfbconfig.h.cmake | 144 ------------------------------------------------ rfb/rfbconfig.h.cmakein | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 145 deletions(-) delete mode 100644 rfb/rfbconfig.h.cmake create mode 100644 rfb/rfbconfig.h.cmakein (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index 3263f34..fc72cc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -277,7 +277,7 @@ TEST_BIG_ENDIAN(LIBVNCSERVER_WORDS_BIGENDIAN) # LIBVNCSERVER_ENOENT_WORKAROUND # inline -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rfb/rfbconfig.h.cmake ${CMAKE_BINARY_DIR}/rfb/rfbconfig.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rfb/rfbconfig.h.cmakein ${CMAKE_BINARY_DIR}/rfb/rfbconfig.h) set(LIBVNCSERVER_SOURCES ${LIBVNCSERVER_DIR}/main.c diff --git a/rfb/rfbconfig.h.cmake b/rfb/rfbconfig.h.cmake deleted file mode 100644 index f2c96ee..0000000 --- a/rfb/rfbconfig.h.cmake +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef _RFB_RFBCONFIG_H -#cmakedefine _RFB_RFBCONFIG_H 1 - -/* rfb/rfbconfig.h. Generated automatically by cmake. */ - -/* Enable 24 bit per pixel in native framebuffer */ -#cmakedefine LIBVNCSERVER_ALLOW24BPP 1 - -/* work around when write() returns ENOENT but does not mean it */ -#cmakedefine LIBVNCSERVER_ENOENT_WORKAROUND 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_ENDIAN_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `jpeg' library (-ljpeg). */ -#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1 - -/* Define if you have the `png' library (-lpng). */ -#cmakedefine LIBVNCSERVER_HAVE_LIBPNG 1 - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1 - -/* Define to 1 if you have the `z' library (-lz). */ -#cmakedefine LIBVNCSERVER_HAVE_LIBZ 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_SYS_ENDIAN_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have that is POSIX.1 compatible. */ -#cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1 - -/* Define to 1 if you have */ -#cmakedefine LIBVNCSERVER_HAVE_SYS_UIO_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vfork' function. */ -#cmakedefine LIBVNCSERVER_HAVE_VFORK 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_VFORK_H 1 - -/* Define to 1 if you have the `vprintf' function. */ -#cmakedefine LIBVNCSERVER_HAVE_VPRINTF 1 - -/* Define to 1 if `fork' works. */ -#cmakedefine LIBVNCSERVER_HAVE_WORKING_FORK 1 - -/* Define to 1 if `vfork' works. */ -#cmakedefine LIBVNCSERVER_HAVE_WORKING_VFORK 1 - -/* Define to 1 if `mmap' exists. */ -#cmakedefine LIBVNCSERVER_HAVE_MMAP 1 - -/* Define to 1 if `fork' exists. */ -#cmakedefine LIBVNCSERVER_HAVE_FORK 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine LIBVNCSERVER_HAVE_WS2TCPIP_H 1 - -/* Enable IPv6 support */ -#cmakedefine LIBVNCSERVER_IPv6 1 - -/* Need a typedef for in_addr_t */ -#cmakedefine LIBVNCSERVER_NEED_INADDR_T 1 - -/* Define to the full name and version of this package. */ -#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @PACKAGE_VERSION@" - -/* Define to the version of this package. */ -#define LIBVNCSERVER_PACKAGE_VERSION "@PACKAGE_VERSION@" -#define LIBVNCSERVER_VERSION "@PACKAGE_VERSION@" -#define LIBVNCSERVER_VERSION_MAJOR "@VERSION_MAJOR@" -#define LIBVNCSERVER_VERSION_MINOR "@VERSION_MINOR@" -#define LIBVNCSERVER_VERSION_PATCHLEVEL "@VERSION_PATCHLEVEL@" - -/* Define to 1 if libgcrypt is present */ -#cmakedefine LIBVNCSERVER_WITH_CLIENT_GCRYPT 1 - -/* Define to 1 if GnuTLS is present */ -#cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1 - -/* Define to 1 if OpenSSL is present */ -#cmakedefine LIBVNCSERVER_HAVE_LIBSSL 1 - -/* Define to 1 to build with websockets */ -#cmakedefine LIBVNCSERVER_WITH_WEBSOCKETS 1 - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -#cmakedefine LIBVNCSERVER_WORDS_BIGENDIAN 1 - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #cmakedefine const @CMAKE_CONST@ */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -/* #ifndef __cplusplus */ -/* #cmakedefine inline @CMAKE_INLINE@ */ -/* #endif */ - -/* Define to `int' if does not define. */ -#cmakedefine HAVE_LIBVNCSERVER_PID_T 1 -#ifndef HAVE_LIBVNCSERVER_PID_T -typedef int pid_t; -#endif - -/* The type for size_t */ -#cmakedefine HAVE_LIBVNCSERVER_SIZE_T 1 -#ifndef HAVE_LIBVNCSERVER_SIZE_T -typedef int size_t; -#endif - -/* The type for socklen */ -#cmakedefine HAVE_LIBVNCSERVER_SOCKLEN_T 1 -#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T -typedef int socklen_t; -#endif - -/* once: _RFB_RFBCONFIG_H */ -#endif diff --git a/rfb/rfbconfig.h.cmakein b/rfb/rfbconfig.h.cmakein new file mode 100644 index 0000000..f2c96ee --- /dev/null +++ b/rfb/rfbconfig.h.cmakein @@ -0,0 +1,144 @@ +#ifndef _RFB_RFBCONFIG_H +#cmakedefine _RFB_RFBCONFIG_H 1 + +/* rfb/rfbconfig.h. Generated automatically by cmake. */ + +/* Enable 24 bit per pixel in native framebuffer */ +#cmakedefine LIBVNCSERVER_ALLOW24BPP 1 + +/* work around when write() returns ENOENT but does not mean it */ +#cmakedefine LIBVNCSERVER_ENOENT_WORKAROUND 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1 + +/* Define if you have the `png' library (-lpng). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBPNG 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#cmakedefine LIBVNCSERVER_HAVE_VFORK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_VFORK_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#cmakedefine LIBVNCSERVER_HAVE_VPRINTF 1 + +/* Define to 1 if `fork' works. */ +#cmakedefine LIBVNCSERVER_HAVE_WORKING_FORK 1 + +/* Define to 1 if `vfork' works. */ +#cmakedefine LIBVNCSERVER_HAVE_WORKING_VFORK 1 + +/* Define to 1 if `mmap' exists. */ +#cmakedefine LIBVNCSERVER_HAVE_MMAP 1 + +/* Define to 1 if `fork' exists. */ +#cmakedefine LIBVNCSERVER_HAVE_FORK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_WS2TCPIP_H 1 + +/* Enable IPv6 support */ +#cmakedefine LIBVNCSERVER_IPv6 1 + +/* Need a typedef for in_addr_t */ +#cmakedefine LIBVNCSERVER_NEED_INADDR_T 1 + +/* Define to the full name and version of this package. */ +#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @PACKAGE_VERSION@" + +/* Define to the version of this package. */ +#define LIBVNCSERVER_PACKAGE_VERSION "@PACKAGE_VERSION@" +#define LIBVNCSERVER_VERSION "@PACKAGE_VERSION@" +#define LIBVNCSERVER_VERSION_MAJOR "@VERSION_MAJOR@" +#define LIBVNCSERVER_VERSION_MINOR "@VERSION_MINOR@" +#define LIBVNCSERVER_VERSION_PATCHLEVEL "@VERSION_PATCHLEVEL@" + +/* Define to 1 if libgcrypt is present */ +#cmakedefine LIBVNCSERVER_WITH_CLIENT_GCRYPT 1 + +/* Define to 1 if GnuTLS is present */ +#cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1 + +/* Define to 1 if OpenSSL is present */ +#cmakedefine LIBVNCSERVER_HAVE_LIBSSL 1 + +/* Define to 1 to build with websockets */ +#cmakedefine LIBVNCSERVER_WITH_WEBSOCKETS 1 + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#cmakedefine LIBVNCSERVER_WORDS_BIGENDIAN 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #cmakedefine const @CMAKE_CONST@ */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +/* #ifndef __cplusplus */ +/* #cmakedefine inline @CMAKE_INLINE@ */ +/* #endif */ + +/* Define to `int' if does not define. */ +#cmakedefine HAVE_LIBVNCSERVER_PID_T 1 +#ifndef HAVE_LIBVNCSERVER_PID_T +typedef int pid_t; +#endif + +/* The type for size_t */ +#cmakedefine HAVE_LIBVNCSERVER_SIZE_T 1 +#ifndef HAVE_LIBVNCSERVER_SIZE_T +typedef int size_t; +#endif + +/* The type for socklen */ +#cmakedefine HAVE_LIBVNCSERVER_SOCKLEN_T 1 +#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T +typedef int socklen_t; +#endif + +/* once: _RFB_RFBCONFIG_H */ +#endif -- cgit v1.2.3 From c80879ee69bcad51564b8b183f63131934006bf5 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 21 Apr 2017 16:20:01 +0200 Subject: CMake: add all function checks that used to be in configure.ac Fixes #174 --- CMakeLists.txt | 15 ++++++++++++++- rfb/rfbconfig.h.cmakein | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index fc72cc5..cf6017d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,7 +159,20 @@ check_function_exists(vfork LIBVNCSERVER_HAVE_VFORK) check_function_exists(vprintf LIBVNCSERVER_HAVE_VPRINTF) check_function_exists(mmap LIBVNCSERVER_HAVE_MMAP) check_function_exists(fork LIBVNCSERVER_HAVE_FORK) - +check_function_exists(ftime LIBVNCSERVER_HAVE_FTIME) +check_function_exists(gethostbyname LIBVNCSERVER_HAVE_GETHOSTBYNAME) +check_function_exists(gethostname LIBVNCSERVER_HAVE_GETHOSTNAME) +check_function_exists(inet_ntoa LIBVNCSERVER_HAVE_INET_NTOA) +check_function_exists(memmove LIBVNCSERVER_HAVE_MEMMOVE) +check_function_exists(memset LIBVNCSERVER_HAVE_MEMSET) +check_function_exists(mkfifo LIBVNCSERVER_HAVE_MKFIFO) +check_function_exists(select LIBVNCSERVER_HAVE_SELECT) +check_function_exists(socket LIBVNCSERVER_HAVE_SOCKET) +check_function_exists(strchr LIBVNCSERVER_HAVE_STRCHR) +check_function_exists(strcspn LIBVNCSERVER_HAVE_STRCSPN) +check_function_exists(strdup LIBVNCSERVER_HAVE_STRDUP) +check_function_exists(strerror LIBVNCSERVER_HAVE_STRERROR) +check_function_exists(strstr LIBVNCSERVER_HAVE_STRSTR) # On systems such as GNU/Linux with glibc, __b64_ntop is defined in a # separate library, libresolv. On some others, such as FreeBSD, it is diff --git a/rfb/rfbconfig.h.cmakein b/rfb/rfbconfig.h.cmakein index f2c96ee..c4dc5c0 100644 --- a/rfb/rfbconfig.h.cmakein +++ b/rfb/rfbconfig.h.cmakein @@ -18,6 +18,48 @@ /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 +/* Define to 1 if you have the `ftime' function. */ +#cmakedefine LIBVNCSERVER_HAVE_FTIME 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostname' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have the `inet_ntoa' function. */ +#cmakedefine LIBVNCSERVER_HAVE_INET_NTOA 1 + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine LIBVNCSERVER_HAVE_MEMMOVE 1 + +/* Define to 1 if you have the `memset' function. */ +#cmakedefine LIBVNCSERVER_HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#cmakedefine LIBVNCSERVER_HAVE_MKFIFO 1 + +/* Define to 1 if you have the `select' function. */ +#cmakedefine LIBVNCSERVER_HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine LIBVNCSERVER_HAVE_SOCKET 1 + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRCHR 1 + +/* Define to 1 if you have the `strcspn' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRCSPN 1 + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRERROR 1 + +/* Define to 1 if you have the `strstr' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRSTR 1 + /* Define to 1 if you have the `jpeg' library (-ljpeg). */ #cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1 -- cgit v1.2.3 From 2c87a631fa4f72178876901c87c85d2889bd7b40 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 May 2017 00:37:25 +0100 Subject: X509 certificate verification for OpenSSL --- libvncclient/tls_openssl.c | 249 ++++++++++++++++++++++++++++----------------- rfb/rfbclient.h | 8 ++ 2 files changed, 165 insertions(+), 92 deletions(-) (limited to 'rfb') diff --git a/libvncclient/tls_openssl.c b/libvncclient/tls_openssl.c index 1b6c986..2bdf3eb 100644 --- a/libvncclient/tls_openssl.c +++ b/libvncclient/tls_openssl.c @@ -168,53 +168,11 @@ InitializeTLS(void) SSLeay_add_ssl_algorithms(); RAND_load_file("/dev/urandom", 1024); - rfbClientLog("OpenSSL initialized.\n"); + rfbClientLog("OpenSSL version %s initialized.\n", SSLeay_version(SSLEAY_VERSION)); rfbTLSInitialized = TRUE; return TRUE; } -static int -ssl_verify (int ok, X509_STORE_CTX *ctx) -{ - unsigned char md5sum[16], fingerprint[40], *f; - rfbClient *client; - int err, i; - unsigned int md5len; - //char buf[257]; - X509 *cert; - SSL *ssl; - - if (ok) - return TRUE; - - ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()); - - client = SSL_CTX_get_app_data (SSL_get_SSL_CTX(ssl)); - - cert = X509_STORE_CTX_get_current_cert (ctx); - err = X509_STORE_CTX_get_error (ctx); - - /* calculate the MD5 hash of the raw certificate */ - md5len = sizeof (md5sum); - X509_digest (cert, EVP_md5 (), md5sum, &md5len); - for (i = 0, f = fingerprint; i < 16; i++, f += 3) - sprintf ((char *) f, "%.2x%c", md5sum[i], i != 15 ? ':' : '\0'); - -#define GET_STRING(name) X509_NAME_oneline (name, buf, 256) - - /* TODO: Don't just ignore certificate checks - - fingerprint = key to check in db - - GET_STRING (X509_get_issuer_name (cert)); - GET_STRING (X509_get_subject_name (cert)); - cert->valid (bool: GOOD or BAD) */ - - ok = TRUE; - - return ok; -} - static int sock_read_ready(SSL *ssl, uint32_t ms) { int r = 0; @@ -251,8 +209,12 @@ static int wait_for_data(SSL *ssl, int ret, int timeout) } break; - default: + default: retval = 3; + long verify_res = SSL_get_verify_result(ssl); + if (verify_res != X509_V_OK) + rfbClientLog("Could not verify server certificate: %s.\n", + X509_verify_cert_error_string(verify_res)); break; } @@ -261,17 +223,131 @@ static int wait_for_data(SSL *ssl, int ret, int timeout) return retval; } +static rfbBool +load_crls_from_file(char *file, SSL_CTX *ssl_ctx) +{ + X509_STORE *st; + X509_CRL *crl; + int i; + int count = 0; + BIO *bio; + STACK_OF(X509_INFO) *xis = NULL; + X509_INFO *xi; + + st = SSL_CTX_get_cert_store(ssl_ctx); + + int rv = 0; + + bio = BIO_new_file(file, "r"); + if (bio == NULL) + return FALSE; + + xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); + BIO_free(bio); + + for (i = 0; i < sk_X509_INFO_num(xis); i++) + { + xi = sk_X509_INFO_value(xis, i); + if (xi->crl) + { + X509_STORE_add_crl(st, xi->crl); + xi->crl = NULL; + count++; + } + } + + sk_X509_INFO_pop_free(xis, X509_INFO_free); + + if (count > 0) + return TRUE; + else + return FALSE; +} + static SSL * -open_ssl_connection (rfbClient *client, int sockfd, rfbBool anonTLS) +open_ssl_connection (rfbClient *client, int sockfd, rfbBool anonTLS, rfbCredential *cred) { SSL_CTX *ssl_ctx = NULL; SSL *ssl = NULL; int n, finished = 0; + X509_VERIFY_PARAM *param; + uint8_t verify_crls = cred->x509Credential.x509CrlVerifyMode; - ssl_ctx = SSL_CTX_new (SSLv23_client_method ()); - SSL_CTX_set_default_verify_paths (ssl_ctx); - SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, &ssl_verify); - ssl = SSL_new (ssl_ctx); + if (!(ssl_ctx = SSL_CTX_new(SSLv23_client_method()))) + { + rfbClientLog("Could not create new SSL context.\n"); + return NULL; + } + + param = X509_VERIFY_PARAM_new(); + + /* Setup verification if not anonymous */ + if (!anonTLS) + { + if (cred->x509Credential.x509CACertFile) + { + if (!SSL_CTX_load_verify_locations(ssl_ctx, cred->x509Credential.x509CACertFile, NULL)) + { + rfbClientLog("Failed to load CA certificate from %s.\n", + cred->x509Credential.x509CACertFile); + goto error_free_ctx; + } + } else { + rfbClientLog("Using default paths for certificate verification.\n"); + SSL_CTX_set_default_verify_paths (ssl_ctx); + } + + if (cred->x509Credential.x509CACrlFile) + { + if (!load_crls_from_file(cred->x509Credential.x509CACrlFile, ssl_ctx)) + { + rfbClientLog("CRLs could not be loaded.\n"); + goto error_free_ctx; + } + if (verify_crls == rfbX509CrlVerifyNone) verify_crls = rfbX509CrlVerifyAll; + } + + if (cred->x509Credential.x509ClientCertFile && cred->x509Credential.x509ClientKeyFile) + { + if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cred->x509Credential.x509ClientCertFile) != 1) + { + rfbClientLog("Client certificate could not be loaded.\n"); + goto error_free_ctx; + } + + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, cred->x509Credential.x509ClientKeyFile, + SSL_FILETYPE_PEM) != 1) + { + rfbClientLog("Client private key could not be loaded.\n"); + goto error_free_ctx; + } + + if (SSL_CTX_check_private_key(ssl_ctx) == 0) { + rfbClientLog("Client certificate and private key do not match.\n"); + goto error_free_ctx; + } + } + + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); + + if (verify_crls == rfbX509CrlVerifyClient) + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + else if (verify_crls == rfbX509CrlVerifyAll) + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + + if(!X509_VERIFY_PARAM_set1_host(param, client->serverHost, strlen(client->serverHost))) + { + rfbClientLog("Could not set server name for verification.\n"); + goto error_free_ctx; + } + SSL_CTX_set1_param(ssl_ctx, param); + } + + if (!(ssl = SSL_new (ssl_ctx))) + { + rfbClientLog("Could not create a new SSL session.\n"); + goto error_free_ctx; + } /* TODO: finetune this list, take into account anonTLS bool */ SSL_set_cipher_list(ssl, "ALL"); @@ -289,24 +365,32 @@ open_ssl_connection (rfbClient *client, int sockfd, rfbBool anonTLS) { finished = 1; SSL_shutdown(ssl); - SSL_free(ssl); - SSL_CTX_free(ssl_ctx); - return NULL; + goto error_free_ssl; } } } while( n != 1 && finished != 1 ); + X509_VERIFY_PARAM_free(param); return ssl; + +error_free_ssl: + SSL_free(ssl); + +error_free_ctx: + X509_VERIFY_PARAM_free(param); + SSL_CTX_free(ssl_ctx); + + return NULL; } static rfbBool -InitializeTLSSession(rfbClient* client, rfbBool anonTLS) +InitializeTLSSession(rfbClient* client, rfbBool anonTLS, rfbCredential *cred) { if (client->tlsSession) return TRUE; - client->tlsSession = open_ssl_connection (client, client->sock, anonTLS); + client->tlsSession = open_ssl_connection (client, client->sock, anonTLS, cred); if (!client->tlsSession) return FALSE; @@ -316,13 +400,6 @@ InitializeTLSSession(rfbClient* client, rfbBool anonTLS) return TRUE; } -static rfbBool -SetTLSAnonCredential(rfbClient* client) -{ - rfbClientLog("TLS anonymous credential created.\n"); - return TRUE; -} - static rfbBool HandshakeTLS(rfbClient* client) { @@ -344,7 +421,8 @@ return TRUE; timeout--; continue; } - rfbClientLog("TLS handshake failed: -.\n"); + rfbClientLog("TLS handshake failed.\n"); + FreeTLS(client); return FALSE; } @@ -429,22 +507,31 @@ ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result) rfbBool HandleAnonTLSAuth(rfbClient* client) { - if (!InitializeTLS() || !InitializeTLSSession(client, TRUE)) return FALSE; - - if (!SetTLSAnonCredential(client)) return FALSE; + if (!InitializeTLS() || !InitializeTLSSession(client, TRUE, NULL)) return FALSE; if (!HandshakeTLS(client)) return FALSE; return TRUE; } +static void +FreeX509Credential(rfbCredential *cred) +{ + if (cred->x509Credential.x509CACertFile) free(cred->x509Credential.x509CACertFile); + if (cred->x509Credential.x509CACrlFile) free(cred->x509Credential.x509CACrlFile); + if (cred->x509Credential.x509ClientCertFile) free(cred->x509Credential.x509ClientCertFile); + if (cred->x509Credential.x509ClientKeyFile) free(cred->x509Credential.x509ClientKeyFile); + free(cred); +} + rfbBool HandleVeNCryptAuth(rfbClient* client) { uint8_t major, minor, status; uint32_t authScheme; rfbBool anonTLS; -// gnutls_certificate_credentials_t x509_cred = NULL; + rfbCredential *cred = NULL; + rfbBool result = TRUE; if (!InitializeTLS()) return FALSE; @@ -499,7 +586,6 @@ HandleVeNCryptAuth(rfbClient* client) /* Get X509 Credentials if it's not anonymous */ if (!anonTLS) { - rfbCredential *cred; if (!client->GetCredential) { @@ -512,39 +598,18 @@ HandleVeNCryptAuth(rfbClient* client) rfbClientLog("Reading credential failed\n"); return FALSE; } - - /* TODO: don't just ignore this - x509_cred = CreateX509CertCredential(cred); - FreeX509Credential(cred); - if (!x509_cred) return FALSE; */ } /* Start up the TLS session */ - if (!InitializeTLSSession(client, anonTLS)) return FALSE; + if (!InitializeTLSSession(client, anonTLS, cred)) result = FALSE; - if (anonTLS) - { - if (!SetTLSAnonCredential(client)) return FALSE; - } - else - { -/* TODO: don't just ignore this - if ((ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_CERTIFICATE, x509_cred)) < 0) - { - rfbClientLog("Cannot set x509 credential: %s.\n", gnutls_strerror(ret)); - FreeTLS(client); */ - return FALSE; - // } - } - - if (!HandshakeTLS(client)) return FALSE; - - /* TODO: validate certificate */ + if (!HandshakeTLS(client)) result = FALSE; /* We are done here. The caller should continue with client->subAuthScheme * to do actual sub authentication. */ - return TRUE; + if (cred) FreeX509Credential(cred); + return result; } int diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 72e7a5a..4ac9cd6 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -136,6 +136,7 @@ typedef union _rfbCredential char *x509CACrlFile; char *x509ClientCertFile; char *x509ClientKeyFile; + uint8_t x509CrlVerifyMode; /* Only required for OpenSSL - see meanings below */ } x509Credential; /** Plain (VeNCrypt), MSLogon (UltraVNC) */ struct @@ -148,6 +149,13 @@ typedef union _rfbCredential #define rfbCredentialTypeX509 1 #define rfbCredentialTypeUser 2 +/* When using OpenSSL, CRLs can be included in both the x509CACrlFile and appended + to the x509CACertFile as is common with OpenSSL. When rfbX509CrlVerifyAll is + specified the CRL list must include CRLs for all certificates in the chain */ +#define rfbX509CrlVerifyNone 0 /* No CRL checking is performed */ +#define rfbX509CrlVerifyClient 1 /* Only the leaf server certificate is checked */ +#define rfbX509CrlVerifyAll 2 /* All certificates in the server chain are checked */ + struct _rfbClient; /** -- cgit v1.2.3 From a90a43cda546f6f4304623ebd5e6dd9cdb87fc16 Mon Sep 17 00:00:00 2001 From: Andreas Weigel Date: Thu, 23 Feb 2017 10:05:40 +0100 Subject: remove Hixie-specific MD5 and check functions --- libvncserver/rfbserver.c | 5 ---- libvncserver/websockets.c | 63 ----------------------------------------------- rfb/rfb.h | 1 - 3 files changed, 69 deletions(-) (limited to 'rfb') diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c index 040238d..116c488 100644 --- a/libvncserver/rfbserver.c +++ b/libvncserver/rfbserver.c @@ -1999,11 +1999,6 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) char encBuf[64]; char encBuf2[64]; -#ifdef LIBVNCSERVER_WITH_WEBSOCKETS - if (cl->wsctx && webSocketCheckDisconnect(cl)) - return; -#endif - if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c index ab9cabb..73ad81c 100644 --- a/libvncserver/websockets.c +++ b/libvncserver/websockets.c @@ -96,7 +96,6 @@ struct timeval #endif static rfbBool webSocketsHandshake(rfbClientPtr cl, char *scheme); -void webSocketsGenMd5(char * target, char *key1, char *key2, char *key3); static int webSocketsEncodeHybi(rfbClientPtr cl, const char *src, int len, char **dst); @@ -350,56 +349,6 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) return TRUE; } -void -webSocketsGenMd5(char * target, char *key1, char *key2, char *key3) -{ - unsigned int i, spaces1 = 0, spaces2 = 0; - unsigned long num1 = 0, num2 = 0; - unsigned char buf[17]; - struct iovec iov[1]; - - for (i=0; i < strlen(key1); i++) { - if (key1[i] == ' ') { - spaces1 += 1; - } - if ((key1[i] >= 48) && (key1[i] <= 57)) { - num1 = num1 * 10 + (key1[i] - 48); - } - } - num1 = num1 / spaces1; - - for (i=0; i < strlen(key2); i++) { - if (key2[i] == ' ') { - spaces2 += 1; - } - if ((key2[i] >= 48) && (key2[i] <= 57)) { - num2 = num2 * 10 + (key2[i] - 48); - } - } - num2 = num2 / spaces2; - - /* Pack it big-endian */ - buf[0] = (num1 & 0xff000000) >> 24; - buf[1] = (num1 & 0xff0000) >> 16; - buf[2] = (num1 & 0xff00) >> 8; - buf[3] = num1 & 0xff; - - buf[4] = (num2 & 0xff000000) >> 24; - buf[5] = (num2 & 0xff0000) >> 16; - buf[6] = (num2 & 0xff00) >> 8; - buf[7] = num2 & 0xff; - - strncpy((char *)buf+8, key3, 8); - buf[16] = '\0'; - - iov[0].iov_base = buf; - iov[0].iov_len = 16; - digestmd5(iov, 1, target); - target[16] = '\0'; - - return; -} - static int ws_read(void *ctxPtr, char *buf, size_t len) { @@ -492,18 +441,6 @@ webSocketsDecode(rfbClientPtr cl, char *dst, int len) return webSocketsDecodeHybi(wsctx, dst, len); } - -/* returns TRUE if client sent a close frame or a single 'end of frame' - * marker was received, FALSE otherwise - * - * Note: This was a Hixie-only hack! - **/ -rfbBool -webSocketCheckDisconnect(rfbClientPtr cl) -{ - return FALSE; -} - /* returns TRUE if there is data waiting to be read in our internal buffer * or if is there any pending data in the buffer of the SSL implementation */ diff --git a/rfb/rfb.h b/rfb/rfb.h index f982b40..9aace0d 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -763,7 +763,6 @@ extern rfbBool rfbSetNonBlocking(int sock); /* websockets.c */ extern rfbBool webSocketsCheck(rfbClientPtr cl); -extern rfbBool webSocketCheckDisconnect(rfbClientPtr cl); extern int webSocketsEncode(rfbClientPtr cl, const char *src, int len, char **dst); extern int webSocketsDecode(rfbClientPtr cl, char *dst, int len); extern rfbBool webSocketsHasDataInBuffer(rfbClientPtr cl); -- cgit v1.2.3 From f48921becf48355e215d663cebbbbaa720b28a95 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sun, 14 May 2017 20:49:57 +0200 Subject: websockets: restore webSocketCheckDisconnect() to keep API compatibility --- libvncserver/websockets.c | 11 +++++++++++ rfb/rfb.h | 1 + 2 files changed, 12 insertions(+) (limited to 'rfb') diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c index 921015d..d10d992 100644 --- a/libvncserver/websockets.c +++ b/libvncserver/websockets.c @@ -440,6 +440,17 @@ webSocketsDecode(rfbClientPtr cl, char *dst, int len) return webSocketsDecodeHybi(wsctx, dst, len); } +/** + * This is a stub function that was once used for Hixie-encoding. + * We keep it for API compatibility. + */ +rfbBool +webSocketCheckDisconnect(rfbClientPtr cl) +{ + return FALSE; +} + + /* returns TRUE if there is data waiting to be read in our internal buffer * or if is there any pending data in the buffer of the SSL implementation */ diff --git a/rfb/rfb.h b/rfb/rfb.h index 9aace0d..f982b40 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -763,6 +763,7 @@ extern rfbBool rfbSetNonBlocking(int sock); /* websockets.c */ extern rfbBool webSocketsCheck(rfbClientPtr cl); +extern rfbBool webSocketCheckDisconnect(rfbClientPtr cl); extern int webSocketsEncode(rfbClientPtr cl, const char *src, int len, char **dst); extern int webSocketsDecode(rfbClientPtr cl, char *dst, int len); extern rfbBool webSocketsHasDataInBuffer(rfbClientPtr cl); -- cgit v1.2.3 From cb4e15c1aecbe283b87e4e97c1d485062ef7f571 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 21 Apr 2017 01:24:56 +0100 Subject: Added SASL authentication support Added SASL support to OpenSSL --- .appveyor.yml | 29 ++- CMakeLists.txt | 20 ++ client_examples/ppmtest.c | 13 + libvncclient/rfbproto.c | 26 ++ libvncclient/rfbsasl.c | 579 +++++++++++++++++++++++++++++++++++++++++++++ libvncclient/rfbsasl.h | 35 +++ libvncclient/sockets.c | 56 ++++- libvncclient/tls.h | 5 + libvncclient/tls_gnutls.c | 20 +- libvncclient/tls_none.c | 9 + libvncclient/tls_openssl.c | 18 ++ libvncclient/vncviewer.c | 13 + rfb/rfbclient.h | 23 ++ rfb/rfbconfig.h.cmakein | 3 + rfb/rfbproto.h | 6 +- 15 files changed, 839 insertions(+), 16 deletions(-) create mode 100644 libvncclient/rfbsasl.c create mode 100644 libvncclient/rfbsasl.h (limited to 'rfb') diff --git a/.appveyor.yml b/.appveyor.yml index dd07eeb..0393f3a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,8 +1,14 @@ +#environment: +# APPVEYOR_RDP_PASSWORD: Pa55word + os: - Visual Studio 2013 - Visual Studio 2015 +#init: +# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + install: - mkdir deps - cd deps @@ -22,13 +28,32 @@ install: - cmake . -DZLIB_INCLUDE_DIR=..\zlib -DZLIB_LIBRARY=..\zlib\debug\zlibstaticd.lib - cmake --build . - cd .. + # Berkeley DB - required by SASL + - curl -fsSL -o db-4.1.25.tar.gz http://download.oracle.com/berkeley-db/db-4.1.25.tar.gz + - 7z x db-4.1.25.tar.gz -so | 7z x -si -ttar > nul + - move db-4.1.25 db + - cd db\build_win32 + - C:\"Program Files (x86)"\"Microsoft Visual Studio 12.0"\Common7\IDE\devenv.exe db_dll.dsp /upgrade + - msbuild /p:Configuration=Release db_dll.vcxproj + - cd ..\.. + # Cyrus SASL + - curl -fsSL -o cyrus-sasl-2.1.26.tar.gz ftp://ftp.cyrusimap.org/cyrus-sasl/cyrus-sasl-2.1.26.tar.gz + - 7z x cyrus-sasl-2.1.26.tar.gz -so | 7z x -si -ttar > nul + - move cyrus-sasl-2.1.26 sasl + - cd sasl + - '"%vs120comntools%\VsDevCmd.bat"' + - nmake /f NTMakefile OPENSSL_INCLUDE=c:\OpenSSL-Win32\include OPENSSL_LIBPATH=c:\OpenSSL-Win32\lib DB_INCLUDE=c:\projects\libvncserver\deps\db\build_win32 DB_LIBPATH=c:\projects\libvncserver\deps\db\build_win32\release DB_LIB=libdb41.lib install + - cd .. # go back to source root - cd .. - build_script: - mkdir build - cd build - - cmake .. -DZLIB_INCLUDE_DIR=..\deps\zlib -DZLIB_LIBRARY=..\deps\zlib\debug\zlibstaticd.lib -DPNG_PNG_INCLUDE_DIR=..\deps\libpng -DPNG_LIBRARY=..\deps\libpng\debug\libpng16_staticd.lib + - cmake .. -DZLIB_INCLUDE_DIR=..\deps\zlib -DZLIB_LIBRARY=..\deps\zlib\debug\zlibstaticd.lib -DPNG_PNG_INCLUDE_DIR=..\deps\libpng -DPNG_LIBRARY=..\deps\libpng\debug\libpng16_staticd.lib -D SASL2_INCLUDE_DIR=c:\cmu\include -D LIBSASL2_LIBRARIES=c:\cmu\lib\libsasl.lib .. - cmake --build . - ctest -C Debug --output-on-failure + +#on_finish: +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + diff --git a/CMakeLists.txt b/CMakeLists.txt index cf6017d..5d991bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ option(WITH_TIGHTVNC_FILETRANSFER "Enable filetransfer if there is pthreads supp option(WITH_24BPP "Allow 24 bpp" ON) option(WITH_IPv6 "Enable IPv6 Support" ON) option(WITH_WEBSOCKETS "Build with websockets support" ON) +option(WITH_SASL "Build with SASL support" ON) @@ -286,6 +287,18 @@ endif(NOT HAVE_LIBVNCSERVER_IN_ADDR_T) TEST_BIG_ENDIAN(LIBVNCSERVER_WORDS_BIGENDIAN) +if(WITH_SASL) + find_path(SASL2_INCLUDE_DIR sasl/sasl.h) + find_library(LIBSASL2_LIBRARIES sasl2 libsasl.lib) +endif(WITH_SASL) + +if(WITH_SASL AND LIBSASL2_LIBRARIES AND SASL2_INCLUDE_DIR) + message(STATUS "Building with SASL: ${LIBSASL2_LIBRARIES} and ${SASL2_INCLUDE_DIR}") + set(LIBVNCSERVER_HAVE_SASL 1) + set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${LIBSASL2_LIBRARIES}) + include_directories(${SASL2_INCLUDE_DIR}) +endif(WITH_SASL AND LIBSASL2_LIBRARIES AND SASL2_INCLUDE_DIR) + # TODO: # LIBVNCSERVER_ENOENT_WORKAROUND # inline @@ -344,6 +357,13 @@ else() ) endif() +if(LIBVNCSERVER_HAVE_SASL) + set(LIBVNCCLIENT_SOURCES + ${LIBVNCCLIENT_SOURCES} + ${LIBVNCCLIENT_DIR}/rfbsasl.c + ) +endif() + if(ZLIB_FOUND) add_definitions(-DLIBVNCSERVER_HAVE_LIBZ) include_directories(${ZLIB_INCLUDE_DIR}) diff --git a/client_examples/ppmtest.c b/client_examples/ppmtest.c index b8602f0..eeafc22 100644 --- a/client_examples/ppmtest.c +++ b/client_examples/ppmtest.c @@ -58,12 +58,25 @@ static void SaveFramebufferAsPPM(rfbClient* client, int x, int y, int w, int h) fclose(f); } +char * getuser(rfbClient *client) +{ +return strdup("testuser@test"); +} + +char * getpassword(rfbClient *client) +{ +return strdup("Password"); +} + int main(int argc, char **argv) { rfbClient* client = rfbGetClient(8,3,4); time_t t=time(NULL); + client->GetUser = getuser; + client->GetPassword = getpassword; + if(argc>1 && !strcmp("-print",argv[1])) { client->GotFrameBufferUpdate = PrintRect; argv[1]=argv[0]; argv++; argc--; diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index e099f1a..27589b8 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -66,6 +66,10 @@ #include #endif +#ifdef LIBVNCSERVER_HAVE_SASL +#include "rfbsasl.h" +#endif /* LIBVNCSERVER_HAVE_SASL */ + #include "minilzo.h" #include "tls.h" @@ -500,6 +504,9 @@ ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) #if defined(LIBVNCSERVER_HAVE_GNUTLS) || defined(LIBVNCSERVER_HAVE_LIBSSL) tAuth[loop]==rfbVeNCrypt || #endif +#ifdef LIBVNCSERVER_HAVE_SASL + tAuth[loop]==rfbSASL || +#endif /* LIBVNCSERVER_HAVE_SASL */ (tAuth[loop]==rfbARD && client->GetCredential) || (!subAuth && (tAuth[loop]==rfbTLS || (tAuth[loop]==rfbVeNCrypt && client->GetCredential)))) { @@ -1079,6 +1086,12 @@ InitialiseRFBConnection(rfbClient* client) if (!HandleVncAuth(client)) return FALSE; break; +#ifdef LIBVNCSERVER_HAVE_SASL + case rfbSASL: + if (!HandleSASLAuth(client)) return FALSE; + break; +#endif /* LIBVNCSERVER_HAVE_SASL */ + case rfbMSLogon: if (!HandleMSLogonAuth(client)) return FALSE; break; @@ -1117,6 +1130,12 @@ InitialiseRFBConnection(rfbClient* client) if (!HandleVncAuth(client)) return FALSE; break; +#ifdef LIBVNCSERVER_HAVE_SASL + case rfbSASL: + if (!HandleSASLAuth(client)) return FALSE; + break; +#endif /* LIBVNCSERVER_HAVE_SASL */ + default: rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", (int)subAuthScheme); @@ -1146,6 +1165,13 @@ InitialiseRFBConnection(rfbClient* client) if (!HandlePlainAuth(client)) return FALSE; break; +#ifdef LIBVNCSERVER_HAVE_SASL + case rfbVeNCryptX509SASL: + case rfbVeNCryptTLSSASL: + if (!HandleSASLAuth(client)) return FALSE; + break; +#endif /* LIBVNCSERVER_HAVE_SASL */ + default: rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", client->subAuthScheme); diff --git a/libvncclient/rfbsasl.c b/libvncclient/rfbsasl.c new file mode 100644 index 0000000..dc7d3bc --- /dev/null +++ b/libvncclient/rfbsasl.c @@ -0,0 +1,579 @@ +/* + * The software in this file is derived from the vncconnection.c source file + * from the GTK VNC Widget with modifications by S. Waterman + * for compatibility with libvncserver. The copyright and license + * statements below apply only to this source file and to no other parts of the + * libvncserver library. + * + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori + * Copyright (C) 2009-2010 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * rfbsasl.c - functions to deal with client side of the SASL protocol. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#define _XOPEN_SOURCE 600 +#endif + +#include +#include + +#ifdef WIN32 +#undef SOCKET +#include +#define EWOULDBLOCK WSAEWOULDBLOCK +#define socklen_t int +#define close closesocket +#define read(sock,buf,len) recv(sock,buf,len,0) +#define write(sock,buf,len) send(sock,buf,len,0) +#ifdef LIBVNCSERVER_HAVE_WS2TCPIP_H +#undef socklen_t +#include +#endif /* LIBVNCSERVER_HAVE_WS2TCPIP_H */ +#else /* WIN32 */ +#include +#endif /* WIN32 */ + +#include "rfbsasl.h" + +#include "tls.h" + +#ifdef _MSC_VER +# define snprintf _snprintf /* MSVC went straight to the underscored syntax */ +#endif + +/* + * NB, keep in sync with similar method in qemud/remote.c + */ +static char *vnc_connection_addr_to_string(char *host, int port) +{ + char * buf = (char *)malloc(strlen(host) + 7); + sprintf(buf, "%s;%hu", host, port); + return buf; +} + +static int log_func(void *context, + int level, + const char *message) +{ + rfbClientLog("SASL: %s\n", message); + + return SASL_OK; +} + +static int user_callback_adapt(void *context, + int id, + const char **result, + unsigned *len) +{ + rfbClient* client = (rfbClient *)context; + + if (id != SASL_CB_AUTHNAME) { + rfbClientLog("Unrecognized SASL callback ID %d\n", id); + return SASL_FAIL; + } + + if (!client->GetUser) { + rfbClientLog("Client user callback not found\n"); + return SASL_FAIL; + } + + *result = client->GetUser(client); + + if (! *result) return SASL_FAIL; + /**len = strlen(*result);*/ + return SASL_OK; +} + +static int password_callback_adapt(sasl_conn_t *conn, + void * context, + int id, + sasl_secret_t **secret) +{ + rfbClient* client = (rfbClient *)context; + char * password; + + if (id != SASL_CB_PASS) { + rfbClientLog("Unrecognized SASL callback ID %d\n", id); + return SASL_FAIL; + } + + if (client->saslSecret) { /* If we've already got it just return it. */ + *secret = client->saslSecret; + return SASL_OK; + } + + if (!client->GetPassword) { + rfbClientLog("Client password callback not found\n"); + return SASL_FAIL; + } + + password = client->GetPassword(client); + + if (! password) return SASL_FAIL; + + sasl_secret_t *lsec = (sasl_secret_t *)malloc(sizeof(sasl_secret_t) + strlen(password)); + if (!lsec) { + rfbClientLog("Could not allocate sasl_secret_t\n"); + return SASL_FAIL; + } + + strcpy(lsec->data, password); + lsec->len = strlen(password); + client->saslSecret = lsec; + *secret = lsec; + + /* Clear client password */ + size_t i; + for (i = 0; i < lsec->len; i++) { + password[i] = '\0'; + } + free(password); + + return SASL_OK; +} + +#define SASL_MAX_MECHLIST_LEN 300 +#define SASL_MAX_DATA_LEN (1024 * 1024) + +/* Perform the SASL authentication process + */ +rfbBool +HandleSASLAuth(rfbClient *client) +{ + sasl_conn_t *saslconn = NULL; + sasl_security_properties_t secprops; + const char *clientout; + char *serverin = NULL; + unsigned int clientoutlen, serverinlen; + int err, complete = 0; + char *localAddr = NULL, *remoteAddr = NULL; + const void *val; + sasl_ssf_t ssf; + sasl_callback_t saslcb[] = { + {SASL_CB_LOG, (void *)log_func, NULL}, + {SASL_CB_AUTHNAME, client->GetUser ? (void *)user_callback_adapt : NULL, client}, + {SASL_CB_PASS, client->GetPassword ? (void *)password_callback_adapt : NULL, client}, + { .id = 0 }, + }; + sasl_interact_t *interact = NULL; + uint32_t mechlistlen; + char *mechlist; + char *wantmech; + const char *mechname; + rfbBool ret; + + client->saslconn = NULL; + + /* Sets up the SASL library as a whole */ + err = sasl_client_init(NULL); + rfbClientLog("Client initialize SASL authentication %d\n", err); + if (err != SASL_OK) { + rfbClientLog("failed to initialize SASL library: %d (%s)\n", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + + /* Get local address in form IPADDR:PORT */ + struct sockaddr_storage localAddress; + socklen_t addressLength = sizeof(localAddress); + char buf[INET6_ADDRSTRLEN]; + int port; + + if (getsockname(client->sock, (struct sockaddr*)&localAddress, &addressLength)) { + rfbClientLog("failed to get local address\n"); + goto error; + } + + if (localAddress.ss_family == AF_INET) { + struct sockaddr_in *sa_in = (struct sockaddr_in*)&localAddress; + inet_ntop(AF_INET, &(sa_in->sin_addr), buf, INET_ADDRSTRLEN); + port = ntohs(sa_in->sin_port); + localAddr = vnc_connection_addr_to_string(buf, port); + } else if (localAddress.ss_family == AF_INET6) { + struct sockaddr_in6 *sa_in = (struct sockaddr_in6*)&localAddress; + inet_ntop(AF_INET6, &(sa_in->sin6_addr), buf, INET6_ADDRSTRLEN); + port = ntohs(sa_in->sin6_port); + localAddr = vnc_connection_addr_to_string(buf, port); + } else { + rfbClientLog("failed to get local address\n"); + goto error; + } + + /* Get remote address in form IPADDR:PORT */ + remoteAddr = vnc_connection_addr_to_string(client->serverHost, client->serverPort); + + rfbClientLog("Client SASL new host:'%s' local:'%s' remote:'%s'\n", client->serverHost, localAddr, remoteAddr); + + /* Setup a handle for being a client */ + err = sasl_client_new("vnc", + client->serverHost, + localAddr, + remoteAddr, + saslcb, + SASL_SUCCESS_DATA, + &saslconn); + free(localAddr); + free(remoteAddr); + + if (err != SASL_OK) { + rfbClientLog("Failed to create SASL client context: %d (%s)\n", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + + /* Initialize some connection props we care about */ + if (client->tlsSession) { + if (!(ssf = (sasl_ssf_t)GetTLSCipherBits(client))) { + rfbClientLog("%s", "invalid cipher size for TLS session\n"); + goto error; + } + + rfbClientLog("Setting external SSF %d\n", ssf); + err = sasl_setprop(saslconn, SASL_SSF_EXTERNAL, &ssf); + if (err != SASL_OK) { + rfbClientLog("cannot set external SSF %d (%s)\n", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + } + + memset (&secprops, 0, sizeof secprops); + /* If we've got TLS, we don't care about SSF */ + secprops.min_ssf = client->tlsSession ? 0 : 56; /* Equiv to DES supported by all Kerberos */ + secprops.max_ssf = client->tlsSession ? 0 : 100000; /* Very strong ! AES == 256 */ + secprops.maxbufsize = 100000; + /* If we're not TLS, then forbid any anonymous or trivially crackable auth */ + secprops.security_flags = client->tlsSession ? 0 : + SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT; + + err = sasl_setprop(saslconn, SASL_SEC_PROPS, &secprops); + if (err != SASL_OK) { + rfbClientLog("cannot set security props %d (%s)\n", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + + /* Get the supported mechanisms from the server */ + if (!ReadFromRFBServer(client, (char *)&mechlistlen, 4)) { + rfbClientLog("failed to read mechlistlen\n"); + goto error; + } + mechlistlen = rfbClientSwap32IfLE(mechlistlen); + rfbClientLog("mechlistlen is %d\n", mechlistlen); + if (mechlistlen > SASL_MAX_MECHLIST_LEN) { + rfbClientLog("mechlistlen %d too long\n", mechlistlen); + goto error; + } + + mechlist = malloc(mechlistlen+1); + if (!ReadFromRFBServer(client, mechlist, mechlistlen)) { + free(mechlist); + goto error; + } + mechlist[mechlistlen] = '\0'; + + /* Allow the client to influence the mechanism selected. */ + if (client->GetSASLMechanism) { + wantmech = client->GetSASLMechanism(client, mechlist); + + if (wantmech && *wantmech != 0) { + if (strstr(mechlist, wantmech) == NULL) { + rfbClientLog("Client requested SASL mechanism %s not supported by server\n", + wantmech); + free(mechlist); + free(wantmech); + goto error; + } else { + free(mechlist); + mechlist = wantmech; + } + } + } + + rfbClientLog("Client start negotiation mechlist '%s'\n", mechlist); + + restart: + /* Start the auth negotiation on the client end first */ + err = sasl_client_start(saslconn, + mechlist, + &interact, + &clientout, + &clientoutlen, + &mechname); + if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) { + rfbClientLog("Failed to start SASL negotiation: %d (%s)\n", + err, sasl_errdetail(saslconn)); + free(mechlist); + mechlist = NULL; + goto error; + } + + /* Need to gather some credentials from the client */ + if (err == SASL_INTERACT) { + rfbClientLog("User interaction required but not currently supported\n"); + goto error; + } + + rfbClientLog("Server start negotiation with mech %s. Data %d bytes %p '%s'\n", + mechname, clientoutlen, clientout, clientout); + + if (clientoutlen > SASL_MAX_DATA_LEN) { + rfbClientLog("SASL negotiation data too long: %d bytes\n", + clientoutlen); + goto error; + } + + /* Send back the chosen mechname */ + uint32_t mechnamelen = rfbClientSwap32IfLE(strlen(mechname)); + if (!WriteToRFBServer(client, (char *)&mechnamelen, 4)) goto error; + if (!WriteToRFBServer(client, (char *)mechname, strlen(mechname))) goto error; + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (clientout) { + uint32_t colsw = rfbClientSwap32IfLE(clientoutlen + 1); + if (!WriteToRFBServer(client, (char *)&colsw, 4)) goto error; + if (!WriteToRFBServer(client, (char *)clientout, clientoutlen + 1)) goto error; + } else { + uint32_t temp = 0; + if (!WriteToRFBServer(client, (char *)&temp, 4)) goto error; + } + + rfbClientLog("%s", "Getting sever start negotiation reply\n"); + /* Read the 'START' message reply from server */ + if (!ReadFromRFBServer(client, (char *)&serverinlen, 4)) goto error; + serverinlen = rfbClientSwap32IfLE(serverinlen); + + if (serverinlen > SASL_MAX_DATA_LEN) { + rfbClientLog("SASL negotiation data too long: %d bytes\n", + serverinlen); + goto error; + } + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (serverinlen) { + serverin = malloc(serverinlen); + if (!ReadFromRFBServer(client, serverin, serverinlen)) goto error; + serverin[serverinlen-1] = '\0'; + serverinlen--; + } else { + serverin = NULL; + } + if (!ReadFromRFBServer(client, (char *)&complete, 1)) goto error; + + rfbClientLog("Client start result complete: %d. Data %d bytes %p '%s'\n", + complete, serverinlen, serverin, serverin); + + /* Loop-the-loop... + * Even if the server has completed, the client must *always* do at least one step + * in this loop to verify the server isn't lying about something. Mutual auth */ + for (;;) { + restep: + err = sasl_client_step(saslconn, + serverin, + serverinlen, + &interact, + &clientout, + &clientoutlen); + if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) { + rfbClientLog("Failed SASL step: %d (%s)\n", + err, sasl_errdetail(saslconn)); + goto error; + } + + /* Need to gather some credentials from the client */ + if (err == SASL_INTERACT) { + rfbClientLog("User interaction required but not currently supported\n"); + goto error; + } + + if (serverin) { + free(serverin); + serverin = NULL; + } + + rfbClientLog("Client step result %d. Data %d bytes %p '%s'\n", err, clientoutlen, clientout, clientout); + + /* Previous server call showed completion & we're now locally complete too */ + if (complete && err == SASL_OK) + break; + + /* Not done, prepare to talk with the server for another iteration */ + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (clientout) { + uint32_t colsw = rfbClientSwap32IfLE(clientoutlen + 1); + if (!WriteToRFBServer(client, (char *)&colsw, 4)) goto error; + if (!WriteToRFBServer(client, (char *)clientout, clientoutlen + 1)) goto error; + } else { + uint32_t temp = 0; + if (!WriteToRFBServer(client, (char *)&temp, 4)) goto error; + } + + rfbClientLog("Server step with %d bytes %p\n", clientoutlen, clientout); + + if (!ReadFromRFBServer(client, (char *)&serverinlen, 4)) goto error; + serverinlen = rfbClientSwap32IfLE(serverinlen); + + if (serverinlen > SASL_MAX_DATA_LEN) { + rfbClientLog("SASL negotiation data too long: %d bytes\n", + serverinlen); + goto error; + } + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (serverinlen) { + serverin = malloc(serverinlen); + if (!ReadFromRFBServer(client, serverin, serverinlen)) goto error; + serverin[serverinlen-1] = '\0'; + serverinlen--; + } else { + serverin = NULL; + } + if (!ReadFromRFBServer(client, (char *)&complete, 1)) goto error; + + rfbClientLog("Client step result complete: %d. Data %d bytes %p '%s'\n", + complete, serverinlen, serverin, serverin); + + /* This server call shows complete, and earlier client step was OK */ + if (complete && err == SASL_OK) { + free(serverin); + serverin = NULL; + break; + } + } + + /* Check for suitable SSF if non-TLS */ + if (!client->tlsSession) { + err = sasl_getprop(saslconn, SASL_SSF, &val); + if (err != SASL_OK) { + rfbClientLog("cannot query SASL ssf on connection %d (%s)\n", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + ssf = *(const int *)val; + rfbClientLog("SASL SSF value %d\n", ssf); + if (ssf < 56) { /* 56 == DES level, good for Kerberos */ + rfbClientLog("negotiation SSF %d was not strong enough\n", ssf); + goto error; + } + } + + rfbClientLog("%s", "SASL authentication complete\n"); + + uint32_t result; + if (!ReadFromRFBServer(client, (char *)&result, 4)) { + rfbClientLog("Failed to read authentication result\n"); + goto error; + } + result = rfbClientSwap32IfLE(result); + + if (result != 0) { + rfbClientLog("Authentication failure\n"); + goto error; + } + rfbClientLog("Authentication successful - switching to SSF\n"); + + /* This must come *after* check-auth-result, because the former + * is defined to be sent unencrypted, and setting saslconn turns + * on the SSF layer encryption processing */ + client->saslconn = saslconn; + + /* Clear SASL secret from memory if set - it'll be free'd on dispose */ + if (client->saslSecret) { + size_t i; + for (i = 0; i < client->saslSecret->len; i++) + client->saslSecret->data[i] = '\0'; + client->saslSecret->len = 0; + } + + return TRUE; + + error: + if (client->saslSecret) { + size_t i; + for (i = 0; i < client->saslSecret->len; i++) + client->saslSecret->data[i] = '\0'; + client->saslSecret->len = 0; + } + + if (saslconn) + sasl_dispose(&saslconn); + return FALSE; +} + +int +ReadFromSASL(rfbClient* client, char *out, unsigned int n) +{ + size_t want; + + if (client->saslDecoded == NULL) { + char *encoded; + int encodedLen; + int err, ret; + + encodedLen = 8192; + encoded = (char *)malloc(encodedLen); + + ret = read(client->sock, encoded, encodedLen); + if (ret < 0) { + free(encoded); + return ret; + } + if (ret == 0) { + free(encoded); + errno = EIO; + return -EIO; + } + + err = sasl_decode(client->saslconn, encoded, ret, + &client->saslDecoded, &client->saslDecodedLength); + free(encoded); + if (err != SASL_OK) { + rfbClientLog("Failed to decode SASL data %s\n", + sasl_errstring(err, NULL, NULL)); + return -EINVAL; + } + client->saslDecodedOffset = 0; + } + + want = client->saslDecodedLength - client->saslDecodedOffset; + if (want > n) + want = n; + + memcpy(out, + client->saslDecoded + client->saslDecodedOffset, + want); + client->saslDecodedOffset += want; + if (client->saslDecodedOffset == client->saslDecodedLength) { + client->saslDecodedLength = client->saslDecodedOffset = 0; + client->saslDecoded = NULL; + } + + if (!want) { + errno = EAGAIN; + return -EAGAIN; + } + + return want; +} diff --git a/libvncclient/rfbsasl.h b/libvncclient/rfbsasl.h new file mode 100644 index 0000000..8231096 --- /dev/null +++ b/libvncclient/rfbsasl.h @@ -0,0 +1,35 @@ +#ifndef RFBSASL_H +#define RFBSASL_H + +/* + * Copyright (C) 2017 S. Waterman. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +/* + * Perform the SASL authentication process + */ +rfbBool HandleSASLAuth(rfbClient *client); + +/* + * Read from SASL when the SASL SSF is in use. + */ +int ReadFromSASL(rfbClient* client, char *out, unsigned int n); + +#endif /* RFBSASL_H */ diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c index 1019580..8ed51a5 100644 --- a/libvncclient/sockets.c +++ b/libvncclient/sockets.c @@ -59,6 +59,10 @@ #endif #include "tls.h" +#ifdef LIBVNCSERVER_HAVE_SASL +#include "rfbsasl.h" +#endif /* LIBVNCSERVER_HAVE_SASL */ + #ifdef _MSC_VER # define snprintf _snprintf #endif @@ -154,16 +158,24 @@ ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) while (client->buffered < n) { int i; - if (client->tlsSession) { + if (client->tlsSession) i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); - } else { + else +#ifdef LIBVNCSERVER_HAVE_SASL + if (client->saslconn) + i = ReadFromSASL(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); + else { +#endif /* LIBVNCSERVER_HAVE_SASL */ i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); +#ifdef WIN32 + if (i < 0) errno=WSAGetLastError(); +#endif +#ifdef LIBVNCSERVER_HAVE_SASL } +#endif + if (i <= 0) { if (i < 0) { -#ifdef WIN32 - errno=WSAGetLastError(); -#endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); @@ -192,11 +204,15 @@ ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) while (n > 0) { int i; - if (client->tlsSession) { + if (client->tlsSession) i = ReadFromTLS(client, out, n); - } else { + else +#ifdef LIBVNCSERVER_HAVE_SASL + if (client->saslconn) + i = ReadFromSASL(client, out, n); + else +#endif i = read(client->sock, out, n); - } if (i <= 0) { if (i < 0) { @@ -248,6 +264,12 @@ WriteToRFBServer(rfbClient* client, char *buf, int n) fd_set fds; int i = 0; int j; + const char *obuf = buf; +#ifdef LIBVNCSERVER_HAVE_SASL + const char *output; + unsigned int outputlen; + int err; +#endif /* LIBVNCSERVER_HAVE_SASL */ if (client->serverPort==-1) return TRUE; /* vncrec playing */ @@ -259,9 +281,23 @@ WriteToRFBServer(rfbClient* client, char *buf, int n) return TRUE; } +#ifdef LIBVNCSERVER_HAVE_SASL + if (client->saslconn) { + err = sasl_encode(client->saslconn, + buf, n, + &output, &outputlen); + if (err != SASL_OK) { + rfbClientLog("Failed to encode SASL data %s", + sasl_errstring(err, NULL, NULL)); + return FALSE; + } + obuf = output; + n = outputlen; + } +#endif /* LIBVNCSERVER_HAVE_SASL */ while (i < n) { - j = write(client->sock, buf + i, (n - i)); + j = write(client->sock, obuf + i, (n - i)); if (j <= 0) { if (j < 0) { #ifdef WIN32 @@ -294,8 +330,6 @@ WriteToRFBServer(rfbClient* client, char *buf, int n) return TRUE; } - - static int initSockets() { #ifdef WIN32 WSADATA trash; diff --git a/libvncclient/tls.h b/libvncclient/tls.h index 48d159b..a5a2ac6 100644 --- a/libvncclient/tls.h +++ b/libvncclient/tls.h @@ -48,4 +48,9 @@ int WriteToTLS(rfbClient* client, char *buf, unsigned int n); /* Free TLS resources */ void FreeTLS(rfbClient* client); +#ifdef LIBVNCSERVER_HAVE_SASL +/* Get the number of bits in the current cipher */ +int GetTLSCipherBits(rfbClient* client); +#endif /* LIBVNCSERVER_HAVE_SASL */ + #endif /* TLS_H */ diff --git a/libvncclient/tls_gnutls.c b/libvncclient/tls_gnutls.c index b9ffe89..75bde35 100644 --- a/libvncclient/tls_gnutls.c +++ b/libvncclient/tls_gnutls.c @@ -170,7 +170,7 @@ InitializeTLSSession(rfbClient* client, rfbBool anonTLS) static rfbBool SetTLSAnonCredential(rfbClient* client) { - gnutls_anon_client_credentials anonCred; + gnutls_anon_client_credentials_t anonCred; int ret; if ((ret = gnutls_anon_allocate_client_credentials(&anonCred)) < 0 || @@ -252,6 +252,10 @@ ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result) if (t==rfbVeNCryptTLSNone || t==rfbVeNCryptTLSVNC || t==rfbVeNCryptTLSPlain || +#ifdef LIBVNCSERVER_HAVE_SASL + t==rfbVeNCryptTLSSASL || + t==rfbVeNCryptX509SASL || +#endif /*LIBVNCSERVER_HAVE_SASL */ t==rfbVeNCryptX509None || t==rfbVeNCryptX509VNC || t==rfbVeNCryptX509Plain) @@ -411,6 +415,9 @@ HandleVeNCryptAuth(rfbClient* client) case rfbVeNCryptTLSNone: case rfbVeNCryptTLSVNC: case rfbVeNCryptTLSPlain: +#ifdef LIBVNCSERVER_HAVE_SASL + case rfbVeNCryptTLSSASL: +#endif /* LIBVNCSERVER_HAVE_SASL */ anonTLS = TRUE; break; default: @@ -535,3 +542,14 @@ void FreeTLS(rfbClient* client) client->tlsSession = NULL; } } + +#ifdef LIBVNCSERVER_HAVE_SASL +int +GetTLSCipherBits(rfbClient* client) +{ + gnutls_cipher_algorithm_t cipher = gnutls_cipher_get((gnutls_session_t)client->tlsSession); + + return gnutls_cipher_get_key_size(cipher) * 8; +} +#endif /* LIBVNCSERVER_HAVE_SASL */ + diff --git a/libvncclient/tls_none.c b/libvncclient/tls_none.c index 91a9f93..4dfcb27 100644 --- a/libvncclient/tls_none.c +++ b/libvncclient/tls_none.c @@ -56,3 +56,12 @@ void FreeTLS(rfbClient* client) } +#ifdef LIBVNCSERVER_HAVE_SASL +int +GetTLSCipherBits(rfbClient* client) +{ + rfbClientLog("TLS is not supported.\n"); + return 0; +} +#endif /* LIBVNCSERVER_HAVE_SASL */ + diff --git a/libvncclient/tls_openssl.c b/libvncclient/tls_openssl.c index 1b6c986..4f758d0 100644 --- a/libvncclient/tls_openssl.c +++ b/libvncclient/tls_openssl.c @@ -397,6 +397,10 @@ ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result) if (t==rfbVeNCryptTLSNone || t==rfbVeNCryptTLSVNC || t==rfbVeNCryptTLSPlain || +#ifdef LIBVNCSERVER_HAVE_SASL + t==rfbVeNCryptTLSSASL || + t==rfbVeNCryptX509SASL || +#endif /*LIBVNCSERVER_HAVE_SASL */ t==rfbVeNCryptX509None || t==rfbVeNCryptX509VNC || t==rfbVeNCryptX509Plain) @@ -489,6 +493,9 @@ HandleVeNCryptAuth(rfbClient* client) case rfbVeNCryptTLSNone: case rfbVeNCryptTLSVNC: case rfbVeNCryptTLSPlain: +#ifdef LIBVNCSERVER_HAVE_SASL + case rfbVeNCryptTLSSASL: +#endif /* LIBVNCSERVER_HAVE_SASL */ anonTLS = TRUE; break; default: @@ -614,3 +621,14 @@ void FreeTLS(rfbClient* client) SSL_free(client->tlsSession); } +#ifdef LIBVNCSERVER_HAVE_SASL +int GetTLSCipherBits(rfbClient* client) +{ + SSL *ssl = (SSL *)(client->tlsSession); + + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); + + return SSL_CIPHER_get_bits(cipher, NULL); +} +#endif /* LIBVNCSERVER_HAVE_SASL */ + diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c index 780a1cb..407b4a5 100644 --- a/libvncclient/vncviewer.c +++ b/libvncclient/vncviewer.c @@ -350,6 +350,13 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel, client->listen6Sock = -1; client->listen6Address = NULL; client->clientAuthSchemes = NULL; + +#ifdef LIBVNCSERVER_HAVE_SASL + client->GetSASLMechanism = NULL; + client->GetUser = NULL; + client->saslSecret = NULL; +#endif /* LIBVNCSERVER_HAVE_SASL */ + return client; } @@ -534,5 +541,11 @@ void rfbClientCleanup(rfbClient* client) { free(client->destHost); if (client->clientAuthSchemes) free(client->clientAuthSchemes); + +#ifdef LIBVNCSERVER_HAVE_SASL + if (client->saslSecret) + free(client->saslSecret); +#endif /* LIBVNCSERVER_HAVE_SASL */ + free(client); } diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 72e7a5a..053bd42 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -52,6 +52,10 @@ #include #include +#ifdef LIBVNCSERVER_HAVE_SASL +#include +#endif /* LIBVNCSERVER_HAVE_SASL */ + #define rfbClientSwap16IfLE(s) \ (*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) @@ -197,6 +201,11 @@ typedef rfbBool (*GotJpegProc)(struct _rfbClient* client, const uint8_t* buffer, typedef rfbBool (*LockWriteToTLSProc)(struct _rfbClient* client); typedef rfbBool (*UnlockWriteToTLSProc)(struct _rfbClient* client); +#ifdef LIBVNCSERVER_HAVE_SASL +typedef char* (*GetUserProc)(struct _rfbClient* client); +typedef char* (*GetSASLMechanismProc)(struct _rfbClient* client, char* mechlist); +#endif /* LIBVNCSERVER_HAVE_SASL */ + typedef struct _rfbClient { uint8_t* frameBuffer; int width, height; @@ -391,6 +400,20 @@ typedef struct _rfbClient { GotBitmapProc GotBitmap; /** Hook for custom JPEG decoding and rendering */ GotJpegProc GotJpeg; + +#ifdef LIBVNCSERVER_HAVE_SASL + sasl_conn_t *saslconn; + const char *saslDecoded; + unsigned int saslDecodedLength; + unsigned int saslDecodedOffset; + sasl_secret_t *saslSecret; + + /* Callback to allow the client to choose a preferred mechanism. The string returned will + be freed once no longer required. */ + GetSASLMechanismProc GetSASLMechanism; + GetUserProc GetUser; + +#endif /* LIBVNCSERVER_HAVE_SASL */ } rfbClient; /* cursor.c */ diff --git a/rfb/rfbconfig.h.cmakein b/rfb/rfbconfig.h.cmakein index c4dc5c0..7638921 100644 --- a/rfb/rfbconfig.h.cmakein +++ b/rfb/rfbconfig.h.cmakein @@ -148,6 +148,9 @@ /* Define to 1 if OpenSSL is present */ #cmakedefine LIBVNCSERVER_HAVE_LIBSSL 1 +/* Define to 1 if Cyrus SASL is present */ +#cmakedefine LIBVNCSERVER_HAVE_SASL 1 + /* Define to 1 to build with websockets */ #cmakedefine LIBVNCSERVER_WITH_WEBSOCKETS 1 diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h index f0d6ea1..c5b2723 100644 --- a/rfb/rfbproto.h +++ b/rfb/rfbproto.h @@ -67,9 +67,8 @@ typedef int8_t rfbBool; #include #include -#else -#include #endif +#include #ifdef LIBVNCSERVER_HAVE_LIBZ #include @@ -287,6 +286,9 @@ typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ #define rfbUltra 17 #define rfbTLS 18 #define rfbVeNCrypt 19 +#ifdef LIBVNCSERVER_HAVE_SASL +#define rfbSASL 20 +#endif /* LIBVNCSERVER_HAVE_SASL */ #define rfbARD 30 #define rfbMSLogon 0xfffffffa -- cgit v1.2.3 From df11e806a31ec0fe0f3f58917ed1e98769adb910 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sat, 2 Sep 2017 17:20:58 +0200 Subject: Move HAVE_SASL #ifdefs into header file to have less LOC --- libvncclient/rfbproto.c | 3 --- libvncclient/rfbsasl.h | 4 ++++ libvncclient/sockets.c | 3 --- rfb/rfbproto.h | 2 -- 4 files changed, 4 insertions(+), 8 deletions(-) (limited to 'rfb') diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index 27589b8..572af9d 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -66,10 +66,7 @@ #include #endif -#ifdef LIBVNCSERVER_HAVE_SASL #include "rfbsasl.h" -#endif /* LIBVNCSERVER_HAVE_SASL */ - #include "minilzo.h" #include "tls.h" diff --git a/libvncclient/rfbsasl.h b/libvncclient/rfbsasl.h index 8231096..2936364 100644 --- a/libvncclient/rfbsasl.h +++ b/libvncclient/rfbsasl.h @@ -20,6 +20,8 @@ * USA. */ +#ifdef LIBVNCSERVER_HAVE_SASL + #include /* @@ -32,4 +34,6 @@ rfbBool HandleSASLAuth(rfbClient *client); */ int ReadFromSASL(rfbClient* client, char *out, unsigned int n); +#endif /* LIBVNCSERVER_HAVE_SASL */ + #endif /* RFBSASL_H */ diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c index 8ed51a5..2d505c7 100644 --- a/libvncclient/sockets.c +++ b/libvncclient/sockets.c @@ -58,10 +58,7 @@ #include #endif #include "tls.h" - -#ifdef LIBVNCSERVER_HAVE_SASL #include "rfbsasl.h" -#endif /* LIBVNCSERVER_HAVE_SASL */ #ifdef _MSC_VER # define snprintf _snprintf diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h index c5b2723..b447170 100644 --- a/rfb/rfbproto.h +++ b/rfb/rfbproto.h @@ -286,9 +286,7 @@ typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ #define rfbUltra 17 #define rfbTLS 18 #define rfbVeNCrypt 19 -#ifdef LIBVNCSERVER_HAVE_SASL #define rfbSASL 20 -#endif /* LIBVNCSERVER_HAVE_SASL */ #define rfbARD 30 #define rfbMSLogon 0xfffffffa -- cgit v1.2.3 From beb82f8dde3c1e1d4d6600e568283919e5a04712 Mon Sep 17 00:00:00 2001 From: Wiki Wang Date: Fri, 15 Sep 2017 14:21:07 +0800 Subject: Add trle decoder --- libvncclient/rfbproto.c | 63 +++++++++++ libvncclient/trle.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++ rfb/rfbproto.h | 1 + 3 files changed, 360 insertions(+) create mode 100644 libvncclient/trle.c (limited to 'rfb') diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index df8b6d0..242fd52 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -161,6 +161,13 @@ static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTRLE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTRLE15(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTRLE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTRLE24(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTRLE24Up(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTRLE24Down(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTRLE32(rfbClient* client, int rx, int ry, int rw, int rh); #ifdef LIBVNCSERVER_HAVE_LIBZ static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh); @@ -1295,6 +1302,8 @@ SetFormatAndEncodings(rfbClient* client) encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlibHex); if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) requestCompressLevel = TRUE; + } else if (strncasecmp(encStr,"trle",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTRLE); } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) { encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { @@ -2010,6 +2019,47 @@ HandleRFBServerMessage(rfbClient* client) break; } + case rfbEncodingTRLE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleTRLE8(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h)) + return FALSE; + break; + case 16: + if (client->si.format.greenMax > 0x1F) { + if (!HandleTRLE16(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h)) + return FALSE; + } else { + if (!HandleTRLE15(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h)) + return FALSE; + } + break; + case 32: { + uint32_t maxColor = + (client->format.redMax << client->format.redShift) | + (client->format.greenMax << client->format.greenShift) | + (client->format.blueMax << client->format.blueShift); + if ((client->format.bigEndian && (maxColor & 0xff) == 0) || + (!client->format.bigEndian && (maxColor & 0xff000000) == 0)) { + if (!HandleTRLE24(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h)) + return FALSE; + } else if (!client->format.bigEndian && (maxColor & 0xff) == 0) { + if (!HandleTRLE24Up(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h)) + return FALSE; + } else if (client->format.bigEndian && (maxColor & 0xff000000) == 0) { + if (!HandleTRLE24Down(client, rect.r.x, rect.r.y, rect.r.w, + rect.r.h)) + return FALSE; + } else if (!HandleTRLE32(client, rect.r.x, rect.r.y, rect.r.w, + rect.r.h)) + return FALSE; + break; + } + } + break; + } + #ifdef LIBVNCSERVER_HAVE_LIBZ case rfbEncodingZlib: { @@ -2300,6 +2350,7 @@ HandleRFBServerMessage(rfbClient* client) #include "ultra.c" #include "zlib.c" #include "tight.c" +#include "trle.c" #include "zrle.c" #undef BPP #define BPP 16 @@ -2309,8 +2360,11 @@ HandleRFBServerMessage(rfbClient* client) #include "ultra.c" #include "zlib.c" #include "tight.c" +#include "trle.c" #include "zrle.c" #define REALBPP 15 +#include "trle.c" +#define REALBPP 15 #include "zrle.c" #undef BPP #define BPP 32 @@ -2320,14 +2374,23 @@ HandleRFBServerMessage(rfbClient* client) #include "ultra.c" #include "zlib.c" #include "tight.c" +#include "trle.c" #include "zrle.c" #define REALBPP 24 +#include "trle.c" +#define REALBPP 24 #include "zrle.c" #define REALBPP 24 #define UNCOMP 8 +#include "trle.c" +#define REALBPP 24 +#define UNCOMP 8 #include "zrle.c" #define REALBPP 24 #define UNCOMP -8 +#include "trle.c" +#define REALBPP 24 +#define UNCOMP -8 #include "zrle.c" #undef BPP diff --git a/libvncclient/trle.c b/libvncclient/trle.c new file mode 100644 index 0000000..b8d6e5c --- /dev/null +++ b/libvncclient/trle.c @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2017 Wiki Wang . All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * trle.c - handle trle encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles a trle + * encoded rectangle with BPP bits per pixel. + */ + +#ifndef REALBPP +#define REALBPP BPP +#endif + +#if !defined(UNCOMP) || UNCOMP == 0 +#define HandleTRLE CONCAT2E(HandleTRLE, REALBPP) +#elif UNCOMP > 0 +#define HandleTRLE CONCAT3E(HandleTRLE, REALBPP, Down) +#else +#define HandleTRLE CONCAT3E(HandleTRLE, REALBPP, Up) +#endif +#define CARDBPP CONCAT3E(uint, BPP, _t) +#define CARDREALBPP CONCAT3E(uint, REALBPP, _t) + +#if REALBPP != BPP && defined(UNCOMP) && UNCOMP != 0 +#if UNCOMP > 0 +#define UncompressCPixel(pointer) ((*(CARDBPP *)pointer) >> UNCOMP) +#else +#define UncompressCPixel(pointer) ((*(CARDBPP *)pointer) << (-(UNCOMP))) +#endif +#else +#define UncompressCPixel(pointer) (*(CARDBPP *)pointer) +#endif + +static rfbBool HandleTRLE(rfbClient *client, int rx, int ry, int rw, int rh) { + int x, y, w, h; + uint8_t type, last_type; + int min_buffer_size = 16 * 16 * (REALBPP / 8) * 2; + uint8_t *buffer; + CARDBPP palette[128]; + int bpp, mask, divider; + CARDBPP color; + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed REALBPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if (client->raw_buffer_size < min_buffer_size) { + + if (client->raw_buffer != NULL) { + + free(client->raw_buffer); + } + + client->raw_buffer_size = min_buffer_size; + client->raw_buffer = (char *)malloc(client->raw_buffer_size); + } + + rfbClientLog("Update %d %d %d %d\n", rx, ry, rw, rh); + + for (y = ry; y < ry + rh; y += 16) { + for (x = rx; x < rx + rw; x += 16) { + w = h = 16; + if (rx + rw - x < 16) + w = rx + rw - x; + if (ry + rh - y < 16) + h = ry + rh - y; + + if (!ReadFromRFBServer(client, &type, 1)) + return FALSE; + + buffer = client->raw_buffer; + + switch (type) { + case_0: + case 0: { + if (!ReadFromRFBServer(client, buffer, w * h * REALBPP / 8)) + return FALSE; +#if REALBPP != BPP + int i, j; + + for (j = y * client->width; j < (y + h) * client->width; + j += client->width) + for (i = x; i < x + w; i++, buffer += REALBPP / 8) + ((CARDBPP *)client->frameBuffer)[j + i] = UncompressCPixel(buffer); +#else + client->GotBitmap(client, buffer, x, y, w, h); +#endif + type = last_type; + break; + } + case 1: { + if (!ReadFromRFBServer(client, buffer, REALBPP / 8)) + return FALSE; + + color = UncompressCPixel(buffer); + + client->GotFillRect(client, x, y, w, h, color); + + last_type = type; + break; + } + case_127: + case 127: + switch (last_type) { + case 0: + return FALSE; + case 1: + client->GotFillRect(client, x, y, w, h, color); + type = last_type; + break; + case 128: + return FALSE; + default: + if (last_type >= 130) { + last_type = last_type & 0x7f; + + bpp = (last_type > 4 ? (last_type > 16 ? 8 : 4) + : (last_type > 2 ? 2 : 1)), + mask = (1 << bpp) - 1, divider = (8 / bpp); + } + if (last_type <= 16) { + int i, j, shift; + + if (!ReadFromRFBServer(client, buffer, + (w + divider - 1) / divider * h)) + return FALSE; + + /* read palettized pixels */ + for (j = y * client->width; j < (y + h) * client->width; + j += client->width) { + for (i = x, shift = 8 - bpp; i < x + w; i++) { + ((CARDBPP *)client->frameBuffer)[j + i] = + palette[((*buffer) >> shift) & mask]; + shift -= bpp; + if (shift < 0) { + shift = 8 - bpp; + buffer++; + } + } + if (shift < 8 - bpp) + buffer++; + + type = last_type; + } + } else + return FALSE; + } + break; + case 128: { + int i = 0, j = 0; + while (j < h) { + int color, length; + /* read color */ + if (!ReadFromRFBServer(client, buffer, REALBPP / 8 + 1)) + return FALSE; + color = UncompressCPixel(buffer); + buffer += REALBPP / 8; + /* read run length */ + length = 1; + while (*buffer == 0xff) { + if (!ReadFromRFBServer(client, buffer + 1, 1)) + return FALSE; + length += *buffer; + buffer++; + } + length += *buffer; + buffer++; + while (j < h && length > 0) { + ((CARDBPP *)client->frameBuffer)[(y + j) * client->width + x + i] = + color; + length--; + i++; + if (i >= w) { + i = 0; + j++; + } + } + if (length > 0) + rfbClientLog("Warning: possible TRLE corruption\n"); + } + + type = last_type; + + break; + } + case_129: + case 129: { + int i, j; + /* read palettized pixels */ + i = j = 0; + while (j < h) { + int color, length; + /* read color */ + if (!ReadFromRFBServer(client, buffer, 1)) + return FALSE; + color = palette[(*buffer) & 0x7f]; + length = 1; + if (*buffer & 0x80) { + if (!ReadFromRFBServer(client, buffer + 1, 1)) + return FALSE; + buffer++; + /* read run length */ + while (*buffer == 0xff) { + if (!ReadFromRFBServer(client, buffer + 1, 1)) + return FALSE; + length += *buffer; + buffer++; + } + length += *buffer; + } + buffer++; + while (j < h && length > 0) { + ((CARDBPP *)client->frameBuffer)[(y + j) * client->width + x + i] = + color; + length--; + i++; + if (i >= w) { + i = 0; + j++; + } + } + if (length > 0) + rfbClientLog("Warning: possible TRLE corruption\n"); + } + + if (type == 129) { + type = last_type; + } + + break; + } + default: + if (type <= 16) { + int i; + + bpp = (type > 4 ? (type > 16 ? 8 : 4) : (type > 2 ? 2 : 1)), + mask = (1 << bpp) - 1, divider = (8 / bpp); + + if (!ReadFromRFBServer(client, buffer, type * REALBPP / 8)) + return FALSE; + + /* read palette */ + for (i = 0; i < type; i++, buffer += REALBPP / 8) + palette[i] = UncompressCPixel(buffer); + + last_type = type; + goto case_127; + } else if (type >= 130) { + int i; + + if (!ReadFromRFBServer(client, buffer, (type - 128) * REALBPP / 8)) + return FALSE; + + /* read palette */ + for (i = 0; i < type - 128; i++, buffer += REALBPP / 8) + palette[i] = UncompressCPixel(buffer); + + last_type = type; + goto case_129; + } else + return FALSE; + } + last_type = type; + } + } + + return TRUE; +} + +#undef CARDBPP +#undef CARDREALBPP +#undef HandleTRLE +#undef UncompressCPixel +#undef REALBPP +#undef UNCOMP diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h index b447170..dfb2c28 100644 --- a/rfb/rfbproto.h +++ b/rfb/rfbproto.h @@ -438,6 +438,7 @@ typedef struct { #define rfbEncodingTightPng 0xFFFFFEFC /* -260 */ #define rfbEncodingZlibHex 8 #define rfbEncodingUltra 9 +#define rfbEncodingTRLE 15 #define rfbEncodingZRLE 16 #define rfbEncodingZYWRLE 17 -- cgit v1.2.3 From d7b14624cbb9ed7b9df3532658e1edba8da606a6 Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 6 Nov 2017 17:25:41 -0600 Subject: Include Tight decoding optimizations from TurboVNC - As with the encoder, the decoder now uses the TurboJPEG wrapper, which allows it to decode JPEG images directly into the framebuffer. This eliminates a buffer copy (CopyRectangle()) as well as the expensive RGB pixel conversion in DecompressJpegRectBPP(). The TurboJPEG wrapper performs RGB pixel conversion more optimally, and only when necessary (it uses the libjpeg-turbo colorspace extensions when available, in order to avoid RGB conversion.) - The other Tight subencoding types are also now decoded directly into the framebuffer, which eliminates buffer copies. - The Tight decoder now supports the rfbTightNoZlib extension, which allows the server to bypass zlib compression when Compression Level 0 is selected. The encoder already supports this extension. Passing the data stream through zlib when Compression Level 0 is selected needlessly wastes CPU time, since all zlib is doing is copying the data internally into its own structures. --- CMakeLists.txt | 7 ++ libvncclient/rfbproto.c | 13 --- libvncclient/tight.c | 231 +++++++++++++++++++++-------------------------- libvncclient/vncviewer.c | 4 - rfb/rfbclient.h | 12 ++- 5 files changed, 119 insertions(+), 148 deletions(-) (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index f605202..caf1832 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,6 +317,13 @@ set(LIBVNCCLIENT_SOURCES ${COMMON_DIR}/minilzo.c ) +if(JPEG_FOUND) + set(LIBVNCCLIENT_SOURCES + ${LIBVNCCLIENT_SOURCES} + ${COMMON_DIR}/turbojpeg.c + ) +endif() + if(GNUTLS_FOUND) set(LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_SOURCES} diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index df8b6d0..9cd23b8 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -47,12 +47,6 @@ #define Z_NULL NULL #endif #endif -#ifdef LIBVNCSERVER_HAVE_LIBJPEG -#ifdef _RPCNDR_H /* This Windows header typedefs 'boolean', jpeglib has to know */ -#define HAVE_BOOLEAN -#endif -#include -#endif #ifndef _MSC_VER /* Strings.h is not available in MSVC */ @@ -171,13 +165,6 @@ static rfbBool HandleTight16(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleTight32(rfbClient* client, int rx, int ry, int rw, int rh); static long ReadCompactLen (rfbClient* client); - -static void JpegInitSource(j_decompress_ptr cinfo); -static boolean JpegFillInputBuffer(j_decompress_ptr cinfo); -static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes); -static void JpegTermSource(j_decompress_ptr cinfo); -static void JpegSetSrcManager(j_decompress_ptr cinfo, uint8_t *compressedData, - int compressedLen); #endif static rfbBool HandleZRLE8(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleZRLE15(rfbClient* client, int rx, int ry, int rw, int rh); diff --git a/libvncclient/tight.c b/libvncclient/tight.c index 2447ad8..64883e5 100644 --- a/libvncclient/tight.c +++ b/libvncclient/tight.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2017 D. R. Commander. All Rights Reserved. + * Copyright (C) 2004-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (C) 2004 Landmark Graphics Corporation. All Rights Reserved. * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. * * This is free software; you can redistribute it and/or modify @@ -71,16 +74,16 @@ /* Type declarations */ -typedef void (*filterPtrBPP)(rfbClient* client, int, CARDBPP *); +typedef void (*filterPtrBPP)(rfbClient* client, int, int, int); /* Prototypes */ static int InitFilterCopyBPP (rfbClient* client, int rw, int rh); static int InitFilterPaletteBPP (rfbClient* client, int rw, int rh); static int InitFilterGradientBPP (rfbClient* client, int rw, int rh); -static void FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); -static void FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); -static void FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); +static void FilterCopyBPP (rfbClient* client, int srcx, int srcy, int numRows); +static void FilterPaletteBPP (rfbClient* client, int srcx, int srcy, int numRows); +static void FilterGradientBPP (rfbClient* client, int srcx, int srcy, int numRows); #if BPP != 8 static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h); @@ -96,9 +99,17 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) uint8_t filter_id; filterPtrBPP filterFn; z_streamp zs; - char *buffer2; int err, stream_id, compressedLen, bitsPixel; int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes; + rfbBool readUncompressed = FALSE; + + if (client->frameBuffer == NULL) + return FALSE; + + if (rx + rw > client->width || ry + rh > client->height) { + rfbClientLog("Rect out of bounds: %dx%d at (%d, %d)\n", rx, ry, rw, rh); + return FALSE; + } if (!ReadFromRFBServer(client, (char *)&comp_ctl, 1)) return FALSE; @@ -114,6 +125,11 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) comp_ctl >>= 1; } + if ((comp_ctl & rfbTightNoZlib) == rfbTightNoZlib) { + comp_ctl &= ~(rfbTightNoZlib); + readUncompressed = TRUE; + } + /* Handle solid rectangles. */ if (comp_ctl == rfbTightFill) { #if BPP == 32 @@ -195,10 +211,7 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) if (!ReadFromRFBServer(client, (char*)client->buffer, rh * rowSize)) return FALSE; - buffer2 = &client->buffer[TIGHT_MIN_TO_COMPRESS * 4]; - filterFn(client, rh, (CARDBPP *)buffer2); - - client->GotBitmap(client, (uint8_t *)buffer2, rx, ry, rw, rh); + filterFn(client, rx, ry, rh); return TRUE; } @@ -209,6 +222,14 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) rfbClientLog("Incorrect data received from the server.\n"); return FALSE; } + if (readUncompressed) { + if (!ReadFromRFBServer(client, (char*)client->buffer, compressedLen)) + return FALSE; + + filterFn(client, rx, ry, rh); + + return TRUE; + } /* Now let's initialize compression stream if needed. */ stream_id = comp_ctl & 0x03; @@ -229,7 +250,6 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) /* Read, decode and draw actual pixel data in a loop. */ bufferSize = RFB_BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC; - buffer2 = &client->buffer[bufferSize]; if (rowSize > bufferSize) { /* Should be impossible when RFB_BUFFER_SIZE >= 16384 */ rfbClientLog("Internal error: incorrect buffer size.\n"); @@ -271,14 +291,12 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) numRows = (bufferSize - zs->avail_out) / rowSize; - filterFn(client, numRows, (CARDBPP *)buffer2); + filterFn(client, rx, ry+rowsProcessed, numRows); extraBytes = bufferSize - zs->avail_out - numRows * rowSize; if (extraBytes > 0) memcpy(client->buffer, &client->buffer[numRows * rowSize], extraBytes); - client->GotBitmap(client, (uint8_t *)buffer2, rx, ry+rowsProcessed, rw, numRows); - rowsProcessed += numRows; } while (zs->avail_out == 0); @@ -317,16 +335,19 @@ InitFilterCopyBPP (rfbClient* client, int rw, int rh) } static void -FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst) +FilterCopyBPP (rfbClient* client, int srcx, int srcy, int numRows) { + CARDBPP *dst = + (CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8]; + int y; #if BPP == 32 - int x, y; + int x; if (client->cutZeros) { for (y = 0; y < numRows; y++) { for (x = 0; x < client->rectWidth; x++) { - dst[y*client->rectWidth+x] = + dst[y*client->width+x] = RGB24_TO_PIXEL32(client->buffer[(y*client->rectWidth+x)*3], client->buffer[(y*client->rectWidth+x)*3+1], client->buffer[(y*client->rectWidth+x)*3+2]); @@ -336,7 +357,9 @@ FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst) } #endif - memcpy (dst, client->buffer, numRows * client->rectWidth * (BPP / 8)); + for (y = 0; y < numRows; y++) + memcpy (&dst[y*client->width], &client->buffer[y*client->rectWidth], + client->rectWidth * (BPP / 8)); } static int @@ -356,8 +379,10 @@ InitFilterGradientBPP (rfbClient* client, int rw, int rh) #if BPP == 32 static void -FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst) +FilterGradient24 (rfbClient* client, int srcx, int srcy, int numRows) { + CARDBPP *dst = + (CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8]; int x, y, c; uint8_t thisRow[2048*3]; uint8_t pix[3]; @@ -370,7 +395,7 @@ FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst) pix[c] = client->tightPrevRow[c] + client->buffer[y*client->rectWidth*3+c]; thisRow[c] = pix[c]; } - dst[y*client->rectWidth] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + dst[y*client->width] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); /* Remaining pixels of a row */ for (x = 1; x < client->rectWidth; x++) { @@ -385,7 +410,7 @@ FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst) pix[c] = (uint8_t)est[c] + client->buffer[(y*client->rectWidth+x)*3+c]; thisRow[x*3+c] = pix[c]; } - dst[y*client->rectWidth+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + dst[y*client->width+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); } memcpy(client->tightPrevRow, thisRow, client->rectWidth * 3); @@ -395,8 +420,10 @@ FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst) #endif static void -FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst) +FilterGradientBPP (rfbClient* client, int srcx, int srcy, int numRows) { + CARDBPP *dst = + (CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8]; int x, y, c; CARDBPP *src = (CARDBPP *)client->buffer; uint16_t *thatRow = (uint16_t *)client->tightPrevRow; @@ -408,7 +435,7 @@ FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst) #if BPP == 32 if (client->cutZeros) { - FilterGradient24(client, numRows, dst); + FilterGradient24(client, srcx, srcy, numRows); return; } #endif @@ -428,7 +455,7 @@ FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst) pix[c] = (uint16_t)(((src[y*client->rectWidth] >> shift[c]) + thatRow[c]) & max[c]); thisRow[c] = pix[c]; } - dst[y*client->rectWidth] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + dst[y*client->width] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); /* Remaining pixels of a row */ for (x = 1; x < client->rectWidth; x++) { @@ -442,7 +469,7 @@ FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst) pix[c] = (uint16_t)(((src[y*client->rectWidth+x] >> shift[c]) + est[c]) & max[c]); thisRow[x*3+c] = pix[c]; } - dst[y*client->rectWidth+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + dst[y*client->width+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); } memcpy(thatRow, thisRow, client->rectWidth * 3 * sizeof(uint16_t)); } @@ -487,9 +514,11 @@ InitFilterPaletteBPP (rfbClient* client, int rw, int rh) } static void -FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst) +FilterPaletteBPP (rfbClient* client, int srcx, int srcy, int numRows) { int x, y, b, w; + CARDBPP *dst = + (CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8]; uint8_t *src = (uint8_t *)client->buffer; CARDBPP *palette = (CARDBPP *)client->tightPalette; @@ -498,16 +527,16 @@ FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst) for (y = 0; y < numRows; y++) { for (x = 0; x < client->rectWidth / 8; x++) { for (b = 7; b >= 0; b--) - dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + dst[y*client->width+x*8+7-b] = palette[src[y*w+x] >> b & 1]; } for (b = 7; b >= 8 - client->rectWidth % 8; b--) { - dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + dst[y*client->width+x*8+7-b] = palette[src[y*w+x] >> b & 1]; } } } else { for (y = 0; y < numRows; y++) for (x = 0; x < client->rectWidth; x++) - dst[y*client->rectWidth+x] = palette[(int)src[y*client->rectWidth+x]]; + dst[y*client->width+x] = palette[(int)src[y*client->rectWidth+x]]; } } @@ -522,13 +551,9 @@ FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst) static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h) { - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; int compressedLen; - uint8_t *compressedData; - CARDBPP *pixelPtr; - JSAMPROW rowPointer[1]; - int dx, dy; + uint8_t *compressedData, *dst; + int pixelSize, pitch, flags = 0; compressedLen = (int)ReadCompactLen(client); if (compressedLen <= 0) { @@ -550,47 +575,57 @@ DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h) if(client->GotJpeg != NULL) return client->GotJpeg(client, compressedData, compressedLen, x, y, w, h); - cinfo.err = jpeg_std_error(&jerr); - cinfo.client_data = client; - jpeg_create_decompress(&cinfo); - - JpegSetSrcManager(&cinfo, compressedData, compressedLen); + if (!client->tjhnd) { + if ((client->tjhnd = tjInitDecompress()) == NULL) { + rfbClientLog("TurboJPEG error: %s\n", tjGetErrorStr()); + free(compressedData); + return FALSE; + } + } - jpeg_read_header(&cinfo, TRUE); - cinfo.out_color_space = JCS_RGB; +#if BPP == 16 + flags = 0; + pixelSize = 3; + pitch = w * pixelSize; + dst = (uint8_t *)client->buffer; +#else + if (client->format.bigEndian) flags |= TJ_ALPHAFIRST; + if (client->format.redShift == 16 && client->format.blueShift == 0) + flags |= TJ_BGR; + if (client->format.bigEndian) flags ^= TJ_BGR; + pixelSize = BPP / 8; + pitch = client->width * pixelSize; + dst = &client->frameBuffer[y * pitch + x * pixelSize]; +#endif - jpeg_start_decompress(&cinfo); - if (cinfo.output_width != w || cinfo.output_height != h || - cinfo.output_components != 3) { - rfbClientLog("Tight Encoding: Wrong JPEG data received.\n"); - jpeg_destroy_decompress(&cinfo); + if (tjDecompress(client->tjhnd, compressedData, (unsigned long)compressedLen, + dst, w, pitch, h, pixelSize, flags)==-1) { + rfbClientLog("TurboJPEG error: %s\n", tjGetErrorStr()); free(compressedData); return FALSE; } - rowPointer[0] = (JSAMPROW)client->buffer; - dy = 0; - while (cinfo.output_scanline < cinfo.output_height) { - jpeg_read_scanlines(&cinfo, rowPointer, 1); - if (client->jpegError) { - break; - } - pixelPtr = (CARDBPP *)&client->buffer[RFB_BUFFER_SIZE / 2]; - for (dx = 0; dx < w; dx++) { - *pixelPtr++ = - RGB24_TO_PIXEL(BPP, client->buffer[dx*3], client->buffer[dx*3+1], client->buffer[dx*3+2]); + free(compressedData); + +#if BPP == 16 + pixelSize = BPP / 8; + pitch = client->width * pixelSize; + dst = &client->frameBuffer[y * pitch + x * pixelSize]; + { + CARDBPP *dst16=(CARDBPP *)dst, *dst2; + char *src = client->buffer; + int i, j; + + for (j = 0; j < h; j++) { + for (i = 0, dst2 = dst16; i < w; i++, dst2++, src += 3) { + *dst2 = RGB24_TO_PIXEL(BPP, src[0], src[1], src[2]); + } + dst16 += client->width; } - client->GotBitmap(client, (uint8_t *)&client->buffer[RFB_BUFFER_SIZE / 2], x, y + dy, w, 1); - dy++; } +#endif - if (!client->jpegError) - jpeg_finish_decompress(&cinfo); - - jpeg_destroy_decompress(&cinfo); - free(compressedData); - - return !client->jpegError; + return TRUE; } #else @@ -617,70 +652,6 @@ ReadCompactLen (rfbClient* client) return len; } -/* - * JPEG source manager functions for JPEG decompression in Tight decoder. - */ - -static void -JpegInitSource(j_decompress_ptr cinfo) -{ - rfbClient* client=(rfbClient*)cinfo->client_data; - client->jpegError = FALSE; -} - -static boolean -JpegFillInputBuffer(j_decompress_ptr cinfo) -{ - rfbClient* client=(rfbClient*)cinfo->client_data; - client->jpegError = TRUE; - client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; - client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; - - return TRUE; -} - -static void -JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes) -{ - rfbClient* client=(rfbClient*)cinfo->client_data; - if (num_bytes < 0 || num_bytes > client->jpegSrcManager->bytes_in_buffer) { - client->jpegError = TRUE; - client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; - client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; - } else { - client->jpegSrcManager->next_input_byte += (size_t) num_bytes; - client->jpegSrcManager->bytes_in_buffer -= (size_t) num_bytes; - } -} - -static void -JpegTermSource(j_decompress_ptr cinfo) -{ - /* nothing to do here. */ -} - -static void -JpegSetSrcManager(j_decompress_ptr cinfo, - uint8_t *compressedData, - int compressedLen) -{ - rfbClient* client=(rfbClient*)cinfo->client_data; - client->jpegBufferPtr = compressedData; - client->jpegBufferLen = (size_t)compressedLen; - - if(client->jpegSrcManager == NULL) - client->jpegSrcManager = malloc(sizeof(struct jpeg_source_mgr)); - client->jpegSrcManager->init_source = JpegInitSource; - client->jpegSrcManager->fill_input_buffer = JpegFillInputBuffer; - client->jpegSrcManager->skip_input_data = JpegSkipInputData; - client->jpegSrcManager->resync_to_restart = jpeg_resync_to_restart; - client->jpegSrcManager->term_source = JpegTermSource; - client->jpegSrcManager->next_input_byte = (JOCTET*)client->jpegBufferPtr; - client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; - - cinfo->src = client->jpegSrcManager; -} - #endif #undef CARDBPP diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c index 407b4a5..2a13f0e 100644 --- a/libvncclient/vncviewer.c +++ b/libvncclient/vncviewer.c @@ -319,7 +319,6 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel, #ifdef LIBVNCSERVER_HAVE_LIBJPEG memset(client->zlibStreamActive,0,sizeof(rfbBool)*4); - client->jpegSrcManager = NULL; #endif #endif @@ -517,9 +516,6 @@ void rfbClientCleanup(rfbClient* client) { client->decompStream.msg != NULL) rfbClientLog("inflateEnd: %s\n", client->decompStream.msg ); } - - if (client->jpegSrcManager) - free(client->jpegSrcManager); #endif #endif diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 72d672a..ec6ee55 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -7,6 +7,7 @@ */ /* + * Copyright (C) 2017 D. R. Commander. All Rights Reserved. * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. @@ -51,6 +52,7 @@ #endif #include #include +#include "turbojpeg.h" #ifdef LIBVNCSERVER_HAVE_SASL #include @@ -295,7 +297,7 @@ typedef struct _rfbClient { uint8_t tightPrevRow[2048*3*sizeof(uint16_t)]; #ifdef LIBVNCSERVER_HAVE_LIBJPEG - /** JPEG decoder state. */ + /** JPEG decoder state (obsolete-- do not use). */ rfbBool jpegError; struct jpeg_source_mgr* jpegSrcManager; @@ -422,6 +424,14 @@ typedef struct _rfbClient { GetUserProc GetUser; #endif /* LIBVNCSERVER_HAVE_SASL */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /** JPEG decoder state. */ + tjhandle tjhnd; + +#endif +#endif } rfbClient; /* cursor.c */ -- cgit v1.2.3 From dd873fce451e4b7d7cc69056a62e107aae7c8e7a Mon Sep 17 00:00:00 2001 From: Eddie James Date: Mon, 18 Jun 2018 16:17:41 -0500 Subject: Tight: export SendCompressedData and SendTightHeader functions These functions can be used to send already compressed jpegs to a client, circumventing the usual rect/region update methods which operate on a raw rgb framebuffer. Rename the functions with the usual rfb prefix and add the prototypes in rfb.h. Signed-off-by: Eddie James --- libvncserver/tight.c | 25 +++++++++++-------------- rfb/rfb.h | 2 ++ 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'rfb') diff --git a/libvncserver/tight.c b/libvncserver/tight.c index bca374d..1081c8f 100644 --- a/libvncserver/tight.c +++ b/libvncserver/tight.c @@ -191,7 +191,6 @@ static rfbBool CheckSolidTile32 (rfbClientPtr cl, int x, int y, int w, int h, static rfbBool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h); static rfbBool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); -static rfbBool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); static rfbBool SendSolidRect (rfbClientPtr cl); static rfbBool SendMonoRect (rfbClientPtr cl, int x, int y, int w, int h); @@ -200,8 +199,6 @@ static rfbBool SendFullColorRect (rfbClientPtr cl, int x, int y, int w, int h); static rfbBool CompressData (rfbClientPtr cl, int streamId, int dataLen, int zlibLevel, int zlibStrategy); -static rfbBool SendCompressedData (rfbClientPtr cl, char *buf, - int compressedLen); static void FillPalette8 (int count); static void FillPalette16 (int count); @@ -430,7 +427,7 @@ SendRectEncodingTight(rfbClientPtr cl, /* Send solid-color rectangle. */ - if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) + if (!rfbSendTightHeader(cl, x_best, y_best, w_best, h_best)) return FALSE; fbptr = (cl->scaledScreen->frameBuffer + @@ -683,7 +680,7 @@ SendSubrect(rfbClientPtr cl, return FALSE; } - if (!SendTightHeader(cl, x, y, w, h)) + if (!rfbSendTightHeader(cl, x, y, w, h)) return FALSE; fbptr = (cl->scaledScreen->frameBuffer @@ -767,8 +764,8 @@ SendSubrect(rfbClientPtr cl, return success; } -static rfbBool -SendTightHeader(rfbClientPtr cl, +rfbBool +rfbSendTightHeader(rfbClientPtr cl, int x, int y, int w, @@ -1044,7 +1041,7 @@ CompressData(rfbClientPtr cl, } if (zlibLevel == 0) - return SendCompressedData (cl, tightBeforeBuf, dataLen); + return rfbSendCompressedDataTight(cl, tightBeforeBuf, dataLen); pz = &cl->zsStruct[streamId]; @@ -1083,12 +1080,12 @@ CompressData(rfbClientPtr cl, return FALSE; } - return SendCompressedData(cl, tightAfterBuf, - tightAfterBufSize - pz->avail_out); + return rfbSendCompressedDataTight(cl, tightAfterBuf, + tightAfterBufSize - pz->avail_out); } -static rfbBool SendCompressedData(rfbClientPtr cl, char *buf, - int compressedLen) +rfbBool rfbSendCompressedDataTight(rfbClientPtr cl, char *buf, + int compressedLen) { int i, portionLen; @@ -1665,7 +1662,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); - return SendCompressedData(cl, tightAfterBuf, (int)size); + return rfbSendCompressedDataTight(cl, tightAfterBuf, (int)size); } static void @@ -1899,6 +1896,6 @@ static rfbBool SendPngRect(rfbClientPtr cl, int x, int y, int w, int h) { rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); /* rfbLog("<< SendPngRect\n"); */ - return SendCompressedData(cl, tightAfterBuf, pngDstDataLen); + return rfbSendCompressedDataTight(cl, tightAfterBuf, pngDstDataLen); } #endif diff --git a/rfb/rfb.h b/rfb/rfb.h index f982b40..6401e78 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -895,6 +895,8 @@ extern rfbBool rfbTightDisableGradient; extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); extern rfbBool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); +extern rfbBool rfbSendTightHeader(rfbClientPtr cl, int x, int y, int w, int h); +extern rfbBool rfbSendCompressedDataTight(rfbClientPtr cl, char *buf, int compressedLen); #if defined(LIBVNCSERVER_HAVE_LIBPNG) extern rfbBool rfbSendRectEncodingTightPng(rfbClientPtr cl, int x,int y,int w,int h); -- cgit v1.2.3 From 49f1d8de47179087c8e83da9e76d3cc03a7488c4 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 29 Jun 2018 12:31:26 +0200 Subject: build: remove LIBVNCSERVER_WITH_CLIENT_TLS #define It is not used anywhere anymore. --- rfb/rfbconfig.h.cmakein | 3 --- 1 file changed, 3 deletions(-) (limited to 'rfb') diff --git a/rfb/rfbconfig.h.cmakein b/rfb/rfbconfig.h.cmakein index 7638921..613149a 100644 --- a/rfb/rfbconfig.h.cmakein +++ b/rfb/rfbconfig.h.cmakein @@ -142,9 +142,6 @@ /* Define to 1 if libgcrypt is present */ #cmakedefine LIBVNCSERVER_WITH_CLIENT_GCRYPT 1 -/* Define to 1 if GnuTLS is present */ -#cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1 - /* Define to 1 if OpenSSL is present */ #cmakedefine LIBVNCSERVER_HAVE_LIBSSL 1 -- cgit v1.2.3 From e775aec64e75d5b3e5580ab2f0a860efe9ce4d1b Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sun, 8 Jul 2018 17:56:23 +0200 Subject: build: decouple GnuTLS|OpenSSL detection from WebSockets support --- CMakeLists.txt | 31 +++++++++++++++---------------- rfb/rfb.h | 5 ----- 2 files changed, 15 insertions(+), 21 deletions(-) (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index b9f3044..8097158 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,20 +224,6 @@ endif(LIBVNCSERVER_HAVE_SYS_UIO_H) if(WITH_WEBSOCKETS AND LIBVNCSERVER_HAVE_CRYPTO) set(LIBVNCSERVER_WITH_WEBSOCKETS 1) - if(GNUTLS_FOUND) - message(STATUS "Building websockets with GnuTLS") - set(WEBSOCKET_LIBRARIES ${GNUTLS_LIBRARIES}) - set(WSSRCS ${LIBVNCSERVER_DIR}/rfbssl_gnutls) - include_directories(${GNUTLS_INCLUDE_DIR}) - elseif(OPENSSL_FOUND) - message(STATUS "Building websockets with OpenSSL") - set(WEBSOCKET_LIBRARIES ${OPENSSL_LIBRARIES}) - set(WSSRCS ${LIBVNCSERVER_DIR}/rfbssl_openssl) - else() - message(STATUS "Building websockets without SSL") - set(WEBSOCKET_LIBRARIES) - set(WSSRCS ${LIBVNCSERVER_DIR}/rfbssl_none.c) - endif() endif(WITH_WEBSOCKETS AND LIBVNCSERVER_HAVE_CRYPTO) if(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES) @@ -351,17 +337,30 @@ if(GNUTLS_FOUND) ${LIBVNCCLIENT_SOURCES} ${LIBVNCCLIENT_DIR}/tls_gnutls.c ) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/rfbssl_gnutls.c + ) + include_directories(${GNUTLS_INCLUDE_DIR}) elseif(OPENSSL_FOUND) set(LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_SOURCES} ${LIBVNCCLIENT_DIR}/tls_openssl.c ) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/rfbssl_openssl.c + ) include_directories(${OPENSSL_INCLUDE_DIR}) else() set(LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_SOURCES} ${LIBVNCCLIENT_DIR}/tls_none.c ) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/rfbssl_none.c + ) endif() if(LIBVNCSERVER_HAVE_SASL) @@ -417,7 +416,6 @@ if(LIBVNCSERVER_WITH_WEBSOCKETS) ${LIBVNCSERVER_DIR}/ws_decode.c ${COMMON_DIR}/base64.c ${CRYPTO_SOURCES} - ${WSSRCS} ) endif(LIBVNCSERVER_WITH_WEBSOCKETS) @@ -440,7 +438,8 @@ target_link_libraries(vncserver ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${CRYPTO_LIBRARIES} - ${WEBSOCKET_LIBRARIES} + ${GNUTLS_LIBRARIES} + ${OPENSSL_LIBRARIES} ) SET_TARGET_PROPERTIES(vncclient vncserver diff --git a/rfb/rfb.h b/rfb/rfb.h index 6401e78..3d6d31e 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -378,10 +378,8 @@ typedef struct _rfbScreenInfo rfbDisplayFinishedHookPtr displayFinishedHook; /** xvpHook is called to handle an xvp client message */ rfbXvpHookPtr xvpHook; -#ifdef LIBVNCSERVER_WITH_WEBSOCKETS char *sslkeyfile; char *sslcertfile; -#endif int ipv6port; /**< The port to listen on when using IPv6. */ char* listen6Interface; /* We have an additional IPv6 listen socket since there are systems that @@ -690,12 +688,9 @@ typedef struct _rfbClientRec { int turboQualityLevel; /* 1-100 scale */ #endif #endif - -#ifdef LIBVNCSERVER_WITH_WEBSOCKETS rfbSslCtx *sslctx; wsCtx *wsctx; char *wspath; /* Requests path component */ -#endif } rfbClientRec, *rfbClientPtr; /** -- cgit v1.2.3 From 1781ecda341fb06fd414a4d84bb363b070958ea4 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sun, 8 Jul 2018 20:53:43 +0200 Subject: CMake: add a LIBVNCSERVER_HAVE_GNUTLS #define --- CMakeLists.txt | 4 ++++ rfb/rfbconfig.h.cmakein | 3 +++ 2 files changed, 7 insertions(+) (limited to 'rfb') diff --git a/CMakeLists.txt b/CMakeLists.txt index 8097158..995cbc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -232,6 +232,10 @@ if(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${LIBGCRYPT_LIBRARIES}) endif(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES) +if(GNUTLS_FOUND) + set(LIBVNCSERVER_HAVE_GNUTLS 1) +endif(GNUTLS_FOUND) + if(OPENSSL_FOUND) set(LIBVNCSERVER_HAVE_LIBSSL 1) endif(OPENSSL_FOUND) diff --git a/rfb/rfbconfig.h.cmakein b/rfb/rfbconfig.h.cmakein index 613149a..2d165c5 100644 --- a/rfb/rfbconfig.h.cmakein +++ b/rfb/rfbconfig.h.cmakein @@ -142,6 +142,9 @@ /* Define to 1 if libgcrypt is present */ #cmakedefine LIBVNCSERVER_WITH_CLIENT_GCRYPT 1 +/* Define to 1 if GnuTLS is present */ +#cmakedefine LIBVNCSERVER_HAVE_GNUTLS 1 + /* Define to 1 if OpenSSL is present */ #cmakedefine LIBVNCSERVER_HAVE_LIBSSL 1 -- cgit v1.2.3 From cedae6e6f97b14f5df3ea7c5f7efd59f2bc9ad82 Mon Sep 17 00:00:00 2001 From: Quentin BUATHIER Date: Thu, 9 Aug 2018 09:33:59 +0200 Subject: Fix the concurrent issue hapenning between the freeing of the client and the clientOutput thread --- libvncserver/main.c | 29 ++++++++++++++++++++++++++--- libvncserver/rfbserver.c | 5 +++++ rfb/rfb.h | 1 + 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'rfb') diff --git a/libvncserver/main.c b/libvncserver/main.c index 106ebab..c34ae7e 100644 --- a/libvncserver/main.c +++ b/libvncserver/main.c @@ -33,6 +33,7 @@ #include #include #include +#include #endif #include @@ -533,6 +534,7 @@ clientInput(void *data) FD_ZERO(&rfds); FD_SET(cl->sock, &rfds); + FD_SET(cl->pipe_notify_client_thread[0], &rfds); FD_ZERO(&efds); FD_SET(cl->sock, &efds); @@ -541,9 +543,13 @@ clientInput(void *data) if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1)) FD_SET(cl->sock, &wfds); + int nfds = cl->pipe_notify_client_thread[0] > cl->sock ? cl->pipe_notify_client_thread[0] : cl->sock; + tv.tv_sec = 60; /* 1 minute */ tv.tv_usec = 0; - n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv); + + n = select(nfds + 1, &rfds, &wfds, &efds, &tv); + if (n < 0) { rfbLogPerror("ReadExact: select"); break; @@ -558,6 +564,13 @@ clientInput(void *data) if (FD_ISSET(cl->sock, &wfds)) rfbSendFileTransferChunk(cl); + if (FD_ISSET(cl->pipe_notify_client_thread[0], &rfds)) + { + // Reset the pipe + char buf; + while (read(cl->pipe_notify_client_thread[0], &buf, sizeof(buf)) == sizeof(buf)); + } + if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds)) { #ifdef LIBVNCSERVER_WITH_WEBSOCKETS @@ -628,8 +641,12 @@ rfbStartOnHoldClient(rfbClientPtr cl) { cl->onHold = FALSE; #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD - if(cl->screen->backgroundLoop) - pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl); + if(cl->screen->backgroundLoop) { + pipe(cl->pipe_notify_client_thread); + fcntl(cl->pipe_notify_client_thread[0], F_SETFL, O_NONBLOCK); + + pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl); + } #endif } @@ -1091,7 +1108,13 @@ void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) { rfbCloseClient(currentCl); } +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + // Notify the thread and join it + write(currentCl->pipe_notify_client_thread[1], "\x00", 1); + pthread_join(currentCl->client_thread, NULL); +#else rfbClientConnectionGone(currentCl); +#endif currentCl = nextCl; } diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c index 7af6aed..f13050d 100644 --- a/libvncserver/rfbserver.c +++ b/libvncserver/rfbserver.c @@ -621,6 +621,11 @@ rfbClientConnectionGone(rfbClientPtr cl) UNLOCK(cl->sendMutex); TINI_MUTEX(cl->sendMutex); +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + close(cl->pipe_notify_client_thread[0]); + close(cl->pipe_notify_client_thread[1]); +#endif + rfbPrintStats(cl); rfbResetStats(cl); diff --git a/rfb/rfb.h b/rfb/rfb.h index 3d6d31e..9c60f3d 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -465,6 +465,7 @@ typedef struct _rfbClientRec { int protocolMinorVersion; #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + int pipe_notify_client_thread[2]; pthread_t client_thread; #endif -- cgit v1.2.3 From e611616723035d2345cf27e43c8b2eef958d5696 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Thu, 27 Sep 2018 20:37:06 +0200 Subject: Remove the turbojpeg.h dependency from public headers Closes #230 --- libvncclient/tight.c | 2 ++ rfb/rfbclient.h | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'rfb') diff --git a/libvncclient/tight.c b/libvncclient/tight.c index 64883e5..df01812 100644 --- a/libvncclient/tight.c +++ b/libvncclient/tight.c @@ -23,6 +23,8 @@ #ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBJPEG +#include "turbojpeg.h" + /* * tight.c - handle ``tight'' encoding. * diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index ec6ee55..87f4eaa 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -52,7 +52,6 @@ #endif #include #include -#include "turbojpeg.h" #ifdef LIBVNCSERVER_HAVE_SASL #include @@ -428,7 +427,7 @@ typedef struct _rfbClient { #ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBJPEG /** JPEG decoder state. */ - tjhandle tjhnd; + void *tjhnd; #endif #endif -- cgit v1.2.3 From 66ead2a7f23a30b4f441c18f5d884ea398055391 Mon Sep 17 00:00:00 2001 From: Tobias Junghans Date: Tue, 6 Nov 2018 10:33:44 +0100 Subject: rfb: add header guard for default8x16 --- rfb/default8x16.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'rfb') diff --git a/rfb/default8x16.h b/rfb/default8x16.h index 252f411..6096b1c 100644 --- a/rfb/default8x16.h +++ b/rfb/default8x16.h @@ -1,3 +1,6 @@ +#ifndef _DEFAULT_8_X_16_H +#define _DEFAULT_8_X_16_H + static unsigned char default8x16FontData[4096+1]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, @@ -259,3 +262,5 @@ static unsigned char default8x16FontData[4096+1]={ static int default8x16FontMetaData[256*5+1]={ 0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,}; static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData }; + +#endif -- cgit v1.2.3 From 5f9a07d7e1613dbccd5a27e845dbb8a7f2a27b2e Mon Sep 17 00:00:00 2001 From: Tobias Junghans Date: Tue, 6 Nov 2018 14:22:56 +0100 Subject: LibVNCClient: add support for custom auth handlers This allows to register custom authentication handlers in order to support additional security types. --- client_examples/backchannel.c | 4 +++- libvncclient/rfbproto.c | 29 +++++++++++++++++++++++++++++ rfb/rfbclient.h | 3 +++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'rfb') diff --git a/client_examples/backchannel.c b/client_examples/backchannel.c index 04d154e..a7db9a0 100644 --- a/client_examples/backchannel.c +++ b/client_examples/backchannel.c @@ -71,7 +71,9 @@ static rfbClientProtocolExtension backChannel = { backChannelEncodings, /* encodings */ NULL, /* handleEncoding */ handleBackChannelMessage, /* handleMessage */ - NULL /* next extension */ + NULL, /* next extension */ + NULL, /* securityTypes */ + NULL /* handleAuthentication */ }; int diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index ac2a983..fbe579c 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -474,9 +474,11 @@ ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) uint8_t count=0; uint8_t loop=0; uint8_t flag=0; + rfbBool extAuthHandler; uint8_t tAuth[256]; char buf1[500],buf2[10]; uint32_t authScheme; + rfbClientProtocolExtension* e; if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; @@ -495,7 +497,18 @@ ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE; rfbClientLog("%d) Received security type %d\n", loop, tAuth[loop]); if (flag) continue; + extAuthHandler=FALSE; + for (e = rfbClientExtensions; e; e = e->next) { + if (!e->handleAuthentication) continue; + uint32_t const* secType; + for (secType = e->securityTypes; secType && *secType; secType++) { + if (tAuth[loop]==*secType) { + extAuthHandler=TRUE; + } + } + } if (tAuth[loop]==rfbVncAuth || tAuth[loop]==rfbNoAuth || + extAuthHandler || #if defined(LIBVNCSERVER_HAVE_GNUTLS) || defined(LIBVNCSERVER_HAVE_LIBSSL) tAuth[loop]==rfbVeNCrypt || #endif @@ -1176,6 +1189,22 @@ InitialiseRFBConnection(rfbClient* client) break; default: + { + rfbBool authHandled=FALSE; + rfbClientProtocolExtension* e; + for (e = rfbClientExtensions; e; e = e->next) { + uint32_t const* secType; + if (!e->handleAuthentication) continue; + for (secType = e->securityTypes; secType && *secType; secType++) { + if (authScheme==*secType) { + if (!e->handleAuthentication(client, authScheme)) return FALSE; + if (!rfbHandleAuthResult(client)) return FALSE; + authHandled=TRUE; + } + } + } + if (authHandled) break; + } rfbClientLog("Unknown authentication scheme from VNC server: %d\n", (int)authScheme); return FALSE; diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 87f4eaa..1a80f0d 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -620,6 +620,9 @@ typedef struct _rfbClientProtocolExtension { rfbBool (*handleMessage)(rfbClient* cl, rfbServerToClientMsg* message); struct _rfbClientProtocolExtension* next; + uint32_t const* securityTypes; + /** returns TRUE if it handled the authentication */ + rfbBool (*handleAuthentication)(rfbClient* cl, uint32_t authScheme); } rfbClientProtocolExtension; void rfbClientRegisterExtension(rfbClientProtocolExtension* e); -- cgit v1.2.3 From e66a8a17f3fb2dc87ebd35535c9a310068ba3b4a Mon Sep 17 00:00:00 2001 From: Tobias Junghans Date: Thu, 22 Nov 2018 15:19:37 +0100 Subject: Allow to use global LZO library instead of miniLZO The complete LZO library nowadays is installed on many systems so we can optionally make use of it and omit internal miniLZO implementation. --- .travis.yml | 2 +- CMakeLists.txt | 27 +++++++++++++++++++++++++-- cmake/Modules/FindLZO.cmake | 31 +++++++++++++++++++++++++++++++ libvncclient/rfbproto.c | 4 ++++ libvncserver/ultra.c | 4 ++++ rfb/rfbconfig.h.cmakein | 3 +++ 6 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 cmake/Modules/FindLZO.cmake (limited to 'rfb') diff --git a/.travis.yml b/.travis.yml index ea8b9e5..dde1238 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_install: script: - mkdir build - cd build - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update; sudo apt-get --no-install-suggests --no-install-recommends install libsdl2-dev; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update; sudo apt-get --no-install-suggests --no-install-recommends install libsdl2-dev liblzo2-dev; fi - if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then brew update; brew install sdl2; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cmake .. -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl; else cmake ..; fi - cmake --build . diff --git a/CMakeLists.txt b/CMakeLists.txt index 727c970..68cd843 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CM # all the build configuration switches option(BUILD_SHARED_LIBS "Build shared libraries" ${UNIX}) option(WITH_ZLIB "Search for the zlib compression library to support additional encodings" ON) +option(WITH_LZO "Search for the LZO compression library to omit internal miniLZO implementation" ON) option(WITH_JPEG "Search for the libjpeg compression library to support additional encodings" ON) option(WITH_PNG "Search for the PNG compression library to support additional encodings" ON) option(WITH_SDL "Search for the Simple Direct Media Layer library to build an example SDL vnc client" ON) @@ -56,6 +57,9 @@ if(WITH_ZLIB) find_package(ZLIB) endif(WITH_ZLIB) +if(WITH_LZO) + find_package(LZO) +endif() if(WITH_JPEG) find_package(JPEG) @@ -189,6 +193,11 @@ if(ZLIB_FOUND) else() unset(ZLIB_LIBRARIES) # would otherwise contain -NOTFOUND, confusing target_link_libraries() endif(ZLIB_FOUND) +if(LZO_FOUND) + set(LIBVNCSERVER_HAVE_LZO 1) +else() + unset(LZO_LIBRARIES CACHE) # would otherwise contain -NOTFOUND, confusing target_link_libraries() +endif() if(JPEG_FOUND) set(LIBVNCSERVER_HAVE_LIBJPEG 1) else() @@ -317,7 +326,6 @@ set(LIBVNCSERVER_SOURCES ${COMMON_DIR}/d3des.c ${COMMON_DIR}/vncauth.c ${LIBVNCSERVER_DIR}/cargs.c - ${COMMON_DIR}/minilzo.c ${LIBVNCSERVER_DIR}/ultra.c ${LIBVNCSERVER_DIR}/scale.c ) @@ -328,7 +336,6 @@ set(LIBVNCCLIENT_SOURCES ${LIBVNCCLIENT_DIR}/rfbproto.c ${LIBVNCCLIENT_DIR}/sockets.c ${LIBVNCCLIENT_DIR}/vncviewer.c - ${COMMON_DIR}/minilzo.c ) if(JPEG_FOUND) @@ -388,6 +395,20 @@ if(ZLIB_FOUND) ) endif(ZLIB_FOUND) +if(LZO_FOUND) + add_definitions(-DLIBVNCSERVER_HAVE_LZO) + include_directories(${LZO_INCLUDE_DIR}) +else() + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${COMMON_DIR}/minilzo.c + ) + set(LIBVNCCLIENT_SOURCES + ${LIBVNCCLIENT_SOURCES} + ${COMMON_DIR}/minilzo.c + ) +endif() + if(JPEG_FOUND) add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG) include_directories(${JPEG_INCLUDE_DIR}) @@ -434,6 +455,7 @@ endif(WIN32) target_link_libraries(vncclient ${ADDITIONAL_LIBS} ${ZLIB_LIBRARIES} + ${LZO_LIBRARIES} ${JPEG_LIBRARIES} ${GNUTLS_LIBRARIES} ${OPENSSL_LIBRARIES} @@ -441,6 +463,7 @@ target_link_libraries(vncclient target_link_libraries(vncserver ${ADDITIONAL_LIBS} ${ZLIB_LIBRARIES} + ${LZO_LIBRARIES} ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${CRYPTO_LIBRARIES} diff --git a/cmake/Modules/FindLZO.cmake b/cmake/Modules/FindLZO.cmake new file mode 100644 index 0000000..d313fae --- /dev/null +++ b/cmake/Modules/FindLZO.cmake @@ -0,0 +1,31 @@ +# Find liblzo2 +# LZO_FOUND - system has the LZO library +# LZO_INCLUDE_DIR - the LZO include directory +# LZO_LIBRARIES - The libraries needed to use LZO + +if (LZO_INCLUDE_DIR AND LZO_LIBRARIES) + # in cache already + SET(LZO_FOUND TRUE) +else (LZO_INCLUDE_DIR AND LZO_LIBRARIES) + FIND_PATH(LZO_INCLUDE_DIR NAMES lzo/lzo1x.h) + + FIND_LIBRARY(LZO_LIBRARIES NAMES lzo2) + + if (LZO_INCLUDE_DIR AND LZO_LIBRARIES) + set(LZO_FOUND TRUE) + endif (LZO_INCLUDE_DIR AND LZO_LIBRARIES) + + if (LZO_FOUND) + if (NOT LZO_FIND_QUIETLY) + message(STATUS "Found LZO: ${LZO_LIBRARIES}") + endif (NOT LZO_FIND_QUIETLY) + else (LZO_FOUND) + if (LZO_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find LZO") + else() + message(STATUS "Could NOT find LZO") + endif (LZO_FIND_REQUIRED) + endif (LZO_FOUND) + +# MARK_AS_ADVANCED(LZO_INCLUDE_DIR LZO_LIBRARIES) +endif (LZO_INCLUDE_DIR AND LZO_LIBRARIES) diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index 4541e0d..82536cd 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -61,7 +61,11 @@ #endif #include "sasl.h" +#ifdef LIBVNCSERVER_HAVE_LZO +#include +#else #include "minilzo.h" +#endif #include "tls.h" #ifdef _MSC_VER diff --git a/libvncserver/ultra.c b/libvncserver/ultra.c index 83bddaa..cd625a5 100644 --- a/libvncserver/ultra.c +++ b/libvncserver/ultra.c @@ -8,7 +8,11 @@ */ #include +#ifdef LIBVNCSERVER_HAVE_LZO +#include +#else #include "minilzo.h" +#endif /* * cl->beforeEncBuf contains pixel data in the client's format. diff --git a/rfb/rfbconfig.h.cmakein b/rfb/rfbconfig.h.cmakein index 2d165c5..f5d8d78 100644 --- a/rfb/rfbconfig.h.cmakein +++ b/rfb/rfbconfig.h.cmakein @@ -72,6 +72,9 @@ /* Define to 1 if you have the `z' library (-lz). */ #cmakedefine LIBVNCSERVER_HAVE_LIBZ 1 +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#cmakedefine LIBVNCSERVER_HAVE_LZO 1 + /* Define to 1 if you have the header file. */ #cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1 -- cgit v1.2.3 From d3a4292aa9ade2a335e0915523506b73e94251d7 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Sun, 6 Jan 2019 19:34:04 +0100 Subject: Move pipe_notify_client_thread to end of rfbClientRec in order to retain ABI compatibility. --- rfb/rfb.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'rfb') diff --git a/rfb/rfb.h b/rfb/rfb.h index 9c60f3d..2a5600e 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -465,7 +465,6 @@ typedef struct _rfbClientRec { int protocolMinorVersion; #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD - int pipe_notify_client_thread[2]; pthread_t client_thread; #endif @@ -692,6 +691,9 @@ typedef struct _rfbClientRec { rfbSslCtx *sslctx; wsCtx *wsctx; char *wspath; /* Requests path component */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + int pipe_notify_client_thread[2]; +#endif } rfbClientRec, *rfbClientPtr; /** -- cgit v1.2.3