E-MailRelay
gssl.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gssl.cpp
19///
20
21#include "gdef.h"
22#include "gssl.h"
23#include "gstr.h"
24#include "gexception.h"
25#include "glog.h"
26#include <algorithm>
27
28GSsl::Library * GSsl::Library::m_this = nullptr ;
29
30GSsl::Library::Library( bool active , const std::string & library_config , LogFn log_fn , bool verbose )
31{
32 if( m_this == nullptr )
33 m_this = this ;
34
35 if( active )
36 {
37 G::StringArray config = G::Str::splitIntoTokens( library_config , "," ) ;
38 m_imp = newLibraryImp( config , log_fn , verbose ) ;
39 bool ignore_extra = LibraryImpBase::consume( config , "ignoreextra" ) ;
40 if( !config.empty() && !ignore_extra )
41 G_WARNING( "GSsl::Library::Library: tls-config: tls configuration items ignored: [" << G::Str::join(",",config) << "]" ) ;
42 }
43}
44
46{
47 if( m_this == this )
48 m_this = nullptr ;
49}
50
52{
53 return true ;
54}
55
57{
58 return m_this ;
59}
60
62{
63 return m_imp != nullptr ;
64}
65
66std::string GSsl::Library::id() const
67{
68 return m_imp->id() ;
69}
70
72{
73 return m_imp && m_imp->generateKeyAvailable() ;
74}
75
76std::string GSsl::Library::generateKey( const std::string & name ) const
77{
78 return m_imp ? m_imp->generateKey( name ) : std::string() ;
79}
80
81void GSsl::Library::addProfile( const std::string & profile_name , bool is_server_profile ,
82 const std::string & key_file , const std::string & cert_file , const std::string & ca_file ,
83 const std::string & default_peer_certificate_name , const std::string & default_peer_host_name ,
84 const std::string & profile_config )
85{
86 if( m_imp != nullptr )
87 m_imp->addProfile( profile_name , is_server_profile , key_file , cert_file , ca_file ,
88 default_peer_certificate_name , default_peer_host_name , profile_config ) ;
89}
90
91bool GSsl::Library::hasProfile( const std::string & profile_name ) const
92{
93 return m_imp->hasProfile( profile_name ) ;
94}
95
96const GSsl::Profile & GSsl::Library::profile( const std::string & profile_name ) const
97{
98 if( !imp().hasProfile(profile_name) )
99 throw G::Exception( "invalid tls profile name [" + profile_name + "]" ) ;
100 return imp().profile( profile_name ) ;
101}
102
103bool GSsl::Library::enabledAs( const std::string & profile_name )
104{
105 return instance() != nullptr && instance()->enabled() && instance()->hasProfile( profile_name ) ;
106}
107
109{
110 if( instance() == nullptr )
111 throw G::Exception( "no tls library instance" ) ;
112 return instance()->imp() ;
113}
114
115GSsl::LibraryImpBase & GSsl::Library::imp()
116{
117 if( m_imp == nullptr )
118 throw G::Exception( "no tls library instance" ) ;
119 return *m_imp ;
120}
121
122const GSsl::LibraryImpBase & GSsl::Library::imp() const
123{
124 if( m_imp == nullptr )
125 throw G::Exception( "no tls library instance" ) ;
126 return *m_imp ;
127}
128
129void GSsl::Library::log( int level , const std::string & log_line )
130{
131 if( level == 1 )
132 G_DEBUG( "GSsl::Library::log: tls: " << log_line ) ;
133 else if( level == 2 )
134 G_LOG( "GSsl::Library::log: tls: " << log_line ) ;
135 else
136 G_WARNING( "GSsl::Library::log: tls: " << log_line ) ;
137}
138
140{
141 return instance() == nullptr || instance()->m_imp == nullptr ? G::StringArray() : impstance().digesters(require_state) ;
142}
143
144GSsl::Digester GSsl::Library::digester( const std::string & hash_function , const std::string & state , bool need_state ) const
145{
146 return impstance().digester( hash_function , state , need_state ) ;
147}
148
149// ==
150
151GSsl::Protocol::Protocol( const Profile & profile , const std::string & peer_certificate_name , const std::string & peer_host_name ) :
152 m_imp( profile.newProtocol(peer_certificate_name,peer_host_name) )
153{
154}
155
157= default;
158
160{
161 return m_imp->peerCertificate() ;
162}
163
165{
166 return m_imp->peerCertificateChain() ;
167}
168
169std::string GSsl::Protocol::protocol() const
170{
171 return m_imp->protocol() ;
172}
173
174std::string GSsl::Protocol::cipher() const
175{
176 return m_imp->cipher() ;
177}
178
180{
181 return m_imp->verified() ;
182}
183
184std::string GSsl::Protocol::str( Result result )
185{
186 if( result == Result::ok ) return "Result_ok" ;
187 if( result == Result::read ) return "Result_read" ;
188 if( result == Result::write ) return "Result_write" ;
189 if( result == Result::error ) return "Result_error" ;
190 return "Result_undefined" ;
191}
192
193GSsl::Protocol::Result GSsl::Protocol::connect( G::ReadWrite & io )
194{
195 return m_imp->connect( io ) ;
196}
197
198GSsl::Protocol::Result GSsl::Protocol::accept( G::ReadWrite & io )
199{
200 return m_imp->accept( io ) ;
201}
202
203GSsl::Protocol::Result GSsl::Protocol::read( char * buffer , std::size_t buffer_size_in , ssize_t & data_size_out )
204{
205 return m_imp->read( buffer , buffer_size_in , data_size_out ) ;
206}
207
208GSsl::Protocol::Result GSsl::Protocol::write( const char * buffer , std::size_t data_size_in , ssize_t & data_size_out)
209{
210 return m_imp->write( buffer , data_size_in , data_size_out ) ;
211}
212
213GSsl::Protocol::Result GSsl::Protocol::shutdown()
214{
215 return m_imp->shutdown() ;
216}
217
218// ==
219
220GSsl::Digester::Digester( std::unique_ptr<DigesterImpBase> p ) :
221 m_imp(p.release())
222{
223}
224
225void GSsl::Digester::add( const std::string & s )
226{
227 m_imp->add( s ) ;
228}
229
231{
232 return m_imp->value() ;
233}
234
236{
237 return m_imp->state() ;
238}
239
240std::size_t GSsl::Digester::blocksize() const
241{
242 return m_imp->blocksize() ;
243}
244
245std::size_t GSsl::Digester::valuesize() const
246{
247 return m_imp->valuesize() ;
248}
249
250std::size_t GSsl::Digester::statesize() const
251{
252 return m_imp->statesize() ;
253}
254
255// ==
256
257bool GSsl::LibraryImpBase::consume( G::StringArray & list , const std::string & key )
258{
259 auto p = std::find( list.begin() , list.end() , key ) ;
260 if( p != list.end() )
261 {
262 list.erase( p ) ;
263 return true ;
264 }
265 else
266 {
267 return false ;
268 }
269}
270
A class for objects that can perform a cryptographic hash.
Definition: gssl.h:213
std::size_t valuesize() const
Returns the hash function's value size in bytes.
Definition: gssl.cpp:245
std::size_t statesize() const
Returns the size of the state() string in bytes, or zero if state() is not implemented.
Definition: gssl.cpp:250
std::string value()
Returns the hash value.
Definition: gssl.cpp:230
void add(const std::string &)
Adds data of arbitrary size.
Definition: gssl.cpp:225
std::size_t blocksize() const
Returns the hash function's block size in bytes.
Definition: gssl.cpp:240
std::string state()
Returns the intermediate state.
Definition: gssl.cpp:235
Digester(std::unique_ptr< DigesterImpBase >)
Constructor, used by the Library class.
Definition: gssl.cpp:220
A base interface for GSsl::Library pimple classes.
Definition: gssl.h:390
static bool consume(G::StringArray &list, const std::string &item)
A convenience function that removes the item from the list and returns true iff is was removed.
Definition: gssl.cpp:257
A singleton class for initialising the underlying TLS library.
Definition: gssl.h:253
static bool enabledAs(const std::string &profile_name)
A static convenience function that returns true if there is an enabled() Library instance() that has ...
Definition: gssl.cpp:103
Digester digester(const std::string &name, const std::string &state=std::string(), bool need_state=false) const
Returns a digester object.
Definition: gssl.cpp:144
bool hasProfile(const std::string &profile_name) const
Returns true if the named profile has been add()ed.
Definition: gssl.cpp:91
Library(bool active=true, const std::string &library_config=std::string(), LogFn=Library::log, bool verbose=true)
Constructor.
Definition: gssl.cpp:30
bool generateKeyAvailable() const
Returns true if generateKey() is implemented.
Definition: gssl.cpp:71
static Library * instance()
Returns a pointer to a library object, if any.
Definition: gssl.cpp:56
std::string id() const
Returns the TLS library name and version.
Definition: gssl.cpp:66
static LibraryImpBase & impstance()
Returns a reference to the pimple object when enabled().
Definition: gssl.cpp:108
static bool real()
Returns true if this is a real TLS library.
Definition: gssl.cpp:51
void addProfile(const std::string &profile_name, bool is_server_profile, const std::string &key_file=std::string(), const std::string &cert_file=std::string(), const std::string &ca_path=std::string(), const std::string &default_peer_certificate_name=std::string(), const std::string &default_peer_host_name=std::string(), const std::string &profile_config=std::string())
Creates a named Profile object that can be retrieved by profile().
Definition: gssl.cpp:81
const Profile & profile(const std::string &profile_name) const
Returns an opaque reference to the named profile.
Definition: gssl.cpp:96
bool enabled() const
Returns true if this is a real TLS library and the constructor's active parameter was set.
Definition: gssl.cpp:61
static G::StringArray digesters(bool need_state=false)
Returns a list of hash function names (such as "MD5") that the TLS library can do,...
Definition: gssl.cpp:139
~Library()
Destructor. Cleans up the underlying TLS library.
Definition: gssl.cpp:45
static void log(int level, const std::string &line)
The default logging callback function, where the level is 1 for debug, 2 for info,...
Definition: gssl.cpp:129
std::string generateKey(const std::string &name) const
Generates a test certificate as a PEM string with embedded newlines, also containing the private-key.
Definition: gssl.cpp:76
A base interface for profile classes that work with concrete classes derived from GSsl::LibraryImpBas...
Definition: gssl.h:430
Protocol(const Profile &, const std::string &peer_certificate_name=std::string(), const std::string &peer_host_name=std::string())
Constructor.
Definition: gssl.cpp:151
~Protocol()
Destructor.
Result shutdown()
Initiates the protocol shutdown by sending a "close notify shutdown alert" and does a socket shutdown...
Definition: gssl.cpp:213
Result read(char *buffer, std::size_t buffer_size_in, ssize_t &data_size_out)
Reads user data into the supplied buffer.
Definition: gssl.cpp:203
std::string cipher() const
Returns the cipher name, or the empty string if not yet available.
Definition: gssl.cpp:174
bool verified() const
Returns true if the peer certificate has been verified.
Definition: gssl.cpp:179
static std::string str(Result result)
Converts a result enumeration into a printable string.
Definition: gssl.cpp:184
std::string peerCertificateChain() const
Returns the peer certificate chain in PEM format, starting with the peer certificate and progressing ...
Definition: gssl.cpp:164
std::string protocol() const
Returns the protocol version like "TLSv1.2" or the empty string.
Definition: gssl.cpp:169
Result write(const char *buffer, std::size_t data_size_in, ssize_t &data_size_out)
Writes user data.
Definition: gssl.cpp:208
Result connect(G::ReadWrite &io)
Starts the protocol actively (as a client).
Definition: gssl.cpp:193
Result accept(G::ReadWrite &io)
Starts the protocol passively (as a server).
Definition: gssl.cpp:198
std::string peerCertificate() const
Returns the peer certificate in PEM format.
Definition: gssl.cpp:159
A general-purpose exception class derived from std::exception and containing an error message.
Definition: gexception.h:45
An abstract interface for reading and writing from a non-blocking i/o channel.
Definition: greadwrite.h:50
static std::string join(const std::string &sep, const StringArray &strings)
Concatenates an array of strings with separators.
Definition: gstr.cpp:1195
static void splitIntoTokens(const std::string &in, StringArray &out, string_view ws, char esc='\0')
Splits the string into 'ws'-delimited tokens.
Definition: gstr.cpp:1073
An interface to an underlying TLS library.
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:31