TCP- and SSL-Connection Examples
This commit is contained in:
		| @@ -3,7 +3,7 @@ | |||||||
| ##       1         2         3         4         5         6         7         8 | ##       1         2         3         4         5         6         7         8 | ||||||
| ## 45678901234567890123456789012345678901234567890123456789012345678901234567890 | ## 45678901234567890123456789012345678901234567890123456789012345678901234567890 | ||||||
|  |  | ||||||
| noinst_PROGRAMS = pcsc-demo cryptoki-demo | noinst_PROGRAMS = pcsc-demo cryptoki-demo openssl-tcp-demo openssl-ssl-demo | ||||||
|  |  | ||||||
| AM_CPPFLAGS = -I${top_srcdir}/src | AM_CPPFLAGS = -I${top_srcdir}/src | ||||||
| if !MINGW32 | if !MINGW32 | ||||||
| @@ -27,4 +27,20 @@ else | |||||||
| cryptoki_demo_LDADD += -ldl -lpthread -lssl | cryptoki_demo_LDADD += -ldl -lpthread -lssl | ||||||
| endif | endif | ||||||
|  |  | ||||||
|  | openssl_tcp_demo_SOURCES = openssl-tcp-demo.cxx | ||||||
|  | openssl_tcp_demo_LDFLAGS = -L${top_builddir}/src | ||||||
|  | if MINGW32 | ||||||
|  | openssl_tcp_demo_LDADD = -leay32 | ||||||
|  | else | ||||||
|  | openssl_tcp_demo_LDADD = -ldl -lpthread -lssl | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | openssl_ssl_demo_SOURCES = openssl-ssl-demo.cxx | ||||||
|  | openssl_ssl_demo_LDFLAGS = -L${top_builddir}/src | ||||||
|  | if MINGW32 | ||||||
|  | openssl_ssl_demo_LDADD = -leay32 | ||||||
|  | else | ||||||
|  | openssl_ssl_demo_LDADD = -ldl -lpthread -lssl | ||||||
|  | endif | ||||||
|  |  | ||||||
| MAINTAINERCLEANFILES = makefile.in | MAINTAINERCLEANFILES = makefile.in | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								doc/examples/openssl-ssl-demo.cxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								doc/examples/openssl-ssl-demo.cxx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | /*! @file | ||||||
|  |  | ||||||
|  |     @id $Id$ | ||||||
|  | */ | ||||||
|  | //       1         2         3         4         5         6         7         8 | ||||||
|  | // 45678901234567890123456789012345678901234567890123456789012345678901234567890 | ||||||
|  |  | ||||||
|  | #define OPENSSL_LOG(X) | ||||||
|  | #include <openssl.hxx> | ||||||
|  | #include <iostream> | ||||||
|  |  | ||||||
|  | int main(int argc, char** argv) try { | ||||||
|  |   openssl::Init init; | ||||||
|  |   std::string host(argc>1?argv[1]:"dev.swisssign.com"); | ||||||
|  |   std::string port(argc>2?argv[2]:"443"); | ||||||
|  |   std::string path(argc>3?argv[3]:"/"); | ||||||
|  |   std::cout<<"Connect to: "<<host<<':'<<port<<std::endl; | ||||||
|  |   openssl::SSL ssl | ||||||
|  |     (openssl::TrustStore("/usr/lib/ssl/certs/SwissSign_Gold_CA_-_G2.pem")); | ||||||
|  |   ssl.connect(host+':'+port)<<"GET "<<path<<" HTTP/1.1\n" | ||||||
|  |                             <<"Host: "<<host<<"\n" | ||||||
|  |                             <<"Connection: Close\n\n"; | ||||||
|  |   while (ssl) std::cout<<ssl; | ||||||
|  |   return 0; | ||||||
|  |  } catch (const std::exception& x) { | ||||||
|  |   std::cerr<<"**** ERROR: "<<x.what()<<std::endl; | ||||||
|  |   return 1; | ||||||
|  |  } | ||||||
							
								
								
									
										25
									
								
								doc/examples/openssl-tcp-demo.cxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								doc/examples/openssl-tcp-demo.cxx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | /*! @file | ||||||
|  |  | ||||||
|  |     @id $Id$ | ||||||
|  | */ | ||||||
|  | //       1         2         3         4         5         6         7         8 | ||||||
|  | // 45678901234567890123456789012345678901234567890123456789012345678901234567890 | ||||||
|  |  | ||||||
|  | //#define OPENSSL_LOG(X) | ||||||
|  | #include <openssl.hxx> | ||||||
|  | #include <iostream> | ||||||
|  |  | ||||||
|  | int main(int argc, char** argv) try { | ||||||
|  |   openssl::Init init; | ||||||
|  |   std::string host(argc>1?argv[1]:"swisssign.com"); | ||||||
|  |   std::string port(argc>2?argv[2]:"80"); | ||||||
|  |   std::cout<<"Connect to: "<<host<<':'<<port<<std::endl; | ||||||
|  |   openssl::TCP ssl(host+':'+port); | ||||||
|  |   ssl<<"GET / HTTP/1.1\x0D\x0AHost: "<<host | ||||||
|  |      <<"\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A"; | ||||||
|  |   while (ssl) std::cout<<ssl; | ||||||
|  |   return 0; | ||||||
|  |  } catch (const std::exception& x) { | ||||||
|  |   std::cerr<<"**** ERROR: "<<x.what()<<std::endl; | ||||||
|  |   return 1; | ||||||
|  |  } | ||||||
							
								
								
									
										543
									
								
								src/openssl.hxx
									
									
									
									
									
								
							
							
						
						
									
										543
									
								
								src/openssl.hxx
									
									
									
									
									
								
							| @@ -23,7 +23,25 @@ | |||||||
