diff options
author | Jose <jose@zeroc.com> | 2017-03-16 16:11:24 +0100 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2017-03-16 16:11:24 +0100 |
commit | c6f4057a8975e2312d82f22af59f2069d2b5e8ab (patch) | |
tree | 1312f2c5798821dd8b4c583f30983542d9528790 /cpp/src/IceSSL/Util.cpp | |
parent | Removed C# Ice.BatchRequestInterceptor (ICE-7662) (diff) | |
download | ice-c6f4057a8975e2312d82f22af59f2069d2b5e8ab.tar.bz2 ice-c6f4057a8975e2312d82f22af59f2069d2b5e8ab.tar.xz ice-c6f4057a8975e2312d82f22af59f2069d2b5e8ab.zip |
Fixed (ICE-7621) - Refactor IceSSL API to support multiple implementations
Diffstat (limited to 'cpp/src/IceSSL/Util.cpp')
-rwxr-xr-x | cpp/src/IceSSL/Util.cpp | 1815 |
1 files changed, 20 insertions, 1795 deletions
diff --git a/cpp/src/IceSSL/Util.cpp b/cpp/src/IceSSL/Util.cpp index 52cd3c5144c..08f97a0c6fb 100755 --- a/cpp/src/IceSSL/Util.cpp +++ b/cpp/src/IceSSL/Util.cpp @@ -21,15 +21,9 @@ #include <Ice/Network.h> #include <Ice/Object.h> #include <Ice/StringConverter.h> -#include <fstream> +#include <Ice/UniqueRef.h> -#ifdef ICE_USE_OPENSSL -# include <openssl/err.h> -// -// Avoid old style cast warnings from OpenSSL macros -// -# pragma GCC diagnostic ignored "-Wold-style-cast" -#endif +#include <fstream> using namespace std; using namespace Ice; @@ -37,16 +31,23 @@ using namespace IceInternal; using namespace IceUtil; using namespace IceSSL; -#ifdef ICE_OS_UWP -using namespace concurrency; -using namespace Platform; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::Storage; -using namespace Windows::Storage::Streams; -using namespace Windows::Security::Cryptography; -using namespace Windows::Security::Cryptography::Core; -using namespace Windows::Security::Cryptography::Certificates; +#if defined(__APPLE__) + +std::string +IceSSL::fromCFString(CFStringRef v) +{ + string s; + if(v) + { + CFIndex size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(v), kCFStringEncodingUTF8); + vector<char> buffer; + buffer.resize(size + 1); + CFStringGetCString(v, &buffer[0], buffer.size(), kCFStringEncodingUTF8); + s.assign(&buffer[0]); + } + return s; +} + #endif #ifdef ICE_CPP11_MAPPING @@ -73,14 +74,8 @@ IceSSL::PasswordPrompt::getPassword() } #endif - -#if !defined(ICE_USE_OPENSSL) - -namespace -{ - bool -parseBytes(const string& arg, vector<unsigned char>& buffer) +IceSSL::parseBytes(const string& arg, vector<unsigned char>& buffer) { string v = IceUtilInternal::toUpper(arg); @@ -118,1776 +113,6 @@ parseBytes(const string& arg, vector<unsigned char>& buffer) return true; } -} - -#endif - -#if defined(ICE_USE_OPENSSL) - -namespace -{ - -# ifndef OPENSSL_NO_DH -# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -// The following arrays are predefined Diffie Hellman group parameters. -// These are known strong primes, distributed with the OpenSSL library -// in the files dh512.pem, dh1024.pem, dh2048.pem and dh4096.pem. -// They are not keys themselves, but the basis for generating DH keys -// on the fly. - -unsigned char dh512_p[] = -{ - 0xF5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C, - 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29, - 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B, - 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C, - 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55, - 0xE9,0x2A,0x05,0x5F, -}; - -unsigned char dh512_g[] = { 0x02 }; - -unsigned char dh1024_p[] = -{ - 0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4, - 0x91,0x07,0x36,0x6B,0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C, - 0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0, - 0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D, - 0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C, - 0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40, - 0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03, - 0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB, - 0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D, - 0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB, - 0xA2,0x5E,0xC3,0x55,0xE9,0x2F,0x78,0xC7, -}; - -unsigned char dh1024_g[] = { 0x02 }; - -unsigned char dh2048_p[] = -{ - 0xF6,0x42,0x57,0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6, - 0xA9,0x42,0xF3,0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1, - 0x6E,0xB9,0x4B,0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9, - 0x8F,0x40,0x55,0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD, - 0xF7,0x4C,0x64,0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17, - 0xD4,0xA1,0xD3,0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F, - 0x3D,0x3D,0x8D,0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD, - 0xB8,0xAE,0x74,0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30, - 0x61,0xCE,0x7C,0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E, - 0xC7,0x01,0xAA,0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4, - 0x1A,0xF0,0xBF,0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58, - 0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B, - 0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C, - 0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B, - 0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD, - 0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C, - 0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C, - 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29, - 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B, - 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C, - 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55, - 0xE9,0x32,0x0B,0x3B, -}; - -unsigned char dh2048_g[] = { 0x02 }; - -unsigned char dh4096_p[] = -{ - 0xFA,0x14,0x72,0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09, - 0x2D,0xC0,0xA8,0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09, - 0xE2,0xE9,0x3E,0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43, - 0x37,0x23,0x90,0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF, - 0x78,0x62,0xA6,0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA, - 0x35,0xFF,0x59,0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE, - 0xCD,0x38,0x87,0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22, - 0xF3,0x5A,0xED,0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A, - 0x20,0x77,0xD4,0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63, - 0x40,0x8B,0x3A,0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3, - 0x7B,0x29,0x56,0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC, - 0xA2,0x45,0x12,0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23, - 0xF0,0xF3,0xEF,0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1, - 0xA8,0x32,0x46,0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8, - 0x03,0xE5,0xDD,0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C, - 0xC8,0xDF,0x7C,0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE, - 0xA3,0x7D,0x26,0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD, - 0x68,0x84,0x7F,0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36, - 0x7A,0x11,0x43,0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82, - 0x49,0xCC,0x5C,0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39, - 0x73,0xFB,0x60,0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67, - 0xF7,0x66,0x3F,0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5, - 0x8F,0x66,0xF9,0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D, - 0xF8,0xE0,0xCC,0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3, - 0x13,0x73,0xA6,0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00, - 0x85,0x79,0xFC,0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75, - 0xA4,0x40,0xFA,0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F, - 0x04,0x43,0x3D,0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9, - 0x90,0xCF,0x83,0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF, - 0x0B,0x8B,0xBE,0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03, - 0x82,0xF6,0x62,0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5, - 0x5B,0x2B,0x5E,0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E, - 0xFF,0x5C,0x15,0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15, - 0x51,0x07,0x79,0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2, - 0xC8,0xD4,0x5C,0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8, - 0x80,0xA4,0xC7,0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F, - 0x6B,0x54,0xB0,0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84, - 0x37,0xC8,0x03,0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0, - 0xC8,0x5D,0x83,0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45, - 0x29,0xD4,0xCB,0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E, - 0xDB,0x90,0x90,0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9, - 0x4E,0x78,0xAC,0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1, - 0xB9,0xBD,0x78,0xE1,0x84,0x41,0xA0,0xDF, -}; - -unsigned char dh4096_g[] = { 0x02 }; - -# else -// -// With OpenSSL 1.1.0 is no longer possible to acess the DH p and g -// data members to set the DH params. We still use the same default -// parameters but they were converted to DER format using -// i2d_DHparams and can be restored using d2i_DHparams - -unsigned char dh512[] = -{ - 0x30,0x46,0x02,0x41,0x00,0xF5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29, - 0x40,0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4, - 0x03,0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F, - 0xAB,0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4, - 0x5D,0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA, - 0xAB,0xA2,0x5E,0xC3,0x55,0xE9,0x2A,0x05,0x5F,0x02,0x01,0x02, -}; - -unsigned char dh1024[] = -{ - 0x30,0x81,0x87,0x02,0x81,0x81,0x00,0xF4,0x88,0xFD,0x58,0x4E, - 0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,0x33, - 0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,0x5B, - 0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,0x18, - 0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,0x7C, - 0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,0xB5, - 0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,0x84, - 0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,0x7A, - 0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,0x02, - 0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,0xBD, - 0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,0xE9, - 0x2F,0x78,0xC7,0x02,0x01,0x02, -}; - -unsigned char dh2048[] = -{ - 0x30,0x82,0x01,0x08,0x02,0x82,0x01,0x01,0x00,0xF6,0x42,0x57, - 0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6,0xA9,0x42,0xF3, - 0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1,0x6E,0xB9,0x4B, - 0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9,0x8F,0x40,0x55, - 0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD,0xF7,0x4C,0x64, - 0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17,0xD4,0xA1,0xD3, - 0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F,0x3D,0x3D,0x8D, - 0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD,0xB8,0xAE,0x74, - 0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30,0x61,0xCE,0x7C, - 0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E,0xC7,0x01,0xAA, - 0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4,0x1A,0xF0,0xBF, - 0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB, - 0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,0x33,0x6C,0x38, - 0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E, - 0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E, - 0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57, - 0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF, - 0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A, - 0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95, - 0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3, - 0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B, - 0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,0xE9,0x32,0x0B, - 0x3B,0x02,0x01,0x02, -}; - -unsigned char dh4096[] = -{ - 0x30,0x82,0x02,0x08,0x02,0x82,0x02,0x01,0x00,0xFA,0x14,0x72, - 0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09,0x2D,0xC0,0xA8, - 0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09,0xE2,0xE9,0x3E, - 0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43,0x37,0x23,0x90, - 0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF,0x78,0x62,0xA6, - 0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA,0x35,0xFF,0x59, - 0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE,0xCD,0x38,0x87, - 0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22,0xF3,0x5A,0xED, - 0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A,0x20,0x77,0xD4, - 0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63,0x40,0x8B,0x3A, - 0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3,0x7B,0x29,0x56, - 0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC,0xA2,0x45,0x12, - 0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23,0xF0,0xF3,0xEF, - 0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1,0xA8,0x32,0x46, - 0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8,0x03,0xE5,0xDD, - 0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C,0xC8,0xDF,0x7C, - 0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE,0xA3,0x7D,0x26, - 0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD,0x68,0x84,0x7F, - 0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36,0x7A,0x11,0x43, - 0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82,0x49,0xCC,0x5C, - 0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39,0x73,0xFB,0x60, - 0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67,0xF7,0x66,0x3F, - 0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5,0x8F,0x66,0xF9, - 0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D,0xF8,0xE0,0xCC, - 0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3,0x13,0x73,0xA6, - 0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00,0x85,0x79,0xFC, - 0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75,0xA4,0x40,0xFA, - 0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F,0x04,0x43,0x3D, - 0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9,0x90,0xCF,0x83, - 0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF,0x0B,0x8B,0xBE, - 0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03,0x82,0xF6,0x62, - 0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5,0x5B,0x2B,0x5E, - 0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E,0xFF,0x5C,0x15, - 0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15,0x51,0x07,0x79, - 0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2,0xC8,0xD4,0x5C, - 0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8,0x80,0xA4,0xC7, - 0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F,0x6B,0x54,0xB0, - 0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84,0x37,0xC8,0x03, - 0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0,0xC8,0x5D,0x83, - 0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45,0x29,0xD4,0xCB, - 0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E,0xDB,0x90,0x90, - 0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9,0x4E,0x78,0xAC, - 0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1,0xB9,0xBD,0x78, - 0xE1,0x84,0x41,0xA0,0xDF,0x02,0x01,0x02, -}; -# endif - -} - -// -// Convert a predefined parameter set into a DH value. -// -# if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) -static DH* -convertDH(const unsigned char* buf, int len) -{ - return d2i_DHparams(0, &buf, len); -} -# else -static DH* -convertDH(unsigned char* p, int plen, unsigned char* g, int glen) -{ - assert(p != 0); - assert(g != 0); - - DH* dh = DH_new(); - - if(dh != 0) - { - dh->p = BN_bin2bn(p, plen, 0); - dh->g = BN_bin2bn(g, glen, 0); - - if((dh->p == 0) || (dh->g == 0)) - { - DH_free(dh); - dh = 0; - } - } - return dh; -} -# endif - -IceSSL::DHParams::DHParams() : - _dh512(0), _dh1024(0), _dh2048(0), _dh4096(0) -{ -} - -IceSSL::DHParams::~DHParams() -{ - for(ParamList::iterator p = _params.begin(); p != _params.end(); ++p) - { - DH_free(p->second); - } - DH_free(_dh512); - DH_free(_dh1024); - DH_free(_dh2048); - DH_free(_dh4096); -} - -bool -IceSSL::DHParams::add(int keyLength, const string& file) -{ - BIO* bio = BIO_new(BIO_s_file()); - if(BIO_read_filename(bio, file.c_str()) <= 0) - { - BIO_free(bio); - return false; - } - DH* dh = PEM_read_bio_DHparams(bio, 0, 0, 0); - BIO_free(bio); - if(!dh) - { - return false; - } - ParamList::iterator p = _params.begin(); - while(p != _params.end() && keyLength > p->first) - { - ++p; - } - _params.insert(p, KeyParamPair(keyLength, dh)); - return true; -} - -DH* -IceSSL::DHParams::get(int keyLength) -{ - // - // First check the set of parameters specified by the user. - // Return the first set whose key length is at least keyLength. - // - for(ParamList::iterator p = _params.begin(); p != _params.end(); ++p) - { - if(p->first >= keyLength) - { - return p->second; - } - } - - // - // No match found. Use one of the predefined parameter sets instead. - // - IceUtil::Mutex::Lock sync(*this); -# if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) - if(keyLength >= 4096) - { - if(!_dh4096) - { - _dh4096 = convertDH(dh4096, (int) sizeof(dh4096)); - } - return _dh4096; - } - else if(keyLength >= 2048) - { - if(!_dh2048) - { - _dh2048 = convertDH(dh2048, (int) sizeof(dh2048)); - } - return _dh2048; - } - else if(keyLength >= 1024) - { - if(!_dh1024) - { - _dh1024 = convertDH(dh1024, (int) sizeof(dh1024)); - } - return _dh1024; - } - else - { - if(!_dh512) - { - _dh512 = convertDH(dh512, (int) sizeof(dh512)); - } - return _dh512; - } -# else - if(keyLength >= 4096) - { - if(!_dh4096) - { - _dh4096 = convertDH(dh4096_p, (int) sizeof(dh4096_p), dh4096_g, (int) sizeof(dh4096_g)); - } - return _dh4096; - } - else if(keyLength >= 2048) - { - if(!_dh2048) - { - _dh2048 = convertDH(dh2048_p, (int) sizeof(dh2048_p), dh2048_g, (int) sizeof(dh2048_g)); - } - return _dh2048; - } - else if(keyLength >= 1024) - { - if(!_dh1024) - { - _dh1024 = convertDH(dh1024_p, (int) sizeof(dh1024_p), dh1024_g, (int) sizeof(dh1024_g)); - } - return _dh1024; - } - else - { - if(!_dh512) - { - _dh512 = convertDH(dh512_p, (int) sizeof(dh512_p), dh512_g, (int) sizeof(dh512_g)); - } - return _dh512; - } -# endif -} - -# endif - -string -IceSSL::getSslErrors(bool verbose) -{ - ostringstream ostr; - - const char* file; - const char* data; - int line; - int flags; - unsigned long err; - int count = 0; - while((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) - { - if(count > 0) - { - ostr << endl; - } - - if(verbose) - { - if(count > 0) - { - ostr << endl; - } - - char buf[200]; - ERR_error_string_n(err, buf, sizeof(buf)); - - ostr << "error # = " << err << endl; - ostr << "message = " << buf << endl; - ostr << "location = " << file << ", " << line; - if(flags & ERR_TXT_STRING) - { - ostr << endl; - ostr << "data = " << data; - } - } - else - { - const char* reason = ERR_reason_error_string(err); - ostr << (reason == ICE_NULLPTR ? "unknown reason" : reason); - if(flags & ERR_TXT_STRING) - { - ostr << ": " << data; - } - } - - ++count; - } - - ERR_clear_error(); - - return ostr.str(); -} - -#elif defined(ICE_USE_SECURE_TRANSPORT) - -string -IceSSL::errorToString(CFErrorRef err) -{ - ostringstream os; - if(err) - { - UniqueRef<CFStringRef> s(CFErrorCopyDescription(err)); - os << "(error: " << CFErrorGetCode(err) << " description: " << fromCFString(s.get()) << ")"; - } - return os.str(); -} - -string -IceSSL::errorToString(OSStatus status) -{ - ostringstream os; - os << "(error: " << status; -#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) - UniqueRef<CFStringRef> s(SecCopyErrorMessageString(status, 0)); - if(s) - { - os << " description: " << fromCFString(s.get()); - } -#endif - os << ")"; - return os.str(); -} - -std::string -IceSSL::fromCFString(CFStringRef v) -{ - string s; - if(v) - { - CFIndex size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(v), kCFStringEncodingUTF8); - vector<char> buffer; - buffer.resize(size + 1); - CFStringGetCString(v, &buffer[0], buffer.size(), kCFStringEncodingUTF8); - s.assign(&buffer[0]); - } - return s; -} - -#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) -CFDictionaryRef -IceSSL::getCertificateProperty(SecCertificateRef cert, CFTypeRef key) -{ - UniqueRef<CFDictionaryRef> property; - UniqueRef<CFArrayRef> keys(CFArrayCreate(ICE_NULLPTR, &key , 1, &kCFTypeArrayCallBacks)); - UniqueRef<CFErrorRef> err; - UniqueRef<CFDictionaryRef> values(SecCertificateCopyValues(cert, keys.get(), &err.get())); - if(err) - { - ostringstream os; - os << "IceSSL: error getting property for certificate:\n" << errorToString(err); - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - - assert(values); - property.retain(static_cast<CFDictionaryRef>(CFDictionaryGetValue(values.get(), key))); - return property.release(); -} -#endif - -namespace -{ - -CFMutableDataRef -readCertFile(const string& file) -{ - ifstream is(IceUtilInternal::streamFilename(file).c_str(), ios::in | ios::binary); - if(!is.good()) - { - throw CertificateReadException(__FILE__, __LINE__, "error opening file " + file); - } - - is.seekg(0, is.end); - size_t size = is.tellg(); - is.seekg(0, is.beg); - - UniqueRef<CFMutableDataRef> data(CFDataCreateMutable(kCFAllocatorDefault, size)); - CFDataSetLength(data.get(), size); - is.read(reinterpret_cast<char*>(CFDataGetMutableBytePtr(data.get())), size); - if(!is.good()) - { - throw CertificateReadException(__FILE__, __LINE__, "error reading file " + file); - } - return data.release(); -} - -#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) -// -// Check the certificate basic constraints to check if the certificate is marked as a CA. -// -bool -isCA(SecCertificateRef cert) -{ - UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, kSecOIDBasicConstraints)); - if(property) - { - CFArrayRef propertyValues = static_cast<CFArrayRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue)); - for(int i = 0, size = CFArrayGetCount(propertyValues); i < size; ++i) - { - CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(propertyValues, i)); - CFStringRef label = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyLabel)); - if(CFEqual(label, CFSTR("Certificate Authority"))) - { - return CFEqual(static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue)), CFSTR("Yes")); - } - } - } - return false; -} - -// -// Load keychain items (Certificates or Private Keys) from a file. On return items param contain -// the list of items, the caller must release it. -// -CFArrayRef -loadKeychainItems(const string& file, SecExternalItemType type, SecKeychainRef keychain, const string& passphrase, - const PasswordPromptPtr& prompt, int retryMax) -{ - UniqueRef<CFMutableDataRef> data(readCertFile(file)); - - SecItemImportExportKeyParameters params; - memset(¶ms, 0, sizeof(params)); - params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; - params.flags |= kSecKeyNoAccessControl; - if(!passphrase.empty()) - { - params.passphrase = toCFString(passphrase); - } - - UniqueRef<CFArrayRef> items; - SecExternalItemType importType = type; - SecExternalFormat format = type == kSecItemTypeUnknown ? kSecFormatPKCS12 : kSecFormatUnknown; - UniqueRef<CFStringRef> path(toCFString(file)); - OSStatus err = SecItemImport(data.get(), path.get(), &format, &importType, 0, ¶ms, keychain, &items.get()); - - // - // If passphrase failure and no password was configured, we obtain - // the password from the given prompt or configure the import to - // prompt the user with an alert dialog. - // - UniqueRef<CFStringRef> passphraseHolder; - UniqueRef<CFStringRef> alertPromptHolder; - if(passphrase.empty() && - (err == errSecPassphraseRequired || err == errSecInvalidData || err == errSecPkcs12VerifyFailure)) - { - if(!prompt) - { - params.flags |= kSecKeySecurePassphrase; - ostringstream os; - os << "Enter the password for\n" << file; - alertPromptHolder.reset(toCFString(os.str())); - params.alertPrompt = alertPromptHolder.get(); - } - - int count = 0; - while((err == errSecPassphraseRequired || err == errSecInvalidData || err == errSecPkcs12VerifyFailure) && - count < retryMax) - { - if(prompt) - { - passphraseHolder.reset(toCFString(prompt->getPassword())); - params.passphrase = passphraseHolder.get(); - } - err = SecItemImport(data.get(), path.get(), &format, &importType, 0, ¶ms, keychain, &items.get()); - ++count; - } - } - - if(err != noErr) - { - ostringstream os; - os << "IceSSL: error reading " << (type == kSecItemTypePrivateKey ? "private key" : "certificate"); - os << " `" << file << "':\n" << errorToString(err); - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - - if(type != kSecItemTypeUnknown && importType != kSecItemTypeAggregate && importType != type) - { - ostringstream os; - os << "IceSSL: error reading " << (type == kSecItemTypePrivateKey ? "private key" : "certificate"); - os << " `" << file << "' doesn't contain the expected item"; - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - - return items.release(); -} - -SecKeychainRef -openKeychain(const std::string& path, const std::string& keychainPassword) -{ - string keychainPath = path; - UniqueRef<SecKeychainRef> keychain; - OSStatus err = 0; - if(keychainPath.empty()) - { - if((err = SecKeychainCopyDefault(&keychain.get()))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to retrieve default keychain:\n" + errorToString(err)); - } - } - else - { - // - // KeyChain path is relative to the current working directory. - // - if(!IceUtilInternal::isAbsolutePath(keychainPath)) - { - string cwd; - if(IceUtilInternal::getcwd(cwd) == 0) - { - keychainPath = string(cwd) + '/' + keychainPath; - } - } - - if((err = SecKeychainOpen(keychainPath.c_str(), &keychain.get()))) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unable to open keychain: `" + - keychainPath + "'\n" + errorToString(err)); - } - } - - SecKeychainStatus status; - err = SecKeychainGetStatus(keychain.get(), &status); - if(err == noErr) - { - const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str(); - if((err = SecKeychainUnlock(keychain.get(), keychainPassword.size(), pass, pass != 0))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to unlock keychain:\n" + errorToString(err)); - } - } - else if(err == errSecNoSuchKeychain) - { - const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str(); - keychain.reset(0); - if((err = SecKeychainCreate(keychainPath.c_str(), keychainPassword.size(), pass, pass == 0, 0, &keychain.get()))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to create keychain:\n" + errorToString(err)); - } - } - else - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to open keychain:\n" + errorToString(err)); - } - - // - // Set keychain settings to avoid keychain lock. - // - SecKeychainSettings settings; - settings.version = SEC_KEYCHAIN_SETTINGS_VERS1; - settings.lockOnSleep = FALSE; - settings.useLockInterval = FALSE; - settings.lockInterval = INT_MAX; - if((err = SecKeychainSetSettings(keychain.get(), &settings))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error setting keychain settings:\n" + errorToString(err)); - } - - return keychain.release(); -} - -// -// Imports a certificate private key and optionally add it to a keychain. -// -SecIdentityRef -loadPrivateKey(const string& file, SecCertificateRef cert, SecKeychainRef keychain, const string& password, - const PasswordPromptPtr& prompt, int retryMax) -{ - // - // Check if we already imported the certificate - // - UniqueRef<CFDataRef> hash; - UniqueRef<CFDictionaryRef> subjectKeyProperty(getCertificateProperty(cert, kSecOIDSubjectKeyIdentifier)); - if(subjectKeyProperty) - { - CFArrayRef values = static_cast<CFArrayRef>(CFDictionaryGetValue(subjectKeyProperty.get(), - kSecPropertyKeyValue)); - for(int i = 0; i < CFArrayGetCount(values); ++i) - { - CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(values, i)); - if(CFEqual(CFDictionaryGetValue(dict, kSecPropertyKeyLabel), CFSTR("Key Identifier"))) - { - hash.retain(static_cast<CFDataRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue))); - break; - } - } - } - - const void* values[] = { keychain }; - UniqueRef<CFArrayRef> searchList(CFArrayCreate(kCFAllocatorDefault, values, 1, &kCFTypeArrayCallBacks)); - - UniqueRef<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(0, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - - CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); - CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne); - CFDictionarySetValue(query.get(), kSecMatchSearchList, searchList.get()); - CFDictionarySetValue(query.get(), kSecAttrSubjectKeyID, hash.get()); - CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); - - UniqueRef<CFTypeRef> value(0); - OSStatus err = SecItemCopyMatching(query.get(), &value.get()); - UniqueRef<SecCertificateRef> item(static_cast<SecCertificateRef>(const_cast<void*>(value.release()))); - if(err == noErr) - { - // - // If the certificate has already been imported, create the - // identity. The key should also have been imported. - // - UniqueRef<SecIdentityRef> identity; - err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity.get()); - if(err != noErr) - { - ostringstream os; - os << "IceSSL: error creating certificate identity:\n" << errorToString(err); - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - return identity.release(); - } - else if(err != errSecItemNotFound) - { - ostringstream os; - os << "IceSSL: error searching for keychain items:\n" << errorToString(err); - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - - // - // If the certificate isn't already in the keychain, load the - // private key into the keychain and add the certificate. - // - UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypePrivateKey, keychain, password, prompt, retryMax)); - int count = CFArrayGetCount(items.get()); - UniqueRef<SecKeyRef> key; - for(int i = 0; i < count; ++i) - { - SecKeychainItemRef item = - static_cast<SecKeychainItemRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0))); - if(SecKeyGetTypeID() == CFGetTypeID(item)) - { - key.retain(reinterpret_cast<SecKeyRef>(item)); - break; - } - } - if(!key) - { - throw CertificateReadException(__FILE__, __LINE__, "IceSSL: no key in file `" + file + "'"); - } - - // - // Add the certificate to the keychain - // - query.reset(CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - - CFDictionarySetValue(query.get(), kSecUseKeychain, keychain); - CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); - CFDictionarySetValue(query.get(), kSecValueRef, cert); - CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); - - value.reset(0); - err = SecItemAdd(query.get(), static_cast<CFTypeRef*>(&value.get())); - UniqueRef<CFArrayRef> added(static_cast<CFArrayRef>(value.release())); - if(err != noErr) - { - ostringstream os; - os << "IceSSL: failure adding certificate to keychain\n" << errorToString(err); - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - item.retain(static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(added.get(), 0)))); - - // - // Create the association between the private key and the certificate, - // kSecKeyLabel attribute should match the subject key identifier. - // - vector<SecKeychainAttribute> attributes; - if(hash) - { - SecKeychainAttribute attr; - attr.tag = kSecKeyLabel; - attr.data = const_cast<UInt8*>(CFDataGetBytePtr(hash.get())); - attr.length = CFDataGetLength(hash.get()); - attributes.push_back(attr); - } - - // - // kSecKeyPrintName attribute correspond to the keychain display - // name. - // - string label; - UniqueRef<CFStringRef> commonName(0); - if(SecCertificateCopyCommonName(item.get(), &commonName.get()) == noErr) - { - label = fromCFString(commonName.get()); - SecKeychainAttribute attr; - attr.tag = kSecKeyPrintName; - attr.data = const_cast<char*>(label.c_str()); - attr.length = label.size(); - attributes.push_back(attr); - } - - SecKeychainAttributeList attrs; - attrs.attr = &attributes[0]; - attrs.count = attributes.size(); - SecKeychainItemModifyAttributesAndData(reinterpret_cast<SecKeychainItemRef>(key.get()), &attrs, 0, 0); - - UniqueRef<SecIdentityRef> identity; - err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity.get()); - if(err != noErr) - { - ostringstream os; - os << "IceSSL: error creating certificate identity:\n" << errorToString(err); - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - return identity.release(); -} -#else - -CFArrayRef -loadCerts(const string& file) -{ - UniqueRef<CFArrayRef> certs(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); - if(file.find(".pem") != string::npos) - { - vector<char> buffer; - readFile(file, buffer); - string strbuf(buffer.begin(), buffer.end()); - string::size_type size, startpos, endpos = 0; - bool first = true; - while(true) - { - startpos = strbuf.find("-----BEGIN CERTIFICATE-----", endpos); - if(startpos != string::npos) - { - startpos += sizeof("-----BEGIN CERTIFICATE-----"); - endpos = strbuf.find("-----END CERTIFICATE-----", startpos); - if(endpos == string::npos) - { - InitializationException ex(__FILE__, __LINE__); - ex.reason = "IceSSL: certificate " + file + " is not a valid PEM-encoded certificate"; - throw ex; - } - size = endpos - startpos; - } - else if(first) - { - startpos = 0; - endpos = string::npos; - size = strbuf.size(); - } - else - { - break; - } - - vector<unsigned char> data(IceInternal::Base64::decode(string(&buffer[startpos], size))); - UniqueRef<CFDataRef> certdata(CFDataCreate(kCFAllocatorDefault, &data[0], data.size())); - UniqueRef<SecCertificateRef> cert(SecCertificateCreateWithData(0, certdata.get())); - if(!cert) - { - InitializationException ex(__FILE__, __LINE__); - ex.reason = "IceSSL: certificate " + file + " is not a valid PEM-encoded certificate"; - throw ex; - } - CFArrayAppendValue(const_cast<CFMutableArrayRef>(certs.get()), cert.get()); - first = false; - } - } - else - { - UniqueRef<CFDataRef> data(readCertFile(file)); - UniqueRef<SecCertificateRef> cert(SecCertificateCreateWithData(0, data.get())); - if(!cert) - { - InitializationException ex(__FILE__, __LINE__); - ex.reason = "IceSSL: certificate " + file + " is not a valid DER-encoded certificate"; - throw ex; - } - CFArrayAppendValue(const_cast<CFMutableArrayRef>(certs.get()), cert.get()); - } - return certs.release(); -} -#endif - -} - -// -// Imports a certificate (it might contain an identity or certificate depending on the format). -// -CFArrayRef -IceSSL::loadCertificateChain(const string& file, const string& keyFile, const std::string& keychainPath, - const string& keychainPassword, const string& password, const PasswordPromptPtr& prompt, - int retryMax) -{ - UniqueRef<CFArrayRef> chain; -#if defined(ICE_USE_SECURE_TRANSPORT_IOS) - UniqueRef<CFDataRef> cert(readCertFile(file)); - - UniqueRef<CFMutableDictionaryRef> settings(CFDictionaryCreateMutable(0, - 1, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - UniqueRef<CFArrayRef> items; - OSStatus err; - int count = 0; - do - { - UniqueRef<CFStringRef> pass(toCFString(password.empty() && prompt ? prompt->getPassword() : password)); - CFDictionarySetValue(settings.get(), kSecImportExportPassphrase, pass.get()); - err = SecPKCS12Import(cert.get(), settings.get(), &items.get()); - ++count; - } - while(password.empty() && prompt && err == errSecAuthFailed && count < retryMax); - - if(err != noErr) - { - ostringstream os; - os << "IceSSL: unable to import certificate from file " << file << " (error = " << err << ")"; - throw InitializationException(__FILE__, __LINE__, os.str()); - } - - for(int i = 0; i < CFArrayGetCount(items.get()); ++i) - { - CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(items.get(), i)); - SecIdentityRef identity = static_cast<SecIdentityRef>( - const_cast<void*>(CFDictionaryGetValue(dict, kSecImportItemIdentity))); - if(identity) - { - CFArrayRef certs = static_cast<CFArrayRef>(CFDictionaryGetValue(dict, kSecImportItemCertChain)); - chain.reset(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, certs)); - CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(chain.get()), 0, identity); - } - } - - if(!chain) - { - ostringstream os; - os << "IceSSL: couldn't find identity in file " << file; - throw InitializationException(__FILE__, __LINE__, os.str()); - } -#else - UniqueRef<SecKeychainRef> keychain(openKeychain(keychainPath, keychainPassword)); - if(keyFile.empty()) - { - chain.reset(loadKeychainItems(file, kSecItemTypeUnknown, keychain.get(), password, prompt, retryMax)); - } - else - { - // - // Load the certificate, don't load into the keychain as it - // might already have been imported. - // - UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, password, prompt, retryMax)); - SecCertificateRef cert = - static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0))); - if(SecCertificateGetTypeID() != CFGetTypeID(cert)) - { - ostringstream os; - os << "IceSSL: couldn't find certificate in `" << file << "'"; - throw CertificateReadException(__FILE__, __LINE__, os.str()); - } - - // - // Load the private key for the given certificate. This will - // add the certificate/key to the keychain if they aren't - // already present in the keychain. - // - UniqueRef<SecIdentityRef> identity(loadPrivateKey(keyFile, cert, keychain.get(), password, prompt, retryMax)); - chain.reset(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, items.get())); - CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(chain.get()), 0, identity.get()); - } -#endif - return chain.release(); -} - -SecCertificateRef -IceSSL::loadCertificate(const string& file) -{ - UniqueRef<SecCertificateRef> cert; -#if defined(ICE_USE_SECURE_TRANSPORT_IOS) - UniqueRef<CFArrayRef> certs(loadCerts(file)); - assert(CFArrayGetCount(certs.get()) > 0); - cert.retain((SecCertificateRef)CFArrayGetValueAtIndex(certs.get(), 0)); -#else - UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0)); - cert.retain((SecCertificateRef)CFArrayGetValueAtIndex(items.get(), 0)); -#endif - return cert.release(); -} - -CFArrayRef -IceSSL::loadCACertificates(const string& file) -{ -#if defined(ICE_USE_SECURE_TRANSPORT_IOS) - return loadCerts(file); -#else - UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0)); - UniqueRef<CFArrayRef> certificateAuthorities(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); - int count = CFArrayGetCount(items.get()); - for(CFIndex i = 0; i < count; ++i) - { - SecCertificateRef cert = - static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), i))); - assert(SecCertificateGetTypeID() == CFGetTypeID(cert)); - if(isCA(cert)) - { - CFArrayAppendValue(const_cast<CFMutableArrayRef>(certificateAuthorities.get()), cert); - } - } - return certificateAuthorities.release(); -#endif -} - -CFArrayRef -IceSSL::findCertificateChain(const std::string& keychainPath, const std::string& keychainPassword, const string& value) -{ - // - // Search the keychain using key:value pairs. The following keys are supported: - // - // Label - // Serial - // Subject - // SubjectKeyId - // - // A value must be enclosed in single or double quotes if it contains whitespace. - // - UniqueRef<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(0, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - -#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) - UniqueRef<SecKeychainRef> keychain(openKeychain(keychainPath, keychainPassword)); - const void* values[] = { keychain.get() }; - UniqueRef<CFArrayRef> searchList(CFArrayCreate(kCFAllocatorDefault, values, 1, &kCFTypeArrayCallBacks)); - CFDictionarySetValue(query.get(), kSecMatchSearchList, searchList.get()); -#endif - CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne); - CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); - CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); - CFDictionarySetValue(query.get(), kSecMatchCaseInsensitive, kCFBooleanTrue); - - size_t start = 0; - size_t pos; - bool valid = false; - while((pos = value.find(':', start)) != string::npos) - { - string field = IceUtilInternal::toUpper(IceUtilInternal::trim(value.substr(start, pos - start))); - string arg; - if(field != "LABEL" && field != "SERIAL" && field != "SUBJECT" && field != "SUBJECTKEYID") - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown key in `" + value + "'"); - } - - start = pos + 1; - while(start < value.size() && (value[start] == ' ' || value[start] == '\t')) - { - ++start; - } - - if(start == value.size()) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: missing argument in `" + value + "'"); - } - - if(value[start] == '"' || value[start] == '\'') - { - size_t end = start; - ++end; - while(end < value.size()) - { - if(value[end] == value[start] && value[end - 1] != '\\') - { - break; - } - ++end; - } - if(end == value.size() || value[end] != value[start]) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unmatched quote in `" + value + "'"); - } - ++start; - arg = value.substr(start, end - start); - start = end + 1; - } - else - { - size_t end = value.find_first_of(" \t", start); - if(end == string::npos) - { - arg = value.substr(start); - start = value.size(); - } - else - { - arg = value.substr(start, end - start); - start = end + 1; - } - } - - if(field == "SUBJECT" || field == "LABEL") - { - UniqueRef<CFStringRef> v(toCFString(arg)); - CFDictionarySetValue(query.get(), field == "LABEL" ? kSecAttrLabel : kSecMatchSubjectContains, v.get()); - valid = true; - } - else if(field == "SUBJECTKEYID" || field == "SERIAL") - { - vector<unsigned char> buffer; - if(!parseBytes(arg, buffer)) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid value `" + value + "'"); - } - UniqueRef<CFDataRef> v(CFDataCreate(kCFAllocatorDefault, &buffer[0], buffer.size())); - CFDictionarySetValue(query.get(), field == "SUBJECTKEYID" ? kSecAttrSubjectKeyID : kSecAttrSerialNumber, - v.get()); - valid = true; - } - } - - if(!valid) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid value `" + value + "'"); - } - - UniqueRef<SecCertificateRef> cert; - OSStatus err = SecItemCopyMatching(query.get(), (CFTypeRef*)&cert.get()); - if(err != noErr) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: find certificate `" + value + "' failed:\n" + errorToString(err)); - } - - // - // Retrieve the certificate chain - // - UniqueRef<SecPolicyRef> policy(SecPolicyCreateSSL(true, 0)); - UniqueRef<SecTrustRef> trust; - err = SecTrustCreateWithCertificates(reinterpret_cast<CFArrayRef>(cert.get()), policy.get(), &trust.get()); - if(err || !trust) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error creating trust object" + - (err ? ":\n" + errorToString(err) : "")); - } - - SecTrustResultType trustResult; - if((err = SecTrustEvaluate(trust.get(), &trustResult))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error evaluating trust:\n" + errorToString(err)); - } - - int chainLength = SecTrustGetCertificateCount(trust.get()); - UniqueRef<CFArrayRef> items(CFArrayCreateMutable(kCFAllocatorDefault, chainLength, &kCFTypeArrayCallBacks)); - for(int i = 0; i < chainLength; ++i) - { - CFArrayAppendValue(const_cast<CFMutableArrayRef>(items.get()), SecTrustGetCertificateAtIndex(trust.get(), i)); - } - - // - // Replace the first certificate in the chain with the - // identity. - // - UniqueRef<SecIdentityRef> identity; -#if defined(ICE_USE_SECURE_TRANSPORT_IOS) - - // - // SecIdentityCreateWithCertificate isn't supported on iOS so we lookup the identity - // using the certicate label. If the user added the identity with SecItemAdd the - // identity has the same label as the certificate. - // - query.reset(CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); - CFDictionarySetValue(query.get(), kSecValueRef, cert.get()); - CFDictionarySetValue(query.get(), kSecReturnAttributes, kCFBooleanTrue); - UniqueRef<CFDictionaryRef> attributes; - err = SecItemCopyMatching(query.get(), reinterpret_cast<CFTypeRef*>(&attributes.get())); - if(err != noErr) - { - ostringstream os; - os << "IceSSL: couldn't create identity for certificate found in the keychain:\n" << errorToString(err); - throw PluginInitializationException(__FILE__, __LINE__, os.str()); - } - - // Now lookup the identity with the label - query.reset(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne); - CFDictionarySetValue(query.get(), kSecClass, kSecClassIdentity); - CFDictionarySetValue(query.get(), kSecAttrLabel, (CFDataRef)CFDictionaryGetValue(attributes.get(), kSecAttrLabel)); - CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); - err = SecItemCopyMatching(query.get(), (CFTypeRef*)&identity.get()); - if(err == noErr) - { - UniqueRef<SecCertificateRef> cert2; - if((err = SecIdentityCopyCertificate(identity.get(), &cert2.get())) == noErr) - { - err = CFEqual(cert2.get(), cert.get()) ? noErr : errSecItemNotFound; - } - } -#else - err = SecIdentityCreateWithCertificate(keychain.get(), cert.get(), &identity.get()); -#endif - if(err != noErr) - { - ostringstream os; - os << "IceSSL: couldn't create identity for certificate found in the keychain:\n" << errorToString(err); - throw PluginInitializationException(__FILE__, __LINE__, os.str()); - } - CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(items.get()), 0, identity.get()); - return items.release(); -} - -#elif defined(ICE_USE_SCHANNEL) - -namespace -{ - -void -addMatchingCertificates(HCERTSTORE source, HCERTSTORE target, DWORD findType, const void* findParam) -{ - PCCERT_CONTEXT next = 0; - do - { - if((next = CertFindCertificateInStore(source, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, - findType, findParam, next))) - { - if(!CertAddCertificateContextToStore(target, next, CERT_STORE_ADD_ALWAYS, 0)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString()); - } - } - } - while(next); -} - -} - -vector<PCCERT_CONTEXT> -IceSSL::findCertificates(const string& location, const string& name, const string& value, vector<HCERTSTORE>& stores) -{ - DWORD storeLoc; - if(location == "CurrentUser") - { - storeLoc = CERT_SYSTEM_STORE_CURRENT_USER; - } - else - { - storeLoc = CERT_SYSTEM_STORE_LOCAL_MACHINE; - } - - HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, storeLoc, Ice::stringToWstring(name).c_str()); - if(!store) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: failed to open certificate store `" + name + - "':\n" + IceUtilInternal::lastErrorToString()); - } - - // - // Start with all of the certificates in the collection and filter as necessary. - // - // - If the value is "*", return all certificates. - // - Otherwise, search using key:value pairs. The following keys are supported: - // - // Issuer - // IssuerDN - // Serial - // Subject - // SubjectDN - // SubjectKeyId - // Thumbprint - // - // A value must be enclosed in single or double quotes if it contains whitespace. - // - HCERTSTORE tmpStore = 0; - try - { - if(value != "*") - { - if(value.find(':', 0) == string::npos) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: no key in `" + value + "'"); - } - size_t start = 0; - size_t pos; - while((pos = value.find(':', start)) != string::npos) - { - string field = IceUtilInternal::toUpper(IceUtilInternal::trim(value.substr(start, pos - start))); - if(field != "SUBJECT" && field != "SUBJECTDN" && field != "ISSUER" && field != "ISSUERDN" && - field != "THUMBPRINT" && field != "SUBJECTKEYID" && field != "SERIAL") - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown key in `" + value + "'"); - } - - start = pos + 1; - while(start < value.size() && (value[start] == ' ' || value[start] == '\t')) - { - ++start; - } - - if(start == value.size()) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: missing argument in `" + value + "'"); - } - - string arg; - if(value[start] == '"' || value[start] == '\'') - { - size_t end = start; - ++end; - while(end < value.size()) - { - if(value[end] == value[start] && value[end - 1] != '\\') - { - break; - } - ++end; - } - if(end == value.size() || value[end] != value[start]) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unmatched quote in `" + value + "'"); - } - ++start; - arg = value.substr(start, end - start); - start = end + 1; - } - else - { - size_t end = value.find_first_of(" \t", start); - if(end == string::npos) - { - arg = value.substr(start); - start = value.size(); - } - else - { - arg = value.substr(start, end - start); - start = end + 1; - } - } - - tmpStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0); - if(!tmpStore) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString()); - } - - if(field == "SUBJECT" || field == "ISSUER") - { - const wstring argW = Ice::stringToWstring(arg); - DWORD findType = field == "SUBJECT" ? CERT_FIND_SUBJECT_STR : CERT_FIND_ISSUER_STR; - addMatchingCertificates(store, tmpStore, findType, argW.c_str()); - } - else if(field == "SUBJECTDN" || field == "ISSUERDN") - { - const wstring argW = Ice::stringToWstring(arg); - DWORD flags[] = { - CERT_OID_NAME_STR, - CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, - CERT_OID_NAME_STR | CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG, - CERT_OID_NAME_STR | CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG | CERT_NAME_STR_REVERSE_FLAG - }; - for(size_t i = 0; i < sizeof(flags) / sizeof(DWORD); ++i) - { - DWORD length = 0; - if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), flags[i], 0, 0, &length, 0)) - { - throw PluginInitializationException( - __FILE__, __LINE__, - "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property:\n" + - IceUtilInternal::lastErrorToString()); - } - - vector<BYTE> buffer(length); - if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), flags[i], 0, &buffer[0], &length, 0)) - { - throw PluginInitializationException( - __FILE__, __LINE__, - "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property:\n" + - IceUtilInternal::lastErrorToString()); - } - - CERT_NAME_BLOB name = { length, &buffer[0] }; - - DWORD findType = field == "SUBJECTDN" ? CERT_FIND_SUBJECT_NAME : CERT_FIND_ISSUER_NAME; - addMatchingCertificates(store, tmpStore, findType, &name); - } - } - else if(field == "THUMBPRINT" || field == "SUBJECTKEYID") - { - vector<BYTE> buffer; - if(!parseBytes(arg, buffer)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: invalid `IceSSL.FindCert' property: can't decode the value"); - } - - CRYPT_HASH_BLOB hash = { static_cast<DWORD>(buffer.size()), &buffer[0] }; - DWORD findType = field == "THUMBPRINT" ? CERT_FIND_HASH : CERT_FIND_KEY_IDENTIFIER; - addMatchingCertificates(store, tmpStore, findType, &hash); - } - else if(field == "SERIAL") - { - vector<BYTE> buffer; - if(!parseBytes(arg, buffer)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property"); - } - - CRYPT_INTEGER_BLOB serial = { static_cast<DWORD>(buffer.size()), &buffer[0] }; - PCCERT_CONTEXT next = 0; - do - { - if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, - CERT_FIND_ANY, 0, next))) - { - if(CertCompareIntegerBlob(&serial, &next->pCertInfo->SerialNumber)) - { - if(!CertAddCertificateContextToStore(tmpStore, next, CERT_STORE_ADD_ALWAYS, 0)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error adding certificate to store:\n" + - IceUtilInternal::lastErrorToString()); - } - } - } - } - while(next); - } - CertCloseStore(store, 0); - store = tmpStore; - } - } - } - catch(...) - { - if(store && store != tmpStore) - { - CertCloseStore(store, 0); - } - - if(tmpStore) - { - CertCloseStore(tmpStore, 0); - tmpStore = 0; - } - throw; - } - - vector<PCCERT_CONTEXT> certs; - if(store) - { - PCCERT_CONTEXT next = 0; - do - { - if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, 0, - next))) - { - certs.push_back(next); - } - } - while(next); - stores.push_back(store); - } - return certs; -} -#elif defined (ICE_OS_UWP) - -namespace -{ - -// -// Find a certificate in the Application Personal certificate store -// with the given friendly name. Returns the matching certificate or -// nullptr if none is found. -// -Certificates::Certificate^ -findPersonalCertificate(String^ friendlyName) -{ - CertificateQuery^ query = ref new CertificateQuery(); - query->IncludeDuplicates = true; - query->IncludeExpiredCertificates = true; - query->FriendlyName = friendlyName; - query->StoreName = StandardCertificateStoreNames::Personal; - - try - { - auto certificates = IceInternal::runSync(CertificateStores::FindAllAsync(query)); - return certificates->Size > 0 ? certificates->GetAt(0) : nullptr; - } - catch(Platform::Exception^ ex) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); - } -} - -// -// Import a certificate in the Application Personal certificate store -// with the given friendly name. Returns true if there was a password -// error and false otherwise. If the import fails because a different -// error PluginInitializationException exception is throw. -// -bool -importPfxData(String^ friendlyName, String^ data, String^ password) -{ - try - { - IceInternal::runSync(CertificateEnrollmentManager::ImportPfxDataAsync( - data, - password, - ExportOption::NotExportable, - KeyProtectionLevel::NoConsent, - InstallOptions::None, - friendlyName)); - return false; // The import succcess - } - catch(Platform::Exception^ ex) - { - if(HRESULT_CODE(ex->HResult) == ERROR_DECRYPTION_FAILED) - { - return true; // Password error - } - else - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); - } - } -} - -} - -Certificates::Certificate^ -IceSSL::importPersonalCertificate(const string& file, function<string ()> password, bool passwordPrompt, - int passwordRetryMax) -{ - auto uri = ref new Uri(ref new String(stringToWstring(file).c_str())); - try - { - auto file = IceInternal::runSync(StorageFile::GetFileFromApplicationUriAsync(uri)); - auto buffer = IceInternal::runSync(FileIO::ReadBufferAsync(file)); - - // - // Create a hash of the certificate to use as a friendly name, this will allow us - // to uniquely identify the certificate in the store. - // - auto hasher = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha1); - auto hash = hasher->CreateHash(); - - hash->Append(buffer); - String^ friendlyName = CryptographicBuffer::EncodeToBase64String(hash->GetValueAndReset()); - - // - // If the certificate is already in the store we avoid importing it. - // - Certificates::Certificate^ cert = findPersonalCertificate(friendlyName); - if(cert) - { - return cert; - } - else - { - String^ data = CryptographicBuffer::EncodeToBase64String(buffer); - int count = 0; - bool passwordErr = false; - do - { - passwordErr = importPfxData(friendlyName, data, - ref new String(stringToWstring(password()).c_str())); - } - while(passwordPrompt && passwordErr && ++count < passwordRetryMax); - if(passwordErr) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: error decoding certificate"); - } - return findPersonalCertificate(friendlyName); - } - } - catch(Platform::Exception^ ex) - { - if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND) - { - throw PluginInitializationException(__FILE__, __LINE__, "certificate file not found:\n" + file); - } - else - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); - } - } -} - -IVectorView<Certificates::Certificate^>^ -IceSSL::findCertificates(const string& name, const string& value) -{ - CertificateQuery^ query = ref new CertificateQuery(); - query->StoreName = ref new String(stringToWstring(name).c_str()); - query->IncludeDuplicates = true; - query->IncludeExpiredCertificates = true; - - if(value != "*") - { - if(value.find(':', 0) == string::npos) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: no key in `" + value + "'"); - } - size_t start = 0; - size_t pos; - while((pos = value.find(':', start)) != string::npos) - { - string field = IceUtilInternal::toUpper(IceUtilInternal::trim(value.substr(start, pos - start))); - if(field != "ISSUER" && field != "THUMBPRINT" && field != "FRIENDLYNAME") - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown key in `" + value + "'"); - } - - start = pos + 1; - while(start < value.size() && (value[start] == ' ' || value[start] == '\t')) - { - ++start; - } - - if(start == value.size()) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: missing argument in `" + value + "'"); - } - - string arg; - if(value[start] == '"' || value[start] == '\'') - { - size_t end = start; - ++end; - while(end < value.size()) - { - if(value[end] == value[start] && value[end - 1] != '\\') - { - break; - } - ++end; - } - if(end == value.size() || value[end] != value[start]) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unmatched quote in `" + value + "'"); - } - ++start; - arg = value.substr(start, end - start); - start = end + 1; - } - else - { - size_t end = value.find_first_of(" \t", start); - if(end == string::npos) - { - arg = value.substr(start); - start = value.size(); - } - else - { - arg = value.substr(start, end - start); - start = end + 1; - } - } - - if(field == "ISSUER") - { - query->IssuerName = ref new String(stringToWstring(arg).c_str()); - } - else if(field == "FRIENDLYNAME") - { - query->FriendlyName = ref new String(stringToWstring(arg).c_str()); - } - else if(field == "THUMBPRINT") - { - vector<BYTE> buffer; - if(!parseBytes(arg, buffer)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: invalid `IceSSL.FindCert' property: can't decode the value"); - } - query->Thumbprint = ref new Array<unsigned char>(&buffer[0], static_cast<unsigned int>(buffer.size())); - } - } - } - - try - { - return IceInternal::runSync(CertificateStores::FindAllAsync(query)); - } - catch(Platform::Exception^ ex) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); - } -} -#endif - void IceSSL::readFile(const string& file, vector<char>& buffer) { |