summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CTestCustom.cmake.in1
-rw-r--r--Source/CMakeLists.txt3
-rw-r--r--Source/cmSystemTools.cxx88
-rw-r--r--Source/cmSystemTools.h3
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx16
5 files changed, 109 insertions, 2 deletions
diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in
index f29ac70aee..d3cff518c5 100644
--- a/CTestCustom.cmake.in
+++ b/CTestCustom.cmake.in
@@ -32,6 +32,7 @@ set(CTEST_CUSTOM_WARNING_EXCEPTION
"remark: .*LOOP WAS VECTORIZED"
"warning .980: wrong number of actual arguments to intrinsic function .std::basic_"
"LINK : warning LNK4089: all references to.*ADVAPI32.dll.*discarded by /OPT:REF"
+ "LINK : warning LNK4089: all references to.*CRYPT32.dll.*discarded by /OPT:REF"
"LINK : warning LNK4089: all references to.*PSAPI.DLL.*discarded by /OPT:REF"
"LINK : warning LNK4089: all references to.*RPCRT4.dll.*discarded by /OPT:REF"
"LINK : warning LNK4089: all references to.*SHELL32.dll.*discarded by /OPT:REF"
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 1886519cf0..16b9ea10b6 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -558,7 +558,8 @@ endif()
if(WIN32 AND NOT UNIX)
# We need the rpcrt4 library on Windows.
- target_link_libraries(CMakeLib rpcrt4)
+ # We need the crypt32 library on Windows for crypto/cert APIs.
+ target_link_libraries(CMakeLib rpcrt4 crypt32)
endif()
#
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index a117238b16..583e1d0ee1 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1013,6 +1013,94 @@ std::string cmSystemTools::ComputeStringMD5(const std::string& input)
#endif
}
+//----------------------------------------------------------------------------
+std::string cmSystemTools::ComputeCertificateThumbprint(
+ const std::string& source)
+{
+ std::string thumbprint;
+
+#ifdef _WIN32
+ BYTE* certData = NULL;
+ CRYPT_INTEGER_BLOB cryptBlob;
+ HCERTSTORE certStore = NULL;
+ PCCERT_CONTEXT certContext = NULL;
+
+ HANDLE certFile = CreateFile(cmsys::Encoding::ToWide(source.c_str()).c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (certFile != INVALID_HANDLE_VALUE && certFile != NULL)
+ {
+ DWORD fileSize = GetFileSize(certFile, NULL);
+ if (fileSize != INVALID_FILE_SIZE)
+ {
+ certData = new BYTE[fileSize];
+ if (certData != NULL)
+ {
+ DWORD dwRead = 0;
+ if (ReadFile(certFile, certData, fileSize, &dwRead, NULL))
+ {
+ cryptBlob.cbData = fileSize;
+ cryptBlob.pbData = certData;
+
+ // Verify that this is a valid cert
+ if (PFXIsPFXBlob(&cryptBlob))
+ {
+ // Open the certificate as a store
+ certStore = PFXImportCertStore(
+ &cryptBlob, NULL, CRYPT_EXPORTABLE);
+ if (certStore != NULL)
+ {
+ // There should only be 1 cert.
+ certContext = CertEnumCertificatesInStore(certStore,
+ certContext);
+ if (certContext != NULL)
+ {
+ // The hash is 20 bytes
+ BYTE hashData[20];
+ DWORD hashLength = 20;
+
+ // Buffer to print the hash. Each byte takes 2 chars +
+ // terminating character
+ char hashPrint[41];
+ char *pHashPrint = hashPrint;
+ // Get the hash property from the certificate
+ if (CertGetCertificateContextProperty(certContext,
+ CERT_HASH_PROP_ID, hashData, &hashLength))
+ {
+ for (DWORD i = 0; i < hashLength; i++)
+ {
+ // Convert each byte to hexadecimal
+ sprintf(pHashPrint, "%02X", hashData[i]);
+ pHashPrint += 2;
+ }
+ *pHashPrint = '\0';
+ thumbprint = hashPrint;
+ }
+ CertFreeCertificateContext(certContext);
+ }
+ CertCloseStore(certStore, 0);
+ }
+ }
+ }
+ delete[] certData;
+ }
+ }
+ CloseHandle(certFile);
+ }
+#else
+ (void)source;
+ cmSystemTools::Message("ComputeCertificateThumbprint is not implemented",
+ "Error");
+#endif
+
+ return thumbprint;
+}
+
void cmSystemTools::Glob(const std::string& directory,
const std::string& regexp,
std::vector<std::string>& files)
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index fb58307d04..c12a1db969 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -194,6 +194,9 @@ public:
/** Compute the md5sum of a string. */
static std::string ComputeStringMD5(const std::string& input);
+ ///! Get the SHA thumbprint for a certificate file
+ static std::string ComputeCertificateThumbprint(const std::string& source);
+
/**
* Run a single executable command
*
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 80b8591e80..28a0425bd9 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2893,7 +2893,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
(*this->BuildFileStream) << cmVS10EscapeXML(artifactDir) <<
"\\</AppxPackageArtifactsDir>\n";
this->WriteString("<ProjectPriFullPath>"
- "$(TargetDir)resources.pri</ProjectPriFullPath>", 2);
+ "$(TargetDir)resources.pri</ProjectPriFullPath>\n", 2);
// If we are missing files and we don't have a certificate and
// aren't targeting WP8.0, add a default certificate
@@ -2911,6 +2911,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
this->WriteString("<", 2);
(*this->BuildFileStream) << "PackageCertificateKeyFile>"
<< pfxFile << "</PackageCertificateKeyFile>\n";
+ std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
+ if (!thumb.empty())
+ {
+ this->WriteString("<PackageCertificateThumbprint>", 2);
+ (*this->BuildFileStream) << thumb
+ << "</PackageCertificateThumbprint>\n";
+ }
this->WriteString("</PropertyGroup>\n", 1);
}
else if(!pfxFile.empty())
@@ -2919,6 +2926,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
this->WriteString("<", 2);
(*this->BuildFileStream) << "PackageCertificateKeyFile>"
<< pfxFile << "</PackageCertificateKeyFile>\n";
+ std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
+ if (!thumb.empty())
+ {
+ this->WriteString("<PackageCertificateThumbprint>", 2);
+ (*this->BuildFileStream) << thumb
+ << "</PackageCertificateThumbprint>\n";
+ }
this->WriteString("</PropertyGroup>\n", 1);
}
}