Revision: 4198
          http://tigervnc.svn.sourceforge.net/tigervnc/?rev=4198&view=rev
Author:   atkac
Date:     2010-11-18 13:33:57 +0000 (Thu, 18 Nov 2010)

Log Message:
-----------
[Development] client: Add dialog window to accept/save invalid X509
certificates. (Guillaume Destuynder)

Modified Paths:
--------------
    trunk/common/rfb/CSecurityTLS.cxx
    trunk/common/rfb/CSecurityTLS.h
    trunk/common/rfb/SecurityClient.cxx
    trunk/common/rfb/SecurityClient.h
    trunk/common/rfb/UserMsgBox.h
    trunk/unix/vncviewer/CConn.cxx
    trunk/unix/vncviewer/CConn.h
    trunk/unix/vncviewer/vncviewer.cxx

Modified: trunk/common/rfb/CSecurityTLS.cxx
===================================================================
--- trunk/common/rfb/CSecurityTLS.cxx   2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/common/rfb/CSecurityTLS.cxx   2010-11-18 13:33:57 UTC (rev 4198)
@@ -2,6 +2,7 @@
  * Copyright (C) 2004 Red Hat Inc.
  * Copyright (C) 2005 Martin Koegler
  * Copyright (C) 2010 TigerVNC Team
+ * Copyright (C) 2010 m-privacy GmbH
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,13 +28,18 @@
 #error "This header should not be compiled without HAVE_GNUTLS defined"
 #endif
 
+#include <stdlib.h>
+#include <unistd.h>
+
 #include <rfb/CSecurityTLS.h>
 #include <rfb/SSecurityVeNCrypt.h> 
 #include <rfb/CConnection.h>
 #include <rfb/LogWriter.h>
 #include <rfb/Exception.h>
+#include <rfb/UserMsgBox.h>
 #include <rdr/TLSInStream.h>
 #include <rdr/TLSOutStream.h>
+#include <os/os.h>
 
 #include <gnutls/x509.h>
 
@@ -76,6 +82,26 @@
   crlfile = x509crl.getData();
 }
 
+void CSecurityTLS::setDefaults()
+{
+  char* homeDir = NULL;
+
+  if (gethomedir(&homeDir) == -1) {
+    vlog.error("Could not obtain home directory path");
+    return;
+  }
+
+  CharArray caDefault(strlen(homeDir)+17);
+  sprintf(caDefault.buf, "%s/.vnc/x509_certs", homeDir);
+  delete [] homeDir;
+
+  /* XXX Do we need access() check here? */
+  if (!access(caDefault.buf, R_OK))
+    x509ca.setDefaultStr(strdup(caDefault.buf));
+  else
+    vlog.error("Failed to open ~/.vnc/x509_certs");
+}
+
 void CSecurityTLS::shutdown()
 {
   if (session)
@@ -206,6 +232,7 @@
   const gnutls_datum *cert_list;
   unsigned int cert_list_size = 0;
   unsigned int i;
+  gnutls_datum_t info;
 
   if (anon)
     return;
@@ -226,25 +253,108 @@
     throw AuthFailureException("certificate verification failed");
   }
 
-  if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
-    throw AuthFailureException("certificate issuer unknown");
+  if (status & GNUTLS_CERT_REVOKED) {
+    throw AuthFailureException("certificate has been revoked");
+  }
 
