From: Adam Tkac Date: Wed, 21 Jul 2010 09:09:19 +0000 (+0000) Subject: [Development] Implement VeNCrypt X509 subtypes on the client side. X-Git-Tag: v1.0.90~207 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f5f6a00dfb329b5e4b8c8349f8cac8b0036abbc9;p=tigervnc.git [Development] Implement VeNCrypt X509 subtypes on the client side. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4106 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- diff --git a/common/rfb/CSecurityX509.cxx b/common/rfb/CSecurityX509.cxx new file mode 100644 index 00000000..dfcd497b --- /dev/null +++ b/common/rfb/CSecurityX509.cxx @@ -0,0 +1,127 @@ +/* + * 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 new file mode 100644 index 00000000..f49b15ae --- /dev/null +++ b/common/rfb/CSecurityX509.h @@ -0,0 +1,59 @@ +/* + * 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 4160a9d6..260f4b6d 100644 --- a/common/rfb/Makefile.am +++ b/common/rfb/Makefile.am @@ -1,9 +1,9 @@ noinst_LTLIBRARIES = librfb.la -VENCRYPT_HDRS = CSecurityTLS.h CSecurityTLSBase.h \ +VENCRYPT_HDRS = CSecurityTLS.h CSecurityTLSBase.h CSecurityX509.h \ SSecurityTLS.h SSecurityTLSBase.h SSecurityX509.h -VENCRYPT_SRCS = CSecurityTLS.cxx CSecurityTLSBase.cxx \ +VENCRYPT_SRCS = CSecurityTLS.cxx CSecurityTLSBase.cxx CSecurityX509.cxx \ SSecurityTLS.cxx SSecurityTLSBase.cxx SSecurityX509.cxx HDRS = Blacklist.h CapsContainer.h CapsList.h CConnection.h \ diff --git a/common/rfb/Security.cxx b/common/rfb/Security.cxx index c6ab4107..37ecc153 100644 --- a/common/rfb/Security.cxx +++ b/common/rfb/Security.cxx @@ -40,6 +40,7 @@ #include #ifdef HAVE_GNUTLS #include +#include #include #include #endif @@ -156,6 +157,12 @@ CSecurity* Security::GetCSecurity(U32 secType) case secTypeTLSVnc: return new CSecurityStack(secTypeTLSVnc, "TLS with VNCAuth", new CSecurityTLS(), new CSecurityVncAuth()); + case secTypeX509None: + return new CSecurityStack(secTypeX509None, "X509 with no password", + new CSecurityX509()); + case secTypeX509Vnc: + return new CSecurityStack(secTypeX509None, "X509 with VNCAuth", + new CSecurityX509(), new CSecurityVncAuth()); #endif }