From: Adam Tkac Date: Wed, 21 Jul 2010 09:27:34 +0000 (+0000) Subject: [Development] Rename CSecurityTLSBase class to CSecurityTLS. X-Git-Tag: v1.0.90~203 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3c5be39e92ef06902a5c502616ec052381345f7a;p=tigervnc.git [Development] Rename CSecurityTLSBase class to CSecurityTLS. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4110 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx new file mode 100644 index 00000000..7b2456db --- /dev/null +++ b/common/rfb/CSecurityTLS.cxx @@ -0,0 +1,237 @@ +/* + * 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 header should not be compiled without HAVE_GNUTLS defined" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TLS_DEBUG + +using namespace rfb; + +StringParameter CSecurityTLS::x509ca("x509ca", "X509 CA certificate", "", ConfViewer); +StringParameter CSecurityTLS::x509crl("x509crl", "X509 CRL file", "", ConfViewer); + +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(bool _anon) : session(0), anon_cred(0), + anon(_anon), fis(0), fos(0) +{ + cafile = x509ca.getData(); + crlfile = x509crl.getData(); +} + +void CSecurityTLS::shutdown() +{ + 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; + } + + if (session) { + gnutls_deinit(session); + session = 0; + + gnutls_global_deinit(); + } +} + + +CSecurityTLS::~CSecurityTLS() +{ + shutdown(); + + if (fis) + delete fis; + if (fos) + delete fos; + + delete[] cafile; + delete[] crlfile; +} + +bool CSecurityTLS::processMsg(CConnection* cc) +{ + rdr::InStream* is = cc->getInStream(); + rdr::OutStream* os = cc->getOutStream(); + client = cc; + + initGlobal(); + + if (!session) { + if (!is->checkNoWait(1)) + return false; + + if (is->readU8() == 0) + return true; + + gnutls_init(&session, GNUTLS_CLIENT); + gnutls_set_default_priority(session); + + setParam(); + + gnutls_transport_set_pull_function(session, rdr::gnutls_InStream_pull); + gnutls_transport_set_push_function(session, rdr::gnutls_OutStream_push); + gnutls_transport_set_ptr2(session, + (gnutls_transport_ptr) is, + (gnutls_transport_ptr) os); + } + + int err; + err = gnutls_handshake(session); + if (err != GNUTLS_E_SUCCESS && !gnutls_error_is_fatal(err)) + return false; + + if (err != GNUTLS_E_SUCCESS) { + vlog.error("TLS Handshake failed: %s\n", gnutls_strerror (err)); + shutdown(); + throw AuthFailureException("TLS Handshake failed"); + } + + checkSession(); + + cc->setStreams(fis = new rdr::TLSInStream(is, session), + fos = new rdr::TLSOutStream(os, session)); + + return true; +} + +void CSecurityTLS::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 CSecurityTLS::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/CSecurityTLS.h b/common/rfb/CSecurityTLS.h new file mode 100644 index 00000000..de8615ae --- /dev/null +++ b/common/rfb/CSecurityTLS.h @@ -0,0 +1,74 @@ +/* + * 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 compiled without HAVE_GNUTLS defined" +#endif + +#include +#include +#include +#include +#include +#include + +namespace rfb { + class CSecurityTLS : public CSecurity { + public: + CSecurityTLS(bool _anon); + virtual ~CSecurityTLS(); + 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(); + 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; + }; +} + +#endif diff --git a/common/rfb/CSecurityTLSBase.cxx b/common/rfb/CSecurityTLSBase.cxx deleted file mode 100644 index bc9d3f52..00000000 --- a/common/rfb/CSecurityTLSBase.cxx +++ /dev/null @@ -1,237 +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 header should not be compiled without HAVE_GNUTLS defined" -#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 -static void debug_log(int level, const char* str) -{ - vlog.debug(str); -} -#endif - -void CSecurityTLSBase::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; - } -} - -CSecurityTLSBase::CSecurityTLSBase(bool _anon) : session(0), anon_cred(0), - anon(_anon), fis(0), fos(0) -{ - cafile = x509ca.getData(); - crlfile = x509crl.getData(); -} - -void CSecurityTLSBase::shutdown() -{ - 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; - } - - if (session) { - gnutls_deinit(session); - session = 0; - - gnutls_global_deinit(); - } -} - - -CSecurityTLSBase::~CSecurityTLSBase() -{ - shutdown(); - - if (fis) - delete fis; - if (fos) - delete fos; - - delete[] cafile; - delete[] crlfile; -} - -bool CSecurityTLSBase::processMsg(CConnection* cc) -{ - rdr::InStream* is = cc->getInStream(); - rdr::OutStream* os = cc->getOutStream(); - client = cc; - - initGlobal(); - - if (!session) { - if (!is->checkNoWait(1)) - return false; - - if (is->readU8() == 0) - return true; - - gnutls_init(&session, GNUTLS_CLIENT); - gnutls_set_default_priority(session); - - setParam(); - - gnutls_transport_set_pull_function(session, rdr::gnutls_InStream_pull); - gnutls_transport_set_push_function(session, rdr::gnutls_OutStream_push); - gnutls_transport_set_ptr2(session, - (gnutls_transport_ptr) is, - (gnutls_transport_ptr) os); - } - - int err; - err = gnutls_handshake(session); - if (err != GNUTLS_E_SUCCESS && !gnutls_error_is_fatal(err)) - return false; - - if (err != GNUTLS_E_SUCCESS) { - vlog.error("TLS Handshake failed: %s\n", gnutls_strerror (err)); - shutdown(); - throw AuthFailureException("TLS Handshake failed"); - } - - checkSession(); - - cc->setStreams(fis = new rdr::TLSInStream(is, session), - fos = new rdr::TLSOutStream(os, session)); - - 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 deleted file mode 100644 index b9432640..00000000 --- a/common/rfb/CSecurityTLSBase.h +++ /dev/null @@ -1,74 +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_TLSBASE_H__ -#define __C_SECURITY_TLSBASE_H__ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifndef HAVE_GNUTLS -#error "This header should not be compiled without HAVE_GNUTLS defined" -#endif - -#include -#include -#include -#include -#include -#include - -namespace rfb { - class CSecurityTLSBase : public CSecurity { - public: - 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(); - 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; - }; -} - -#endif diff --git a/common/rfb/Makefile.am b/common/rfb/Makefile.am index b8ddca45..78c959f0 100644 --- a/common/rfb/Makefile.am +++ b/common/rfb/Makefile.am @@ -1,8 +1,8 @@ noinst_LTLIBRARIES = librfb.la -VENCRYPT_HDRS = CSecurityTLSBase.h SSecurityTLS.h +VENCRYPT_HDRS = CSecurityTLS.h SSecurityTLS.h -VENCRYPT_SRCS = CSecurityTLSBase.cxx SSecurityTLS.cxx +VENCRYPT_SRCS = CSecurityTLS.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 18fc56fa..b7ce7149 100644 --- a/common/rfb/Security.cxx +++ b/common/rfb/Security.cxx @@ -39,7 +39,7 @@ #include #include #ifdef HAVE_GNUTLS -#include +#include #include #endif #include @@ -151,16 +151,16 @@ CSecurity* Security::GetCSecurity(U32 secType) #ifdef HAVE_GNUTLS case secTypeTLSNone: return new CSecurityStack(secTypeTLSNone, "TLS with no password", - new CSecurityTLSBase(true)); + new CSecurityTLS(true)); case secTypeTLSVnc: return new CSecurityStack(secTypeTLSVnc, "TLS with VNCAuth", - new CSecurityTLSBase(true), new CSecurityVncAuth()); + new CSecurityTLS(true), new CSecurityVncAuth()); case secTypeX509None: return new CSecurityStack(secTypeX509None, "X509 with no password", - new CSecurityTLSBase(false)); + new CSecurityTLS(false)); case secTypeX509Vnc: return new CSecurityStack(secTypeX509None, "X509 with VNCAuth", - new CSecurityTLSBase(false), new CSecurityVncAuth()); + new CSecurityTLS(false), new CSecurityVncAuth()); #endif }