git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4109 3789f03b-4d11-0410-bbf8-ca57d06f2519tags/v1.0.90
@@ -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 <config.h> | |||
#endif | |||
#ifndef HAVE_GNUTLS | |||
#error "This source should not be compiled without HAVE_GNUTLS defined" | |||
#endif | |||
#include <rfb/CSecurityTLS.h> | |||
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) | |||
{ | |||
} | |||
@@ -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 <config.h> | |||
#endif | |||
#ifndef HAVE_GNUTLS | |||
#error "This header should not be included without HAVE_GNUTLS defined" | |||
#endif | |||
#include <rfb/CSecurityTLSBase.h> | |||
#include <rfb/SSecurityVeNCrypt.h> | |||
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__ */ |
@@ -28,16 +28,22 @@ | |||
#endif | |||
#include <rfb/CSecurityTLSBase.h> | |||
#include <rfb/SSecurityVeNCrypt.h> | |||
#include <rfb/CConnection.h> | |||
#include <rfb/LogWriter.h> | |||
#include <rfb/Exception.h> | |||
#include <rdr/TLSInStream.h> | |||
#include <rdr/TLSOutStream.h> | |||
#include <gnutls/x509.h> | |||
#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); | |||
} | |||
} | |||
@@ -31,6 +31,7 @@ | |||
#endif | |||
#include <rfb/CSecurity.h> | |||
#include <rfb/SSecurityVeNCrypt.h> | |||
#include <rfb/Security.h> | |||
#include <rdr/InStream.h> | |||
#include <rdr/OutStream.h> | |||
@@ -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; | |||
}; |
@@ -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 <config.h> | |||
#endif | |||
#ifndef HAVE_GNUTLS | |||
#error "This source should not be compiled without HAVE_GNUTLS defined" | |||
#endif | |||
#include <rfb/CSecurityX509.h> | |||
#include <rfb/CConnection.h> | |||
#include <rfb/Exception.h> | |||
#include <rfb/LogWriter.h> | |||
#include <gnutls/x509.h> | |||
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); | |||
} | |||
} | |||
@@ -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 <config.h> | |||
#endif | |||
#ifndef HAVE_GNUTLS | |||
#error "This header should not be included without HAVE_GNUTLS defined" | |||
#endif | |||
#include <rfb/CSecurityTLSBase.h> | |||
#include <rfb/SSecurityVeNCrypt.h> /* 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__ */ |
@@ -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 \ |
@@ -39,8 +39,7 @@ | |||
#include <rfb/SSecurityVncAuth.h> | |||
#include <rfb/SSecurityVeNCrypt.h> | |||
#ifdef HAVE_GNUTLS | |||
#include <rfb/CSecurityTLS.h> | |||
#include <rfb/CSecurityX509.h> | |||
#include <rfb/CSecurityTLSBase.h> | |||
#include <rfb/SSecurityTLS.h> | |||
#endif | |||
#include <rfb/util.h> | |||
@@ -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 | |||
} | |||