VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gssl.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
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.h
19 ///
20 /// An interface to an underlying TLS library.
21 ///
22 
23 #ifndef G_SSL_H
24 #define G_SSL_H
25 
26 #include "gdef.h"
27 #include "greadwrite.h"
28 #include <string>
29 #include <utility>
30 
31 namespace GSsl
32 {
33  class Library ;
34  class Profile ;
35  class Protocol ;
36  class LibraryImp ;
37  class ProtocolImp ;
38 }
39 
40 /// \class GSsl::Protocol
41 /// A TLS protocol class. A protocol object should be constructed for each
42 /// secure socket. The Protocol::connect() and Protocol::accept() methods
43 /// are used to link the connection's i/o methods with the Protocol object.
44 /// Event handling for the connection is performed by the client code
45 /// according to the result codes from read(), write(), connect() and
46 /// accept().
47 ///
48 /// Client code will generally need separate states to reflect an incomplete
49 /// read(), write(), connect() or accept() in order that they can be retried.
50 /// The distinction between a return code of Result_read or Result_write
51 /// should dictate whether the connection is put into the event loop's read
52 /// list or write list but it should not influence the resulting state; in
53 /// each state socket read events and write events can be handled identically,
54 /// by retrying the incomplete function call.
55 ///
56 /// The protocol is half-duplex in the sense that it is not possible to read()
57 /// data while a write() is incomplete or write() data while a read() is
58 /// incomplete. (Nor is it allowed to issue a second call while the first is
59 /// still incomplete.)
60 ///
61 /// All logging is done indirectly through a logging function pointer; the
62 /// first parameter is the logging level which is 1 for verbose debug
63 /// messages, 2 for useful information, and 3 for warnings and errors.
64 ///
66 {
67 public:
68  typedef size_t size_type ;
69  typedef ssize_t ssize_type ;
70  enum Result { Result_ok , Result_read , Result_write , Result_error , Result_more } ;
71  typedef void (*LogFn)( int , const std::string & ) ;
72 
73  explicit Protocol( const Profile & , LogFn log_fn ) ;
74  ///< Constructor.
75 
76  ~Protocol() ;
77  ///< Destructor.
78 
79  Result connect( G::ReadWrite & io ) ;
80  ///< Starts the protocol actively (as a client).
81 
82  Result accept( G::ReadWrite & io ) ;
83  ///< Starts the protocol passively (as a server).
84 
85  Result stop() ;
86  ///< Initiates the protocol shutdown.
87 
88  Result read( char * buffer , size_type buffer_size_in , ssize_type & data_size_out ) ;
89  ///< Reads user data into the supplied buffer.
90  ///<
91  ///< Returns Result_read if there is not enough transport data
92  ///< to complete the internal TLS data packet. In this case the
93  ///< file descriptor should remain in the select() read list and
94  ///< the Protocol::read() should be retried using the same parameters
95  ///< once the file descriptor is ready to be read.
96  ///<
97  ///< Returns Result_write if the TLS layer tried to write to the
98  ///< file descriptor and had flow control asserted. In this case
99  ///< the file descriptor should be added to the select() write
100  ///< list and the Protocol::read() should be retried using the
101  ///< same parameters once the file descriptor is ready to be
102  ///< written.
103  ///<
104  ///< Returns Result_ok if the internal TLS data packet is complete
105  ///< and it has been completely deposited in the supplied buffer.
106  ///<
107  ///< Returns Result_more if the internal TLS data packet is complete
108  ///< and the supplied buffer was too small to take it all. In this
109  ///< case there will be no read event to trigger more read()s, so
110  ///< beware of stalling.
111  ///<
112  ///< Returns Result_error if the transport connnection was lost
113  ///< or if the TLS session was shut down by the peer or on error.
114 
115  Result write( const char * buffer , size_type data_size_in , ssize_type & data_size_out ) ;
116  ///< Writes user data.
117  ///<
118  ///< Returns Result_ok if fully sent.
119  ///<
120  ///< Returns Result_read if the TLS layer needs more transport
121  ///< data (eg. for a renegotiation). The write() should be repeated
122  ///< using the same parameters on the file descriptor's next
123  ///< readable event.
124  ///<
125  ///< Returns Result_write if the TLS layer was blocked in
126  ///< writing transport data. The write() should be repeated
127  ///< using the same parameters on the file descriptor's next
128  ///< writable event.
129  ///<
130  ///< Never returns Result_more.
131  ///<
132  ///< Returns Result_error if the transport connnection was lost
133  ///< or if the TLS session was shut down by the peer or on error.
134 
135  static std::string str( Result result ) ;
136  ///< Converts a result enumeration into a printable string.
137  ///< Used in logging and diagnostics.
138 
139  std::pair<std::string,bool> peerCertificate( int format = 0 ) ;
140  ///< Returns the peer certificate and a verified flag.
141  ///< The default format of the certificate is printable
142  ///< with embedded newlines. Depending on the implementation
143  ///< it may be in PEM format, which can be interpreted using
144  ///< (eg.) "openssl x509 -in foo.pem -noout -text".
145 
146 private:
147  Protocol( const Protocol & ) ; // not implemented
148  void operator=( const Protocol & ) ; // not implemented
149 
150 private:
151  ProtocolImp * m_imp ;
152 } ;
153 
154 /// \class GSsl::Library
155 /// A singleton class for initialising the underlying TLS library.
156 ///
158 {
159 public:
160  explicit Library( bool active = true , const std::string & extra_config = std::string() ) ;
161  ///< Constructor. The 'active' parameter can be set to false as an
162  ///< optimisation if the library is not going to be used; calls to
163  ///< add() will do nothing, calls to has() will return false, and calls
164  ///< to profile() will throw.
165 
166  explicit Library( bool active , const std::string & server_key_and_cert_file ,
167  const std::string & server_ca_file , const std::string & extra_config = std::string() ) ;
168  ///< A convenience constructor that adds two profiles; one called
169  ///< "server" using the two files, and one called "client".
170 
171  ~Library() ;
172  ///< Destructor. Cleans up the underlying TLS library.
173 
174  static Library * instance() ;
175  ///< Returns a pointer to a library object, if any.
176 
177  void add( const std::string & profile_name , const std::string & key_and_cert_file = std::string() ,
178  const std::string & ca_file = std::string() , const std::string & profile_extra_config = std::string() ) ;
179  ///< Creates a named Profile object that can be retrieved by profile().
180  ///<
181  ///< A typical application will have two profiles named "client" and "server".
182  ///<
183  ///< The "key-and-cert-file" parameter points to a file containing our own
184  ///< key and certificate. This is mandatory if acting as a server, ie. using
185  ///< Protocol::accept().
186  ///<
187  ///< The "ca-file" parameter points to a file (or possibly a directory)
188  ///< containing a list of CA certificates. If this is supplied then peer
189  ///< certificates will be requested and verified. Special values of
190  ///< "<none>" and "<default>" have the obvious meaning. A "client" profile
191  ///< will normally use "<default>" so that it can verify the server.
192  ///<
193  ///< The profile-extra-config string should be empty by default; the format
194  ///< and interpretation are undefined at this interface. An extra-config
195  ///< string can also be supplied to the Protocol, in which case this config
196  ///< string is completely ignored.
197 
198  bool has( const std::string & profile_name ) const ;
199  ///< Returns true if the named profile has been add()ed.
200 
201  const Profile & profile( const std::string & profile_name ) const ;
202  ///< Returns an opaque reference to the named profile. The profile
203  ///< can be used to construct a protocol instance.
204 
205  bool enabled() const ;
206  ///< Returns true if this is a real TLS library and the constructor's active
207  ///< parameter was set.
208 
209  static std::string id() ;
210  ///< Returns a library identifier (typically name and version).
211 
212  static std::string credit( const std::string & prefix , const std::string & eol , const std::string & eot ) ;
213  ///< Returns a library credit string.
214 
215 private:
216  friend class GSsl::Profile ;
217  Library( const Library & ) ; // not implemented
218  void operator=( const Library & ) ; // not implemented
219  const LibraryImp & imp() const ;
220  LibraryImp & imp() ;
221 
222 private:
223  static Library * m_this ;
224  LibraryImp * m_imp ;
225 } ;
226 
227 #endif
static Library * instance()
Returns a pointer to a library object, if any.
Definition: gssl_none.cpp:46
Protocol(const Profile &, LogFn log_fn)
Constructor.
Definition: gssl_none.cpp:82
An abstract interface for reading and writing from a non-blocking i/o channel.
Definition: greadwrite.h:49
bool has(const std::string &profile_name) const
Returns true if the named profile has been add()ed.
Definition: gssl_none.cpp:55
void add(const std::string &profile_name, const std::string &key_and_cert_file=std::string(), const std::string &ca_file=std::string(), const std::string &profile_extra_config=std::string())
Creates a named Profile object that can be retrieved by profile().
Definition: gssl_none.cpp:51
A TLS protocol class.
Definition: gssl.h:65
static std::string str(Result result)
Converts a result enumeration into a printable string.
Definition: gssl_none.cpp:115
~Library()
Destructor. Cleans up the underlying TLS library.
Definition: gssl_none.cpp:40
std::pair< std::string, bool > peerCertificate(int format=0)
Returns the peer certificate and a verified flag.
Definition: gssl_none.cpp:120
Library(bool active=true, const std::string &extra_config=std::string())
Constructor.
Definition: gssl_none.cpp:28
Result stop()
Initiates the protocol shutdown.
Definition: gssl_none.cpp:100
Result accept(G::ReadWrite &io)
Starts the protocol passively (as a server).
Definition: gssl_none.cpp:95
Result connect(G::ReadWrite &io)
Starts the protocol actively (as a client).
Definition: gssl_none.cpp:90
static std::string credit(const std::string &prefix, const std::string &eol, const std::string &eot)
Returns a library credit string.
Definition: gssl_none.cpp:75
const Profile & profile(const std::string &profile_name) const
Returns an opaque reference to the named profile.
Definition: gssl_none.cpp:60
Result read(char *buffer, size_type buffer_size_in, ssize_type &data_size_out)
Reads user data into the supplied buffer.
Definition: gssl_none.cpp:105
A singleton class for initialising the underlying TLS library.
Definition: gssl.h:157
static std::string id()
Returns a library identifier (typically name and version).
Definition: gssl_none.cpp:70
~Protocol()
Destructor.
Definition: gssl_none.cpp:86
bool enabled() const
Returns true if this is a real TLS library and the constructor's active parameter was set...
Definition: gssl_none.cpp:65
Result write(const char *buffer, size_type data_size_in, ssize_type &data_size_out)
Writes user data.
Definition: gssl_none.cpp:110