From 0e61c34932211b0f230f3a04000e81feb1382604 Mon Sep 17 00:00:00 2001 From: Adam Tkac Date: Wed, 21 Jul 2010 09:23:25 +0000 Subject: [PATCH] [Development] Merge CSecurityTLS and CSecurityX509 classes into CSecurityTLSBase class. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4109 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- common/rfb/CSecurityTLS.cxx | 66 ---------------- common/rfb/CSecurityTLS.h | 53 ------------- common/rfb/CSecurityTLSBase.cxx | 131 +++++++++++++++++++++++++++----- common/rfb/CSecurityTLSBase.h | 20 ++++- common/rfb/CSecurityX509.cxx | 127 ------------------------------- common/rfb/CSecurityX509.h | 59 -------------- common/rfb/Makefile.am | 6 +- common/rfb/Security.cxx | 11 ++- 8 files changed, 137 insertions(+), 336 deletions(-) delete mode 100644 common/rfb/CSecurityTLS.cxx delete mode 100644 common/rfb/CSecurityTLS.h delete mode 100644 common/rfb/CSecurityX509.cxx delete mode 100644 common/rfb/CSecurityX509.h diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx deleted file mode 100644 index ae095fae..00000000 --- a/common/rfb/CSecurityTLS.cxx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2004 Red Hat Inc. - * Copyright (C) 2005 Martin Koegler - * Copyright (C) 2010 TigerVNC Team - * - * 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_CONFIG_H -#include -#endif - -#ifndef HAVE_GNUTLS -#error "This source should not be compiled without HAVE_GNUTLS defined" -#endif - -#include - -using namespace rfb; - -CSecurityTLS::CSecurityTLS() : anon_cred(0) -{ -} - -CSecurityTLS::~CSecurityTLS() -{ - shutdown(); - if (anon_cred) - gnutls_anon_free_client_credentials (anon_cred); -} - - -void CSecurityTLS::freeResources() -{ - if (anon_cred) - gnutls_anon_free_client_credentials(anon_cred); - anon_cred=0; - } - -void CSecurityTLS::setParam(gnutls_session 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); -} - -void CSecurityTLS::checkSession(gnutls_session session) -{ - -} - diff --git a/common/rfb/CSecurityTLS.h b/common/rfb/CSecurityTLS.h deleted file mode 100644 index 9e5ed72c..00000000 --- a/common/rfb/CSecurityTLS.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2004 Red Hat Inc. - * Copyright (C) 2005 Martin Koegler - * Copyright (C) 2010 TigerVNC Team - * - * 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_CONFIG_H -#include -#endif - -#ifndef HAVE_GNUTLS -#error "This header should not be included without HAVE_GNUTLS defined" -#endif - -#include -#include - -namespace rfb { - class CSecurityTLS : public CSecurityTLSBase { - public: - CSecurityTLS(); - virtual ~CSecurityTLS(); - virtual int getType() const { return secTypeTLSNone; }; - virtual const char* description() const { return "TLS Encryption without VncAuth"; } - protected: - virtual void freeResources(); - virtual void setParam(gnutls_session session); - virtual void checkSession(gnutls_session session); - - private: - gnutls_anon_client_credentials anon_cred; - }; -} - -#endif /* __C_SECURITY_TLS_H__ */ diff --git a/common/rfb/CSecurityTLSBase.cxx b/common/rfb/CSecurityTLSBase.cxx index 289015ad..bc9d3f52 100644 --- a/common/rfb/CSecurityTLSBase.cxx +++ b/common/rfb/CSecurityTLSBase.cxx @@ -28,16 +28,22 @@ #endif #include +#include #include #include #include #include #include +#include + #define TLS_DEBUG using namespace rfb; +StringParameter CSecurityTLSBase::x509ca("x509ca", "X509 CA certificate", "", ConfViewer); +StringParameter CSecurityTLSBase::x509crl("x509crl", "X509 CRL file", "", ConfViewer); + static LogWriter vlog("TLS"); #ifdef TLS_DEBUG @@ -63,31 +69,48 @@ void CSecurityTLSBase::initGlobal() } } -CSecurityTLSBase::CSecurityTLSBase() : session(0) +CSecurityTLSBase::CSecurityTLSBase(bool _anon) : session(0), anon_cred(0), + anon(_anon), fis(0), fos(0) { - fis = 0; - fos = 0; + cafile = x509ca.getData(); + crlfile = x509crl.getData(); } void CSecurityTLSBase::shutdown() { - if(session) - ;//gnutls_bye(session, GNUTLS_SHUT_RDWR); -} + if (session) + gnutls_bye(session, GNUTLS_SHUT_RDWR); + if (anon_cred) { + gnutls_anon_free_client_credentials(anon_cred); + anon_cred = 0; + } + + if (cert_cred) { + gnutls_certificate_free_credentials(cert_cred); + cert_cred = 0; + } -CSecurityTLSBase::~CSecurityTLSBase() -{ if (session) { - //gnutls_bye(session, GNUTLS_SHUT_RDWR); - gnutls_deinit (session); + gnutls_deinit(session); session = 0; + + gnutls_global_deinit(); } +} + + +CSecurityTLSBase::~CSecurityTLSBase() +{ + shutdown(); + if (fis) delete fis; if (fos) delete fos; - /* FIXME: should be doing gnutls_global_deinit() at some point */ + + delete[] cafile; + delete[] crlfile; } bool CSecurityTLSBase::processMsg(CConnection* cc) @@ -108,7 +131,7 @@ bool CSecurityTLSBase::processMsg(CConnection* cc) gnutls_init(&session, GNUTLS_CLIENT); gnutls_set_default_priority(session); - setParam(session); + setParam(); gnutls_transport_set_pull_function(session, rdr::gnutls_InStream_pull); gnutls_transport_set_push_function(session, rdr::gnutls_OutStream_push); @@ -124,13 +147,11 @@ bool CSecurityTLSBase::processMsg(CConnection* cc) if (err != GNUTLS_E_SUCCESS) { vlog.error("TLS Handshake failed: %s\n", gnutls_strerror (err)); - gnutls_bye(session, GNUTLS_SHUT_RDWR); - freeResources(); - gnutls_deinit(session); - session = 0; + shutdown(); throw AuthFailureException("TLS Handshake failed"); } - checkSession(session); + + checkSession(); cc->setStreams(fis = new rdr::TLSInStream(is, session), fos = new rdr::TLSOutStream(os, session)); @@ -138,3 +159,79 @@ bool CSecurityTLSBase::processMsg(CConnection* cc) return true; } +void CSecurityTLSBase::setParam() +{ + static const int kx_anon_priority[] = { GNUTLS_KX_ANON_DH, 0 }; + static const int kx_priority[] = { GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, + GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0 }; + + if (anon) { + gnutls_kx_set_priority(session, kx_anon_priority); + gnutls_anon_allocate_client_credentials(&anon_cred); + gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred); + + vlog.debug("Anonymous session has been set"); + } else { + gnutls_kx_set_priority(session, kx_priority); + gnutls_certificate_allocate_credentials(&cert_cred); + + if (*cafile && gnutls_certificate_set_x509_trust_file(cert_cred,cafile,GNUTLS_X509_FMT_PEM) < 0) + throw AuthFailureException("load of CA cert failed"); + + if (*crlfile && gnutls_certificate_set_x509_crl_file(cert_cred,crlfile,GNUTLS_X509_FMT_PEM) < 0) + throw AuthFailureException("load of CRL failed"); + + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred); + + vlog.debug("X509 session has been set"); + } +} + +void CSecurityTLSBase::checkSession() +{ + int status; + const gnutls_datum *cert_list; + unsigned int cert_list_size = 0; + unsigned int i; + + if (anon) + return; + + if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) + throw AuthFailureException("unsupported certificate type"); + + cert_list = gnutls_certificate_get_peers(session, &cert_list_size); + if (!cert_list_size) + throw AuthFailureException("unsupported certificate type"); + + status = gnutls_certificate_verify_peers(session); + if (status == GNUTLS_E_NO_CERTIFICATE_FOUND) + throw AuthFailureException("no certificate sent"); + + if (status < 0) { + vlog.error("X509 verify failed: %s\n", gnutls_strerror (status)); + throw AuthFailureException("certificate verification failed"); + } + + if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) + throw AuthFailureException("certificate issuer unknown"); + + if (status & GNUTLS_CERT_INVALID) + throw AuthFailureException("certificate not trusted"); + + 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"); + + if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) { +#if 0 + throw AuthFailureException("Hostname mismatch"); /* Non-fatal for now... */ +#endif + } + gnutls_x509_crt_deinit(crt); + } +} + diff --git a/common/rfb/CSecurityTLSBase.h b/common/rfb/CSecurityTLSBase.h index f7230b3b..b9432640 100644 --- a/common/rfb/CSecurityTLSBase.h +++ b/common/rfb/CSecurityTLSBase.h @@ -31,6 +31,7 @@ #endif #include +#include #include #include #include @@ -39,21 +40,32 @@ namespace rfb { class CSecurityTLSBase : public CSecurity { public: - CSecurityTLSBase(); + CSecurityTLSBase(bool _anon); virtual ~CSecurityTLSBase(); virtual bool processMsg(CConnection* cc); + virtual int getType() const { return anon ? secTypeTLSNone : secTypeX509None; } + virtual const char* description() const + { return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; } + + static StringParameter x509ca; + static StringParameter x509crl; protected: void shutdown(); - virtual void freeResources() = 0; - virtual void setParam(gnutls_session session) = 0; - virtual void checkSession(gnutls_session session) = 0; + void freeResources(); + void setParam(); + void checkSession(); CConnection *client; private: static void initGlobal(); gnutls_session session; + gnutls_anon_client_credentials anon_cred; + gnutls_certificate_credentials cert_cred; + bool anon; + + char *cafile, *crlfile; rdr::InStream* fis; rdr::OutStream* fos; }; diff --git a/common/rfb/CSecurityX509.cxx b/common/rfb/CSecurityX509.cxx deleted file mode 100644 index dfcd497b..00000000 --- a/common/rfb/CSecurityX509.cxx +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2005 Martin Koegler - * Copyright (C) 2010 TigerVNC Team - * - * 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_CONFIG_H -#include -#endif - -#ifndef HAVE_GNUTLS -#error "This source should not be compiled without HAVE_GNUTLS defined" -#endif - -#include -#include -#include -#include - -#include - -using namespace rfb; - -StringParameter CSecurityX509::x509ca("x509ca", "X509 CA certificate", "", ConfViewer); -StringParameter CSecurityX509::x509crl("x509crl", "X509 CRL file", "", ConfViewer); - -static LogWriter vlog("CSecurityX509"); - -CSecurityX509::CSecurityX509() : cert_cred(0) -{ - cafile = x509ca.getData(); - crlfile = x509crl.getData(); -} - -CSecurityX509::~CSecurityX509() -{ - shutdown(); - if (cert_cred) - gnutls_certificate_free_credentials(cert_cred); - delete[] cafile; - delete[] crlfile; -} - - -void CSecurityX509::freeResources() -{ - if (cert_cred) - gnutls_certificate_free_credentials(cert_cred); - cert_cred = 0; - } - -void CSecurityX509::setParam(gnutls_session session) -{ - int kx_priority[] = { GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0 }; - gnutls_kx_set_priority(session, kx_priority); - - gnutls_certificate_allocate_credentials(&cert_cred); - - if (*cafile && gnutls_certificate_set_x509_trust_file(cert_cred,cafile,GNUTLS_X509_FMT_PEM) < 0) - throw AuthFailureException("load of CA cert failed"); - - if (*crlfile && gnutls_certificate_set_x509_crl_file(cert_cred,crlfile,GNUTLS_X509_FMT_PEM) < 0) - throw AuthFailureException("load of CRL failed"); - - gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred); -} - -void CSecurityX509::checkSession(gnutls_session session) -{ - int status; - const gnutls_datum *cert_list; - unsigned int cert_list_size = 0; - unsigned int i; - - if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) - throw AuthFailureException("unsupported certificate type"); - - cert_list = gnutls_certificate_get_peers(session, &cert_list_size); - if (!cert_list_size) - throw AuthFailureException("unsupported certificate type"); - - status = gnutls_certificate_verify_peers(session); - if (status == GNUTLS_E_NO_CERTIFICATE_FOUND) - throw AuthFailureException("no certificate sent"); - - if (status < 0) { - vlog.error("X509 verify failed: %s\n", gnutls_strerror (status)); - throw AuthFailureException("certificate verification failed"); - } - - if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) - throw AuthFailureException("certificate issuer unknown"); - - if (status & GNUTLS_CERT_INVALID) - throw AuthFailureException("certificate not trusted"); - - 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"); - - if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) { -#if 0 - /* FIXME: This must be changed to OK/Cancel checkbox */ - throw AuthFailureException("Hostname mismatch"); /* Non-fatal for now... */ -#endif - } - gnutls_x509_crt_deinit(crt); - } -} - diff --git a/common/rfb/CSecurityX509.h b/common/rfb/CSecurityX509.h deleted file mode 100644 index f49b15ae..00000000 --- a/common/rfb/CSecurityX509.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2005 Martin Koegler - * Copyright (C) 2010 TigerVNC Team - * - * 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_X509_H__ -#define __C_SECURITY_X509_H__ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifndef HAVE_GNUTLS -#error "This header should not be included without HAVE_GNUTLS defined" -#endif - -#include -#include /* To get secTypeX509None defined */ - -namespace rfb { - - class CSecurityX509 : public CSecurityTLSBase { - public: - CSecurityX509(); - virtual ~CSecurityX509(); - virtual int getType() const { return secTypeX509None; }; - virtual const char* description() const { return "X509 Encryption without VncAuth"; } - - static StringParameter x509ca; - static StringParameter x509crl; - - protected: - virtual void freeResources(); - virtual void setParam(gnutls_session session); - virtual void checkSession(gnutls_session session); - - private: - gnutls_certificate_credentials cert_cred; - char *cafile; - char *crlfile; - }; -} - -#endif /* __C_SECURITY_TLS_H__ */ diff --git a/common/rfb/Makefile.am b/common/rfb/Makefile.am index 68b83b87..b8ddca45 100644 --- a/common/rfb/Makefile.am +++ b/common/rfb/Makefile.am @@ -1,10 +1,8 @@ noinst_LTLIBRARIES = librfb.la -VENCRYPT_HDRS = CSecurityTLS.h CSecurityTLSBase.h CSecurityX509.h \ - SSecurityTLS.h +VENCRYPT_HDRS = CSecurityTLSBase.h SSecurityTLS.h -VENCRYPT_SRCS = CSecurityTLS.cxx CSecurityTLSBase.cxx CSecurityX509.cxx \ - SSecurityTLS.cxx +VENCRYPT_SRCS = CSecurityTLSBase.cxx SSecurityTLS.cxx HDRS = Blacklist.h CapsContainer.h CapsList.h CConnection.h \ CMsgHandler.h CMsgReader.h CMsgReaderV3.h CMsgWriter.h \ diff --git a/common/rfb/Security.cxx b/common/rfb/Security.cxx index d2f40bec..18fc56fa 100644 --- a/common/rfb/Security.cxx +++ b/common/rfb/Security.cxx @@ -39,8 +39,7 @@ #include #include #ifdef HAVE_GNUTLS -#include -#include +#include #include #endif #include @@ -152,16 +151,16 @@ CSecurity* Security::GetCSecurity(U32 secType) #ifdef HAVE_GNUTLS case secTypeTLSNone: return new CSecurityStack(secTypeTLSNone, "TLS with no password", - new CSecurityTLS()); + new CSecurityTLSBase(true)); case secTypeTLSVnc: return new CSecurityStack(secTypeTLSVnc, "TLS with VNCAuth", - new CSecurityTLS(), new CSecurityVncAuth()); + new CSecurityTLSBase(true), new CSecurityVncAuth()); case secTypeX509None: return new CSecurityStack(secTypeX509None, "X509 with no password", - new CSecurityX509()); + new CSecurityTLSBase(false)); case secTypeX509Vnc: return new CSecurityStack(secTypeX509None, "X509 with VNCAuth", - new CSecurityX509(), new CSecurityVncAuth()); + new CSecurityTLSBase(false), new CSecurityVncAuth()); #endif } -- 2.39.5