-  if (status & GNUTLS_CERT_INVALID)
-    throw AuthFailureException("certificate not trusted");
+  if (status & GNUTLS_CERT_NOT_ACTIVATED) {
+    throw AuthFailureException("certificate has not been activated");
+  }
 
   for (i = 0; i < cert_list_size; i++) {
     gnutls_x509_crt crt;
     gnutls_x509_crt_init(&crt);
 
     if (gnutls_x509_crt_import(crt, &cert_list[i],GNUTLS_X509_FMT_DER) < 0)
-      throw AuthFailureException("Decoding of certificate failed");
+      throw AuthFailureException("decoding of certificate failed");
 
+    if (gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info)) {
+        gnutls_free(info.data);
+       throw AuthFailureException("Could not find certificate to display");
+    }
+
     if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) {
-#if 0
-      throw AuthFailureException("Hostname mismatch"); /* Non-fatal for now... 
*/
-#endif
+      char buf[255];
+      sprintf(buf, "Hostname (%s) does not match any certificate, do you want 
to continue?", client->getServerName());
+      vlog.debug("hostname mismatch");
+      if(!msg->showMsgBox(UserMsgBox::M_YESNO, "hostname mismatch", buf))
+        throw AuthFailureException("hostname mismatch");
     }
+
+    if (status & GNUTLS_CERT_EXPIRED) {
+      vlog.debug("certificate has expired");
+      if (!msg->showMsgBox(UserMsgBox::M_YESNO, "certficate has expired", "The 
certificate of the server has expired, do you want to continue?"))
+        throw AuthFailureException("certificate has expired");
+    }
+
+    if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
+      size_t out_size;
+      char *homeDir = NULL;
+      char *out_buf = NULL;
+      char *certinfo = NULL;
+      int len = 0;
+
+      vlog.debug("certificate issuer unknown");
+
+      len = snprintf(NULL, 0, "This certificate has been signed by an unknown 
authority:\n\n%s\n\nDo you want to save it and continue?\n ", info.data);
+      if (len < 0)
+        AuthFailureException("certificate decoding error");
+
+      vlog.debug("%s", info.data);
+
+      certinfo = new char[len];
+      if (certinfo == NULL)
+        throw AuthFailureException("Out of memory");
+
+      snprintf(certinfo, len, "This certificate has been signed by an unknown 
authority:\n\n%s\n\nDo you want to save it and continue? ", info.data);
+
+      for (int i = 0; i < len - 1; i++)
+        if (certinfo[i] == ',' && certinfo[i + 1] == ' ')
+               certinfo[i] = '\n';
+
+     if (!msg->showMsgBox(UserMsgBox::M_YESNO, "certificate issuer unknown",
+                         certinfo)) {
+        delete [] certinfo;
+       throw AuthFailureException("certificate issuer unknown");
+      }
+      delete [] certinfo;
+
+      if (gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, NULL, &out_size)
+         == GNUTLS_E_SHORT_MEMORY_BUFFER)
+        AuthFailureException("Out of memory");
+
+      // Save cert
+      out_buf =  new char[out_size];
+      if (out_buf == NULL)
+        AuthFailureException("Out of memory");
+
+      if (gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, out_buf, &out_size)
+         < 0)
+        AuthFailureException("certificate issuer unknown, and certificate "
+                            "export failed");
+      
+      if (gethomedir(&homeDir) == -1)
+        vlog.error("Could not obtain home directory path");
+      else {
+       FILE *f;
+        CharArray caSave(strlen(homeDir)+17);
+       sprintf(caSave.buf, "%s/.vnc/x509_certs", homeDir);
+       delete [] homeDir;
+               f = fopen(caSave.buf, "a+");
+       if (!f)
+          msg->showMsgBox(UserMsgBox::M_OK, "certificate save failed",
+                         "Could not save the certificate");
+       else {
+          fprintf(f, "%s\n", out_buf);
+         fclose(f);
+       }
+      }
+      delete [] out_buf;
+    } else if (status & GNUTLS_CERT_INVALID)
+        throw AuthFailureException("certificate not trusted");
+
     gnutls_x509_crt_deinit(crt);
+    gnutls_free(info.data);
   }
 }
 

Modified: trunk/common/rfb/CSecurityTLS.h
===================================================================
--- trunk/common/rfb/CSecurityTLS.h     2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/common/rfb/CSecurityTLS.h     2010-11-18 13:33:57 UTC (rev 4198)
@@ -33,11 +33,13 @@
 #include <rfb/CSecurity.h>
 #include <rfb/SSecurityVeNCrypt.h>
 #include <rfb/Security.h>
+#include <rfb/UserMsgBox.h>
 #include <rdr/InStream.h>
 #include <rdr/OutStream.h>
 #include <gnutls/gnutls.h>
 
 namespace rfb {
+  class UserMsgBox;
   class CSecurityTLS : public CSecurity {
   public:
     CSecurityTLS(bool _anon);
@@ -46,9 +48,11 @@
     virtual int getType() const { return anon ? secTypeTLSNone : 
secTypeX509None; }
     virtual const char* description() const
       { return anon ? "TLS Encryption without VncAuth" : "X509 Encryption 
without VncAuth"; }
+    static void setDefaults();
 
     static StringParameter x509ca;
     static StringParameter x509crl;
+    static UserMsgBox *msg;
 
   protected:
     void shutdown();

Modified: trunk/common/rfb/SecurityClient.cxx
===================================================================
--- trunk/common/rfb/SecurityClient.cxx 2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/common/rfb/SecurityClient.cxx 2010-11-18 13:33:57 UTC (rev 4198)
@@ -37,6 +37,9 @@
 using namespace rfb;
 
 UserPasswdGetter *CSecurity::upg = NULL;
+#ifdef HAVE_GNUTLS
+UserMsgBox *CSecurityTLS::msg = NULL;
+#endif
 
 StringParameter SecurityClient::secTypes
 ("SecurityTypes",
@@ -51,6 +54,9 @@
 CSecurity* SecurityClient::GetCSecurity(U32 secType)
 {
   assert (CSecurity::upg != NULL); /* (upg == NULL) means bug in the viewer */
+#ifdef HAVE_GNUTLS
+  assert (CSecurityTLS::msg != NULL);
+#endif
 
   if (!IsSupported(secType))
     goto bail;
@@ -86,3 +92,9 @@
   throw Exception("Security type not supported");
 }
 
+void SecurityClient::setDefaults()
+{
+#ifdef HAVE_GNUTLS
+    CSecurityTLS::setDefaults();
+#endif
+}

Modified: trunk/common/rfb/SecurityClient.h
===================================================================
--- trunk/common/rfb/SecurityClient.h   2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/common/rfb/SecurityClient.h   2010-11-18 13:33:57 UTC (rev 4198)
@@ -35,6 +35,8 @@
     /* Create client side CSecurity class instance */
     CSecurity* GetCSecurity(rdr::U32 secType);
 
+    static void setDefaults(void);
+
     static StringParameter secTypes;
   };
 

Modified: trunk/common/rfb/UserMsgBox.h
===================================================================
--- trunk/common/rfb/UserMsgBox.h       2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/common/rfb/UserMsgBox.h       2010-11-18 13:33:57 UTC (rev 4198)
@@ -33,6 +33,7 @@
       M_DEFBUTTON1 = 0,
       M_DEFBUTTON2 = 0x100
     };
+    /* TODO Implement as function with variable arguments */
     virtual bool showMsgBox(int flags,const char* title, const char* text)=0;
   };
 }