| #include <cstdio> | #include <cstdio> | ||||||
| #include <cassert> | #include <cassert> | ||||||
|  |  | ||||||
| #include <iostream> //! @todo remove (debug only) | #ifndef OPENSSL_LOG | ||||||
|  |   #include <iostream> | ||||||
|  |   #if __GNUC__ >= 2 | ||||||
|  |     //! Openssl Logging | ||||||
|  |     /*! If you want to change openssl logging mechanism, just | ||||||
|  |         redefine your own OPENSSL_LOG macro before <code>#include | ||||||
|  |         <openssl.hxx></code>. Define it empty for no logging at | ||||||
|  |         all. By default logs to <code>std::clog</code>. */ | ||||||
|  |     #define OPENSSL_LOG(X) std::clog<<X<<" @ "<<__PRETTY_FUNCTION__<<std::endl | ||||||
|  |   #else | ||||||
|  |     //! Openssl Logging | ||||||
|  |     /*! If you want to change openssl logging mechanism, just | ||||||
|  |         redefine your own OPENSSL_LOG macro before <code>#include | ||||||
|  |         <openssl.hxx></code>. Define it empty for no logging at | ||||||
|  |         all. By default logs to <code>std::clog</code>. */ | ||||||
|  |     #define OPENSSL_LOG(X) std::clog<<X<<" @ "<<__FILE__<<__LINE__<<std::endl | ||||||
|  |   #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| /*! @defgroup gopenssl C++ Wrapper around OpenSSL API */ | /*! @defgroup gopenssl C++ Wrapper around OpenSSL API */ | ||||||
| //@{ | //@{ | ||||||
| @@ -43,6 +61,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       exception(const std::string& reason) throw(): |       exception(const std::string& reason) throw(): | ||||||
|           _what("openssl: "+reason) { |           _what("openssl: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|       ~exception() throw() {} |       ~exception() throw() {} | ||||||
|       const char* what() const throw() { |       const char* what() const throw() { | ||||||
| @@ -56,6 +75,15 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       openssl_error(const std::string& reason) throw(): |       openssl_error(const std::string& reason) throw(): | ||||||
|           exception(reason+'\n'+ERR_error_string(ERR_get_error(), 0)) { |           exception(reason+'\n'+ERR_error_string(ERR_get_error(), 0)) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|  |   }; | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   class cannot_init: public openssl_error { | ||||||
|  |     public: | ||||||
|  |       cannot_init(const std::string& reason) throw(): | ||||||
|  |           openssl_error("openssl initialization: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -63,6 +91,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       encryption_error(const std::string& reason) throw(): |       encryption_error(const std::string& reason) throw(): | ||||||
|           openssl_error("encryption: "+reason) { |           openssl_error("encryption: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -70,6 +99,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       pkcs12_error(const std::string& reason) throw(): |       pkcs12_error(const std::string& reason) throw(): | ||||||
|           openssl_error("pkcs12: "+reason) { |           openssl_error("pkcs12: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -77,6 +107,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       pkcs7_error(const std::string& reason) throw(): |       pkcs7_error(const std::string& reason) throw(): | ||||||
|           openssl_error("pkcs7: "+reason) { |           openssl_error("pkcs7: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -84,6 +115,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       x509_error(const std::string& reason) throw(): |       x509_error(const std::string& reason) throw(): | ||||||
|           openssl_error("x509: "+reason) { |           openssl_error("x509: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -91,13 +123,15 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       key_error(const std::string& reason) throw(): |       key_error(const std::string& reason) throw(): | ||||||
|           openssl_error("private key: "+reason) { |           openssl_error("private key: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class bio_error: public openssl_error { |   class tcp_error: public openssl_error { | ||||||
|     public: |     public: | ||||||
|       bio_error(const std::string& reason) throw(): |       tcp_error(const std::string& reason) throw(): | ||||||
|           openssl_error("bio: "+reason) { |           openssl_error("tcp "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -105,6 +139,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       ssl_error(const std::string& reason) throw(): |       ssl_error(const std::string& reason) throw(): | ||||||
|           openssl_error("ssl: "+reason) { |           openssl_error("ssl: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -112,6 +147,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       cannot_encrypt(std::string reason) throw(): |       cannot_encrypt(std::string reason) throw(): | ||||||
|           encryption_error("cannot encrypt text: "+reason) { |           encryption_error("cannot encrypt text: "+reason) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -119,6 +155,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       allocation_failed() throw(): |       allocation_failed() throw(): | ||||||
|           x509_error("memory allocation failed") { |           x509_error("memory allocation failed") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -126,6 +163,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       x509_decoding_failed(const std::string& der) throw(): |       x509_decoding_failed(const std::string& der) throw(): | ||||||
|           x509_error("certificate decoding failed:\n"+crypto::readable(der)) { |           x509_error("certificate decoding failed:\n"+crypto::readable(der)) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -133,6 +171,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       undefined_certificate() throw(): |       undefined_certificate() throw(): | ||||||
|           x509_error("certificate must not be 0") { |           x509_error("certificate must not be 0") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -140,6 +179,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       x509_parsing_failed() throw(): |       x509_parsing_failed() throw(): | ||||||
|           x509_error("parsing DER encoded certificate failed") { |           x509_error("parsing DER encoded certificate failed") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -147,6 +187,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       x509_copy_failed() throw(): |       x509_copy_failed() throw(): | ||||||
|           x509_error("certificate object copy failed") { |           x509_error("certificate object copy failed") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -154,6 +195,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       key_copy_failed() throw(): |       key_copy_failed() throw(): | ||||||
|           key_error("key object copy failed") { |           key_error("key object copy failed") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -161,6 +203,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       undefined_key() throw(): |       undefined_key() throw(): | ||||||
|           key_error("private key must not be 0") { |           key_error("private key must not be 0") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -168,6 +211,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       pkcs12_reading_failed(const std::string& file) throw(): |       pkcs12_reading_failed(const std::string& file) throw(): | ||||||
|           pkcs12_error("reading DER encoded p12 file failed: "+file) { |           pkcs12_error("reading DER encoded p12 file failed: "+file) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -175,23 +219,29 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       pkcs12_parsing_failed(const std::string& file) throw(): |       pkcs12_parsing_failed(const std::string& file) throw(): | ||||||
|           pkcs12_error("parsing DER encoded p12 file failed: "+file) { |           pkcs12_error("parsing DER encoded p12 file failed: "+file) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class pkcs12_no_private_key: public pkcs12_error { |   class pkcs12_no_private_key: public pkcs12_error { | ||||||
|     public: |     public: | ||||||
|       pkcs12_no_private_key() throw(): pkcs12_error("no private key") {} |       pkcs12_no_private_key() throw(): pkcs12_error("no private key") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class pkcs12_no_x509: public pkcs12_error { |   class pkcs12_no_x509: public pkcs12_error { | ||||||
|     public: |     public: | ||||||
|       pkcs12_no_x509() throw(): pkcs12_error("no x509 certificate") {} |       pkcs12_no_x509() throw(): pkcs12_error("no x509 certificate") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class pkcs7_reading_failed: public pkcs7_error { |   class pkcs7_reading_failed: public pkcs7_error { | ||||||
|     public: |     public: | ||||||
|       pkcs7_reading_failed(const std::string& file) throw(): |       pkcs7_reading_failed(const std::string& file) throw(): | ||||||
|           pkcs7_error("reading DER encoded p7 file failed: "+file) { |           pkcs7_error("reading DER encoded p7 file failed: "+file) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -199,6 +249,7 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       pkcs7_parsing_failed() throw(): |       pkcs7_parsing_failed() throw(): | ||||||
|           pkcs7_error("parsing DER encoded p7 failed") { |           pkcs7_error("parsing DER encoded p7 failed") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|       pkcs7_parsing_failed(const std::string& file) throw(): |       pkcs7_parsing_failed(const std::string& file) throw(): | ||||||
|           pkcs7_error("parsing DER encoded p7 file failed: "+file) { |           pkcs7_error("parsing DER encoded p7 file failed: "+file) { | ||||||
| @@ -207,52 +258,75 @@ namespace openssl { | |||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class pkcs7_unsupported_format: public pkcs7_error { |   class pkcs7_unsupported_format: public pkcs7_error { | ||||||
|     public: |     public: | ||||||
|       pkcs7_unsupported_format() throw(): pkcs7_error("format not supported") {} |       pkcs7_unsupported_format() throw(): pkcs7_error("format not supported") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class pkcs7_no_x509: public pkcs7_error { |   class pkcs7_no_x509: public pkcs7_error { | ||||||
|     public: |     public: | ||||||
|       pkcs7_no_x509() throw(): pkcs7_error("no x509 certificate") {} |       pkcs7_no_x509() throw(): pkcs7_error("no x509 certificate") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class cannot_open_file: public exception { |   class cannot_open_file: public exception { | ||||||
|     public: |     public: | ||||||
|       cannot_open_file(const std::string& file) throw(): |       cannot_open_file(const std::string& file) throw(): | ||||||
|           exception("cannot open file: "+file) { |           exception("cannot open file: "+file) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class bio_connection_failed: public bio_error { |   class tcp_connection_failed: public tcp_error { | ||||||
|     public: |     public: | ||||||
|       bio_connection_failed(const std::string& hostPort) throw(): |       tcp_connection_failed(const std::string& hostPort) throw(): | ||||||
|           bio_error("connection failed to: "+hostPort) { |           tcp_error("connection failed to: "+hostPort) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class bio_closed_connection: public bio_error { |   class tcp_server_not_specified: public tcp_error { | ||||||
|     public: |     public: | ||||||
|       bio_closed_connection() throw(): bio_error("closed connection") {} |       tcp_server_not_specified() throw(): | ||||||
|  |           tcp_error("reconnect without prior connect") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class bio_read_error: public bio_error { |   class tcp_closed_connection: public tcp_error { | ||||||
|     public: |     public: | ||||||
|       bio_read_error() throw(): bio_error("read error") {} |       tcp_closed_connection() throw(): tcp_error("closed connection") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class bio_write_error: public bio_error { |   class tcp_read_error: public tcp_error { | ||||||
|     public: |     public: | ||||||
|       bio_write_error() throw(): bio_error("write error") {} |       tcp_read_error() throw(): tcp_error("read error") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|  |   }; | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   class tcp_write_error: public tcp_error { | ||||||
|  |     public: | ||||||
|  |       tcp_write_error() throw(): tcp_error("write error") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class ssl_cannot_create_context: public ssl_error { |   class ssl_cannot_create_context: public ssl_error { | ||||||
|     public: |     public: | ||||||
|       ssl_cannot_create_context() throw(): ssl_error("cannot create context") {} |       ssl_cannot_create_context() throw(): ssl_error("cannot create context") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class ssl_certificate_file_not_loaded: public ssl_error { |   class ssl_certificate_file_not_loaded: public ssl_error { | ||||||
|     public: |     public: | ||||||
|       ssl_certificate_file_not_loaded(const std::string& file) throw(): |       ssl_certificate_file_not_loaded(const std::string& file) throw(): | ||||||
|           ssl_error("certificate file not loaded: "+file) { |           ssl_error("certificate file not loaded: "+file) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
| @@ -260,6 +334,154 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       ssl_certificate_folder_not_loaded(const std::string& path) throw(): |       ssl_certificate_folder_not_loaded(const std::string& path) throw(): | ||||||
|           ssl_error("certificate folder not loaded: "+path) { |           ssl_error("certificate folder not loaded: "+path) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|  |   }; | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   class ssl_no_connection: public ssl_error { | ||||||
|  |     public: | ||||||
|  |       ssl_no_connection() throw(): | ||||||
|  |           ssl_error("no ssl connection") { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|  |   }; | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   class ssl_verification_failed: public ssl_error { | ||||||
|  |     public: | ||||||
|  |       ssl_verification_failed(int num) throw(): | ||||||
|  |           ssl_error("certificate verification failed: "+reason(num)) { | ||||||
|  |         OPENSSL_LOG("**** exception ****"); | ||||||
|  |       } | ||||||
|  |       static std::string reason(int num) { | ||||||
|  |         switch (num) { | ||||||
|  |           case X509_V_OK: | ||||||
|  |             return "X509_V_OK: Ok the operation was successful."; | ||||||
|  |           case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: | ||||||
|  |             return "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: Unable to get issuer" | ||||||
|  |               " certificate the issuer certificate could not be found: this" | ||||||
|  |               " occurs if the issuer certificate of an untrusted certificate" | ||||||
|  |               " cannot be found."; | ||||||
|  |           case X509_V_ERR_UNABLE_TO_GET_CRL: "X509_V_ERR_UNABLE_TO_GET_CRL:" | ||||||
|  |               " unable to get certificate CRL the CRL of a certificate could" | ||||||
|  |               " not be found. Unused."; | ||||||
|  |           case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: | ||||||
|  |             return "4 X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: Unable to" | ||||||
|  |               " decrypt certificate's signature the certificate signature" | ||||||
|  |               " could not be decrypted. This means that the actual signature" | ||||||
|  |               " value could not be determined rather than it not matching the" | ||||||
|  |               " expected value, this is only meaningful for RSA keys."; | ||||||
|  |           case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: | ||||||
|  |             return "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: Unable to" | ||||||
|  |               " decode issuer public key the public key in the certificate" | ||||||
|  |               " SubjectPublicKeyInfo could not be read."; | ||||||
|  |           case X509_V_ERR_CERT_SIGNATURE_FAILURE: | ||||||
|  |             return "X509_V_ERR_CERT_SIGNATURE_FAILURE: Certificate signature" | ||||||
|  |               " failure the signature of the certificate is invalid."; | ||||||
|  |           case X509_V_ERR_CRL_SIGNATURE_FAILURE: | ||||||
|  |             return "X509_V_ERR_CRL_SIGNATURE_FAILURE: Crl signature failure" | ||||||
|  |               " the signature of the certificate is invalid. Unused."; | ||||||
|  |           case X509_V_ERR_CERT_NOT_YET_VALID: | ||||||
|  |             return "X509_V_ERR_CERT_NOT_YET_VALID: Certificate is not yet" | ||||||
|  |               " valid the certificate is not yet valid: the notBefore date is" | ||||||
|  |               " after the current time."; | ||||||
|  |           case X509_V_ERR_CERT_HAS_EXPIRED: | ||||||
|  |             return "X509_V_ERR_CERT_HAS_EXPIRED: Certificate has expired the" | ||||||
|  |               " certificate has expired: that is the notAfter date is before" | ||||||
|  |               " the current time."; | ||||||
|  |           case X509_V_ERR_CRL_NOT_YET_VALID: | ||||||
|  |             return "X509_V_ERR_CRL_NOT_YET_VALID: Crl is not yet valid the CRL" | ||||||
|  |               " is not yet valid. Unused."; | ||||||
|  |           case X509_V_ERR_CRL_HAS_EXPIRED: | ||||||
|  |             return "X509_V_ERR_CRL_HAS_EXPIRED: Crl has expired the CRL has" | ||||||
|  |               " expired. Unused."; | ||||||
|  |           case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: | ||||||
|  |             return "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: Format error in" | ||||||
|  |               " certificate's notBefore field the certificate notBefore field" | ||||||
|  |               " contains an invalid time."; | ||||||
|  |           case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: | ||||||
|  |             return "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: Format error in" | ||||||
|  |               " certificate's notAfter field the certificate notAfter field" | ||||||
|  |               " contains an invalid time."; | ||||||
|  |           case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: | ||||||
|  |             return "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: Format error in" | ||||||
|  |               " CRL's lastUpdate field the CRL lastUpdate field contains an" | ||||||
|  |               " invalid time. Unused."; | ||||||
|  |           case X509_V_ERR_OUT_OF_MEM: | ||||||
|  |             return "X509_V_ERR_OUT_OF_MEM: Out of memory an error occurred" | ||||||
|  |               " trying to allocate memory. This should never happen."; | ||||||
|  |           case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: | ||||||
|  |             return "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: Self signed" | ||||||
|  |               " certificate the passed certificate is self signed and the same" | ||||||
|  |               " certificate cannot be found in the list of trusted" | ||||||
|  |               " certificates."; | ||||||
|  |           case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: | ||||||
|  |             return "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: Self signed" | ||||||
|  |               " certificate in certificate chain the certificate chain could" | ||||||
|  |               " be built up using the untrusted certificates but the root" | ||||||
|  |               " could not be found locally."; | ||||||
|  |           case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: | ||||||
|  |             return "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: Unable to" | ||||||
|  |               " get local issuer certificate the issuer certificate of a" | ||||||
|  |               " locally looked up certificate could not be found. This" | ||||||
|  |               " normally means the list of trusted certificates is not" | ||||||
|  |               " complete."; | ||||||
|  |           case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: | ||||||
|  |             return "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: Unable to" | ||||||
|  |               " verify the first certificate no signatures could be verified" | ||||||
|  |               " because the chain contains only one certificate and it is not" | ||||||
|  |               " self signed."; | ||||||
|  |           case X509_V_ERR_CERT_CHAIN_TOO_LONG: | ||||||
|  |             return "X509_V_ERR_CERT_CHAIN_TOO_LONG: Certificate chain too long" | ||||||
|  |               " the certificate chain length is greater than the supplied" | ||||||
|  |               " maximum depth. Unused."; | ||||||
|  |           case X509_V_ERR_CERT_REVOKED: | ||||||
|  |             return "X509_V_ERR_CERT_REVOKED: Certificate revoked the" | ||||||
|  |               " certificate has been revoked. Unused."; | ||||||
|  |           case X509_V_ERR_INVALID_CA: | ||||||
|  |             return "X509_V_ERR_INVALID_CA: Invalid CA certificate a CA" | ||||||
|  |               " certificate is invalid. Either it is not a CA or its" | ||||||
|  |               " extensions are not consistent with the supplied purpose."; | ||||||
|  |           case X509_V_ERR_INVALID_PURPOSE: | ||||||
|  |             return "X509_V_ERR_INVALID_PURPOSE: Unsupported certificate" | ||||||
|  |               " purpose the supplied certificate cannot be used for the" | ||||||
|  |               " specified purpose."; | ||||||
|  |           case X509_V_ERR_CERT_UNTRUSTED: | ||||||
|  |             return "X509_V_ERR_CERT_UNTRUSTED: Certificate not trusted the" | ||||||
|  |               " root CA is not marked as trusted for the specified purpose."; | ||||||
|  |           case X509_V_ERR_CERT_REJECTED: | ||||||
|  |             return "X509_V_ERR_CERT_REJECTED: Certificate rejected the root CA" | ||||||
|  |               " is marked to reject the specified purpose."; | ||||||
|  |           case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: | ||||||
|  |             return "X509_V_ERR_SUBJECT_ISSUER_MISMATCH: Subject issuer" | ||||||
|  |               " mismatch the current candidate issuer certificate was rejected" | ||||||
|  |               " because its subject name did not match the issuer name of the" | ||||||
|  |               " current certificate. Only displayed when the -issuer_checks" | ||||||
|  |               " option is set."; | ||||||
|  |           case X509_V_ERR_AKID_SKID_MISMATCH: | ||||||
|  |             return "X509_V_ERR_AKID_SKID_MISMATCH: Authority and subject key" | ||||||
|  |               " identifier mismatch the current candidate issuer certificate" | ||||||
|  |               " was rejected because its subject key identifier was present" | ||||||
|  |               " and did not match the authority key identifier current" | ||||||
|  |               " certificate. Only displayed when the -issuer_checks option is" | ||||||
|  |               " set."; | ||||||
|  |           case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: | ||||||
|  |             return "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: Authority and" | ||||||
|  |               " issuer serial number mismatch the current candidate issuer" | ||||||
|  |               " certificate was rejected because its issuer name and serial" | ||||||
|  |               " number was present and did not match the authority key" | ||||||
|  |               " identifier of the current certificate. Only displayed when the" | ||||||
|  |               " -issuer_checks option is set."; | ||||||
|  |           case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: | ||||||
|  |             return "X509_V_ERR_KEYUSAGE_NO_CERTSIGN: Ey usage does not include" | ||||||
|  |               " certificate signing the current candidate issuer certificate" | ||||||
|  |               " was rejected because its keyUsage extension does not permit" | ||||||
|  |               " certificate signing."; | ||||||
|  |           default: { | ||||||
|  |             std::stringstream ss; | ||||||
|  |             ss<<"Unknown certificate validation error code: "<<num; | ||||||
|  |             return ss.str(); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   //@} |   //@} | ||||||
| @@ -268,51 +490,18 @@ namespace openssl { | |||||||
|   //@{ |   //@{ | ||||||
|    |    | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|  |   //! Initializes OpenSSL. Must be instanciated exactly once. | ||||||
|   class Init { |   class Init { | ||||||
|     public: |     public: | ||||||
|       Init() { |       Init() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         SSL_load_error_strings(); |         SSL_load_error_strings(); | ||||||
|         ERR_load_BIO_strings(); |         ERR_load_BIO_strings(); | ||||||
|         OpenSSL_add_all_algorithms(); |         OpenSSL_add_all_algorithms(); | ||||||
|  |         if (!SSL_library_init()) throw cannot_init("cannot init SSL library"); | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   inline std::string desEnc(const std::string& txt, DES_cblock key1) { |  | ||||||
|     std::string res(txt); |  | ||||||
|     if (txt.size()%8!=0) |  | ||||||
|       throw cannot_encrypt("text size must be a multiple of eight"); |  | ||||||
|     DES_key_schedule ks1; |  | ||||||
|     DES_set_key_unchecked(&(DES_cblock&)key1, &ks1); |  | ||||||
|     for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { |  | ||||||
|       union { |  | ||||||
|           DES_cblock array; |  | ||||||
|           const char* text; |  | ||||||
|       } in, out; |  | ||||||
|       in.text = txt.begin().operator->()+pos; |  | ||||||
|       out.text = res.begin().operator->()+pos; |  | ||||||
|       DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_ENCRYPT); |  | ||||||
|     } |  | ||||||
|     return res; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   inline std::string desDec(const std::string& txt, DES_cblock key1) { |  | ||||||
|     std::string res(txt); |  | ||||||
|     if (txt.size()%8!=0) |  | ||||||
|       throw cannot_encrypt("text size must be a multiple of eight"); |  | ||||||
|     DES_key_schedule ks1; |  | ||||||
|     DES_set_key_unchecked(&(DES_cblock&)key1, &ks1); |  | ||||||
|     for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { |  | ||||||
|       union { |  | ||||||
|           DES_cblock array; |  | ||||||
|           const char* text; |  | ||||||
|       } in, out; |  | ||||||
|       in.text = txt.begin().operator->()+pos; |  | ||||||
|       out.text = res.begin().operator->()+pos; |  | ||||||
|       DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_DECRYPT); |  | ||||||
|     } |  | ||||||
|     return res; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   class CBlock8 { |   class CBlock8 { | ||||||
|     public: |     public: | ||||||
|       CBlock8() { |       CBlock8() { | ||||||
| @@ -356,10 +545,56 @@ namespace openssl { | |||||||
|       DES_cblock _cb; |       DES_cblock _cb; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   //! Encrypt a string using DES. | ||||||
|  |   /*! @param txt text to encrypt - size must be a multiple of 8 | ||||||
|  |       @param key1 DES key for encryption */ | ||||||
|  |   inline std::string desEnc(const std::string& txt, CBlock8 key1) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|  |     std::string res(txt); | ||||||
|  |     if (txt.size()%8!=0) | ||||||
|  |       throw cannot_encrypt("text size must be a multiple of eight"); | ||||||
|  |     DES_key_schedule ks1; | ||||||
|  |     DES_set_key_unchecked(key1, &ks1); | ||||||
|  |     for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { | ||||||
|  |       union { | ||||||
|  |           DES_cblock array; | ||||||
|  |           const char* text; | ||||||
|  |       } in, out; | ||||||
|  |       in.text = txt.begin().operator->()+pos; | ||||||
|  |       out.text = res.begin().operator->()+pos; | ||||||
|  |       DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_ENCRYPT); | ||||||
|  |     } | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   //! Decrypt a DES encrypted string. | ||||||
|  |   /*! @param txt text to decrypt - size must be a multiple of 8 | ||||||
|  |       @param key1 DES key for decryption */ | ||||||
|  |   inline std::string desDec(const std::string& txt, CBlock8 key1) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|  |     std::string res(txt); | ||||||
|  |     if (txt.size()%8!=0) | ||||||
|  |       throw cannot_encrypt("text size must be a multiple of eight"); | ||||||
|  |     DES_key_schedule ks1; | ||||||
|  |     DES_set_key_unchecked(key1, &ks1); | ||||||
|  |     for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { | ||||||
|  |       union { | ||||||
|  |           DES_cblock array; | ||||||
|  |           const char* text; | ||||||
|  |       } in, out; | ||||||
|  |       in.text = txt.begin().operator->()+pos; | ||||||
|  |       out.text = res.begin().operator->()+pos; | ||||||
|  |       DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_DECRYPT); | ||||||
|  |     } | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   //! DES CBC Encryption | ||||||
|   /*! @param txt If the length is not an integral multiple of eight |   /*! @param txt If the length is not an integral multiple of eight | ||||||
|                  bytes, it is zero filled. The output is always an |                  bytes, it is zero filled. The output is always an | ||||||
|                  integral multiple of eight bytes. */ |                  integral multiple of eight bytes. */ | ||||||
|   inline std::string desCbcEnc(std::string txt, CBlock8 key, CBlock8& ivec) { |   inline std::string desCbcEnc(std::string txt, CBlock8 key, CBlock8& ivec) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); | ||||||
|     std::string res(txt.size(), 0); |     std::string res(txt.size(), 0); | ||||||
|     DES_key_schedule ks; |     DES_key_schedule ks; | ||||||
| @@ -369,18 +604,22 @@ namespace openssl { | |||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //! DES CBC Encryption with empty vector | ||||||
|   /*! @param txt If the length is not an integral multiple of eight |   /*! @param txt If the length is not an integral multiple of eight | ||||||
|                  bytes, it is zero filled. The output is always an |                  bytes, it is zero filled. The output is always an | ||||||
|                  integral multiple of eight bytes. */ |                  integral multiple of eight bytes. */ | ||||||
|   inline std::string desCbcEnc(const std::string& txt, const CBlock8& key) { |   inline std::string desCbcEnc(const std::string& txt, const CBlock8& key) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     CBlock8 ivec; |     CBlock8 ivec; | ||||||
|     return desCbcEnc(txt, key, ivec); |     return desCbcEnc(txt, key, ivec); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //! DES CBC Decryption | ||||||
|   /*! @param txt If the length is not an integral multiple of eight |   /*! @param txt If the length is not an integral multiple of eight | ||||||
|                  bytes, it is zero filled. The output is always an |                  bytes, it is zero filled. The output is always an | ||||||
|                  integral multiple of eight bytes. */ |                  integral multiple of eight bytes. */ | ||||||
|   inline std::string desCbcDec(std::string txt, CBlock8 key, CBlock8& ivec) { |   inline std::string desCbcDec(std::string txt, CBlock8 key, CBlock8& ivec) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); | ||||||
|     std::string res(txt.size(), 0); |     std::string res(txt.size(), 0); | ||||||
|     DES_key_schedule ks; |     DES_key_schedule ks; | ||||||
| @@ -390,10 +629,12 @@ namespace openssl { | |||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //! DES CBC Decryption with empty vector | ||||||
|   /*! @param txt If the length is not an integral multiple of eight |   /*! @param txt If the length is not an integral multiple of eight | ||||||
|                  bytes, it is zero filled. The output is always an |                  bytes, it is zero filled. The output is always an | ||||||
|                  integral multiple of eight bytes. */ |                  integral multiple of eight bytes. */ | ||||||
|   inline std::string desCbcDec(const std::string& txt, const CBlock8& key) { |   inline std::string desCbcDec(const std::string& txt, const CBlock8& key) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     CBlock8 ivec; |     CBlock8 ivec; | ||||||
|     return desCbcDec(txt, key, ivec); |     return desCbcDec(txt, key, ivec); | ||||||
|   } |   } | ||||||
| @@ -404,6 +645,7 @@ namespace openssl { | |||||||
|   inline std::string des2edeCbcEnc(std::string txt, |   inline std::string des2edeCbcEnc(std::string txt, | ||||||
|                                    CBlock8 key1, CBlock8 key2, |                                    CBlock8 key1, CBlock8 key2, | ||||||
|                                    CBlock8 ivec = CBlock8()) { |                                    CBlock8 ivec = CBlock8()) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); | ||||||
|     std::string res(txt.size(), 0); |     std::string res(txt.size(), 0); | ||||||
|     DES_key_schedule ks1, ks2; |     DES_key_schedule ks1, ks2; | ||||||
| @@ -420,6 +662,7 @@ namespace openssl { | |||||||
|   inline std::string des2edeCbcDec(std::string txt, |   inline std::string des2edeCbcDec(std::string txt, | ||||||
|                                    CBlock8 key1, CBlock8 key2, |                                    CBlock8 key1, CBlock8 key2, | ||||||
|                                    CBlock8 ivec = CBlock8()) { |                                    CBlock8 ivec = CBlock8()) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |     if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); | ||||||
|     std::string res(txt.size(), 0); |     std::string res(txt.size(), 0); | ||||||
|     DES_key_schedule ks1, ks2; |     DES_key_schedule ks1, ks2; | ||||||
| @@ -433,6 +676,7 @@ namespace openssl { | |||||||
|   //! @todo untested |   //! @todo untested | ||||||
|   inline std::string des2ecbEnc(std::string txt, |   inline std::string des2ecbEnc(std::string txt, | ||||||
|                                 CBlock8 key1, CBlock8 key2) { |                                 CBlock8 key1, CBlock8 key2) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     std::string res; |     std::string res; | ||||||
|     if (txt.size()%8!=0) |     if (txt.size()%8!=0) | ||||||
|       throw cannot_encrypt("text size must be a multiple of eight"); |       throw cannot_encrypt("text size must be a multiple of eight"); | ||||||
| @@ -450,6 +694,7 @@ namespace openssl { | |||||||
|   //! @todo untested |   //! @todo untested | ||||||
|   inline std::string des2ecbDec(std::string txt, |   inline std::string des2ecbDec(std::string txt, | ||||||
|                                 CBlock8 key1, CBlock8 key2) { |                                 CBlock8 key1, CBlock8 key2) { | ||||||
|  |     OPENSSL_LOG("log"); | ||||||
|     std::string res; |     std::string res; | ||||||
|     if (txt.size()%8!=0) |     if (txt.size()%8!=0) | ||||||
|       throw cannot_encrypt("text size must be a multiple of eight"); |       throw cannot_encrypt("text size must be a multiple of eight"); | ||||||
| @@ -465,20 +710,24 @@ namespace openssl { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|  |   //! X509 Certificate | ||||||
|   class X509 { |   class X509 { | ||||||
|     public: |     public: | ||||||
|       //! Construct empty certificate. |       //! Construct empty certificate. | ||||||
|       X509(): _x509(X509_new()) { |       X509(): _x509(X509_new()) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_x509) throw allocation_failed(); |         if (!_x509) throw allocation_failed(); | ||||||
|       } |       } | ||||||
|       //! Initialize from DER encoded cerificate. |       //! Initialize from DER encoded cerificate. | ||||||
|       X509(const std::string& der): _x509(0) { |       X509(const std::string& der): _x509(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         const unsigned char* c((const unsigned char*)der.begin().operator->()); |         const unsigned char* c((const unsigned char*)der.begin().operator->()); | ||||||
|         if (!(_x509=d2i_X509(0, &c, der.size())) || |         if (!(_x509=d2i_X509(0, &c, der.size())) || | ||||||
|             (const char*)c!=der.begin().operator->()+der.size()) |             (const char*)c!=der.begin().operator->()+der.size()) | ||||||
|           throw x509_decoding_failed(der); |           throw x509_decoding_failed(der); | ||||||
|       } |       } | ||||||
|       X509(const X509& o): _x509(0) { |       X509(const X509& o): _x509(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         unsigned char* d(0); |         unsigned char* d(0); | ||||||
|         int len(i2d_X509(o._x509, &d)); |         int len(i2d_X509(o._x509, &d)); | ||||||
|         if (!len) throw x509_copy_failed(); |         if (!len) throw x509_copy_failed(); | ||||||
| @@ -489,12 +738,15 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Take over OpenSSL allocated certificate. |       //! Take over OpenSSL allocated certificate. | ||||||
|       X509(::X509 *x509): _x509(x509) { |       X509(::X509 *x509): _x509(x509) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_x509) throw undefined_certificate(); |         if (!_x509) throw undefined_certificate(); | ||||||
|       } |       } | ||||||
|       ~X509() { |       ~X509() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_free(_x509); |         X509_free(_x509); | ||||||
|       } |       } | ||||||
|       X509& operator=(const X509& o) { |       X509& operator=(const X509& o) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_free(_x509); |         X509_free(_x509); | ||||||
|         _x509 = 0; |         _x509 = 0; | ||||||
|         unsigned char* d(0); |         unsigned char* d(0); | ||||||
| @@ -507,6 +759,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get DER encoded subject. |       //! Get DER encoded subject. | ||||||
|       std::string subjectDER() const { |       std::string subjectDER() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         unsigned char* c(0); |         unsigned char* c(0); | ||||||
|         int len(i2d_X509_NAME(X509_get_subject_name(_x509), &c)); |         int len(i2d_X509_NAME(X509_get_subject_name(_x509), &c)); | ||||||
|         std::string res((char*)c, len); |         std::string res((char*)c, len); | ||||||
| @@ -515,6 +768,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get DER encoded issuer. |       //! Get DER encoded issuer. | ||||||
|       std::string issuerDER() const { |       std::string issuerDER() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         unsigned char* c(0); |         unsigned char* c(0); | ||||||
|         int len(i2d_X509_NAME(X509_get_issuer_name(_x509), &c)); |         int len(i2d_X509_NAME(X509_get_issuer_name(_x509), &c)); | ||||||
|         std::string res((char*)c, len); |         std::string res((char*)c, len); | ||||||
| @@ -523,6 +777,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get DER encoded value. |       //! Get DER encoded value. | ||||||
|       std::string valueDER() const { |       std::string valueDER() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         unsigned char* c(0); |         unsigned char* c(0); | ||||||
|         int len(i2d_X509(_x509, &c)); |         int len(i2d_X509(_x509, &c)); | ||||||
|         std::string res((char*)c, len); |         std::string res((char*)c, len); | ||||||
| @@ -531,7 +786,8 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get serial number. |       //! Get serial number. | ||||||
|       std::string serial() const { |       std::string serial() const { | ||||||
|         /* @bug http://albistechnologies.com reports: «could be a |         OPENSSL_LOG("log"); | ||||||
|  |         /* @bug tcp://albistechnologies.com reports: «could be a | ||||||
|             failure in openSSL: len too short by 1 if serial number |             failure in openSSL: len too short by 1 if serial number | ||||||
|             starts with 00 ASN1_INTEGER* ser = |             starts with 00 ASN1_INTEGER* ser = | ||||||
|             X509_get_serialNumber(_x509);» |             X509_get_serialNumber(_x509);» | ||||||
| @@ -540,7 +796,7 @@ namespace openssl { | |||||||
|             return std::string((char*)ser->data, ser->length); |             return std::string((char*)ser->data, ser->length); | ||||||
|             @endcode |             @endcode | ||||||
|             - requires memory free? |             - requires memory free? | ||||||
|             - ser->type?!? http://albistechnologies.com prepends |             - ser->type?!? tcp://albistechnologies.com prepends | ||||||
|               tag and length in the first two char-fields. */ |               tag and length in the first two char-fields. */ | ||||||
|         unsigned char* c(0); |         unsigned char* c(0); | ||||||
|         int len(i2d_X509(_x509, &c)); |         int len(i2d_X509(_x509, &c)); | ||||||
| @@ -550,6 +806,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get id. |       //! Get id. | ||||||
|       std::string id() const { |       std::string id() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         unsigned char c[SHA_DIGEST_LENGTH]; |         unsigned char c[SHA_DIGEST_LENGTH]; | ||||||
|         SHA1(_x509->cert_info->key->public_key->data, |         SHA1(_x509->cert_info->key->public_key->data, | ||||||
|              _x509->cert_info->key->public_key->length, |              _x509->cert_info->key->public_key->length, | ||||||
| @@ -558,6 +815,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get common name. |       //! Get common name. | ||||||
|       std::string commonName() const { |       std::string commonName() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_NAME *name(X509_get_subject_name(_x509)); |         X509_NAME *name(X509_get_subject_name(_x509)); | ||||||
|         ASN1_STRING* cn |         ASN1_STRING* cn | ||||||
|           (X509_NAME_ENTRY_get_data |           (X509_NAME_ENTRY_get_data | ||||||
| @@ -568,6 +826,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get country name. |       //! Get country name. | ||||||
|       std::string countryName() const { |       std::string countryName() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_NAME *name(X509_get_subject_name(_x509)); |         X509_NAME *name(X509_get_subject_name(_x509)); | ||||||
|         ASN1_STRING* cn |         ASN1_STRING* cn | ||||||
|           (X509_NAME_ENTRY_get_data |           (X509_NAME_ENTRY_get_data | ||||||
| @@ -578,6 +837,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get locality name. |       //! Get locality name. | ||||||
|       std::string localityName() const { |       std::string localityName() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_NAME *name(X509_get_subject_name(_x509)); |         X509_NAME *name(X509_get_subject_name(_x509)); | ||||||
|         ASN1_STRING* cn |         ASN1_STRING* cn | ||||||
|           (X509_NAME_ENTRY_get_data |           (X509_NAME_ENTRY_get_data | ||||||
| @@ -588,6 +848,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get state or province name. |       //! Get state or province name. | ||||||
|       std::string stateOrProvinceName() const { |       std::string stateOrProvinceName() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_NAME *name(X509_get_subject_name(_x509)); |         X509_NAME *name(X509_get_subject_name(_x509)); | ||||||
|         ASN1_STRING* cn |         ASN1_STRING* cn | ||||||
|           (X509_NAME_ENTRY_get_data |           (X509_NAME_ENTRY_get_data | ||||||
| @@ -599,6 +860,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get organization name. |       //! Get organization name. | ||||||
|       std::string organizationName() const { |       std::string organizationName() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_NAME *name(X509_get_subject_name(_x509)); |         X509_NAME *name(X509_get_subject_name(_x509)); | ||||||
|         ASN1_STRING* cn |         ASN1_STRING* cn | ||||||
|           (X509_NAME_ENTRY_get_data |           (X509_NAME_ENTRY_get_data | ||||||
| @@ -610,6 +872,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Check whether it's a CA certificate. |       //! Check whether it's a CA certificate. | ||||||
|       bool isCa() { |       bool isCa() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         BASIC_CONSTRAINTS* bc(0); |         BASIC_CONSTRAINTS* bc(0); | ||||||
|         int pos(X509_get_ext_by_NID(_x509, NID_basic_constraints, -1)); |         int pos(X509_get_ext_by_NID(_x509, NID_basic_constraints, -1)); | ||||||
|         if (pos>=0) |         if (pos>=0) | ||||||
| @@ -618,6 +881,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get organizational unit name. |       //! Get organizational unit name. | ||||||
|       std::string organizationalUnitName() const { |       std::string organizationalUnitName() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         X509_NAME *name(X509_get_subject_name(_x509)); |         X509_NAME *name(X509_get_subject_name(_x509)); | ||||||
|         ASN1_STRING* cn |         ASN1_STRING* cn | ||||||
|           (X509_NAME_ENTRY_get_data |           (X509_NAME_ENTRY_get_data | ||||||
| @@ -629,6 +893,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|       //! Get key usage flags. |       //! Get key usage flags. | ||||||
|       int keyUsageFlags() const { |       int keyUsageFlags() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         int res(X509v3_KU_UNDEF); |         int res(X509v3_KU_UNDEF); | ||||||
|         int pos(X509_get_ext_by_NID(_x509, NID_key_usage, -1)); |         int pos(X509_get_ext_by_NID(_x509, NID_key_usage, -1)); | ||||||
|         if (pos>=0) { |         if (pos>=0) { | ||||||
| @@ -648,50 +913,65 @@ namespace openssl { | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|  |   //! Private certificate key | ||||||
|   class PrivateKey { |   class PrivateKey { | ||||||
|     public: |     public: | ||||||
|       PrivateKey(): _key(EVP_PKEY_new()) { |       PrivateKey(): _key(EVP_PKEY_new()) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_key) throw allocation_failed(); |         if (!_key) throw allocation_failed(); | ||||||
|       } |       } | ||||||
|       PrivateKey(const PrivateKey& o): _key(0) { |       PrivateKey(const PrivateKey& o): _key(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         copy(o); |         copy(o); | ||||||
|       } |       } | ||||||
|       PrivateKey(EVP_PKEY* k): _key(k) { |       PrivateKey(EVP_PKEY* k): _key(k) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_key) throw undefined_key(); |         if (!_key) throw undefined_key(); | ||||||
|       } |       } | ||||||
|       ~PrivateKey() { |       ~PrivateKey() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         EVP_PKEY_free(_key); |         EVP_PKEY_free(_key); | ||||||
|       } |       } | ||||||
|       PrivateKey& operator=(const PrivateKey& o) { |       PrivateKey& operator=(const PrivateKey& o) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         copy(o); |         copy(o); | ||||||
|         return *this; |         return *this; | ||||||
|       } |       } | ||||||
|       std::string modulus() const { |       std::string modulus() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->n); |         return string(rsa()->n); | ||||||
|       } |       } | ||||||
|       std::string publicExponent() const { |       std::string publicExponent() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->e); |         return string(rsa()->e); | ||||||
|       } |       } | ||||||
|       std::string privateExponent() const { |       std::string privateExponent() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->d); |         return string(rsa()->d); | ||||||
|       } |       } | ||||||
|       std::string prime1() const { |       std::string prime1() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->p); |         return string(rsa()->p); | ||||||
|       } |       } | ||||||
|       std::string prime2() const { |       std::string prime2() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->q); |         return string(rsa()->q); | ||||||
|       } |       } | ||||||
|       std::string exponent1() const { |       std::string exponent1() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->dmp1); |         return string(rsa()->dmp1); | ||||||
|       } |       } | ||||||
|       std::string exponent2() const { |       std::string exponent2() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->dmq1); |         return string(rsa()->dmq1); | ||||||
|       } |       } | ||||||
|       std::string coefficient() const { |       std::string coefficient() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return string(rsa()->iqmp); |         return string(rsa()->iqmp); | ||||||
|       } |       } | ||||||
|     private: |     private: | ||||||
|       void copy(const PrivateKey& o) { |       void copy(const PrivateKey& o) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         EVP_PKEY_free(_key); |         EVP_PKEY_free(_key); | ||||||
|         if (!(_key=EVP_PKEY_new())) throw allocation_failed(); |         if (!(_key=EVP_PKEY_new())) throw allocation_failed(); | ||||||
|         rsa(o); |         rsa(o); | ||||||
| @@ -700,47 +980,57 @@ namespace openssl { | |||||||
|         /*ec(o);*/ |         /*ec(o);*/ | ||||||
|       } |       } | ||||||
|       std::string string(BIGNUM* a) const { |       std::string string(BIGNUM* a) const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         std::string res(BN_num_bytes(a), '0'); |         std::string res(BN_num_bytes(a), '0'); | ||||||
|         BN_bn2bin(a, (unsigned char*)res.begin().operator->()); |         BN_bn2bin(a, (unsigned char*)res.begin().operator->()); | ||||||
|         return res; |         return res; | ||||||
|       } |       } | ||||||
|       void rsa(const PrivateKey& o) { |       void rsa(const PrivateKey& o) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         //! @todo throw exception if 0? |         //! @todo throw exception if 0? | ||||||
|         RSA* tmp(o.rsa()); |         RSA* tmp(o.rsa()); | ||||||
|         if (tmp&&!EVP_PKEY_set1_RSA(_key, tmp)) throw key_copy_failed(); |         if (tmp&&!EVP_PKEY_set1_RSA(_key, tmp)) throw key_copy_failed(); | ||||||
|       } |       } | ||||||
|       void dsa(const PrivateKey& o) { |       void dsa(const PrivateKey& o) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         DSA* tmp(o.dsa()); |         DSA* tmp(o.dsa()); | ||||||
|         if (tmp&&!EVP_PKEY_set1_DSA(_key, tmp)) throw key_copy_failed(); |         if (tmp&&!EVP_PKEY_set1_DSA(_key, tmp)) throw key_copy_failed(); | ||||||
|       } |       } | ||||||
|       void dh(const PrivateKey& o) { |       void dh(const PrivateKey& o) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         DH* tmp(o.dh()); |         DH* tmp(o.dh()); | ||||||
|         if (tmp&&!EVP_PKEY_set1_DH(_key, tmp)) throw key_copy_failed(); |         if (tmp&&!EVP_PKEY_set1_DH(_key, tmp)) throw key_copy_failed(); | ||||||
|       } |       } | ||||||
|     /* Not available on mac osx |     /* Not available on mac osx | ||||||
|       void ec(const PrivateKey& o) { |       void ec(const PrivateKey& o) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         EC_KEY* tmp(o.ec()); |         EC_KEY* tmp(o.ec()); | ||||||
|         if (tmp&&!EVP_PKEY_set1_EC_KEY(_key, tmp)) throw key_copy_failed(); |         if (tmp&&!EVP_PKEY_set1_EC_KEY(_key, tmp)) throw key_copy_failed(); | ||||||
|       } |       } | ||||||
|     */ |     */ | ||||||
|       RSA* rsa() const { |       RSA* rsa() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         //! @todo throw exception if 0? |         //! @todo throw exception if 0? | ||||||
|         return EVP_PKEY_get1_RSA(_key); |         return EVP_PKEY_get1_RSA(_key); | ||||||
|       } |       } | ||||||
|       DSA* dsa() const { |       DSA* dsa() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return EVP_PKEY_get1_DSA(_key); |         return EVP_PKEY_get1_DSA(_key); | ||||||
|       } |       } | ||||||
|       DH* dh() const { |       DH* dh() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return EVP_PKEY_get1_DH(_key); |         return EVP_PKEY_get1_DH(_key); | ||||||
|       } |       } | ||||||
|     /* Not available on mac osx |     /* Not available on mac osx | ||||||
|       EC_KEY* ec() const { |       EC_KEY* ec() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return EVP_PKEY_get1_EC_KEY(_key); |         return EVP_PKEY_get1_EC_KEY(_key); | ||||||
|         }*/ |         }*/ | ||||||
|       EVP_PKEY* _key; |       EVP_PKEY* _key; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|  |   //! PKCS#12 certificate file handler | ||||||
|   class PKCS12 { |   class PKCS12 { | ||||||
|        |        | ||||||
|       //...............................................................typedefs |       //...............................................................typedefs | ||||||
| @@ -753,6 +1043,7 @@ namespace openssl { | |||||||
|       //! Read from a PKCS#12 (.p12) file. |       //! Read from a PKCS#12 (.p12) file. | ||||||
|       PKCS12(std::string filename, std::string password): |       PKCS12(std::string filename, std::string password): | ||||||
|           _key(0), _cert(0) { |           _key(0), _cert(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         FILE* file(fopen(filename.c_str(), "rb")); |         FILE* file(fopen(filename.c_str(), "rb")); | ||||||
|         if (!file) throw cannot_open_file(filename); |         if (!file) throw cannot_open_file(filename); | ||||||
|         ::PKCS12 *p12(d2i_PKCS12_fp(file, 0)); |         ::PKCS12 *p12(d2i_PKCS12_fp(file, 0)); | ||||||
| @@ -776,6 +1067,7 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|        |        | ||||||
|       ~PKCS12() { |       ~PKCS12() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         delete _key; |         delete _key; | ||||||
|         delete _cert; |         delete _cert; | ||||||
|         for (X509List::iterator it(_ca.begin()); it!=_ca.end(); ++it) |         for (X509List::iterator it(_ca.begin()); it!=_ca.end(); ++it) | ||||||
| @@ -783,24 +1075,29 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       bool hasPrivateKey() const { |       bool hasPrivateKey() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return _key; |         return _key; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       bool hasCert() const { |       bool hasCert() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return _cert; |         return _cert; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       const PrivateKey& privateKey() const { |       const PrivateKey& privateKey() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_key) throw pkcs12_no_private_key(); |         if (!_key) throw pkcs12_no_private_key(); | ||||||
|         return *_key; |         return *_key; | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|       const X509& x509() const { |       const X509& x509() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_cert) throw pkcs12_no_x509(); |         if (!_cert) throw pkcs12_no_x509(); | ||||||
|         return *_cert; |         return *_cert; | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|       const X509List& ca() const { |       const X509List& ca() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return _ca; |         return _ca; | ||||||
|       } |       } | ||||||
|        |        | ||||||
| @@ -811,6 +1108,7 @@ namespace openssl { | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|  |   //! PKCS#7 certificate file handler | ||||||
|   class PKCS7 { |   class PKCS7 { | ||||||
|        |        | ||||||
|       //...............................................................typedefs |       //...............................................................typedefs | ||||||
| @@ -842,6 +1140,7 @@ namespace openssl { | |||||||
|        |        | ||||||
|       //! Read PKCS#7 from memory. |       //! Read PKCS#7 from memory. | ||||||
|       PKCS7(const std::string& memory) { |       PKCS7(const std::string& memory) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         BIO* mem(BIO_new_mem_buf((void*)memory.data(), memory.size())); |         BIO* mem(BIO_new_mem_buf((void*)memory.data(), memory.size())); | ||||||
|         ::PKCS7 *p7(d2i_PKCS7_bio(mem, 0)); |         ::PKCS7 *p7(d2i_PKCS7_bio(mem, 0)); | ||||||
|         BIO_free(mem); |         BIO_free(mem); | ||||||
| @@ -859,11 +1158,13 @@ namespace openssl { | |||||||
|       } |       } | ||||||
|        |        | ||||||
|       ~PKCS7() { |       ~PKCS7() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         for (X509List::iterator it(_certs.begin()); it!=_certs.end(); ++it) |         for (X509List::iterator it(_certs.begin()); it!=_certs.end(); ++it) | ||||||
|           delete *it; |           delete *it; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       const X509List& certs() const { |       const X509List& certs() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return _certs; |         return _certs; | ||||||
|       } |       } | ||||||
|        |        | ||||||
| @@ -872,18 +1173,27 @@ namespace openssl { | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|   class BIO { |   //! TCP Connection | ||||||
|  |   class TCP { | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |  | ||||||
|       BIO(const BIO&); |       TCP(const TCP&); | ||||||
|       BIO& operator=(const BIO&); |       TCP& operator=(const TCP&); | ||||||
|        |        | ||||||
|     public: |     public: | ||||||
|        |        | ||||||
|       BIO(): _bio(0) {} |       TCP(): _bio(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|  |       } | ||||||
|        |        | ||||||
|       ~BIO() { |       TCP(const std::string& hostPort): _bio(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|  |         connect(hostPort); | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       virtual ~TCP() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         try { |         try { | ||||||
|           close(); |           close(); | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
| @@ -891,20 +1201,36 @@ namespace openssl { | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|        |        | ||||||
|       BIO& connect(const std::string& hostPort) { |       virtual TCP& connect(const std::string& hostPort) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         close(); |         close(); | ||||||
|         if (!(_bio=BIO_new_connect(const_cast<char*>(hostPort.c_str()))) || |         if (!(_bio=BIO_new_connect(const_cast<char*>(hostPort.c_str()))) || | ||||||
|             BIO_do_connect(_bio)<=0) |             BIO_do_connect(_bio)<=0) | ||||||
|           throw bio_connection_failed(hostPort); |           throw tcp_connection_failed(hostPort); | ||||||
|  |         _hostPort = hostPort; | ||||||
|         return *this; |         return *this; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       BIO& operator>>(std::string& s) { |       virtual TCP& connect() { | ||||||
|  |         if (!_hostPort.size()) throw tcp_server_not_specified(); | ||||||
|  |         close(); | ||||||
|  |         connect(_hostPort); | ||||||
|  |         return *this; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       operator bool() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|  |         return _bio>0; | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       TCP& operator>>(std::string& s) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         s += read(); |         s += read(); | ||||||
|         return *this; |         return *this; | ||||||
|       } |       } | ||||||
|        |        | ||||||
|       BIO& operator<<(const std::string& s) { |       TCP& operator<<(const std::string& s) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return write(s); |         return write(s); | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -913,34 +1239,47 @@ namespace openssl { | |||||||
|           server is waiting for next request, but connection is still |           server is waiting for next request, but connection is still | ||||||
|           open? */ |           open? */ | ||||||
|       std::string read() { |       std::string read() { | ||||||
|         if (!_bio) throw bio_closed_connection(); |         OPENSSL_LOG("log"); | ||||||
|  |         if (_bio<=0) throw tcp_closed_connection(); | ||||||
|         const int BUFF_SZ(1024); |         const int BUFF_SZ(1024); | ||||||
|         char buff[BUFF_SZ]; |         char buff[BUFF_SZ]; | ||||||
|         int x(BIO_read(_bio, buff, BUFF_SZ)); |         int x(BIO_read(_bio, buff, BUFF_SZ)); | ||||||
|         if (x<=0) |         if (x<=0) | ||||||
|           if (BIO_should_retry(_bio)) return read(); |           if (BIO_should_retry(_bio)) return read(); | ||||||
|           else throw bio_read_error(); |           else { | ||||||
|  |             close(); | ||||||
|  |             if (x==0) return std::string(); | ||||||
|  |             else throw tcp_read_error(); | ||||||
|  |           } | ||||||
|  |         else if (x==1024) return std::string(buff, x)+read(); | ||||||
|         return std::string(buff, x); |         return std::string(buff, x); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       BIO& write(const std::string& s) { |       TCP& write(const std::string& s) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|  |         if (_bio<=0) throw tcp_closed_connection(); | ||||||
|         int x(BIO_write(_bio, s.begin().operator->(), s.size())); |         int x(BIO_write(_bio, s.begin().operator->(), s.size())); | ||||||
|         if (x<=0) |         if (x<=0) | ||||||
|           if (BIO_should_retry(_bio)) return write(s); |           if (BIO_should_retry(_bio)) return write(s); | ||||||
|           else throw bio_write_error(); |           else { | ||||||
|         else |             close(); | ||||||
|           if (x<s.size()) return write(s.substr(x)); |             throw tcp_write_error(); | ||||||
|  |           } | ||||||
|  |         else if (x<s.size()) return write(s.substr(x)); | ||||||
|         return *this; |         return *this; | ||||||
|       } |       } | ||||||
|        |        | ||||||
|       void close() { |       virtual TCP& close() { | ||||||
|         BIO_free_all(_bio); |         OPENSSL_LOG("log"); | ||||||
|  |         if (_bio>0) BIO_free_all(_bio); | ||||||
|  |         _bio = 0; | ||||||
|  |         return *this; | ||||||
|       } |       } | ||||||
|        |        | ||||||
|     private: |     protected: | ||||||
|        |        | ||||||
|       friend class SSL; |  | ||||||
|       ::BIO* _bio; |       ::BIO* _bio; | ||||||
|  |       std::string _hostPort; | ||||||
|        |        | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| @@ -949,8 +1288,10 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       TrustStore(const std::string& pathToPemFile): |       TrustStore(const std::string& pathToPemFile): | ||||||
|           _file(pathToPemFile) { |           _file(pathToPemFile) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|       } |       } | ||||||
|       const std::string& file() const { |       const std::string& file() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return _file; |         return _file; | ||||||
|       } |       } | ||||||
|     private: |     private: | ||||||
| @@ -961,15 +1302,17 @@ namespace openssl { | |||||||
|     public: |     public: | ||||||
|       CertificateFolder(const std::string& certificateFolder): |       CertificateFolder(const std::string& certificateFolder): | ||||||
|           _path(certificateFolder) { |           _path(certificateFolder) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|       } |       } | ||||||
|       const std::string& path() const { |       const std::string& path() const { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         return _path; |         return _path; | ||||||
|       } |       } | ||||||
|     private: |     private: | ||||||
|       std::string _path; |       std::string _path; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   class SSL { |   class SSL: public TCP { | ||||||
|     private: |     private: | ||||||
|       SSL(); |       SSL(); | ||||||
|       SSL(const SSL&); |       SSL(const SSL&); | ||||||
| @@ -978,6 +1321,7 @@ namespace openssl { | |||||||
|       SSL(const TrustStore& file): |       SSL(const TrustStore& file): | ||||||
|           _ctx(SSL_CTX_new(SSLv23_client_method())), |           _ctx(SSL_CTX_new(SSLv23_client_method())), | ||||||
|           _ssl(0) { |           _ssl(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_ctx) throw ssl_cannot_create_context(); |         if (!_ctx) throw ssl_cannot_create_context(); | ||||||
|         if (!SSL_CTX_load_verify_locations(_ctx, file.file().c_str(), 0)) |         if (!SSL_CTX_load_verify_locations(_ctx, file.file().c_str(), 0)) | ||||||
|           throw ssl_certificate_file_not_loaded(file.file()); |           throw ssl_certificate_file_not_loaded(file.file()); | ||||||
| @@ -985,42 +1329,63 @@ namespace openssl { | |||||||
|       SSL(const CertificateFolder& folder): |       SSL(const CertificateFolder& folder): | ||||||
|           _ctx(SSL_CTX_new(SSLv23_client_method())), |           _ctx(SSL_CTX_new(SSLv23_client_method())), | ||||||
|           _ssl(0) { |           _ssl(0) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         if (!_ctx) throw ssl_cannot_create_context(); |         if (!_ctx) throw ssl_cannot_create_context(); | ||||||
|         if (!SSL_CTX_load_verify_locations(_ctx, 0, folder.path().c_str())) |         if (!SSL_CTX_load_verify_locations(_ctx, 0, folder.path().c_str())) | ||||||
|           throw ssl_certificate_folder_not_loaded(folder.path()); |           throw ssl_certificate_folder_not_loaded(folder.path()); | ||||||
|       } |       } | ||||||
|       ~SSL() { |       ~SSL() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         close(); |         close(); | ||||||
|         SSL_CTX_free(_ctx); |         SSL_CTX_free(_ctx); | ||||||
|       } |       } | ||||||
|       BIO& connect(const std::string& hostPort) { |       virtual SSL& connect(const std::string& hostPort) { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|         close(); |         close(); | ||||||
|         if (!(_bio._bio=BIO_new_ssl_connect(_ctx))) |         if (!(_bio=BIO_new_ssl_connect(_ctx))) | ||||||
|           throw bio_connection_failed(hostPort); |           throw tcp_connection_failed(hostPort); | ||||||
|         BIO_get_ssl(_bio._bio, &_ssl); |         BIO_get_ssl(_bio, &_ssl); | ||||||
|         if (!_ssl)  |         if (!_ssl) throw ssl_no_connection(); | ||||||
|         SSL_set_mode(_ssl, SSL_MODE_AUTO_RETRY); |         SSL_set_mode(_ssl, SSL_MODE_AUTO_RETRY); | ||||||
|         BIO_set_conn_hostname(_bio._bio, const_cast<char*>(hostPort.c_str())); |         BIO_set_conn_hostname(_bio, const_cast<char*>(hostPort.c_str())); | ||||||
|         if (BIO_do_connect(_bio._bio)<=0) throw bio_connection_failed(hostPort); |         if (BIO_do_connect(_bio)<=0) | ||||||
|         return _bio; |           throw tcp_connection_failed(hostPort); | ||||||
|  |         verify(); | ||||||
|  |         return *this; | ||||||
|       } |       } | ||||||
|       SSL& close() { |       virtual SSL& close() { | ||||||
|         _bio.close(); |         OPENSSL_LOG("log"); | ||||||
|  |         TCP::close(); | ||||||
|         _ssl = 0; //! @todo is this correct? <-- |         _ssl = 0; //! @todo is this correct? <-- | ||||||
|         return *this; |         return *this; | ||||||
|       } |       } | ||||||
|       bool verifyResult() { |     protected: | ||||||
|         return _ssl && SSL_get_verify_result(_ssl)==X509_V_OK; |       void verify() { | ||||||
|  |         OPENSSL_LOG("log"); | ||||||
|  |         if (!_ssl) throw ssl_no_connection(); | ||||||
|  |         int res(SSL_get_verify_result(_ssl)); | ||||||
|  |         if (res!=X509_V_OK) throw ssl_verification_failed(res); | ||||||
|       } |       } | ||||||
|     private: |     private: | ||||||
|       SSL_CTX *_ctx; |       SSL_CTX *_ctx; | ||||||
|       ::SSL *_ssl; |       ::SSL *_ssl; | ||||||
|       BIO _bio; |  | ||||||
|   }; |   }; | ||||||
|    |    | ||||||
|   //@} |   //@} | ||||||
|    |    | ||||||
| } | } | ||||||
|  |  | ||||||
|  | std::ostream& operator<<(std::ostream& os, openssl::TCP& is) { | ||||||
|  |   return os<<is.read(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::istream& operator>>(std::istream& is, openssl::TCP& os) { | ||||||
|  |   std::string s; | ||||||
|  |   is>>s; | ||||||
|  |   os<<s; | ||||||
|  |   return is; | ||||||
|  | } | ||||||
|  |  | ||||||
| //@} | //@} | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user