]> source.dussan.org Git - tigervnc.git/commitdiff
Don't abuse auth failure exception
authorPierre Ossman <ossman@cendio.se>
Wed, 7 Aug 2024 08:35:51 +0000 (10:35 +0200)
committerPierre Ossman <ossman@cendio.se>
Wed, 7 Aug 2024 09:02:18 +0000 (11:02 +0200)
This exception is for when the user fails to authenticate, not all
possible errors that might occur during the authentication phase.

Use more appropriate exception types for the various other problems that
might occur, so that we can present things more accurately to the user.

common/rfb/CSecurityDH.cxx
common/rfb/CSecurityMSLogonII.cxx
common/rfb/CSecurityRSAAES.cxx
common/rfb/CSecurityTLS.cxx
common/rfb/CSecurityVeNCrypt.cxx
common/rfb/SSecurityPlain.cxx
common/rfb/SSecurityRSAAES.cxx
common/rfb/SSecurityTLS.cxx
common/rfb/SSecurityVeNCrypt.cxx
common/rfb/SSecurityVncAuth.cxx

index 6d9650bd228bf839fa0db71d1ad314398e8f6439..257977921fe7d1a2377257824f8d5b0e4aec8be5 100644 (file)
@@ -86,9 +86,9 @@ bool CSecurityDH::readKey()
   uint16_t gen = is->readU16();
   keyLength = is->readU16();
   if (keyLength < MinKeyLength)
-    throw AuthFailureException("DH key is too short");
+    throw Exception("DH key is too short");
   if (keyLength > MaxKeyLength)
-    throw AuthFailureException("DH key is too long");
+    throw Exception("DH key is too long");
   if (!is->hasDataOrRestore(keyLength * 2))
     return false;
   is->clearRestorePoint();
@@ -135,10 +135,10 @@ void CSecurityDH::writeCredentials()
     throw ConnFailedException("failed to generate random padding");
   rs.readBytes(buf, 128);
   if (username.size() >= 64)
-    throw AuthFailureException("username is too long");
+    throw Exception("username is too long");
   memcpy(buf, username.c_str(), username.size() + 1);
   if (password.size() >= 64)
-    throw AuthFailureException("password is too long");
+    throw Exception("password is too long");
   memcpy(buf + 64, password.c_str(), password.size() + 1);
   aes128_encrypt(&aesCtx, 128, buf, buf);
 
index e721cdfcfab4aebade8f4769d7ae9b9e49097b04..24bd4cbd50241f043c86a471212cab61bc54d93e 100644 (file)
@@ -127,10 +127,10 @@ void CSecurityMSLogonII::writeCredentials()
   rs.readBytes(user, 256);
   rs.readBytes(pass, 64);
   if (username.size() >= 256)
-    throw AuthFailureException("username is too long");
+    throw Exception("username is too long");
   memcpy(user, username.c_str(), username.size() + 1);
   if (password.size() >= 64)
-    throw AuthFailureException("password is too long");
+    throw Exception("password is too long");
   memcpy(pass, password.c_str(), password.size() + 1);
 
   // DES-CBC with the original key as IV, and the reversed one as the DES key
index 96d96b01ad9130d8063d5e027aac56cb2cb1c910..9b418c648def8fe3dc1109ee3f358a61dcf9bd06 100644 (file)
@@ -156,7 +156,7 @@ void CSecurityRSAAES::writePublicKey()
   if (!rsa_generate_keypair(&clientPublicKey, &clientKey,
                             &rs, random_func, nullptr, nullptr,
                             clientKeyLength, 0))
-    throw AuthFailureException("failed to generate key");
+    throw Exception("failed to generate key");
   clientKeyN = new uint8_t[rsaKeySize];
   clientKeyE = new uint8_t[rsaKeySize];
   nettle_mpz_get_str_256(rsaKeySize, clientKeyN, clientPublicKey.n);
@@ -175,9 +175,9 @@ bool CSecurityRSAAES::readPublicKey()
   is->setRestorePoint();
   serverKeyLength = is->readU32();
   if (serverKeyLength < MinKeyLength)