Modified: trunk/unix/vncviewer/CConn.cxx
===================================================================
--- trunk/unix/vncviewer/CConn.cxx      2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/unix/vncviewer/CConn.cxx      2010-11-18 13:33:57 UTC (rev 4198)
@@ -75,7 +75,10 @@
   menuKeysym = XStringToKeysym(menuKeyStr.buf);
 
   setShared(shared);
-  CSecurity::upg = this; /* Security instance is created in CConnection 
costructor. */
+  CSecurity::upg = this; /* Security instance is created in CConnection 
constructor. */
+#ifdef HAVE_GNUTLS
+  CSecurityTLS::msg = this;
+#endif
 
   CharArray encStr(preferredEncoding.getData());
   int encNum = encodingNum(encStr.buf);
@@ -125,6 +128,15 @@
   delete sock;
 }
 
+bool CConn::showMsgBox(int flags, const char* title, const char* text)
+{
+  CharArray titleText(strlen(title) + 12);
+  sprintf(titleText.buf, "VNC Viewer: %s", title);
+
+  TXMsgBox msgBox(dpy,text,flags,titleText.buf);
+  return msgBox.show();
+}
+
 // deleteWindow() is called when the user closes the desktop or menu windows.
 
 void CConn::deleteWindow(TXWindow* w) {
@@ -232,7 +244,6 @@
   *password = strDup(dlg.passwdEntry.getText());
 }
 
-
 // CConnection callback methods
 
 // serverInit() is called when the serverInit message has been received.  At

Modified: trunk/unix/vncviewer/CConn.h
===================================================================
--- trunk/unix/vncviewer/CConn.h        2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/unix/vncviewer/CConn.h        2010-11-18 13:33:57 UTC (rev 4198)
@@ -26,6 +26,7 @@
 #include <rfb/CConnection.h>
 #include <rfb/Exception.h>
 #include <rfb/UserPasswdGetter.h>
+#include <rfb/UserMsgBox.h>
 #include <rdr/FdInStream.h>
 #include <list>
 
@@ -44,7 +45,7 @@
               public TXDeleteWindowCallback,
               public rdr::FdInStreamBlockCallback,
               public TXMenuCallback , public OptionsDialogCallback,
-              public TXEventHandler
+              public TXEventHandler, public rfb::UserMsgBox
 {
 public:
 
@@ -61,6 +62,9 @@
   // UserPasswdGetter methods
   virtual void getUserPasswd(char** user, char** password);
 
+  // UserMsgBox methods
+  virtual bool showMsgBox(int flags, const char* title, const char* text);
+
   // TXMenuCallback methods
   void menuSelect(long id, TXMenu* m);
 

Modified: trunk/unix/vncviewer/vncviewer.cxx
===================================================================
--- trunk/unix/vncviewer/vncviewer.cxx  2010-11-18 12:08:35 UTC (rev 4197)
+++ trunk/unix/vncviewer/vncviewer.cxx  2010-11-18 13:33:57 UTC (rev 4198)
@@ -33,6 +33,7 @@
 #include <locale.h>
 #include <os/os.h>
 #include <rfb/Logger_stdio.h>
+#include <rfb/SecurityClient.h>
 #include <rfb/LogWriter.h>
 #include <network/TcpSocket.h>
 #include "TXWindow.h"
@@ -278,6 +279,8 @@
                                 "Copyright (C) 2004-2009 Peter Astrand for 
Cendio AB\n"
                                 "See http://www.tigervnc.org for information 
on TigerVNC.");
 
+  rfb::SecurityClient::setDefaults();
+
   // Write about text to console, still using normal locale codeset
   snprintf(aboutText, sizeof(aboutText),
           gettext(englishAbout), PACKAGE_VERSION, buildtime);


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev
_______________________________________________
Tigervnc-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tigervnc-commits

Reply via email to