E-MailRelay
gssl.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 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
51#ifndef G_LIB_SMALL
53{
54 return true ;
55}
56#endif
57
59{
60 return m_this ;
61}
62
64{
65 return m_imp != nullptr ;
66}
67
68#ifndef G_LIB_SMALL
69std::string GSsl::Library::id() const
70{
71 return m_imp->id() ;
72}
73#endif
74
75void GSsl::Library::addProfile( const std::string & profile_name , bool is_server_profile ,
76 const std::string & key_file , const std::string & cert_file , const std::string & ca_file ,
77 const std::string & default_peer_certificate_name , const std::string & default_peer_host_name ,
78 const std::string & profile_config )
79{
80 if( m_imp != nullptr )
81 m_imp->addProfile( profile_name , is_server_profile , key_file , cert_file , ca_file ,
82 default_peer_certificate_name , default_peer_host_name , profile_config ) ;
83}
84
85bool GSsl::Library::hasProfile( const std::string & profile_name ) const
86{
87 return m_imp->hasProfile( profile_name ) ;
88}
89
90const GSsl::Profile & GSsl::Library::profile( const std::string & profile_name ) const
91{
92 if( !imp().hasProfile(profile_name) )
93 throw BadProfileName( profile_name ) ;
94 return imp().profile( profile_name ) ;
95}
96
97bool GSsl::Library::enabledAs( const std::string & profile_name )
98{
99 return instance() != nullptr && instance()->enabled() && instance()->hasProfile( profile_name ) ;
100}
101
103{
104 if( instance() == nullptr )
105 throw NoInstance() ;
106 return instance()->imp() ;
107}
108
109GSsl::LibraryImpBase & GSsl::Library::imp()
110{
111 if( m_imp == nullptr )
112 throw NoInstance() ;
113 return *m_imp ;
114}
115
116const GSsl::LibraryImpBase & GSsl::Library::imp() const
117{
118 if( m_imp == nullptr )
119 throw NoInstance() ;
120 return *m_imp ;
121}
122
123void GSsl::Library::log( int level , const std::string & log_line )
124{
125 if( level == 1 )
126 G_DEBUG( "GSsl::Library::log: tls: " << log_line ) ;
127 else if( level == 2 )
128 G_LOG( "GSsl::Library::log: tls: " << log_line ) ;
129 else
130 G_WARNING( "GSsl::Library::log: tls: " << log_line ) ;
131}
132
134{
135 return instance() == nullptr || instance()->m_imp == nullptr ? G::StringArray() : impstance().digesters(require_state) ;
136}
137
138GSsl::Digester GSsl::Library::digester( const std::string & hash_function , const std::string & state , bool need_state ) const
139{
140 return impstance().digester( hash_function , state , need_state ) ;
141}
142
143// ==
144
145GSsl::Protocol::Protocol( const Profile & profile , const std::string & peer_certificate_name , const std::string & peer_host_name ) :
146 m_imp( profile.newProtocol(peer_certificate_name,peer_host_name) )
147{
148}
149
151= default;
152
154{
155 return m_imp->peerCertificate() ;
156}
157
158#ifndef G_LIB_SMALL
160{
161 return m_imp->peerCertificateChain() ;
162}
163#endif
164
165std::string GSsl::Protocol::protocol() const
166{
167 return m_imp->protocol() ;
168}
169
170std::string GSsl::Protocol::cipher() const
171{
172 return m_imp->cipher() ;
173}
174
175#ifndef G_LIB_SMALL
177{
178 return m_imp->verified() ;
179}
180#endif
181
182std::string GSsl::Protocol::str( Result result )
183{
184 if( result == Result::ok ) return "Result_ok" ;
185 if( result == Result::read ) return "Result_read" ;
186 if( result == Result::write ) return "Result_write" ;
187 if( result == Result::error ) return "Result_error" ;
188 return "Result_undefined" ;
189}
190
191GSsl::Protocol::Result GSsl::Protocol::connect( G::ReadWrite & io )
192{
193 return m_imp->connect( io ) ;
194}
195
196GSsl::Protocol::Result GSsl::Protocol::accept( G::ReadWrite & io )
197{
198 return m_imp->accept( io ) ;
199}
200
201GSsl::Protocol::Result GSsl::Protocol::read( char * buffer , std::size_t buffer_size_in , ssize_t & data_size_out )
202{
203 return m_imp->read( buffer , buffer_size_in , data_size_out ) ;
204}
205
206GSsl::Protocol::Result GSsl::Protocol::write( const char * buffer , std::size_t data_size_in , ssize_t & data_size_out)
207{
208 return m_imp->write( buffer , data_size_in , data_size_out ) ;
209}
210
211GSsl::Protocol::Result GSsl::Protocol::shutdown()
212{
213 return m_imp->shutdown() ;
214}
215
216// ==
217
218GSsl::Digester::Digester( std::unique_ptr<DigesterImpBase> p ) :
219 m_imp(p.release())
220{
221}
222
223void GSsl::Digester::add( std::string_view sv )
224{
225 m_imp->add( sv ) ;
226}
227
229{
230 return m_imp->value() ;
231}
232
234{
235 return m_imp->state() ;
236}
237
238std::size_t GSsl::Digester::blocksize() const noexcept
239{
240 return m_imp->blocksize() ;
241}
242
243std::size_t GSsl::Digester::valuesize() const noexcept
244{
245 return m_imp->valuesize() ;
246}
247
248std::size_t GSsl::Digester::statesize() const noexcept
249{
250 return m_imp->statesize() ;
251}
252
253// ==
254
255bool GSsl::LibraryImpBase::consume( G::StringArray & list , std::string_view key )
256{
257 auto p = std::find( list.begin() , list.end() , G::sv_to_string(key) ) ;
258 if( p != list.end() )
259 {
260 list.erase( p ) ;
261 return true ;
262 }
263 else
264 {
265 return false ;
266 }
267}
268
A class for objects that can perform a cryptographic hash.
Definition: gssl.h:215
std::string value()
Returns the hash value.
Definition: gssl.cpp:228
std::size_t statesize() const noexcept
Returns the size of the state() string in bytes, or zero if state() is not implemented.
Definition: gssl.cpp:248
std::string state()
Returns the intermediate state.
Definition: gssl.cpp:233
void add(std::string_view)
Adds data of arbitrary size.
Definition: gssl.cpp:223
std::size_t blocksize() const noexcept
Returns the hash function's block size in bytes.
Definition: gssl.cpp:238
std::size_t valuesize() const noexcept
Returns the hash function's value size in bytes.
Definition: gssl.cpp:243
Digester(std::unique_ptr< DigesterImpBase >)
Constructor, used by the Library class.
Definition: gssl.cpp:218
A base interface for GSsl::Library pimple classes.
Definition: gssl.h:385
static bool consume(G::StringArray &list, std::string_view item)
A convenience function that removes the item from the list and returns true iff is was removed.
Definition: gssl.cpp:255
A singleton class for initialising the underlying TLS library.
Definition: gssl.h:255
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:97
bool hasProfile(const std::string &profile_name) const
Returns true if the named profile has been add()ed.
Definition: gssl.cpp:85
static Library * instance()
Returns a pointer to a library object, if any.
Definition: gssl.cpp:58
std::string id() const
Returns the TLS library name and version.
Definition: gssl.cpp:69
static LibraryImpBase & impstance()
Returns a reference to the pimple object when enabled().
Definition: gssl.cpp:102
static bool real()
Returns true if this is a real TLS library.
Definition: gssl.cpp:52
Library(bool active=true, const std::string &library_config={}, LogFn=Library::log, bool verbose=true)
Constructor.
Definition: gssl.cpp:30
void addProfile(const std::string &profile_name, bool is_server_profile, const std::string &key_file={}, const std::string &cert_file={}, const std::string &ca_path={}, const std::string &default_peer_certificate_name={}, const std::string &default_peer_host_name={}, const std::string &profile_config={})
Creates a named Profile object that can be retrieved by profile().
Definition: gssl.cpp:75
const Profile & profile(const std::string &profile_name) const
Returns an opaque reference to the named profile.
Definition: gssl.cpp:90
bool enabled() const
Returns true if this is a real TLS library and the constructor's active parameter was set.
Definition: gssl.cpp:63
Digester digester(const std::string &name, const std::string &state={}, bool need_state=false) const
Returns a digester object.
Definition: gssl.cpp:138
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:133
~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:123
A base interface for profile classes that work with concrete classes derived from GSsl::LibraryImpBas...
Definition: gssl.h:419
~Protocol()
Destructor.
Result shutdown()
Initiates the protocol shutdown by sending a "close notify shutdown alert" and does a socket shutdown...
Definition: gssl.cpp:211
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:201
Protocol(const Profile &, const std::string &peer_certificate_name={}, const std::string &peer_host_name={})
Constructor.
Definition: gssl.cpp:145
std::string cipher() const
Returns the cipher name, or the empty string if not yet available.
Definition: gssl.cpp:170
bool verified() const
Returns true if the peer certificate has been verified.
Definition: gssl.cpp:176
static std::string str(Result result)
Converts a result enumeration into a printable string.
Definition: gssl.cpp:182
std::string peerCertificateChain() const
Returns the peer certificate chain in PEM format, starting with the peer certificate and progressing ...
Definition: gssl.cpp:159
std::string protocol() const
Returns the protocol version like "TLSv1.2" or the empty string.
Definition: gssl.cpp:165
Result write(const char *buffer, std::size_t data_size_in, ssize_t &data_size_out)
Writes user data.
Definition: gssl.cpp:206
Result connect(G::ReadWrite &io)
Starts the protocol actively (as a client).
Definition: gssl.cpp:191
Result accept(G::ReadWrite &io)
Starts the protocol passively (as a server).
Definition: gssl.cpp:196
std::string peerCertificate() const
Returns the peer certificate in PEM format.
Definition: gssl.cpp:153
An abstract interface for reading and writing from a non-blocking i/o channel.
Definition: greadwrite.h:50
static void splitIntoTokens(const std::string &in, StringArray &out, std::string_view ws, char esc='\0')
Splits the string into 'ws'-delimited tokens.
Definition: gstr.cpp:1119
static std::string join(std::string_view sep, const StringArray &strings)
Concatenates an array of strings with separators.
Definition: gstr.cpp:1221
An interface to an underlying TLS library.
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30