The "rfb" library merged with VNC 4.1.1 code.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/merge-with-vnc-4.1.1@522 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/rfb/SConnection.cxx b/rfb/SConnection.cxx
index e969ed8..f8a3f36 100644
--- a/rfb/SConnection.cxx
+++ b/rfb/SConnection.cxx
@@ -1,5 +1,5 @@
-/* Copyright (C) 2002-2004 RealVNC Ltd.  All Rights Reserved.
- *    
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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
@@ -21,7 +21,6 @@
 #include <rfb/secTypes.h>
 #include <rfb/SMsgReaderV3.h>
 #include <rfb/SMsgWriterV3.h>
-#include <rfb/SSecurity.h>
 #include <rfb/SConnection.h>
 #include <rfb/ServerCore.h>
 
@@ -41,10 +40,11 @@
 const SConnection::AccessRights SConnection::AccessFull       = 0xffff;
 
 
-SConnection::SConnection()
+SConnection::SConnection(SSecurityFactory* secFact, bool reverseConnection_)
   : readyForSetColourMapEntries(false),
     is(0), os(0), reader_(0), writer_(0),
-    nSecTypes(0), security(0), state_(RFBSTATE_UNINITIALISED)
+    security(0), securityFactory(secFact), state_(RFBSTATE_UNINITIALISED),
+    reverseConnection(reverseConnection_)
 {
   defaultMajorVersion = 3;
   defaultMinorVersion = 8;
@@ -74,15 +74,6 @@
   os = os_;
 }
 
-void SConnection::addSecType(rdr::U8 secType)
-{
-  if (nSecTypes == maxSecTypes)
-    throw Exception("too many security types");
-  secTypes[nSecTypes++] = secType;
-  vlog.debug("Offering security type %s(%d)",
-             secTypeName(secType),secType);
-}
-
 void SConnection::initialiseProtocol()
 {
   cp.writeVersion(os);
@@ -144,37 +135,40 @@
 
   versionReceived();
 
+  std::list<rdr::U8> secTypes;
+  std::list<rdr::U8>::iterator i;
+  securityFactory->getSecTypes(&secTypes, reverseConnection);
+
   if (cp.isVersion(3,3)) {
 
     // cope with legacy 3.3 client only if "no authentication" or "vnc
     // authentication" is supported.
-
-    int i;
-    for (i = 0; i < nSecTypes; i++) {
-      if (secTypes[i] == secTypeNone || secTypes[i] == secTypeVncAuth) break;
+    for (i=secTypes.begin(); i!=secTypes.end(); i++) {
+      if (*i == secTypeNone || *i == secTypeVncAuth) break;
     }
-    if (i == nSecTypes) {
+    if (i == secTypes.end()) {
       char msg[256];
       sprintf(msg,"No supported security type for %d.%d client",
               cp.majorVersion, cp.minorVersion);
       throwConnFailedException(msg);
     }
 
-    os->writeU32(secTypes[i]);
-    if (secTypes[i] == secTypeNone) os->flush();
+    os->writeU32(*i);
+    if (*i == secTypeNone) os->flush();
     state_ = RFBSTATE_SECURITY;
-    security = getSSecurity(secTypes[i]);
+    security = securityFactory->getSSecurity(*i, reverseConnection);
     processSecurityMsg();
     return;
   }
 
   // list supported security types for >=3.7 clients
 
-  if (nSecTypes == 0)
+  if (secTypes.empty())
     throwConnFailedException("No supported security types");
 
-  os->writeU8(nSecTypes);
-  os->writeBytes(secTypes, nSecTypes);
+  os->writeU8(secTypes.size());
+  for (i=secTypes.begin(); i!=secTypes.end(); i++)
+    os->writeU8(*i);
   os->flush();
   state_ = RFBSTATE_SECURITY_TYPE;
 }
@@ -186,40 +180,33 @@
   int secType = is->readU8();
   vlog.info("Client requests security type %s(%d)",
             secTypeName(secType),secType);
-  int i;
-  for (i = 0; i < nSecTypes; i++) {
-    if (secType == secTypes[i]) break;
+
+  try {
+    state_ = RFBSTATE_SECURITY;
+    security = securityFactory->getSSecurity(secType, reverseConnection);
+  } catch (rdr::Exception& e) {
+    throwConnFailedException(e.str());
   }
-  if (i == nSecTypes) {
-    char msg[256];
-    sprintf(msg,"Security type %s(%d) from client not supported",
-            secTypeName(secType),secType);
-    throwConnFailedException(msg);
-  }
-  state_ = RFBSTATE_SECURITY;
-  security = getSSecurity(secType);
+
   processSecurityMsg();
 }
 
 void SConnection::processSecurityMsg()
 {
   vlog.debug("processing security message");
-  bool done;
-  bool ok = security->processMsg(this, &done);
-  if (done) {
-    state_ = RFBSTATE_QUERYING;
-    if (ok) {
+  try {
+    bool done = security->processMsg(this);
+    if (done) {
+      state_ = RFBSTATE_QUERYING;
       queryConnection(security->getUserName());
-    } else {
-      const char* failureMsg = security->failureMessage();
-      if (!failureMsg) failureMsg = "Authentication failure";
-      approveConnection(false, failureMsg);
     }
-  }
-  if (!ok) {
-    state_ = RFBSTATE_INVALID;
-    authFailure();
-    throw AuthFailureException();
+  } catch (AuthFailureException& e) {
+    vlog.error("AuthFailureException: %s", e.str());
+    os->writeU32(secResultFailed);
+    if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
+      os->writeString(e.str());
+    os->flush();
+    throw;
   }
 }
 
@@ -264,10 +251,6 @@
 {
 }
 
-void SConnection::authFailure()
-{
-}
-
 void SConnection::queryConnection(const char* userName)
 {
   approveConnection(true);
@@ -298,7 +281,6 @@
     authSuccess();
   } else {
     state_ = RFBSTATE_INVALID;
-    authFailure();
     throw AuthFailureException(reason);
   }
 }