summaryrefslogtreecommitdiff
path: root/cpp/src/IceSSL/Util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceSSL/Util.cpp')
-rwxr-xr-xcpp/src/IceSSL/Util.cpp1815
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(&params, 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, &params, 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, &params, 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)
{