gloox 1.0.24
tlsgnutlsclient.cpp
1/*
2 Copyright (c) 2005-2019 by Jakob Schröter <js@camaya.net>
3 This file is part of the gloox library. http://camaya.net/gloox
4
5 This software is distributed under a license. The full license
6 agreement can be found in the file LICENSE in this distribution.
7 This software may not be copied, modified, sold or distributed
8 other than expressed in the named license agreement.
9
10 This software is distributed without any warranty.
11*/
12
13
14
15#include "tlsgnutlsclient.h"
16
17#ifdef HAVE_GNUTLS
18
19#include <errno.h>
20
21namespace gloox
22{
23
24 GnuTLSClient::GnuTLSClient( TLSHandler* th, const std::string& server )
25 : GnuTLSBase( th, server )
26 {
27 }
28
30 {
31 }
32
34 {
36 if( m_credentials )
37 gnutls_certificate_free_credentials( m_credentials );
38 init();
39 }
40
41 bool GnuTLSClient::init( const std::string& /*clientKey*/,
42 const std::string& /*clientCerts*/,
43 const StringList& /*cacerts*/ )
44 {
45 if( m_initLib && gnutls_global_init() != 0 )
46 return false;
47
48 if( gnutls_certificate_allocate_credentials( &m_credentials ) < 0 )
49 return false;
50
51 if( gnutls_init( m_session, GNUTLS_CLIENT ) != 0 )
52 {
53 gnutls_certificate_free_credentials( m_credentials );
54 return false;
55 }
56
57#if GNUTLS_VERSION_NUMBER >= 0x020600
58 int ret = gnutls_priority_set_direct( *m_session, "SECURE128:+PFS:+COMP-ALL:+VERS-TLS-ALL:-VERS-SSL3.0:-VERS-TLS1.3:+SIGN-ALL:+CURVE-ALL", 0 );
59 if( ret != GNUTLS_E_SUCCESS )
60 return false;
61#else
62 const int protocolPriority[] = {
63#ifdef GNUTLS_TLS1_2
64 GNUTLS_TLS1_2,
65#endif
66 GNUTLS_TLS1_1, GNUTLS_TLS1, 0 };
67 const int kxPriority[] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_DHE_DSS, 0 };
68 const int cipherPriority[] = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC,
69 GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0 };
70 const int compPriority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
71 const int macPriority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
72 gnutls_protocol_set_priority( *m_session, protocolPriority );
73 gnutls_cipher_set_priority( *m_session, cipherPriority );
74 gnutls_compression_set_priority( *m_session, compPriority );
75 gnutls_kx_set_priority( *m_session, kxPriority );
76 gnutls_mac_set_priority( *m_session, macPriority );
77#endif
78
79 gnutls_certificate_set_x509_system_trust( m_credentials );
80 gnutls_credentials_set( *m_session, GNUTLS_CRD_CERTIFICATE, m_credentials );
81
82 gnutls_transport_set_ptr( *m_session, static_cast<gnutls_transport_ptr_t>( this ) );
83 gnutls_transport_set_push_function( *m_session, pushFunc );
84 gnutls_transport_set_pull_function( *m_session, pullFunc );
85
86 m_valid = true;
87 return true;
88 }
89
90 void GnuTLSClient::setCACerts( const StringList& cacerts )
91 {
92 m_cacerts = cacerts;
93
94 StringList::const_iterator it = m_cacerts.begin();
95 for( ; it != m_cacerts.end(); ++it )
96 gnutls_certificate_set_x509_trust_file( m_credentials, (*it).c_str(), GNUTLS_X509_FMT_PEM );
97 }
98
99 void GnuTLSClient::setClientCert( const std::string& clientKey, const std::string& clientCerts )
100 {
101 m_clientKey = clientKey;
102 m_clientCerts = clientCerts;
103
104 if( !m_clientKey.empty() && !m_clientCerts.empty() )
105 {
106 gnutls_certificate_set_x509_key_file( m_credentials, m_clientCerts.c_str(),
107 m_clientKey.c_str(), GNUTLS_X509_FMT_PEM );
108 }
109 }
110
111 void GnuTLSClient::getCertInfo()
112 {
113 unsigned int status;
114 bool error = false;
115
116 gnutls_certificate_free_ca_names( m_credentials );
117
118 if( gnutls_certificate_verify_peers2( *m_session, &status ) < 0 )
119 error = true;
120
121 m_certInfo.status = 0;
122 if( status & GNUTLS_CERT_INVALID )
123 m_certInfo.status |= CertInvalid;
124 if( status & GNUTLS_CERT_SIGNER_NOT_FOUND )
125 m_certInfo.status |= CertSignerUnknown;
126 if( status & GNUTLS_CERT_REVOKED )
127 m_certInfo.status |= CertRevoked;
128 if( status & GNUTLS_CERT_SIGNER_NOT_CA )
129 m_certInfo.status |= CertSignerNotCa;
130
131 const gnutls_datum_t* certList = 0;
132 unsigned int certListSize = 0;
133 if( !error && ( ( certList = gnutls_certificate_get_peers( *m_session, &certListSize ) ) == 0 ) )
134 error = true;
135
136 unsigned int certListSizeFull = certListSize;
137
138 gnutls_x509_crt_t* cert = new gnutls_x509_crt_t[certListSize];
139 for( unsigned int i=0; !error && ( i<certListSize ); ++i )
140 {
141 if( gnutls_x509_crt_init( &cert[i] ) < 0
142 || gnutls_x509_crt_import( cert[i], &certList[i], GNUTLS_X509_FMT_DER ) < 0 )
143 error = true;
144 }
145
146 if( certListSize > 1 && ( gnutls_x509_crt_check_issuer( cert[certListSize-1], cert[certListSize-1] ) > 0 ) )
147 certListSize--;
148
149 for( unsigned int i=1; !error && ( i<certListSize ); ++i )
150 {
151 error = !verifyAgainst( cert[i-1], cert[i] );
152 if( error )
153 m_certInfo.status |= CertInvalid;
154 }
155
156 m_certInfo.chain = verifyAgainstCAs( cert[certListSize-1], 0 /*CAList*/, 0 /*CAListSize*/ );
157
158 time_t t = gnutls_x509_crt_get_activation_time( cert[0] );
159 if( t == -1 )
160 error = true;
161 else if( t > time( 0 ) )
162 m_certInfo.status |= CertNotActive;
163 m_certInfo.date_from = static_cast<int>( t );
164
165 t = gnutls_x509_crt_get_expiration_time( cert[0] );
166 if( t == -1 )
167 error = true;
168 else if( t < time( 0 ) )
169 m_certInfo.status |= CertExpired;
170 m_certInfo.date_to = static_cast<int>( t );
171
172 char name[64];
173 size_t nameSize = sizeof( name );
174 gnutls_x509_crt_get_issuer_dn( cert[0], name, &nameSize );
175 m_certInfo.issuer = name;
176
177 nameSize = sizeof( name );
178 gnutls_x509_crt_get_dn( cert[0], name, &nameSize );
179 m_certInfo.server = name;
180
181 const char* info;
182 info = gnutls_compression_get_name( gnutls_compression_get( *m_session ) );
183 if( info )
184 m_certInfo.compression = info;
185
186 info = gnutls_mac_get_name( gnutls_mac_get( *m_session ) );
187 if( info )
188 m_certInfo.mac = info;
189
190 info = gnutls_cipher_get_name( gnutls_cipher_get( *m_session ) );
191 if( info )
192 m_certInfo.cipher = info;
193
194 info = gnutls_protocol_get_name( gnutls_protocol_get_version( *m_session ) );
195 if( info )
196 m_certInfo.protocol = info;
197
198 if( !gnutls_x509_crt_check_hostname( cert[0], m_server.c_str() ) )
199 m_certInfo.status |= CertWrongPeer;
200
201 for( unsigned int i = 0; i < certListSizeFull; ++i )
202 gnutls_x509_crt_deinit( cert[i] );
203
204 delete[] cert;
205
206 m_valid = true;
207 }
208
209 static bool verifyCert( gnutls_x509_crt_t cert, unsigned result )
210 {
211 return ! ( ( result & GNUTLS_CERT_INVALID )
212 || gnutls_x509_crt_get_expiration_time( cert ) < time( 0 )
213 || gnutls_x509_crt_get_activation_time( cert ) > time( 0 ) );
214 }
215
216 bool GnuTLSClient::verifyAgainst( gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer )
217 {
218 unsigned int result;
219 gnutls_x509_crt_verify( cert, &issuer, 1, 0, &result );
220 return verifyCert( cert, result );
221 }
222
223 bool GnuTLSClient::verifyAgainstCAs( gnutls_x509_crt_t cert, gnutls_x509_crt_t* CAList, int CAListSize )
224 {
225 unsigned int result;
226 gnutls_x509_crt_verify( cert, CAList, CAListSize, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &result );
227 return verifyCert( cert, result );
228 }
229
230}
231
232#endif // HAVE_GNUTLS
This is the common base class for (stream) encryption using GnuTLS.
Definition: tlsgnutlsbase.h:39
virtual void cleanup()
virtual void setCACerts(const StringList &cacerts)
virtual void cleanup()
virtual void setClientCert(const std::string &clientKey, const std::string &clientCerts)
virtual bool init(const std::string &clientKey=EmptyString, const std::string &clientCerts=EmptyString, const StringList &cacerts=StringList())
GnuTLSClient(TLSHandler *th, const std::string &server)
An interface that allows for interacting with TLS implementations derived from TLSBase.
Definition: tlshandler.h:35
The namespace for the gloox library.
Definition: adhoc.cpp:28
std::list< std::string > StringList
Definition: gloox.h:1251
@ CertExpired
Definition: gloox.h:979
@ CertWrongPeer
Definition: gloox.h:981
@ CertSignerUnknown
Definition: gloox.h:977
@ CertSignerNotCa
Definition: gloox.h:983
@ CertInvalid
Definition: gloox.h:976
@ CertNotActive
Definition: gloox.h:980
@ CertRevoked
Definition: gloox.h:978
std::string cipher
Definition: gloox.h:1002
bool chain
Definition: gloox.h:992
std::string server
Definition: gloox.h:994
std::string mac
Definition: gloox.h:1003
int date_from
Definition: gloox.h:995
std::string protocol
Definition: gloox.h:1001
std::string issuer
Definition: gloox.h:993
std::string compression
Definition: gloox.h:1004