--- vnc-4.0b5-unixsrc/x0vncserver/Makefile.in.tls 2004-06-11 16:36:08.113307745 +0100 +++ vnc-4.0b5-unixsrc/x0vncserver/Makefile.in 2004-06-11 16:36:46.864918325 +0100 @@ -7,9 +7,9 @@ DEP_LIBS = ../rfb/librfb.a ../network/libnetwork.a ../rdr/librdr.a -EXTRA_LIBS = @ZLIB_LIB@ @X_PRE_LIBS@ @X_LIBS@ -lXtst -lXext -lX11 @X_EXTRA_LIBS@ +EXTRA_LIBS = @ZLIB_LIB@ @X_PRE_LIBS@ @X_LIBS@ -lXtst -lXext -lX11 @X_EXTRA_LIBS@ @LIBGNUTLS_LIBS@ -DIR_CPPFLAGS = -I$(top_srcdir) @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS +DIR_CPPFLAGS = -I$(top_srcdir) @X_CFLAGS@ @LIBGNUTLS_CFLAGS@ # X_CFLAGS are really CPPFLAGS all:: $(program) --- vnc-4.0b5-unixsrc/configure.in.tls 2004-06-11 16:36:08.147303017 +0100 +++ vnc-4.0b5-unixsrc/configure.in 2004-06-11 16:36:46.865918186 +0100 @@ -63,6 +63,14 @@ AC_SUBST(ZLIB_INCLUDE) AC_SUBST(ZLIB_LIB) +AC_ARG_ENABLE(gnutls, [ --enable-gnutls build with gnutls support]) +if test "x$enable_gnutls" = "xyes"; then + AC_LANG_PUSH(C) + AM_PATH_LIBGNUTLS(1.0.0, [AC_DEFINE(HAVE_GNUTLS)], AC_MSG_ERROR([Unable to find GNUTLS])) + LIBGNUTLS_CFLAGS="-DHAVE_GNUTLS $LIBGNUTLS_CFLAGS" + AC_LANG_PUSH(C) +fi + AC_CHECK_FUNC(vsnprintf,VSNPRINTF_DEFINE='-DHAVE_VSNPRINTF',VSNPRINTF_DEFINE=) AC_SUBST(VSNPRINTF_DEFINE) --- vnc-4.0b5-unixsrc/rfb/CSecurity.h.tls 2004-06-11 16:36:08.167300236 +0100 +++ vnc-4.0b5-unixsrc/rfb/CSecurity.h 2004-06-11 16:36:46.867917908 +0100 @@ -38,8 +38,14 @@ class CConnection; class CSecurity { public: + enum statusEnum { + RFB_SECURITY_ERROR, + RFB_SECURITY_COMPLETED, + RFB_SECURITY_DEFER, + RFB_SECURITY_AUTH_TYPES + }; virtual ~CSecurity() {} - virtual bool processMsg(CConnection* cc, bool* done)=0; + virtual statusEnum processMsg(CConnection* cc)=0; virtual void destroy() { delete this; } virtual int getType() const = 0; virtual const char* description() const = 0; --- vnc-4.0b5-unixsrc/rfb/CSecurityTLS.cxx.tls 2004-06-11 16:36:36.557351881 +0100 +++ vnc-4.0b5-unixsrc/rfb/CSecurityTLS.cxx 2004-06-11 16:36:46.868917769 +0100 @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2004 Red Hat Inc. + * + * 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. + */ + +#ifdef HAVE_GNUTLS + +#include +#include +#include +#include +#include + +#undef TLS_DEBUG + +using namespace rfb; + +static LogWriter vlog("TLS"); + +#ifdef TLS_DEBUG +static void debug_log(int level, const char* str) +{ + vlog.debug(str); +} +#endif + +void CSecurityTLS::initGlobal() +{ + static bool globalInitDone = false; + + if (!globalInitDone) { + gnutls_global_init(); + +#ifdef TLS_DEBUG + gnutls_global_set_log_level(10); + gnutls_global_set_log_function(debug_log); +#endif + + globalInitDone = true; + } +} + +CSecurityTLS::CSecurityTLS() : session(0), anon_cred(0) +{ +} + +CSecurityTLS::~CSecurityTLS() +{ + if (session) { + gnutls_bye(session, GNUTLS_SHUT_RDWR); + gnutls_anon_free_client_credentials (anon_cred); + gnutls_deinit (session); + } + + /* FIXME: should be doing gnutls_global_deinit() at some point */ +} + +CSecurityTLS::statusEnum CSecurityTLS::processMsg(CConnection* cc) +{ + rdr::FdInStream* is; + rdr::FdOutStream* os; + + if ((is = dynamic_cast(cc->getInStream())) == 0) { + vlog.error("Cannot use TLS security type with anything other than FdInStream"); + return RFB_SECURITY_ERROR; + } + + if ((os = dynamic_cast(cc->getOutStream())) == 0) { + vlog.error("Cannot use TLS security type with anything other than FdOutStream"); + return RFB_SECURITY_ERROR; + } + + initGlobal(); + + gnutls_init(&session, GNUTLS_CLIENT); + gnutls_set_default_priority(session); + + int kx_priority[] = { GNUTLS_KX_ANON_DH, 0 }; + gnutls_kx_set_priority(session, kx_priority); + + gnutls_anon_allocate_client_credentials(&anon_cred); + gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred); + + gnutls_transport_set_ptr2(session, + (gnutls_transport_ptr)is->getFd(), + (gnutls_transport_ptr)os->getFd()); + + int err; + do { + err = gnutls_handshake(session); + } while (err != GNUTLS_E_SUCCESS && !gnutls_error_is_fatal(err)); + + if (err != GNUTLS_E_SUCCESS) { + vlog.error("TLS Handshake failed: %s\n", gnutls_strerror (err)); + gnutls_bye(session, GNUTLS_SHUT_RDWR); + gnutls_anon_free_client_credentials(anon_cred); + gnutls_deinit(session); + session = 0; + return RFB_SECURITY_ERROR; + } + + is->useTLS(session); + os->useTLS(session); + + return RFB_SECURITY_AUTH_TYPES; +} + +#endif /* HAVE_GNUTLS */ --- vnc-4.0b5-unixsrc/rfb/CConnection.h.tls 2004-06-11 16:36:08.248288973 +0100 +++ vnc-4.0b5-unixsrc/rfb/CConnection.h 2004-06-11 16:36:46.869917630 +0100 @@ -59,6 +59,11 @@ // first one is most preferred. void addSecType(rdr::U8 secType); + // addAuthType() should be called once for each authentication type which + // the client supports. The order in which they're added is such that the + // first one is most preferred. + void addAuthType(rdr::U8 authType); + // setClientSecTypeOrder() determines whether the client should obey // the server's security type preference, by picking the first server security // type that the client supports, or whether it should pick the first type @@ -150,6 +155,7 @@ private: void processVersionMsg(); void processSecurityTypesMsg(); + void processAuthTypesMsg(); void processSecurityMsg(); void processSecurityResultMsg(); void processInitMsg(); @@ -164,9 +170,11 @@ bool deleteStreamsWhenDone; bool shared; CSecurity* security; - enum { maxSecTypes = 8 }; + enum { maxSecTypes = 8, maxAuthTypes = 8 }; int nSecTypes; rdr::U8 secTypes[maxSecTypes]; + int nAuthTypes; + rdr::U8 authTypes[maxAuthTypes]; bool clientSecTypeOrder; stateEnum state_; --- vnc-4.0b5-unixsrc/rfb/Makefile.in.tls 2004-06-11 16:36:08.250288695 +0100 +++ vnc-4.0b5-unixsrc/rfb/Makefile.in 2004-06-11 16:36:46.869917630 +0100 @@ -8,6 +8,7 @@ CMsgWriter.cxx \ CMsgWriterV3.cxx \ CSecurityVncAuth.cxx \ + CSecurityTLS.cxx \ ComparingUpdateTracker.cxx \ Configuration.cxx \ ConnParams.cxx \ @@ -52,7 +53,7 @@ OBJS = d3des.o $(CXXSRCS:.cxx=.o) -DIR_CPPFLAGS = -I$(top_srcdir) @VSNPRINTF_DEFINE@ +DIR_CPPFLAGS = -I$(top_srcdir) @VSNPRINTF_DEFINE@ @LIBGNUTLS_CFLAGS@ library = librfb.a @@ -63,4 +64,6 @@ $(AR) $(library) $(OBJS) $(RANLIB) $(library) +DIR_CFLAGS = -DPIC -fPIC +DIR_CXXFLAGS = -DPIC -fPIC # followed by boilerplate.mk --- vnc-4.0b5-unixsrc/rfb/CSecurityVncAuth.cxx.tls 2004-06-11 16:36:08.252288416 +0100 +++ vnc-4.0b5-unixsrc/rfb/CSecurityVncAuth.cxx 2004-06-11 16:36:46.869917630 +0100 @@ -41,9 +41,8 @@ { } -bool CSecurityVncAuth::processMsg(CConnection* cc, bool* done) +CSecurity::statusEnum CSecurityVncAuth::processMsg(CConnection* cc) { - *done = false; rdr::InStream* is = cc->getInStream(); rdr::OutStream* os = cc->getOutStream(); @@ -52,12 +51,11 @@ CharArray passwd; if (!upg->getUserPasswd(0, &passwd.buf)) { vlog.error("Getting password failed"); - return false; + return RFB_SECURITY_ERROR; } vncAuthEncryptChallenge(challenge, passwd.buf); memset(passwd.buf, 0, strlen(passwd.buf)); os->writeBytes(challenge, vncAuthChallengeSize); os->flush(); - *done = true; - return true; + return RFB_SECURITY_COMPLETED; } --- vnc-4.0b5-unixsrc/rfb/secTypes.cxx.tls 2004-06-11 16:36:08.254288138 +0100 +++ vnc-4.0b5-unixsrc/rfb/secTypes.cxx 2004-06-11 16:36:46.870917491 +0100 @@ -28,6 +28,7 @@ if (strcasecmp(name, "VncAuth") == 0) return secTypeVncAuth; if (strcasecmp(name, "RA2") == 0) return secTypeRA2; if (strcasecmp(name, "RA2ne") == 0) return secTypeRA2ne; + if (strcasecmp(name, "TLS") == 0) return secTypeTLS; return secTypeInvalid; } @@ -38,6 +39,7 @@ case secTypeVncAuth: return "VncAuth"; case secTypeRA2: return "RA2"; case secTypeRA2ne: return "RA2ne"; + case secTypeTLS: return "TLS"; default: return "[unknown secType]"; } } @@ -46,6 +48,7 @@ { switch (num) { case secTypeRA2: return true; + case secTypeTLS: return true; default: return false; } } --- vnc-4.0b5-unixsrc/rfb/CSecurityTLS.h.tls 2004-06-11 16:36:31.135105991 +0100 +++ vnc-4.0b5-unixsrc/rfb/CSecurityTLS.h 2004-06-11 16:36:46.870917491 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2004 Red Hat Inc. + * + * 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. + */ + +#ifndef __C_SECURITY_TLS_H__ +#define __C_SECURITY_TLS_H__ + +#ifdef HAVE_GNUTLS + +#include +#include +#include + +namespace rfb { + class CSecurityTLS : public CSecurity { + public: + CSecurityTLS(); + virtual ~CSecurityTLS(); + virtual statusEnum processMsg(CConnection* cc); + virtual int getType() const { return secTypeTLS; }; + virtual const char* description() const { return "TLS Encryption"; } + + private: + static void initGlobal(); + + gnutls_session session; + gnutls_anon_server_credentials anon_cred; + }; +} + +#endif /* HAVE_GNUTLS */ + +#endif /* __C_SECURITY_TLS_H__ */ --- vnc-4.0b5-unixsrc/rfb/CSecurityNone.h.tls 2004-06-11 16:36:08.312280073 +0100 +++ vnc-4.0b5-unixsrc/rfb/CSecurityNone.h 2004-06-11 16:36:46.871917352 +0100 @@ -28,8 +28,8 @@ class CSecurityNone : public CSecurity { public: - virtual bool processMsg(CConnection* cc, bool* done) { - *done = true; return true; + virtual statusEnum processMsg(CConnection* cc) { + return RFB_SECURITY_COMPLETED; } virtual int getType() const {return secTypeNone;} virtual const char* description() const {return "No Encryption";} --- vnc-4.0b5-unixsrc/rfb/CConnection.cxx.tls 2004-06-11 16:36:08.315279656 +0100 +++ vnc-4.0b5-unixsrc/rfb/CConnection.cxx 2004-06-11 16:36:46.980902194 +0100 @@ -33,7 +33,8 @@ CConnection::CConnection() : is(0), os(0), reader_(0), writer_(0), - shared(false), security(0), nSecTypes(0), clientSecTypeOrder(false), + shared(false), security(0), + nSecTypes(0), nAuthTypes(0), clientSecTypeOrder(false), state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false) { } @@ -64,11 +65,19 @@ void CConnection::addSecType(rdr::U8 secType) { + vlog.debug("adding %d", secType); if (nSecTypes == maxSecTypes) throw Exception("too many security types"); secTypes[nSecTypes++] = secType; } +void CConnection::addAuthType(rdr::U8 authType) +{ + if (nAuthTypes == maxAuthTypes) + throw Exception("too many authentication types"); + authTypes[nAuthTypes++] = authType; +} + void CConnection::setClientSecTypeOrder(bool clientOrder) { clientSecTypeOrder = clientOrder; } @@ -204,15 +213,72 @@ processSecurityMsg(); } +void CConnection::processAuthTypesMsg() +{ + vlog.debug("processing authentication types message"); + + int authType = secTypeInvalid; + + int nServerAuthTypes = is->readU8(); + if (nServerAuthTypes == 0) + throwConnFailedException(); + + int authTypePos = nAuthTypes; + for (int i = 0; i < nServerAuthTypes; i++) { + rdr::U8 serverAuthType = is->readU8(); + vlog.debug("Server offers security type %s(%d)", + secTypeName(serverAuthType),serverAuthType); + + // If we haven't already chosen a authType, try this one + // If we are using the client's preference for types, + // we keep trying types, to find the one that matches and + // which appears first in the client's list of supported types. + if (authType == secTypeInvalid || clientSecTypeOrder) { + for (int j = 0; j < nAuthTypes; j++) { + if (authTypes[j] == serverAuthType && j < authTypePos) { + authType = authTypes[j]; + authTypePos = j; + break; + } + } + // NB: Continue reading the remaining server authTypes, but ignore them + } + } + + // Inform the server of our decision + if (authType != secTypeInvalid) { + os->writeU8(authType); + os->flush(); + vlog.debug("Choosing authentication type %s(%d)",secTypeName(authType),authType); + } + + if (authType == secTypeInvalid) { + state_ = RFBSTATE_INVALID; + vlog.error("No matching authentication types"); + throw Exception("No matching authentication types"); + } + + security = getCSecurity(authType); + processSecurityMsg(); +} + void CConnection::processSecurityMsg() { vlog.debug("processing security message"); - bool done; - if (!security->processMsg(this, &done)) + switch (security->processMsg(this)) { + case CSecurity::RFB_SECURITY_ERROR: throwAuthFailureException(); - if (done) { + case CSecurity::RFB_SECURITY_COMPLETED: state_ = RFBSTATE_SECURITY_RESULT; processSecurityResultMsg(); + break; + case CSecurity::RFB_SECURITY_DEFER: + break; + case CSecurity::RFB_SECURITY_AUTH_TYPES: + processAuthTypesMsg(); + break; + default: + throw Exception("CConnection::processSecurityMsg: invalid security status"); } } --- vnc-4.0b5-unixsrc/rfb/CSecurityVncAuth.h.tls 2004-06-11 16:36:08.317279378 +0100 +++ vnc-4.0b5-unixsrc/rfb/CSecurityVncAuth.h 2004-06-11 16:36:46.980902194 +0100 @@ -30,7 +30,7 @@ public: CSecurityVncAuth(UserPasswdGetter* pg); virtual ~CSecurityVncAuth(); - virtual bool processMsg(CConnection* cc, bool* done); + virtual statusEnum processMsg(CConnection* cc); virtual int getType() const {return secTypeVncAuth;}; virtual const char* description() const {return "No Encryption";} private: --- vnc-4.0b5-unixsrc/network/Makefile.in.tls 2004-06-11 16:36:08.319279100 +0100 +++ vnc-4.0b5-unixsrc/network/Makefile.in 2004-06-11 16:36:46.981902055 +0100 @@ -3,7 +3,7 @@ OBJS = $(SRCS:.cxx=.o) -DIR_CPPFLAGS = -I$(top_srcdir) @SOCKLEN_T_DEFINE@ +DIR_CPPFLAGS = -I$(top_srcdir) @SOCKLEN_T_DEFINE@ @LIBGNUTLS_CFLAGS@ library = libnetwork.a @@ -14,4 +14,5 @@ $(AR) $(library) $(OBJS) $(RANLIB) $(library) +DIR_CXXFLAGS = -DPIC -fPIC # followed by boilerplate.mk --- vnc-4.0b5-unixsrc/vncconfig/Makefile.in.tls 2004-06-11 16:36:08.322278683 +0100 +++ vnc-4.0b5-unixsrc/vncconfig/Makefile.in 2004-06-11 16:36:47.034894685 +0100 @@ -8,9 +8,9 @@ DEP_LIBS = ../tx/libtx.a ../rfb/librfb.a ../network/libnetwork.a \ ../rdr/librdr.a -EXTRA_LIBS = @X_PRE_LIBS@ @X_LIBS@ -lX11 -lXext @X_EXTRA_LIBS@ +EXTRA_LIBS = @X_PRE_LIBS@ @X_LIBS@ -lX11 -lXext @X_EXTRA_LIBS@ @LIBGNUTLS_LIBS@ -DIR_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tx @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS +DIR_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tx @X_CFLAGS@ @LIBGNUTLS_CFLAGS@ # X_CFLAGS are really CPPFLAGS all:: $(program) --- vnc-4.0b5-unixsrc/rdr/FdInStream.h.tls 2004-06-11 16:36:08.324278405 +0100 +++ vnc-4.0b5-unixsrc/rdr/FdInStream.h 2004-06-11 16:36:47.035894546 +0100 @@ -25,6 +25,10 @@ #include +#ifdef HAVE_GNUTLS +#include +#endif + namespace rdr { class FdInStreamBlockCallback { @@ -47,6 +51,10 @@ int pos(); void readBytes(void* data, int length); +#ifdef HAVE_GNUTLS + void useTLS(gnutls_session session); +#endif + void startTiming(); void stopTiming(); unsigned int kbitsPerSecond(); @@ -63,6 +71,10 @@ int timeoutms; FdInStreamBlockCallback* blockCallback; +#ifdef HAVE_GNUTLS + gnutls_session tlsSession; +#endif + bool timing; unsigned int timeWaitedIn100us; unsigned int timedKbits; --- vnc-4.0b5-unixsrc/rdr/FdOutStream.cxx.tls 2004-06-11 16:36:08.327277987 +0100 +++ vnc-4.0b5-unixsrc/rdr/FdOutStream.cxx 2004-06-11 16:36:47.035894546 +0100 @@ -45,6 +45,9 @@ FdOutStream::FdOutStream(int fd_, int timeoutms_, int bufSize_) : fd(fd_), timeoutms(timeoutms_), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +#ifdef HAVE_GNUTLS + ,tlsSession(0) +#endif { ptr = start = new U8[bufSize]; end = start + bufSize; @@ -113,6 +116,13 @@ return nItems; } +#ifdef HAVE_GNUTLS +void FdOutStream::useTLS(gnutls_session session) +{ + tlsSession = session; +} +#endif + // // writeWithTimeout() writes up to the given length in bytes from the given // buffer to the file descriptor. If there is a timeout set and that timeout @@ -127,7 +137,9 @@ { int n; +#ifndef HAVE_GNUTLS do { +#endif do { fd_set fds; @@ -159,15 +171,32 @@ if (n == 0) throw TimedOut(); - do { - n = ::write(fd, data, length); - } while (n < 0 && (errno == EINTR)); +#ifdef HAVE_GNUTLS + if (!tlsSession) { +#endif + + do { + n = ::write(fd, data, length); + } while (n < 0 && (errno == EINTR)); + +#ifdef HAVE_GNUTLS + } else { + + do { + n = gnutls_record_send(tlsSession, data, length); + } while (n == GNUTLS_E_INTERRUPTED); + + if (n < 0) throw TLSException("send",n); + } +#else // NB: This outer loop simply fixes a broken Winsock2 EWOULDBLOCK // condition, found only under Win98 (first edition), with slow // network connections. Should in fact never ever happen... } while (n < 0 && (errno == EWOULDBLOCK)); +#endif /* HAVE_GNUTLS */ + if (n < 0) throw SystemException("write",errno); return n; --- vnc-4.0b5-unixsrc/rdr/FdOutStream.h.tls 2004-06-11 16:36:08.329277709 +0100 +++ vnc-4.0b5-unixsrc/rdr/FdOutStream.h 2004-06-11 16:36:47.088887176 +0100 @@ -25,6 +25,10 @@ #include +#ifdef HAVE_GNUTLS +#include +#endif + namespace rdr { class FdOutStream : public OutStream { @@ -41,6 +45,10 @@ int length(); void writeBytes(const void* data, int length); +#ifdef HAVE_GNUTLS + void useTLS(gnutls_session session); +#endif + private: int overrun(int itemSize, int nItems); int writeWithTimeout(const void* data, int length); @@ -49,6 +57,10 @@ int bufSize; int offset; U8* start; + +#ifdef HAVE_GNUTLS + gnutls_session tlsSession; +#endif }; } --- vnc-4.0b5-unixsrc/rdr/Makefile.in.tls 2004-06-11 16:36:08.331277431 +0100 +++ vnc-4.0b5-unixsrc/rdr/Makefile.in 2004-06-11 16:36:47.089887037 +0100 @@ -5,7 +5,7 @@ OBJS = $(SRCS:.cxx=.o) -DIR_CPPFLAGS = -I$(top_srcdir) @ZLIB_INCLUDE@ +DIR_CPPFLAGS = -I$(top_srcdir) @ZLIB_INCLUDE@ @LIBGNUTLS_CFLAGS@ library = librdr.a --- vnc-4.0b5-unixsrc/rdr/Exception.cxx.tls 2004-06-11 16:36:08.333277153 +0100 +++ vnc-4.0b5-unixsrc/rdr/Exception.cxx 2004-06-11 16:36:47.089887037 +0100 @@ -62,3 +62,17 @@ strncat(str_, buf, len-1-strlen(str_)); strncat(str_, ")", len-1-strlen(str_)); } + +#ifdef HAVE_GNUTLS +TLSException::TLSException(const char* s, int err_) + : Exception(s, "rdr::TLSException"), err(err_) +{ + strncat(str_, ": ", len-1-strlen(str_)); + strncat(str_, gnutls_strerror(err), len-1-strlen(str_)); + strncat(str_, " (", len-1-strlen(str_)); + char buf[20]; + sprintf(buf,"%d",err); + strncat(str_, buf, len-1-strlen(str_)); + strncat(str_, ")", len-1-strlen(str_)); +} +#endif /* HAVE_GNUTLS */ --- vnc-4.0b5-unixsrc/rdr/FdInStream.cxx.tls 2004-06-11 16:36:08.335276875 +0100 +++ vnc-4.0b5-unixsrc/rdr/FdInStream.cxx 2004-06-11 16:36:47.142879667 +0100 @@ -53,6 +53,9 @@ bool closeWhenDone_) : fd(fd_), closeWhenDone(closeWhenDone_), timeoutms(timeoutms_), blockCallback(0), +#ifdef HAVE_GNUTLS + tlsSession(0), +#endif timing(false), timeWaitedIn100us(5), timedKbits(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) { @@ -169,6 +172,13 @@ } #endif +#ifdef HAVE_GNUTLS +void FdInStream::useTLS(gnutls_session session) +{ + tlsSession = session; +} +#endif + // // readWithTimeoutOrCallback() reads up to the given length in bytes from the // file descriptor into a buffer. If the wait argument is false, then zero is @@ -217,12 +227,29 @@ blockCallback->blockCallback(); } - do { - n = ::read(fd, buf, len); - } while (n < 0 && errno == EINTR); +#ifdef HAVE_GNUTLS + if (!tlsSession) { +#endif + + do { + n = ::read(fd, buf, len); + } while (n < 0 && errno == EINTR); - if (n < 0) throw SystemException("read",errno); - if (n == 0) throw EndOfStream(); + if (n < 0) throw SystemException("read",errno); + if (n == 0) throw EndOfStream(); + +#ifdef HAVE_GNUTLS + } else { + + do { + n = gnutls_record_recv(tlsSession, buf, len); + } while (n == GNUTLS_E_INTERRUPTED); + + if (n < 0) throw TLSException("recv",n); + if (n == 0) throw EndOfStream(); + + } +#endif if (timing) { gettimeofday(&after, 0); --- vnc-4.0b5-unixsrc/rdr/Exception.h.tls 2004-06-11 16:36:08.337276597 +0100 +++ vnc-4.0b5-unixsrc/rdr/Exception.h 2004-06-11 16:36:47.143879528 +0100 @@ -22,6 +22,10 @@ #include #include +#ifdef HAVE_GNUTLS +#include +#endif + namespace rdr { struct Exception { @@ -44,7 +48,7 @@ struct SystemException : public Exception { int err; SystemException(const char* s, int err_); - }; + }; struct TimedOut : public Exception { TimedOut(const char* s="Timed out") : Exception(s,"rdr::TimedOut") {} @@ -54,6 +58,13 @@ EndOfStream(const char* s="End of stream") : Exception(s,"rdr::EndOfStream") {} }; + +#ifdef HAVE_GNUTLS + struct TLSException : public Exception { + int err; + TLSException(const char* s, int err_); + }; +#endif } #endif --- vnc-4.0b5-unixsrc/vncviewer/Makefile.in.tls 2004-06-11 16:36:08.339276319 +0100 +++ vnc-4.0b5-unixsrc/vncviewer/Makefile.in 2004-06-11 16:36:47.144879388 +0100 @@ -8,9 +8,9 @@ DEP_LIBS = ../tx/libtx.a ../rfb/librfb.a ../network/libnetwork.a \ ../rdr/librdr.a -EXTRA_LIBS = @ZLIB_LIB@ @X_PRE_LIBS@ @X_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@ +EXTRA_LIBS = @ZLIB_LIB@ @X_PRE_LIBS@ @X_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@ @LIBGNUTLS_LIBS@ -DIR_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tx @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS +DIR_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tx @X_CFLAGS@ @LIBGNUTLS_CFLAGS@ # X_CFLAGS are really CPPFLAGS all:: $(program) --- vnc-4.0b5-unixsrc/vncviewer/CConn.cxx.tls 2004-06-11 16:36:08.341276041 +0100 +++ vnc-4.0b5-unixsrc/vncviewer/CConn.cxx 2004-06-11 16:36:47.201871462 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -64,8 +65,16 @@ menuKeysym = XStringToKeysym(menuKeyStr.buf); setShared(shared); + +#ifdef HAVE_GNUTLS + addSecType(secTypeTLS); +#endif addSecType(secTypeNone); addSecType(secTypeVncAuth); + + addAuthType(secTypeNone); + addAuthType(secTypeVncAuth); + CharArray encStr(preferredEncoding.getData()); int encNum = encodingNum(encStr.buf); if (encNum != -1) { @@ -216,6 +225,10 @@ return new CSecurityNone(); case secTypeVncAuth: return new CSecurityVncAuth(this); +#ifdef HAVE_GNUTLS + case secTypeTLS: + return new CSecurityTLS(); +#endif default: throw rfb::Exception("Unsupported secType?"); } --- vnc-4.0b5-unixsrc/tx/Makefile.in.tls 2004-06-11 16:36:08.392268949 +0100 +++ vnc-4.0b5-unixsrc/tx/Makefile.in 2004-06-11 16:36:47.202871323 +0100 @@ -4,7 +4,7 @@ OBJS = $(SRCS:.cxx=.o) -DIR_CPPFLAGS = -I$(top_srcdir) @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS +DIR_CPPFLAGS = -I$(top_srcdir) @X_CFLAGS@ @LIBGNUTLS_CFLAGS@ # X_CFLAGS are really CPPFLAGS library = libtx.a