Bond's TCP Library  1.0
Bond's TCP Client/Server Library
tcpssl.cpp
1 #include <iostream>
2 #include <cstring>
3 #include <openssl/bio.h>
4 #include <openssl/err.h>
5 #include <openssl/pem.h>
6 #include <openssl/conf.h>
7 #include <openssl/x509.h>
8 #include <openssl/buffer.h>
9 #include <openssl/x509v3.h>
10 #include <openssl/opensslconf.h>
11 #include "tcpssl.h"
12 
13 namespace tcp {
14 
15 using namespace std;
16 
17 bool sslinitialized_ {false};
18 
20 {
21  if (!sslinitialized_) {
22  SSL_library_init();
23  OpenSSL_add_all_algorithms();
24  SSL_load_error_strings();
25  ERR_load_crypto_strings();
26  OpenSSL_add_all_ciphers();
27  sslinitialized_ = true;
28  clog << "OpenSSL library initialized" << endl;
29  }
30 }
31 
33 {
34  ERR_free_strings();
35 }
36 
37 void print_error_string(unsigned long err, const char* const label)
38 {
39  const char* const str = ERR_reason_error_string(err);
40  if(str)
41  cerr << label << ": " << str << endl;
42  else
43  cerr << label << " failed: " << err << hex << " (0x" << err << dec << endl;
44 }
45 
46 int printSSLErrors_cb(const char *str, size_t len, void *u)
47 {
48  (void)u;
49  for (size_t i=0;i<len;i++) {
50  cerr.put(str[i]);
51  }
52  cerr << endl;
53  return 1;
54 }
55 
57 {
58  ERR_print_errors_fp(stdout);
59  ERR_print_errors_cb(&printSSLErrors_cb,NULL);
60 }
61 
62 int wildcmp(const char *wild, const char *string) {
63  // Written by Jack Handy - <A href="mailto:jakkhandy@hotmail.com">jakkhandy@hotmail.com</A>
64  const char *cp = NULL, *mp = NULL;
65 
66  while ((*string) && (*wild != '*')) {
67  if ((*wild != *string) && (*wild != '?')) {
68  return 0;
69  }
70  wild++;
71  string++;
72  }
73 
74  while (*string) {
75  if (*wild == '*') {
76  if (!*++wild) {
77  return 1;
78  }
79  mp = wild;
80  cp = string+1;
81  } else if ((*wild == *string) || (*wild == '?')) {
82  wild++;
83  string++;
84  } else {
85  wild = mp;
86  string = cp++;
87  }
88  }
89 
90  while (*wild == '*') {
91  wild++;
92  }
93  return !*wild;
94 }
95 
97 void print_cn_name(const char* label, X509_NAME* const name)
98 {
99  int idx = -1, success = 0;
100  unsigned char *utf8 = NULL;
101 
102  do {
103  if(!name) break; /* failed */
104 
105  idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
106  if(!(idx > -1)) break; /* failed */
107 
108  X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
109  if(!entry) break; /* failed */
110 
111  ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
112  if(!data) break; /* failed */
113 
114  int length = ASN1_STRING_to_UTF8(&utf8, data);
115  if(!utf8 || !(length > 0)) break; /* failed */
116 
117  clog << " " << label << ": " << utf8 << endl;
118 
119  success = 1;
120 
121  } while (0);
122 
123  if(utf8)
124  OPENSSL_free(utf8);
125 
126  if(!success)
127  clog << " " << label << ": <not available>" << endl;
128 }
129 
131 void print_san_name(const char* label, X509* const cert)
132 {
133  int success = 0;
134  GENERAL_NAMES* names = NULL;
135  unsigned char* utf8 = NULL;
136 
137  do {
138  if(!cert) break; /* failed */
139 
140  names = (GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
141  if(!names) break;
142 
143  int i = 0, count = sk_GENERAL_NAME_num(names);
144  if(!count) break; /* failed */
145 
146  for( i = 0; i < count; ++i )
147  {
148  GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
149  if(!entry) continue;
150 
151  if(GEN_DNS == entry->type)
152  {
153  int len1 = 0, len2 = -1;
154 
155  len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
156  if(utf8) {
157  len2 = (int)strlen((const char*)utf8);
158  }
159 
160  if(len1 != len2) {
161  cerr << " Strlen and ASN1_STRING size do not match (embedded null?): " << len2 << " vs " << len1 << endl;
162  }
163 
164  /* If there's a problem with string lengths, then */
165  /* we skip the candidate and move on to the next. */
166  /* Another policy would be to fails since it probably */
167  /* indicates the client is under attack. */
168  if(utf8 && len1 && len2 && (len1 == len2)) {
169  clog << " " << label << ": " << utf8 << endl;
170  success = 1;
171  }
172 
173  if(utf8) {
174  OPENSSL_free(utf8), utf8 = NULL;
175  }
176  } else {
177  clog << " Unknown GENERAL_NAME type: " << entry->type << endl;
178  }
179  }
180 
181  } while (0);
182 
183  if(names)
184  GENERAL_NAMES_free(names);
185 
186  if(utf8)
187  OPENSSL_free(utf8);
188 
189  if(!success)
190  clog << " " << label << ": <not available>" << endl;
191 
192 }
193 
195 int verify_callback(int preverify, X509_STORE_CTX* x509_ctx)
196 {
197  int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
198  int err = X509_STORE_CTX_get_error(x509_ctx);
199  (void)err;
200 
201  X509* cert = X509_STORE_CTX_get_current_cert(x509_ctx);
202  X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL;
203  X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL;
204 
205  print_cn_name("Issuer (cn)", iname);
206  print_cn_name("Subject (cn)", sname);
207 
208  if(depth == 0) {
209  /* If depth is 0, its the server's certificate. Print the SANs too */
210  print_san_name("Subject (san)", cert);
211  }
212 
213  if (preverify) {
214  clog << "Certificate verification passed" << endl;
215  } else {
216  clog << "Certificate verification failed" << endl;
217  }
218 
219  return preverify;
220 }
221 
222 int ctx_password_callback(char *buf, int size, int rwflag, void *userdata)
223 {
224  SSLContext *ctx = (SSLContext*)userdata;
225  if (ctx != NULL) {
226  return ctx->passwordCallback(buf,size,rwflag);
227  } else {
228  return 0;
229  }
230 }
231 
232 int ssl_password_callback(char *buf, int size, int rwflag, void *userdata)
233 {
234  SSL *ssl = (SSL*)userdata;
235  if (ssl != NULL) {
236  return ssl->passwordCallback(buf,size,rwflag);
237  } else {
238  return 0;
239  }
240 }
241 
242 SSLContext::SSLContext(SSLMode mode) : mode_(mode)
243 {
244  initSSLLibrary();
245  const SSL_METHOD *meth = (mode == SSLMode::SERVER) ? TLS_server_method() : TLS_client_method();
246  unsigned long ssl_err = ERR_get_error();
247  if (meth == NULL) {
248  print_error_string(ssl_err, "TLS_method");
249  return;
250  }
251  ctx_ = SSL_CTX_new(meth);
252  ssl_err = ERR_get_error();
253  if (ctx_ == NULL) {
254  print_error_string(ssl_err, "SSL_CTX_new");
255  return;
256  }
257 }
258 
260 {
261  SSL_CTX_free(ctx_);
262 }
263 
264 void SSLContext::setOptions(bool verifypeer, bool compression, bool tlsonly)
265 {
266  long flags = 0;
267 
268  if (verifypeer) {
269  if (mode_ == SSLMode::SERVER) {
270  SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, verify_callback);
271  } else {
272  SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER, verify_callback);
273  }
274  } else {
275  SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, NULL);
276  }
277  SSL_CTX_set_verify_depth(ctx_, 4);
278 
279  if (tlsonly) {
280  flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
281  SSL_CTX_set_min_proto_version(ctx_,TLS1_VERSION);
282  } else {
283  flags = SSL_OP_ALL;
284  }
285 
286  if (!compression) {
287  flags |= SSL_OP_NO_COMPRESSION;
288  }
289 
290  SSL_CTX_set_options(ctx_, flags);
291 
292  printSSLErrors();
293 }
294 
295 bool SSLContext::setVerifyPaths(string &cafile, string &capath)
296 {
297  char *cafile_ {nullptr};
298  char *capath_ {nullptr};
299  if (!cafile.empty()) {
300  cafile_ = (char*)malloc(cafile.length()+1);
301  strcpy(cafile_,cafile.c_str());
302  }
303  if (!capath.empty()) {
304  capath_ = (char*)malloc(capath.length()+1);
305  strcpy(capath_,capath.c_str());
306  }
307  bool result = setVerifyPaths(cafile_,capath_);
308  if (cafile_)
309  free(cafile_);
310  if (capath_)
311  free(capath_);
312  return result;
313 }
314 
315 bool SSLContext::setVerifyPaths(const char *cafile, const char *capath)
316 {
317  long res = 1;
318  unsigned long ssl_err = 0;
319 
320  if (cafile || capath) {
321  res = SSL_CTX_load_verify_locations(ctx_, cafile, capath);
322  ssl_err = ERR_get_error();
323  if (res == 0) {
324  print_error_string(ssl_err,"SSL_CTX_load_verify_locations");
325  return false;
326  }
327  } else {
328  res = SSL_CTX_set_default_verify_paths(ctx_);
329  ssl_err = ERR_get_error();
330  if (res == 0) {
331  print_error_string(ssl_err,"SSL_CTX_set_default_verify_paths");
332  return false;
333  }
334  }
335 
336  printSSLErrors();
337  return true;
338 }
339 
340 bool SSLContext::setCertificateAndKey(const char *certfile, const char *keyfile)
341 {
342  long res = 1;
343  unsigned long ssl_err = 0;
344 
345  if ((certfile && !keyfile) || (!certfile && keyfile)) {
346  cerr << "Error: Both a certificate and a private key file are required" << endl;
347  return false;
348  }
349 
350  if (certfile && keyfile) {
351  res = SSL_CTX_use_certificate_file(ctx_, certfile, SSL_FILETYPE_PEM);
352  ssl_err = ERR_get_error();
353  if ( res != 1) {
354  print_error_string(ssl_err,"SSL_CTX_use_certificate_file");
355  return false;
356  }
357 
358  res = SSL_CTX_use_PrivateKey_file(ctx_, keyfile, SSL_FILETYPE_PEM);
359  ssl_err = ERR_get_error();
360  if (res != 1) {
361  print_error_string(ssl_err,"SSL_CTX_use_PrivateKey_file");
362  return false;
363  }
364 
365  /* Make sure the key and certificate file match. */
366  res = SSL_CTX_check_private_key(ctx_);
367  ssl_err = ERR_get_error();
368  if ( res != 1) {
369  print_error_string(ssl_err,"SSL_CTX_check_private_key");
370  return false;
371  }
372 
373  SSL_CTX_set_default_passwd_cb(ctx_,&ctx_password_callback);
374  SSL_CTX_set_default_passwd_cb_userdata(ctx_,this);
375 
376  return true;
377  } else {
378  return false;
379  }
380 }
381 
382 int SSLContext::passwordCallback(char *buf, int size, int rwflag)
383 {
384  (void)rwflag;
385  if (!keypass_.empty()) {
386  int lsize = max<int>(size,keypass_.length());
387  strncpy(buf,keypass_.c_str(),lsize);
388  return lsize;
389  } else {
390  return 0;
391  }
392 }
393 
394 /* SSL */
395 
396 SSL::SSL(DataSocket &owner, SSLContext &context) : owner_(owner)
397 {
398  mode_ = context.mode_;
399  ssl_ = SSL_new(context.ctx_);
400 }
401 
403 {
404  SSL_free(ssl_);
405 }
406 
407 void SSL::setOptions(bool verifypeer)
408 {
409  if (verifypeer) {
410  SSL_set_verify(ssl_, SSL_VERIFY_PEER, verify_callback);
411  } else {
412  SSL_set_verify(ssl_, SSL_VERIFY_NONE, NULL);
413  }
414 
415  printSSLErrors();
416 }
417 
418 bool SSL::setCertificateAndKey(const char *certfile, const char *keyfile)
419 {
420  long res = 1;
421  unsigned long ssl_err = 0;
422 
423  if ((certfile && !keyfile) || (!certfile && keyfile)) {
424  cerr << "Error: Both a certificate and a private key file are required" << endl;
425  return false;
426  }
427 
428  if (certfile && keyfile) {
429  res = SSL_use_certificate_file(ssl_, certfile, SSL_FILETYPE_PEM);
430  ssl_err = ERR_get_error();
431  if ( res != 1) {
432  print_error_string(ssl_err,"SSL_use_certificate_file");
433  return false;
434  }
435 
436  res = SSL_use_PrivateKey_file(ssl_, keyfile, SSL_FILETYPE_PEM);
437  ssl_err = ERR_get_error();
438  if (res != 1) {
439  print_error_string(ssl_err,"SSL_use_PrivateKey_file");
440  return false;
441  }
442 
443  /* Make sure the key and certificate file match. */
444  res = SSL_check_private_key(ssl_);
445  ssl_err = ERR_get_error();
446  if ( res != 1) {
447  print_error_string(ssl_err,"SSL_CTX_check_private_key");
448  return false;
449  }
450 
451  SSL_set_default_passwd_cb(ssl_,&ssl_password_callback);
452  SSL_set_default_passwd_cb_userdata(ssl_,this);
453 
454  return true;
455  } else {
456  return false;
457  }
458 }
459 
460 int SSL::passwordCallback(char *buf, int size, int rwflag)
461 {
462  (void)rwflag;
463  if (!keypass_.empty()) {
464  int lsize = max<int>(size,keypass_.length());
465  strncpy(buf,keypass_.c_str(),lsize);
466  return lsize;
467  } else {
468  return 0;
469  }
470 }
471 
472 bool SSL::setfd(int socket)
473 {
474  if (socket == 0) {
475  cerr << "SSL::setfd: socket is NULL" << endl;
476  return false;
477  } else {
478  int res = SSL_set_fd(ssl_,socket);
479  if (res != 1) {
480  unsigned long ssl_err = ERR_get_error();
481  print_error_string(ssl_err,"SSL::set_fd");
482  return false;
483  } else {
484  return true;
485  }
486  }
487 }
488 
490 {
491  if (!subjectName_.empty()) {
492  return subjectName_;
493  }
494 
495  X509 *cert = SSL_get_peer_certificate(ssl_);
496  if (cert) {
497  X509_NAME* sname = X509_get_subject_name(cert);
498  if (sname) {
499 
500  int idx = -1;
501  unsigned char *utf8 = NULL;
502 
503  do {
504  idx = X509_NAME_get_index_by_NID(sname, NID_commonName, -1);
505  if(!(idx > -1)) break; /* failed */
506 
507  X509_NAME_ENTRY* entry = X509_NAME_get_entry(sname, idx);
508  if(!entry) break; /* failed */
509 
510  ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
511  if(!data) break; /* failed */
512 
513  int length = ASN1_STRING_to_UTF8(&utf8, data);
514  if(!utf8 || !(length > 0)) break; /* failed */
515 
516  subjectName_.assign((char*)utf8);
517 
518  } while (0);
519 
520  if(utf8)
521  OPENSSL_free(utf8);
522  }
523  X509_free(cert);
524  }
525  return subjectName_;
526 }
527 
528 bool SSL::validateSubjectName(const string &subjectName, const string &hostname)
529 {
530  return wildcmp(subjectName.c_str(),hostname.c_str());
531 }
532 
534 {
535  if (!verifyResult()) {
536  cerr << "Peer certificate validation failed" << endl;
537  return false;
538  } else {
539 
540  if (!getSubjectName().empty()) {
542  if (!validateSubjectName(subjectName_,hostname_)) {
543  cerr << "Peer certificate subject name '" << subjectName_ << "' does not match host name '" << hostname_ << "'" << endl;
544  return false;
545  }
546  }
547 
548  }
549 
550  return true;
551 }
552 
554 {
555  return (SSL_get_verify_result(ssl_) == X509_V_OK);
556 }
557 
559 {
560  int res = SSL_connect(ssl_);
561  if (res <= 0) {
562  unsigned long ssl_err = ERR_get_error();
563  switch (ssl_err) {
564  case SSL_ERROR_NONE: return true;
565  case SSL_ERROR_WANT_READ: wantsRead(); return connect(); break;
566  case SSL_ERROR_WANT_WRITE: wantsWrite(); return connect(); break;
567  default: print_error_string(ssl_err,"SSL_connect");
568  }
569  printSSLErrors();
570  return false;
571  } else {
572  return true;
573  }
574 }
575 
577 {
578  int res = SSL_accept(ssl_);
579  if (res <= 0) {
580  unsigned long ssl_err = ERR_get_error();
581  switch (ssl_err) {
582  case SSL_ERROR_NONE: return true;
583  case SSL_ERROR_WANT_READ: wantsRead(); return accept(); break;
584  case SSL_ERROR_WANT_WRITE: wantsWrite(); return accept(); break;
585  default: print_error_string(ssl_err,"SSL_accept");
586  }
587  printSSLErrors();
588  return false;
589  } else {
590  return true;
591  }
592 }
593 
594 size_t SSL::read(void *buffer, size_t size)
595 {
598 
599  int res = SSL_read(ssl_,buffer,size);
600  if (res <= 0) {
601  unsigned long ssl_err = SSL_get_error(ssl_,res);
602  switch (ssl_err) {
603  case SSL_ERROR_NONE: return 0;
604  case SSL_ERROR_WANT_READ: return 0; break;
605  case SSL_ERROR_WANT_WRITE: wantsWrite(); return read(buffer,size); break;
606  default: print_error_string(ssl_err,"SSL_read"); return 0;
607  }
608  } else {
609  return res;
610  }
611 }
612 
613 size_t SSL::write(const void *buffer, size_t size)
614 {
617 
618  int res = SSL_write(ssl_,buffer,size);
619  if (res <= 0) {
620  unsigned long ssl_err = SSL_get_error(ssl_,res);
621  switch (ssl_err) {
622  case SSL_ERROR_NONE: return 0;
623  case SSL_ERROR_WANT_READ: wantsRead(); return write(buffer,size); break;
624  case SSL_ERROR_WANT_WRITE: return write(buffer,size); break;
625  default: print_error_string(ssl_err,"SSL_write"); return 0; break;
626  }
627  } else {
628  return res;
629  }
630 }
631 
633 {
634  int res = SSL_clear(ssl_);
635  if ( res != 1) {
636  unsigned long ssl_err = ERR_get_error();
637  print_error_string(ssl_err,"SSL_clear");
638  }
639 }
640 
642 {
643  int res = SSL_shutdown(ssl_);
644  if ( res != 1) {
645  unsigned long ssl_err = ERR_get_error();
646  if (ssl_err != SSL_ERROR_NONE) {
647  print_error_string(ssl_err,"SSL_shutdown");
648  }
649  }
650 }
651 
652 void SSL::wantsRead()
653 {
654  owner_.mtx.lock();
656  owner_.mtx.unlock();
657 }
658 
659 void SSL::wantsWrite()
660 {
661  owner_.mtx.lock();
663  owner_.mtx.unlock();
664 }
665 
666 } // namespace tcp
tcp::freeSSLLibrary
void freeSSLLibrary()
Free up resources created by the openSSL library.
Definition: tcpssl.cpp:32
tcp::printSSLErrors
void printSSLErrors()
This method logs openSSL errors to cerr.
Definition: tcpssl.cpp:56
tcp::SSL::connect
bool connect()
Starts the SSL client handshake sequence.
Definition: tcpssl.cpp:558
tcp::SSL::SSL
SSL(DataSocket &owner, SSLContext &context)
Constructor.
Definition: tcpssl.cpp:396
tcp::SSLContext::mode_
SSLMode mode_
The mode of the context object is passed to SSL objects created from this context.
Definition: tcpssl.h:102
tcp::SSLContext::setVerifyPaths
bool setVerifyPaths(const char *cafile=NULL, const char *capath=NULL)
Use the specified CA certificate or certificate directory.
Definition: tcpssl.cpp:315
tcp::SSLContext::passwordCallback
virtual int passwordCallback(char *buf, int size, int rwflag)
Called when a password to decrypt a private key is required.
Definition: tcpssl.cpp:382
tcp::verify_callback
int verify_callback(int preverify, X509_STORE_CTX *x509_ctx)
Prints the certificate details to clog.
Definition: tcpssl.cpp:195
tcp::Socket::mtx
recursive_mutex mtx
The mutex used to provide exclusive access to the socket.
Definition: tcpsocket.h:141
tcp::print_cn_name
void print_cn_name(const char *label, X509_NAME *const name)
Prints the certificate common name to clog.
Definition: tcpssl.cpp:97
tcp::SSL::write
size_t write(const void *buffer, size_t size)
Encrypts and writes SSL socket data.
Definition: tcpssl.cpp:613
tcp::SSL::performCertPostValidation
bool performCertPostValidation()
Performs a post handshake validation of the peer certificate.
Definition: tcpssl.cpp:533
tcp::SSL::requiresCertPostValidation
bool requiresCertPostValidation
If True, the certificate will be checked for validity on the first read/write operation.
Definition: tcpssl.h:195
tcp::DataSocket
Represents a buffered socket that can send and receive data using optional SSL encryption.
Definition: tcpsocket.h:159
tcp::DataSocket::readToInputBuffer
void readToInputBuffer()
Reads all available data from the socket into inputBuffer.
Definition: tcpsocket.cpp:214
tcp::SSL::validateSubjectName
virtual bool validateSubjectName(const string &subjectName, const string &hostName)
Validate the peer certificate subject name.
Definition: tcpssl.cpp:528
tcp::SSLContext::setOptions
void setOptions(bool verifypeer=false, bool compression=true, bool tlsonly=false)
Sets default options for all SSL objects created from this context.
Definition: tcpssl.cpp:264
tcp::SSL::setfd
bool setfd(int socket)
Sets the socket file descripter for this SSL object.
Definition: tcpssl.cpp:472
tcp::SSL::setOptions
void setOptions(bool verifypeer=false)
Sets default options for all SSL objects created from this context.
Definition: tcpssl.cpp:407
tcp::DataSocket::sendOutputBuffer
void sendOutputBuffer()
Writes all available data from the outputBuffer to the socket.
Definition: tcpsocket.cpp:226
tcp::initSSLLibrary
void initSSLLibrary()
Initialize the openSSL library.
Definition: tcpssl.cpp:19
tcp::DataSocket::disconnected
void disconnected() override
Called when a connection is disconnected.
Definition: tcpsocket.cpp:202
tcp::SSL::shutdown
void shutdown()
Closes the SSL connection gracefully.
Definition: tcpssl.cpp:641
tcp::SSLContext
Encapsulates an openSSL SSL_CTX record.
Definition: tcpssl.h:41
tcp::SSL::read
size_t read(void *buffer, size_t size)
Reads and decrypts SSL socket data.
Definition: tcpssl.cpp:594
tcp::SSLContext::~SSLContext
virtual ~SSLContext()
Destructor.
Definition: tcpssl.cpp:259
tcp::SSL::ssl_
::SSL * ssl_
The openSSL handle for API calls.
Definition: tcpssl.h:218
tcp::SSLContext::setCertificateAndKey
bool setCertificateAndKey(const char *certfile, const char *keyfile)
Sets the certificate filename and key filename.
Definition: tcpssl.cpp:340
tcp::SSL::setCertificateAndKey
bool setCertificateAndKey(const char *certfile, const char *keyfile)
Sets the certificate filename and key filename.
Definition: tcpssl.cpp:418
tcp::SSLContext::SSLContext
SSLContext(SSLMode mode)
Constructor.
Definition: tcpssl.cpp:242
tcpssl.h
Provides ssl client and server functionality.
tcp::wildcmp
int wildcmp(const char *wild, const char *string)
Wildcard compare function.
Definition: tcpssl.cpp:62
tcp::SSL::getSubjectName
string & getSubjectName()
Returns the peer certificate subject name or an empty string if none was sent.
Definition: tcpssl.cpp:489
tcp::SSL::owner_
DataSocket & owner_
A reference to the socket
Definition: tcpssl.h:216
tcp::SSL::~SSL
virtual ~SSL()
Destructor.
Definition: tcpssl.cpp:402
tcp::SSL::mode_
SSLMode mode_
Either SERVER or CLIENT
Definition: tcpssl.h:217
tcp::SSL::verifyResult
bool verifyResult()
Return true if the peer certificate was verified or if no certificate was presented.
Definition: tcpssl.cpp:553
tcp::SSLContext::ctx_
SSL_CTX * ctx_
The openSSL context object.
Definition: tcpssl.h:101
tcp::print_san_name
void print_san_name(const char *label, X509 *const cert)
Prints the certificate subject alt name to clog.
Definition: tcpssl.cpp:131
tcp
A tcp client/server library for linux that supports openSSL and EPoll.
Definition: tcpclient.cpp:5
tcp::SSL::clear
void clear()
Resets the SSL object for another connection.
Definition: tcpssl.cpp:632
tcp::SSL::accept
bool accept()
Starts the SSL server handshake sequence.
Definition: tcpssl.cpp:576
tcp::SSL::passwordCallback
virtual int passwordCallback(char *buf, int size, int rwflag)
Called when a password to decrypt a private key is required.
Definition: tcpssl.cpp:460