-    throw AuthFailureException("server key is too short");
+    throw Exception("server key is too short");
   if (serverKeyLength > MaxKeyLength)
-    throw AuthFailureException("server key is too long");
+    throw Exception("server key is too long");
   size_t size = (serverKeyLength + 7) / 8;
   if (!is->hasDataOrRestore(size * 2))
     return false;
@@ -190,7 +190,7 @@ bool CSecurityRSAAES::readPublicKey()
   nettle_mpz_set_str_256_u(serverKey.n, size, serverKeyN);
   nettle_mpz_set_str_256_u(serverKey.e, size, serverKeyE);
   if (!rsa_public_key_prepare(&serverKey))
-    throw AuthFailureException("server key is invalid");
+    throw Exception("server key is invalid");
   return true;
 }
 
@@ -216,7 +216,7 @@ void CSecurityRSAAES::verifyServer()
     "Please verify that the information is correct and press \"Yes\". "
     "Otherwise press \"No\"", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]);
   if (!msg->showMsgBox(UserMsgBox::M_YESNO, title, text.c_str()))
-    throw AuthFailureException("server key mismatch");
+    throw Exception("server key mismatch");
 }
 
 void CSecurityRSAAES::writeRandom()
@@ -237,7 +237,7 @@ void CSecurityRSAAES::writeRandom()
   }
   if (!res) {
     mpz_clear(x);
-    throw AuthFailureException("failed to encrypt random");
+    throw Exception("failed to encrypt random");
   }
   uint8_t* buffer = new uint8_t[serverKey.size];
   nettle_mpz_get_str_256(serverKey.size, buffer, x);
@@ -256,7 +256,7 @@ bool CSecurityRSAAES::readRandom()
   is->setRestorePoint();
   size_t size = is->readU16();
   if (size != clientKey.size)
-    throw AuthFailureException("client key length doesn't match");
+    throw Exception("client key length doesn't match");
   if (!is->hasDataOrRestore(size))
     return false;
   is->clearRestorePoint();
@@ -269,7 +269,7 @@ bool CSecurityRSAAES::readRandom()
   if (!rsa_decrypt(&clientKey, &randomSize, serverRandom, x) ||
       randomSize != (size_t)keySize / 8) {
     mpz_clear(x);
-    throw AuthFailureException("failed to decrypt server random");
+    throw Exception("failed to decrypt server random");
   }
   mpz_clear(x);
   return true;
@@ -398,7 +398,7 @@ bool CSecurityRSAAES::readHash()
     sha256_digest(&ctx, hashSize, realHash);
   }
   if (memcmp(hash, realHash, hashSize) != 0)
-    throw AuthFailureException("hash doesn't match");
+    throw Exception("hash doesn't match");
   return true;
 }
 
@@ -428,7 +428,7 @@ bool CSecurityRSAAES::readSubtype()
     return false;
   subtype = rais->readU8();
   if (subtype != secTypeRA2UserPass && subtype != secTypeRA2Pass)
-    throw AuthFailureException("unknown RSA-AES subtype");
+    throw Exception("unknown RSA-AES subtype");
   return true;
 }
 
@@ -444,7 +444,7 @@ void CSecurityRSAAES::writeCredentials()
 
   if (subtype == secTypeRA2UserPass) {
     if (username.size() > 255)
-      throw AuthFailureException("username is too long");
+      throw Exception("username is too long");
     raos->writeU8(username.size());
     raos->writeBytes((const uint8_t*)username.data(), username.size());
   } else {
@@ -452,7 +452,7 @@ void CSecurityRSAAES::writeCredentials()
   }
 
   if (password.size() > 255)
-    throw AuthFailureException("password is too long");
+    throw Exception("password is too long");
   raos->writeU8(password.size());
   raos->writeBytes((const uint8_t*)password.data(), password.size());
   raos->flush();
index f9775215c06b64880ea6cb29fca10159221cd416..eca1ea7408d7c3120d360b8a78455b72bb329513 100644 (file)
@@ -40,6 +40,7 @@
 #include <rfb/Exception.h>
 #include <rfb/UserMsgBox.h>
 #include <rfb/util.h>
