Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

tlsgnutlsclient.cpp

00001 /*
00002   Copyright (c) 2005-2008 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 
00014 
00015 #include "tlsgnutlsclient.h"
00016 
00017 #ifdef HAVE_GNUTLS
00018 
00019 #include <errno.h>
00020 
00021 namespace gloox
00022 {
00023 
00024   GnuTLSClient::GnuTLSClient( TLSHandler* th, const std::string& server )
00025     : GnuTLSBase( th, server )
00026   {
00027   }
00028 
00029   GnuTLSClient::~GnuTLSClient()
00030   {
00031   }
00032 
00033   void GnuTLSClient::cleanup()
00034   {
00035     GnuTLSBase::cleanup();
00036     init();
00037   }
00038 
00039   bool GnuTLSClient::init()
00040   {
00041     const int protocolPriority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
00042     const int kxPriority[]       = { GNUTLS_KX_RSA, 0 };
00043     const int cipherPriority[]   = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC,
00044                                      GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0 };
00045     const int compPriority[]     = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
00046     const int macPriority[]      = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
00047 
00048     if( m_initLib && gnutls_global_init() != 0 )
00049       return false;
00050 
00051     if( gnutls_certificate_allocate_credentials( &m_credentials ) < 0 )
00052       return false;
00053 
00054     if( gnutls_init( m_session, GNUTLS_CLIENT ) != 0 )
00055     {
00056       gnutls_certificate_free_credentials( m_credentials );
00057       return false;
00058     }
00059 
00060     gnutls_protocol_set_priority( *m_session, protocolPriority );
00061     gnutls_cipher_set_priority( *m_session, cipherPriority );
00062     gnutls_compression_set_priority( *m_session, compPriority );
00063     gnutls_kx_set_priority( *m_session, kxPriority );
00064     gnutls_mac_set_priority( *m_session, macPriority );
00065     gnutls_credentials_set( *m_session, GNUTLS_CRD_CERTIFICATE, m_credentials );
00066 
00067     gnutls_transport_set_ptr( *m_session, (gnutls_transport_ptr_t)this );
00068     gnutls_transport_set_push_function( *m_session, pushFunc );
00069     gnutls_transport_set_pull_function( *m_session, pullFunc );
00070 
00071     m_valid = true;
00072     return true;
00073   }
00074 
00075   void GnuTLSClient::setCACerts( const StringList& cacerts )
00076   {
00077     m_cacerts = cacerts;
00078 
00079     StringList::const_iterator it = m_cacerts.begin();
00080     for( ; it != m_cacerts.end(); ++it )
00081       gnutls_certificate_set_x509_trust_file( m_credentials, (*it).c_str(), GNUTLS_X509_FMT_PEM );
00082   }
00083 
00084   void GnuTLSClient::setClientCert( const std::string& clientKey, const std::string& clientCerts )
00085   {
00086     m_clientKey = clientKey;
00087     m_clientCerts = clientCerts;
00088 
00089     if( !m_clientKey.empty() && !m_clientCerts.empty() )
00090     {
00091       gnutls_certificate_set_x509_key_file( m_credentials, m_clientKey.c_str(),
00092                                             m_clientCerts.c_str(), GNUTLS_X509_FMT_PEM );
00093     }
00094   }
00095 
00096   void GnuTLSClient::getCertInfo()
00097   {
00098     unsigned int status;
00099     bool error = false;
00100 
00101     gnutls_certificate_free_ca_names( m_credentials );
00102 
00103     if( gnutls_certificate_verify_peers2( *m_session, &status ) < 0 )
00104       error = true;
00105 
00106     m_certInfo.status = 0;
00107     if( status & GNUTLS_CERT_INVALID )
00108       m_certInfo.status |= CertInvalid;
00109     if( status & GNUTLS_CERT_SIGNER_NOT_FOUND )
00110       m_certInfo.status |= CertSignerUnknown;
00111     if( status & GNUTLS_CERT_REVOKED )
00112       m_certInfo.status |= CertRevoked;
00113     if( status & GNUTLS_CERT_SIGNER_NOT_CA )
00114       m_certInfo.status |= CertSignerNotCa;
00115     const gnutls_datum_t* certList = 0;
00116     unsigned int certListSize;
00117     if( !error && ( ( certList = gnutls_certificate_get_peers( *m_session, &certListSize ) ) == 0 ) )
00118       error = true;
00119 
00120     gnutls_x509_crt_t* cert = new gnutls_x509_crt_t[certListSize+1];
00121     for( unsigned int i=0; !error && ( i<certListSize ); ++i )
00122     {
00123       if( gnutls_x509_crt_init( &cert[i] ) < 0
00124           || gnutls_x509_crt_import( cert[i], &certList[i], GNUTLS_X509_FMT_DER ) < 0 )
00125         error = true;
00126     }
00127 
00128     if( ( gnutls_x509_crt_check_issuer( cert[certListSize-1], cert[certListSize-1] ) > 0 )
00129          && certListSize > 0 )
00130       certListSize--;
00131 
00132     bool chain = true;
00133     for( unsigned int i=1; !error && ( i<certListSize ); ++i )
00134     {
00135       chain = error = !verifyAgainst( cert[i-1], cert[i] );
00136     }
00137     if( !chain )
00138       m_certInfo.status |= CertInvalid;
00139     m_certInfo.chain = chain;
00140 
00141     m_certInfo.chain = verifyAgainstCAs( cert[certListSize], 0 /*CAList*/, 0 /*CAListSize*/ );
00142 
00143     int t = (int)gnutls_x509_crt_get_activation_time( cert[0] );
00144     if( t == -1 )
00145       error = true;
00146     else if( t > time( 0 ) )
00147       m_certInfo.status |= CertNotActive;
00148     m_certInfo.date_from = t;
00149 
00150     t = (int)gnutls_x509_crt_get_expiration_time( cert[0] );
00151     if( t == -1 )
00152       error = true;
00153     else if( t < time( 0 ) )
00154       m_certInfo.status |= CertExpired;
00155     m_certInfo.date_to = t;
00156 
00157     char name[64];
00158     size_t nameSize = sizeof( name );
00159     gnutls_x509_crt_get_issuer_dn( cert[0], name, &nameSize );
00160     m_certInfo.issuer = name;
00161 
00162     nameSize = sizeof( name );
00163     gnutls_x509_crt_get_dn( cert[0], name, &nameSize );
00164     m_certInfo.server = name;
00165 
00166     const char* info;
00167     info = gnutls_compression_get_name( gnutls_compression_get( *m_session ) );
00168     if( info )
00169       m_certInfo.compression = info;
00170 
00171     info = gnutls_mac_get_name( gnutls_mac_get( *m_session ) );
00172     if( info )
00173       m_certInfo.mac = info;
00174 
00175     info = gnutls_cipher_get_name( gnutls_cipher_get( *m_session ) );
00176     if( info )
00177       m_certInfo.cipher = info;
00178 
00179     info = gnutls_protocol_get_name( gnutls_protocol_get_version( *m_session ) );
00180     if( info )
00181       m_certInfo.protocol = info;
00182 
00183     if( !gnutls_x509_crt_check_hostname( cert[0], m_server.c_str() ) )
00184       m_certInfo.status |= CertWrongPeer;
00185 
00186     for( unsigned int i = 0; i < certListSize; ++i )
00187       gnutls_x509_crt_deinit( cert[i] );
00188 
00189     delete[] cert;
00190 
00191     m_valid = true;
00192   }
00193 
00194   static bool verifyCert( gnutls_x509_crt_t cert, unsigned result )
00195   {
00196     return ! ( ( result & GNUTLS_CERT_INVALID )
00197       || gnutls_x509_crt_get_expiration_time( cert ) < time( 0 )
00198       || gnutls_x509_crt_get_activation_time( cert ) > time( 0 ) );
00199   }
00200 
00201   bool GnuTLSClient::verifyAgainst( gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer )
00202   {
00203     unsigned int result;
00204     gnutls_x509_crt_verify( cert, &issuer, 1, 0, &result );
00205     return verifyCert( cert, result );
00206   }
00207 
00208   bool GnuTLSClient::verifyAgainstCAs( gnutls_x509_crt_t cert, gnutls_x509_crt_t* CAList, int CAListSize )
00209   {
00210     unsigned int result;
00211     gnutls_x509_crt_verify( cert, CAList, CAListSize, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &result );
00212     return verifyCert( cert, result );
00213   }
00214 
00215 }
00216 
00217 #endif // HAVE_GNUTLS

Generated on Sun Dec 28 22:10:18 2008 for gloox by  doxygen 1.4.1