+#include <rdr/TLSException.h>
 #include <rdr/TLSInStream.h>
 #include <rdr/TLSOutStream.h>
 #include <os/os.h>
@@ -88,8 +89,9 @@ CSecurityTLS::CSecurityTLS(CConnection* cc_, bool _anon)
     anon(_anon), tlsis(nullptr), tlsos(nullptr),
     rawis(nullptr), rawos(nullptr)
 {
-  if (gnutls_global_init() != GNUTLS_E_SUCCESS)
-    throw AuthFailureException("gnutls_global_init failed");
+  int err = gnutls_global_init();
+  if (err != GNUTLS_E_SUCCESS)
+    throw rdr::TLSException("gnutls_global_init()", err);
 }
 
 void CSecurityTLS::shutdown()
@@ -149,17 +151,21 @@ bool CSecurityTLS::processMsg()
   client = cc;
 
   if (!session) {
+    int ret;
+
     if (!is->hasData(1))
       return false;
 
     if (is->readU8() == 0)
-      throw AuthFailureException("Server failed to initialize TLS session");
+      throw Exception("Server failed to initialize TLS session");
 
-    if (gnutls_init(&session, GNUTLS_CLIENT) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_init failed");
+    ret = gnutls_init(&session, GNUTLS_CLIENT);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_init()", ret);
 
-    if (gnutls_set_default_priority(session) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_set_default_priority failed");
+    ret = gnutls_set_default_priority(session);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_set_default_priority()", ret);
 
     setParam();
 
@@ -182,7 +188,7 @@ bool CSecurityTLS::processMsg()
 
     vlog.error("TLS Handshake failed: %s\n", gnutls_strerror (err));
     shutdown();
-    throw AuthFailureException("TLS Handshake failed");
+    throw rdr::TLSException("TLS Handshake failed", err);
   }
 
   vlog.debug("TLS handshake completed with %s",
@@ -209,7 +215,7 @@ void CSecurityTLS::setParam()
     prio = (char*)malloc(strlen(Security::GnuTLSPriority) +
                          strlen(kx_anon_priority) + 1);
     if (prio == nullptr)
-      throw AuthFailureException("Not enough memory for GnuTLS priority string");
+      throw Exception("Not enough memory for GnuTLS priority string");
 
     strcpy(prio, Security::GnuTLSPriority);
     if (anon)
@@ -222,7 +228,7 @@ void CSecurityTLS::setParam()
     if (ret != GNUTLS_E_SUCCESS) {
       if (ret == GNUTLS_E_INVALID_REQUEST)
         vlog.error("GnuTLS priority syntax error at: %s", err);
-      throw AuthFailureException("gnutls_set_priority_direct failed");
+      throw rdr::TLSException("gnutls_set_priority_direct()", ret);
     }
   } else if (anon) {
     const char *err;
@@ -234,7 +240,7 @@ void CSecurityTLS::setParam()
     if (ret != GNUTLS_E_SUCCESS) {
       if (ret == GNUTLS_E_INVALID_REQUEST)
         vlog.error("GnuTLS priority syntax error at: %s", err);
-      throw AuthFailureException("gnutls_set_default_priority_append failed");
+      throw rdr::TLSException("gnutls_set_default_priority_append()", ret);
     }
 #else
     // We don't know what the system default priority is, so we guess
@@ -245,7 +251,7 @@ void CSecurityTLS::setParam()
     prio = (char*)malloc(strlen(gnutls_default_priority) +
                          strlen(kx_anon_priority) + 1);
     if (prio == nullptr)
-      throw AuthFailureException("Not enough memory for GnuTLS priority string");
+      throw Exception("Not enough memory for GnuTLS priority string");
 
     strcpy(prio, gnutls_default_priority);
     strcat(prio, kx_anon_priority);
@@ -257,22 +263,25 @@ void CSecurityTLS::setParam()
     if (ret != GNUTLS_E_SUCCESS) {
       if (ret == GNUTLS_E_INVALID_REQUEST)
         vlog.error("GnuTLS priority syntax error at: %s", err);
-      throw AuthFailureException("gnutls_set_priority_direct failed");
+      throw rdr::TLSException("gnutls_set_priority_direct()", ret);
     }
 #endif
   }
 
   if (anon) {
-    if (gnutls_anon_allocate_client_credentials(&anon_cred) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_anon_allocate_client_credentials failed");
+    ret = gnutls_anon_allocate_client_credentials(&anon_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_anon_allocate_client_credentials()", ret);
 
-    if (gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_credentials_set failed");
+    ret = gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_credentials_set()", ret);
 
     vlog.debug("Anonymous session has been set");
   } else {
-    if (gnutls_certificate_allocate_credentials(&cert_cred) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_certificate_allocate_credentials failed");
+    ret = gnutls_certificate_allocate_credentials(&cert_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_certificate_allocate_credentials()", ret);
 
     if (gnutls_certificate_set_x509_system_trust(cert_cred) < 1)
       vlog.error("Could not load system certificate trust store");
@@ -283,8 +292,9 @@ void CSecurityTLS::setParam()
     if (gnutls_certificate_set_x509_crl_file(cert_cred, X509CRL, GNUTLS_X509_FMT_PEM) < 0)
       vlog.error("Could not load user specified certificate revocation list");
 
-    if (gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_credentials_set failed");
+    ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_credentials_set()", ret);
 
     if (gnutls_server_name_set(session, GNUTLS_NAME_DNS,
                                client->getServerName(),
@@ -306,7 +316,7 @@ void CSecurityTLS::checkSession()
   unsigned int status;
   const gnutls_datum_t *cert_list;
   unsigned int cert_list_size = 0;
-  int err;
+  int err, known;
   bool hostname_match;
 
   const char *hostsDir;
@@ -317,12 +327,12 @@ void CSecurityTLS::checkSession()
     return;
 
   if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
-    throw AuthFailureException("unsupported certificate type");
+    throw Exception("unsupported certificate type");
 
   err = gnutls_certificate_verify_peers2(session, &status);
   if (err != 0) {
     vlog.error("server certificate verification failed: %s", gnutls_strerror(err));
-    throw AuthFailureException("server certificate verification failed");
+    throw rdr::TLSException("server certificate verification()", err);
   }
 
   if (status != 0) {
@@ -340,11 +350,11 @@ void CSecurityTLS::checkSession()
                                                        0) < 0)
         throw Exception("Failed to get certificate error description");
 
-      error = format("Invalid server certificate: %s", status_str.data);
+      error = (const char*)status_str.data;
 
       gnutls_free(status_str.data);
 
-      throw AuthFailureException(error.c_str());
+      throw Exception("Invalid server certificate: %s", error.c_str());
     }
 
     if (gnutls_certificate_verification_status_print(status,
@@ -362,14 +372,14 @@ void CSecurityTLS::checkSession()
 
   cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
   if (!cert_list_size)
-    throw AuthFailureException("empty certificate chain");
+    throw Exception("empty certificate chain");
 
   /* Process only server's certificate, not issuer's certificate */
   gnutls_x509_crt_t crt;
   gnutls_x509_crt_init(&crt);
 
   if (gnutls_x509_crt_import(crt, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
-    throw AuthFailureException("decoding of certificate failed");
+    throw Exception("decoding of certificate failed");
 
   if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) {
     vlog.info("Server certificate doesn't match given server name");
@@ -388,31 +398,32 @@ void CSecurityTLS::checkSession()
 
   hostsDir = os::getvncstatedir();
   if (hostsDir == nullptr) {
-    throw AuthFailureException("Could not obtain VNC state directory "
-                               "path for known hosts storage");
+    throw Exception("Could not obtain VNC state directory path for "
+                    "known hosts storage");
   }
 
   std::string dbPath;
   dbPath = (std::string)hostsDir + "/x509_known_hosts";
 
-  err = gnutls_verify_stored_pubkey(dbPath.c_str(), nullptr,
-                                    client->getServerName(), nullptr,
-                                    GNUTLS_CRT_X509, &cert_list[0], 0);
+  known = gnutls_verify_stored_pubkey(dbPath.c_str(), nullptr,
+                                      client->getServerName(), nullptr,
+                                      GNUTLS_CRT_X509, &cert_list[0], 0);
 
   /* Previously known? */
-  if (err == GNUTLS_E_SUCCESS) {
+  if (known == GNUTLS_E_SUCCESS) {
     vlog.info("Server certificate found in known hosts file");
     gnutls_x509_crt_deinit(crt);
     return;
   }
 
-  if ((err != GNUTLS_E_NO_CERTIFICATE_FOUND) &&
-      (err != GNUTLS_E_CERTIFICATE_KEY_MISMATCH)) {
-    throw AuthFailureException("Could not load known hosts database");
+  if ((known != GNUTLS_E_NO_CERTIFICATE_FOUND) &&
+      (known != GNUTLS_E_CERTIFICATE_KEY_MISMATCH)) {
+    throw rdr::TLSException("Could not load known hosts database", known);
   }
 
-  if (gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info))
-    throw AuthFailureException("Could not find certificate to display");
+  err = gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info);
+  if (err != GNUTLS_E_SUCCESS)
+    throw rdr::TLSException("Could not find certificate to display", err);
 
   len = strlen((char*)info.data);
   for (size_t i = 0; i < len - 1; i++) {
@@ -421,7 +432,7 @@ void CSecurityTLS::checkSession()
   }
 
   /* New host */
-  if (err == GNUTLS_E_NO_CERTIFICATE_FOUND) {
+  if (known == GNUTLS_E_NO_CERTIFICATE_FOUND) {
     std::string text;
 
     vlog.info("Server host not previously known");
@@ -510,7 +521,7 @@ void CSecurityTLS::checkSession()
 
     if (status != 0) {
       vlog.error("Unhandled certificate problems: 0x%x", status);
-      throw AuthFailureException("Unhandled certificate problems");
+      throw Exception("Unhandled certificate problems");
     }
 
     if (!hostname_match) {
@@ -530,7 +541,7 @@ void CSecurityTLS::checkSession()
                            text.c_str()))
         throw AuthCancelledException();
     }
-  } else if (err == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
+  } else if (known == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
     std::string text;
 
     vlog.info("Server host key mismatch");
@@ -626,7 +637,7 @@ void CSecurityTLS::checkSession()
 
     if (status != 0) {
       vlog.error("Unhandled certificate problems: 0x%x", status);
-      throw AuthFailureException("Unhandled certificate problems");
+      throw Exception("Unhandled certificate problems");
     }
 
     if (!hostname_match) {
index 19dcabc33c239d9809f279d54f63a35b1c31a688..d63549762bbe0af26ac384b330a1ad351615dc17 100644 (file)
@@ -107,7 +107,7 @@ bool CSecurityVeNCrypt::processMsg()
       os->writeU8(0);
       os->writeU8(0);
       os->flush();
-      throw AuthFailureException("The server reported an unsupported VeNCrypt version");
+      throw Exception("The server reported an unsupported VeNCrypt version");
      }
 
      haveSentVersion = true;
@@ -119,8 +119,8 @@ bool CSecurityVeNCrypt::processMsg()
       return false;
 
     if (is->readU8())
-      throw AuthFailureException("The server reported it could not support the "
-                                "VeNCrypt version");
+      throw Exception("The server reported it could not support the "
+                      "VeNCrypt version");
 
     haveAgreedVersion = true;
   }
@@ -133,7 +133,7 @@ bool CSecurityVeNCrypt::processMsg()
     nAvailableTypes = is->readU8();
 
     if (!nAvailableTypes)
-      throw AuthFailureException("The server reported no VeNCrypt sub-types");
+      throw Exception("The server reported no VeNCrypt sub-types");
 
     availableTypes = new uint32_t[nAvailableTypes];
     haveNumberOfTypes = true;
@@ -174,7 +174,7 @@ bool CSecurityVeNCrypt::processMsg()
 
       /* Set up the stack according to the chosen type: */
       if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
-       throw AuthFailureException("No valid VeNCrypt sub-type");
+        throw Exception("No valid VeNCrypt sub-type");
 
       vlog.info("Choosing security type %s (%d)", secTypeName(chosenType),
                 chosenType);
@@ -193,7 +193,7 @@ bool CSecurityVeNCrypt::processMsg()
      * happen, since if the server supports 0 sub-types, it doesn't support
      * this security type
      */
-    throw AuthFailureException("The server reported 0 VeNCrypt sub-types");
+    throw Exception("The server reported 0 VeNCrypt sub-types");
   }
 
   return csecurity->processMsg();
index 69c6d9ca97b1e5ae2ae5a3327b8c87013336237a..e009de39e15881d84560f0b7fb97b6eb1cd1ca04 100644 (file)
@@ -87,7 +87,7 @@ bool SSecurityPlain::processMsg()
   char password[1024];
 
   if (!valid)
-    throw AuthFailureException("No password validator configured");
+    throw Exception("No password validator configured");
 
   if (state == 0) {
     if (!is->hasData(8))
index 4aa3911108e9324345f615d369ca833ab12188eb..530dca16c8d18f21431b4072da0dec99fca7ddf7 100644 (file)
@@ -565,7 +565,7 @@ void SSecurityRSAAES::verifyUserPass()
   }
   delete valid;
 #else
-  throw AuthFailureException("No password validator configured");
+  throw Exception("No password validator configured");
 #endif
 }
 
@@ -576,7 +576,7 @@ void SSecurityRSAAES::verifyPass()
   pg->getVncAuthPasswd(&passwd, &passwdReadOnly);
 
   if (passwd.empty())
-    throw AuthFailureException("No password configured for VNC Auth");
+    throw Exception("No password configured");
 
   if (password == passwd) {
     accessRights = AccessDefault;
index e2b82f898eaee02ccabdfac3656d45c5ead40ff6..67dced6c0d6f91b57936d5a1576473653d59c892 100644 (file)
@@ -34,6 +34,7 @@
 #include <rfb/SConnection.h>
 #include <rfb/LogWriter.h>
 #include <rfb/Exception.h>
+#include <rdr/TLSException.h>
 #include <rdr/TLSInStream.h>
 #include <rdr/TLSOutStream.h>
 #include <gnutls/x509.h>
@@ -71,12 +72,15 @@ SSecurityTLS::SSecurityTLS(SConnection* sc_, bool _anon)
     cert_cred(nullptr), anon(_anon), tlsis(nullptr), tlsos(nullptr),
     rawis(nullptr), rawos(nullptr)
 {
+  int ret;
+
 #if defined (SSECURITYTLS__USE_DEPRECATED_DH)
   dh_params = nullptr;
 #endif
 
-  if (gnutls_global_init() != GNUTLS_E_SUCCESS)
-    throw AuthFailureException("gnutls_global_init failed");
+  ret = gnutls_global_init();
+  if (ret != GNUTLS_E_SUCCESS)
+    throw rdr::TLSException("gnutls_global_init()", ret);
 }
 
 void SSecurityTLS::shutdown()
@@ -138,17 +142,21 @@ SSecurityTLS::~SSecurityTLS()
 
 bool SSecurityTLS::processMsg()
 {
+  int err;
+
   vlog.debug("Process security message (session %p)", session);
 
   if (!session) {
     rdr::InStream* is = sc->getInStream();
     rdr::OutStream* os = sc->getOutStream();
 
-    if (gnutls_init(&session, GNUTLS_SERVER) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_init failed");
+    err = gnutls_init(&session, GNUTLS_SERVER);
+    if (err != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_init()", err);
 
-    if (gnutls_set_default_priority(session) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_set_default_priority failed");
+    err = gnutls_set_default_priority(session);
+    if (err != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_set_default_priority()", err);
 
     try {
       setParams();
@@ -170,7 +178,6 @@ bool SSecurityTLS::processMsg()
     rawos = os;
   }
 
-  int err;
   err = gnutls_handshake(session);
   if (err != GNUTLS_E_SUCCESS) {
     if (!gnutls_error_is_fatal(err)) {
@@ -179,7 +186,7 @@ bool SSecurityTLS::processMsg()
     }
     vlog.error("TLS Handshake failed: %s", gnutls_strerror (err));
     shutdown();
-    throw AuthFailureException("TLS Handshake failed");
+    throw rdr::TLSException("TLS Handshake failed", err);
   }
 
   vlog.debug("TLS handshake completed with %s",
@@ -204,7 +211,7 @@ void SSecurityTLS::setParams()
     prio = (char*)malloc(strlen(Security::GnuTLSPriority) +
                          strlen(kx_anon_priority) + 1);
     if (prio == nullptr)
-      throw AuthFailureException("Not enough memory for GnuTLS priority string");
+      throw Exception("Not enough memory for GnuTLS priority string");
 
     strcpy(prio, Security::GnuTLSPriority);
     if (anon)
@@ -217,7 +224,7 @@ void SSecurityTLS::setParams()
     if (ret != GNUTLS_E_SUCCESS) {
       if (ret == GNUTLS_E_INVALID_REQUEST)
         vlog.error("GnuTLS priority syntax error at: %s", err);
-      throw AuthFailureException("gnutls_set_priority_direct failed");
+      throw rdr::TLSException("gnutls_set_priority_direct()", ret);
     }
   } else if (anon) {
     const char *err;
@@ -229,7 +236,7 @@ void SSecurityTLS::setParams()
     if (ret != GNUTLS_E_SUCCESS) {
       if (ret == GNUTLS_E_INVALID_REQUEST)
         vlog.error("GnuTLS priority syntax error at: %s", err);
-      throw AuthFailureException("gnutls_set_default_priority_append failed");
+      throw rdr::TLSException("gnutls_set_default_priority_append()", ret);
     }
 #else
     // We don't know what the system default priority is, so we guess
@@ -240,7 +247,7 @@ void SSecurityTLS::setParams()
     prio = (char*)malloc(strlen(gnutls_default_priority) +
                          strlen(kx_anon_priority) + 1);
     if (prio == nullptr)
-      throw AuthFailureException("Not enough memory for GnuTLS priority string");
+      throw Exception("Not enough memory for GnuTLS priority string");
 
     strcpy(prio, gnutls_default_priority);
     strcat(prio, kx_anon_priority);
@@ -252,36 +259,41 @@ void SSecurityTLS::setParams()
     if (ret != GNUTLS_E_SUCCESS) {
       if (ret == GNUTLS_E_INVALID_REQUEST)
         vlog.error("GnuTLS priority syntax error at: %s", err);
-      throw AuthFailureException("gnutls_set_priority_direct failed");
+      throw rdr::TLSException("gnutls_set_priority_direct()", ret);
     }
 #endif
   }
 
 #if defined (SSECURITYTLS__USE_DEPRECATED_DH)
-  if (gnutls_dh_params_init(&dh_params) != GNUTLS_E_SUCCESS)
-    throw AuthFailureException("gnutls_dh_params_init failed");
-
-  if (gnutls_dh_params_import_pkcs3(dh_params, &ffdhe_pkcs3_param, GNUTLS_X509_FMT_PEM) != GNUTLS_E_SUCCESS)
-    throw AuthFailureException("gnutls_dh_params_import_pkcs3 failed");
+  ret = gnutls_dh_params_init(&dh_params);
+  if (ret != GNUTLS_E_SUCCESS)
+    throw rdr::TLSException("gnutls_dh_params_init()", ret);
+
+  ret = gnutls_dh_params_import_pkcs3(dh_params, &ffdhe_pkcs3_param,
+                                      GNUTLS_X509_FMT_PEM);
+  if (ret != GNUTLS_E_SUCCESS)
+    throw rdr::TLSException("gnutls_dh_params_import_pkcs3()", ret);
 #endif
 
   if (anon) {
-    if (gnutls_anon_allocate_server_credentials(&anon_cred) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_anon_allocate_server_credentials failed");
+    ret = gnutls_anon_allocate_server_credentials(&anon_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_anon_allocate_server_credentials()", ret);
 
 #if defined (SSECURITYTLS__USE_DEPRECATED_DH)
     gnutls_anon_set_server_dh_params(anon_cred, dh_params);
 #endif
 
-    if (gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred)
-        != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_credentials_set failed");
+    ret = gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_credentials_set()", ret);
 
     vlog.debug("Anonymous session has been set");
 
   } else {
-    if (gnutls_certificate_allocate_credentials(&cert_cred) != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_certificate_allocate_credentials failed");
+    ret = gnutls_certificate_allocate_credentials(&cert_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_certificate_allocate_credentials()", ret);
 
 #if defined (SSECURITYTLS__USE_DEPRECATED_DH)
     gnutls_certificate_set_dh_params(cert_cred, dh_params);
@@ -291,16 +303,16 @@ void SSecurityTLS::setParams()
     case GNUTLS_E_SUCCESS:
       break;
     case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
-      throw AuthFailureException("Private key does not match certificate");
+      throw Exception("Private key does not match certificate");
     case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
-      throw AuthFailureException("Unsupported certificate type");
+      throw Exception("Unsupported certificate type");
     default:
-      throw AuthFailureException("Error loading X509 certificate or key");
+      throw Exception("Error loading X509 certificate or key");
     }
 
-    if (gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred)
-        != GNUTLS_E_SUCCESS)
-      throw AuthFailureException("gnutls_credentials_set failed");
+    ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred);
+    if (ret != GNUTLS_E_SUCCESS)
+      throw rdr::TLSException("gnutls_credentials_set()", ret);
 
     vlog.debug("X509 session has been set");
 
index ce160503b38e388ff011c0ae3fa55e925a7027aa..27ee1fe229a3447b8d2a34c311ff5fd53f430bb2 100644 (file)
@@ -101,8 +101,8 @@ bool SSecurityVeNCrypt::processMsg()
     case 0x0001: /* 0.1 Legacy VeNCrypt, not supported */
       os->writeU8(0xFF); /* This is not OK */
       os->flush();
-      throw AuthFailureException("The client cannot support the server's "
-                                "VeNCrypt version");
+      throw Exception("The client cannot support the server's "
+                       "VeNCrypt version");
 
     case 0x0002: /* 0.2 */
       os->writeU8(0); /* OK */
@@ -111,7 +111,7 @@ bool SSecurityVeNCrypt::processMsg()
     default:
       os->writeU8(0xFF); /* Not OK */
       os->flush();
-      throw AuthFailureException("The client returned an unsupported VeNCrypt version");
+      throw Exception("The client returned an unsupported VeNCrypt version");
     }
   }
 
@@ -140,7 +140,7 @@ bool SSecurityVeNCrypt::processMsg()
       os->flush(); 
       haveSentTypes = true;
     } else
-      throw AuthFailureException("There are no VeNCrypt sub-types to send to the client");
+      throw Exception("There are no VeNCrypt sub-types to send to the client");
   }
 
   /* get type back from client (must be one of the ones we sent) */
@@ -165,7 +165,7 @@ bool SSecurityVeNCrypt::processMsg()
 
     /* Set up the stack according to the chosen type */
     if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
-      throw AuthFailureException("No valid VeNCrypt sub-type");
+      throw Exception("No valid VeNCrypt sub-type");
 
     ssecurity = security->GetSSecurity(sc, chosenType);
   }
index 500903a80b8ebc48f79616dd39d7755740982e4f..272c7ca1ecc880d2ea1286a773ca13dbc7bb5221 100644 (file)
@@ -100,7 +100,7 @@ bool SSecurityVncAuth::processMsg()
   pg->getVncAuthPasswd(&passwd, &passwdReadOnly);
 
   if (passwd.empty())
-    throw AuthFailureException("No password configured for VNC Auth");
+    throw Exception("No password configured");
 
   if (verifyResponse(passwd.c_str())) {
     accessRights = AccessDefault;