From 8bf66bb3f92639329af14800eccbdd4310a5cd6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Tue, 7 Oct 2014 23:16:58 +0200 Subject: [PATCH] Added support for loading certificates and private key pairs from PKCS #12 files, as well as loading certificates (without private key) from PEM or DER files. Some code restructuring and cleanup. --- NetSSL_Win/NetSSL_Win_CE_vs90.vcproj | 20 ++ NetSSL_Win/NetSSL_Win_WEC2013_vs110.vcxproj | 10 + .../NetSSL_Win_WEC2013_vs110.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj | 10 + .../NetSSL_Win_WEC2013_vs120.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_vs100.vcxproj | 10 + NetSSL_Win/NetSSL_Win_vs100.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_vs110.vcxproj | 10 + NetSSL_Win/NetSSL_Win_vs110.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_vs120.vcxproj | 10 + NetSSL_Win/NetSSL_Win_vs120.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_vs71.vcproj | 20 ++ NetSSL_Win/NetSSL_Win_vs80.vcproj | 20 ++ NetSSL_Win/NetSSL_Win_vs90.vcproj | 20 ++ NetSSL_Win/NetSSL_Win_x64_vs100.vcxproj | 10 + .../NetSSL_Win_x64_vs100.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj | 10 + .../NetSSL_Win_x64_vs110.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj | 10 + .../NetSSL_Win_x64_vs120.vcxproj.filters | 54 +++- NetSSL_Win/NetSSL_Win_x64_vs90.vcproj | 20 ++ .../include/Poco/Net/AutoSecBufferDesc.h | 4 +- .../Poco/Net/CertificateHandlerFactory.h | 2 +- NetSSL_Win/include/Poco/Net/Context.h | 83 ++++-- .../Poco/Net/InvalidCertificateHandler.h | 2 +- .../include/Poco/Net/KeyConsoleHandler.h | 49 +++ NetSSL_Win/include/Poco/Net/KeyFileHandler.h | 53 ++++ .../include/Poco/Net/PrivateKeyFactory.h | 97 ++++++ .../include/Poco/Net/PrivateKeyFactoryMgr.h | 66 +++++ .../Poco/Net/PrivateKeyPassphraseHandler.h | 86 ++++++ NetSSL_Win/include/Poco/Net/SSLException.h | 8 +- NetSSL_Win/include/Poco/Net/SSLManager.h | 60 +++- .../include/Poco/Net/SecureSocketImpl.h | 9 +- NetSSL_Win/include/Poco/Net/Utility.h | 4 +- NetSSL_Win/include/Poco/Net/X509Certificate.h | 37 +-- NetSSL_Win/src/AcceptCertificateHandler.cpp | 2 +- NetSSL_Win/src/Context.cpp | 280 +++++++++++++++++- NetSSL_Win/src/InvalidCertificateHandler.cpp | 15 +- NetSSL_Win/src/KeyConsoleHandler.cpp | 42 +++ NetSSL_Win/src/KeyFileHandler.cpp | 63 ++++ NetSSL_Win/src/PrivateKeyFactory.cpp | 46 +++ NetSSL_Win/src/PrivateKeyFactoryMgr.cpp | 69 +++++ .../src/PrivateKeyPassphraseHandler.cpp | 48 +++ NetSSL_Win/src/SSLException.cpp | 8 +- NetSSL_Win/src/SSLManager.cpp | 112 ++++++- NetSSL_Win/src/SecureSocketImpl.cpp | 171 ++--------- NetSSL_Win/src/Utility.cpp | 4 +- NetSSL_Win/src/X509Certificate.cpp | 146 ++++++--- NetSSL_Win/testsuite/TestSuite.xml | 14 +- NetSSL_Win/testsuite/any.pfx | Bin 0 -> 2653 bytes NetSSL_Win/testsuite/src/HTTPSServerTest.cpp | 3 +- NetSSL_Win/testsuite/src/HTTPSServerTest.h | 2 +- NetSSL_Win/testsuite/testrunner.xml | 14 +- 53 files changed, 1809 insertions(+), 402 deletions(-) create mode 100644 NetSSL_Win/include/Poco/Net/KeyConsoleHandler.h create mode 100644 NetSSL_Win/include/Poco/Net/KeyFileHandler.h create mode 100644 NetSSL_Win/include/Poco/Net/PrivateKeyFactory.h create mode 100644 NetSSL_Win/include/Poco/Net/PrivateKeyFactoryMgr.h create mode 100644 NetSSL_Win/include/Poco/Net/PrivateKeyPassphraseHandler.h create mode 100644 NetSSL_Win/src/KeyConsoleHandler.cpp create mode 100644 NetSSL_Win/src/KeyFileHandler.cpp create mode 100644 NetSSL_Win/src/PrivateKeyFactory.cpp create mode 100644 NetSSL_Win/src/PrivateKeyFactoryMgr.cpp create mode 100644 NetSSL_Win/src/PrivateKeyPassphraseHandler.cpp create mode 100644 NetSSL_Win/testsuite/any.pfx diff --git a/NetSSL_Win/NetSSL_Win_CE_vs90.vcproj b/NetSSL_Win/NetSSL_Win_CE_vs90.vcproj index 38011e91f..1d95ae5f7 100644 --- a/NetSSL_Win/NetSSL_Win_CE_vs90.vcproj +++ b/NetSSL_Win/NetSSL_Win_CE_vs90.vcproj @@ -452,8 +452,18 @@ RelativePath=".\include\Poco\Net\Context.h"/> + + + + + + + + + + + + + + + @@ -291,6 +296,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_WEC2013_vs110.vcxproj.filters b/NetSSL_Win/NetSSL_Win_WEC2013_vs110.vcxproj.filters index 9d88e0034..02c39a6b7 100644 --- a/NetSSL_Win/NetSSL_Win_WEC2013_vs110.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_WEC2013_vs110.vcxproj.filters @@ -2,40 +2,40 @@ - {0de4c045-244a-4f3d-bbe0-6752e514e24e} + {878fcba1-5071-4bbc-9808-ba399e5f47b2} - {ada49bc2-53fc-485b-af4b-d949b6ab27b6} + {64ad3706-6090-4f59-a7d2-3ad8116fcbba} - {737631db-8e42-4fc8-b5a1-cb271ceb3ef1} + {42c9b776-e1b4-4c74-87d5-b16a75951435} - {199d6a83-c25e-4398-9f16-16957df1ec5c} + {4235c012-9e23-4d54-b8c6-1b08aa3a6a3d} - {ccfb091f-6c84-4b22-b938-2f6b32e12a87} + {530dbfdf-75df-4fe4-88d9-85d9655dae95} - {57f513f0-beb5-4f2b-aed9-1f598a8dcc19} + {547c4e14-71d8-4eed-bbf1-ee5322e24d9f} - {cf0e79e4-80cf-4bf1-af31-e2b85653dfa4} + {70849ccf-117c-4166-beb2-653e442f8c44} - {b0cd62ad-d71b-453a-a44f-3574bd25e1b8} + {797700db-19bc-4dc9-9418-93ab59a55c59} - {c46f75d0-ef5c-4dab-8cc6-5d85eb75868c} + {edb78030-e579-4746-adc6-017d0b853fb2} - {9d2f9d58-7cd4-4d21-b242-99a586ecbb8c} + {78be0b04-6d64-4145-a996-bed7680652df} - {96ed50c7-25e8-488d-a74a-23010163ecb9} + {c6454dbf-ff4f-458e-924f-a47ee413f36f} - {eb75171e-737a-49a4-b3ef-4912a3ff35fc} + {6408e594-6faf-4cad-a766-49898fc6bd8b} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj b/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj index c9a182f53..89f1ea914 100644 --- a/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj +++ b/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj @@ -269,7 +269,12 @@ + + + + + @@ -294,6 +299,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj.filters b/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj.filters index 1ef647816..391e6b1b4 100644 --- a/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_WEC2013_vs120.vcxproj.filters @@ -2,40 +2,40 @@ - {8a779d3f-ea3a-4ef9-8789-f392fabb6cdf} + {4f9a490c-4ba0-4b3c-9b41-12ff62826512} - {eaa03a7b-b6d8-4110-8dd0-c85d218b6670} + {89381472-4f3a-4a9e-bb4d-3aed565b472d} - {0d93ccfa-eb51-4a64-9ff3-d7f9d0a17787} + {71009931-c710-4852-bebf-caebfcd78782} - {44a3be9b-137c-4d5c-a050-cff2bf85b6e4} + {2bd1bb62-f00c-4b30-9465-a641a5433fe3} - {12151fea-3545-437f-ada6-f344b866395e} + {15682e28-1edb-4bcb-a3a7-204c8033cd16} - {8f4abaa6-0008-4802-9c07-137e8c2d6a51} + {ed8e7089-057d-4dde-a61f-3398336f867e} - {1e0dd904-b465-4ed6-8273-923e3b189570} + {400b4e6a-2d12-4892-be3d-c4b4c5c92e8c} - {ecb5d216-1b16-41f1-aa48-0fadadb24b9a} + {97c9808d-cd80-4c04-8c1e-c0bbfb530610} - {7241419b-98f6-45a7-a221-ef8ee00af75e} + {6247b914-a430-44a5-97f4-dfee4addd4aa} - {fabab372-cf09-4422-baf7-e638d55104ec} + {aea80a4f-d26d-4769-9bae-f3cd9db6507b} - {b850bc99-1d30-4d99-be3b-4357b5b3172f} + {cafd83fa-67e8-4779-aaa5-8befa9da9691} - {97df76b8-7e80-4173-9bf9-c67908b85b71} + {52613ccb-eaea-4a69-a7d7-ad8d230ea387} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_vs100.vcxproj b/NetSSL_Win/NetSSL_Win_vs100.vcxproj index bc7389a39..3344105ac 100644 --- a/NetSSL_Win/NetSSL_Win_vs100.vcxproj +++ b/NetSSL_Win/NetSSL_Win_vs100.vcxproj @@ -282,7 +282,12 @@ + + + + + @@ -307,6 +312,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_vs100.vcxproj.filters b/NetSSL_Win/NetSSL_Win_vs100.vcxproj.filters index 57b69a34b..ecb31aab4 100644 --- a/NetSSL_Win/NetSSL_Win_vs100.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_vs100.vcxproj.filters @@ -2,40 +2,40 @@ - {7ee1e1b4-0e1a-4c39-aba3-68b555dc56d5} + {1db08e4f-096e-4037-a390-f99c835d117b} - {f4919f53-f9b8-4b1c-93a7-3d1e9047c6c6} + {18e4f4cc-5ee2-4646-86cf-a0c8ffe7206b} - {e5ad6a9d-395c-40e5-8f05-d0664f6e86f4} + {fe263841-8c54-4ec5-8f4b-98a3d360f6da} - {7119734a-3f01-46b9-a8be-5f319567c86d} + {e2d2b80c-0e99-4f52-80fa-c5bb7f42be5d} - {ca6812ae-b955-491a-9b9f-e79b220d9526} + {98198c86-4f3f-4fe9-98e6-5116b982ec4c} - {6cf50f8e-a04c-499f-a47c-a5a6ec0c5a4b} + {d450601b-36f8-41e9-857e-c101e0e5cb27} - {22fce8a7-0b69-470e-a7b0-d48c6b08d4b0} + {4a3a5dcf-f361-4968-aac5-1c21f27925ac} - {8f50454e-8d4e-4f00-b780-b6963976382b} + {a6c8148f-84fa-4087-9a56-2a35070889a6} - {98792d45-e7e4-4a47-9acd-44d793db87fa} + {892b6b56-8f27-47e6-8ae4-568588181f7d} - {a4e453d6-2a75-4005-82be-7f720c3364a7} + {6eb49c1d-1c52-4c9b-bb6c-6bc5425029fc} - {2b93e185-350f-4168-9944-0fbd0d0c9d2d} + {bd2d5b5f-af01-4749-bf5a-27c238e4e9ce} - {022c91a4-1fb5-48de-b167-5321ba5df672} + {b8459f64-60fd-4716-8c1c-2e9ce1e762cb} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_vs110.vcxproj b/NetSSL_Win/NetSSL_Win_vs110.vcxproj index cc30f98c2..c06145d28 100644 --- a/NetSSL_Win/NetSSL_Win_vs110.vcxproj +++ b/NetSSL_Win/NetSSL_Win_vs110.vcxproj @@ -286,7 +286,12 @@ + + + + + @@ -311,6 +316,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_vs110.vcxproj.filters b/NetSSL_Win/NetSSL_Win_vs110.vcxproj.filters index f74188f8c..a087a0907 100644 --- a/NetSSL_Win/NetSSL_Win_vs110.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_vs110.vcxproj.filters @@ -2,40 +2,40 @@ - {0d224d27-bc89-435d-a0ae-fb8dec155268} + {2a8fd040-2aa8-4e81-a64a-cc145092ff56} - {8e470e8a-7880-411a-9667-baef28840ab0} + {05d6ed94-b35f-429b-895e-bb51d7d9e62c} - {e235ddca-dbcc-42f4-b2d1-663e32797548} + {8fc1f8b1-97d4-471b-a983-e7f0c0095306} - {6f4b6677-c6b6-4510-84f7-e3a76252bc02} + {8517d49f-65b2-4fed-817f-179f310dcebf} - {0fefac11-2f48-4561-bfea-d9bf600dbecc} + {2759a9fa-0352-4260-a24e-74ee17dd0878} - {3d03281d-e887-4478-b5ce-2aa9d8fac1bc} + {c830479b-cb5c-49db-9bda-635001c15a6c} - {d0548b1d-0e3a-4cee-8202-4d66a05514a4} + {af68ba31-a8a4-48ef-9f12-580c79d35cba} - {7da7ecc0-2bf0-4c50-a497-a588ccea2979} + {0cfddb7c-f0df-4132-bfa9-840c461ee133} - {039af20e-8250-4c3b-8bb2-19d1de3c2f33} + {d9862e37-b5e4-4b7f-8529-01bc0106c785} - {f09ae80c-339c-4779-b335-f152fff9f428} + {ec291911-1d24-4eb3-9602-fa358a64a5ac} - {d3406419-0773-4a54-b2be-85df24837d03} + {40e3c6e7-b00a-4fb6-9fbf-47f3143b03ec} - {96ad570e-df18-4b53-9fe9-a2c91c518b39} + {15550519-5a67-4509-8569-804601cd51d0} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_vs120.vcxproj b/NetSSL_Win/NetSSL_Win_vs120.vcxproj index 96ddcd2af..89a7bd833 100644 --- a/NetSSL_Win/NetSSL_Win_vs120.vcxproj +++ b/NetSSL_Win/NetSSL_Win_vs120.vcxproj @@ -289,7 +289,12 @@ + + + + + @@ -314,6 +319,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_vs120.vcxproj.filters b/NetSSL_Win/NetSSL_Win_vs120.vcxproj.filters index d183ee531..181173184 100644 --- a/NetSSL_Win/NetSSL_Win_vs120.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_vs120.vcxproj.filters @@ -2,40 +2,40 @@ - {ebe6a5e7-2493-4ae9-97ed-c7c5c93c6908} + {2dc64dff-d1a5-4558-8b09-6f70cf3d0d87} - {52e82e5d-f026-4f92-b8d6-f51659c5b208} + {b10f9548-97bf-4abd-99b9-87458b72dfa8} - {5d3e1d45-e5c0-431b-a586-ec97c59187d3} + {1f594a4b-f98c-46ee-8cbb-7593d26a9d93} - {42412d3b-fa51-4eea-8df8-1fb8e483b856} + {9125a503-7286-43e1-a0db-d31c63a4b0ca} - {fbb2b30d-a9cf-40e9-bc4d-16bfb63a63f4} + {b322b5e4-e9b8-4a16-9dcb-6903b2cdf6f7} - {2f6f7b79-1002-45e2-8d5f-e929bf2d626a} + {bd400d85-b616-40b6-9048-776d250cf8c3} - {8e1c9de6-9ac0-48d3-bd4f-b44be89b5b0a} + {fd76d398-778e-42a7-bd13-e39b8648db7f} - {3b8cc647-8218-4f9c-b3d7-2b23a0e2a45a} + {cbe1c39a-7dd9-4ff3-8a2b-c4e4fadfba01} - {e010ce1c-fd75-4ff4-af3d-41588d4abc67} + {5cc6ce53-e11e-489b-a287-685d56d52c4b} - {5d656ef6-8fdc-43c5-a7fe-1f18e3b1f2b7} + {6c4d3e9e-5864-46d9-8063-a6898c3face3} - {326f8d7d-dde7-419f-8854-eaebd66e61f2} + {2b536106-7d99-4049-a3c1-176faae6cc46} - {010cf036-cf67-41c5-9487-5788d2e6135e} + {623bca7c-366d-4dae-a81c-1a306094c80b} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_vs71.vcproj b/NetSSL_Win/NetSSL_Win_vs71.vcproj index cbb8b89f4..ef1a01625 100644 --- a/NetSSL_Win/NetSSL_Win_vs71.vcproj +++ b/NetSSL_Win/NetSSL_Win_vs71.vcproj @@ -386,8 +386,18 @@ RelativePath=".\include\Poco\Net\Context.h"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -305,6 +310,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_x64_vs100.vcxproj.filters b/NetSSL_Win/NetSSL_Win_x64_vs100.vcxproj.filters index 23a649cb6..2a943e54a 100644 --- a/NetSSL_Win/NetSSL_Win_x64_vs100.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_x64_vs100.vcxproj.filters @@ -2,40 +2,40 @@ - {68d20854-7ce8-4c53-a6de-36dd7e640d59} + {02054715-caf7-4387-a3ed-85971e5d4cc6} - {5502e3dc-5532-4a19-b407-a4996f2ffb32} + {27266a4f-4abe-4421-b2df-1f29ca6b5309} - {24264860-5aaf-4bc3-aca3-83f4429cccc6} + {e48199ac-031a-4d9d-a09e-b685b40bcb11} - {b31c49b4-e8ca-41c2-a2b7-ea3aab823a75} + {022ff32c-9842-4496-8238-85aecfb84246} - {f6fc067c-19b9-476a-adbc-7055a5f840db} + {08dcb0de-74a7-4197-ab7c-94c16a516f1e} - {ed4f3ec6-2e60-4b1c-8e32-00e783cac4ce} + {e0a9f8d7-b2c3-463f-b032-fed2bd62feea} - {ad625aa7-5e4c-46a2-a630-411fe22c7bd6} + {6fdc8ab6-0ce8-400b-b8ef-0551d51cb089} - {ccf743b3-6354-4668-889a-e63f1176291c} + {60c0bc0c-66d3-421f-8f9f-b6e32cc52f82} - {0751777f-0c80-4848-8a20-d91d0bb147b6} + {7d0d9dea-c941-4c74-a901-28354aba836f} - {1045fa0d-ef89-46a3-96f2-d0a4c83ed9d7} + {4e5bc229-459f-4d1e-b8a7-b13ea7c36972} - {54c09c32-5853-46b4-8806-bb0559326d5d} + {bfdb657c-2486-45d1-a8e5-784b0b06d567} - {c32b77f6-1de3-49f3-88f7-154c696fea8d} + {6dbeba61-0362-4b61-b54c-16889751ddd2} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj b/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj index 0a3943961..a5bcbf88b 100644 --- a/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj +++ b/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj @@ -284,7 +284,12 @@ + + + + + @@ -309,6 +314,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj.filters b/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj.filters index d608ab57f..b8ea290d7 100644 --- a/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_x64_vs110.vcxproj.filters @@ -2,40 +2,40 @@ - {819f3846-c576-4a64-b879-6e3c3f05a6da} + {4ac849e8-e3f4-4c83-ad0b-08dd7654855d} - {ee160c92-8e50-4e92-9f1b-6b5f54643016} + {fbbbf1df-8fba-4fe4-ae82-e9a121a21376} - {e37d55b2-75a6-41c8-9d70-d63197be600d} + {0f4d92d8-00f6-47ae-a7f2-3fec9fc9d59f} - {b1f5ee64-7532-4688-9e18-a528be5012ed} + {611092c3-1434-4c7c-bdb4-78c44bac918b} - {781920bc-375e-4ac6-b63d-065b6e185eed} + {5b29748f-7076-4550-a52c-6e13522ce070} - {6818feb0-88e5-4b11-9391-6a5cffe2ae22} + {0913463a-dc45-42c0-88c5-f31da10435f4} - {4fe9443f-4ad4-4372-a9bb-850e3a127142} + {616f5f0c-1ff1-47f9-89a2-f488c14f899f} - {b60320bc-f6a2-4cef-a509-cf1d17988316} + {a657de56-b2df-4bf8-b7ef-46dde254c622} - {a329f092-bb3e-453b-af7b-8a34f7b2b897} + {fcc60ce9-f7d2-4af8-b8ce-5e267565403a} - {95e2313b-545c-41c1-991e-59076cf8eb1d} + {f7de1e3a-ea31-4299-b4a6-bcffd725fab3} - {3e11bb78-a7d9-441d-afe5-f84801729154} + {8e9ecae9-20f8-4b7b-bf89-14f266ba824e} - {eba3f3e4-320d-42f5-8934-20229e3b85f8} + {4e8d83dd-080d-4bb6-9c26-dfd5d042ec25} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj b/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj index de3561465..aba555e6a 100644 --- a/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj +++ b/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj @@ -287,7 +287,12 @@ + + + + + @@ -312,6 +317,11 @@ + + + + + diff --git a/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj.filters b/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj.filters index f76dc66f3..e6ef42a3a 100644 --- a/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj.filters +++ b/NetSSL_Win/NetSSL_Win_x64_vs120.vcxproj.filters @@ -2,40 +2,40 @@ - {c6e92f67-830f-43d2-8871-563b1ebf3e0e} + {5d1c38b6-27ba-4983-a7e5-ea5e3b89fe8f} - {3661e306-cb33-4c1a-8c96-146fb3e16c43} + {bb27de0c-95a6-4457-865c-ee49e391c6f3} - {2dadc19e-9397-4f4a-9e0a-d98d66c935d2} + {3f8569b1-b27f-45c1-ac84-cf8d6ae36a56} - {c72f9fed-d80d-4218-ba40-dfc948383955} + {60709db2-794d-454b-a542-ca3ea92eb38d} - {aebe522e-5a2c-4a31-a772-64fbc806e5b6} + {dbc89d83-439c-4853-bb77-3b449f9a7d7a} - {952afc48-e512-4761-88d2-f1847f249247} + {a5cbb6a9-0425-40ca-bac5-78278387b55b} - {b65b6131-fb7e-495e-afff-dbba0452b4cb} + {00ba22c2-63d7-4de8-8566-bfc87d3c7024} - {5d96d104-b200-4758-ba01-edf8e456eaec} + {bef4c703-7b55-4215-bd89-a48e39301cde} - {b347465b-1c28-4067-bb49-24dd61e102ac} + {9a90f1d1-2008-4edd-b1a2-b3b94ad4f4c6} - {a40b1375-c4ad-4008-9962-e6a8327787f5} + {2a35f7c6-2ea5-46c8-ba84-fe5beaa3fb81} - {ef45f264-d09f-445b-87fd-243715195af8} + {7ad1640f-1620-4266-9522-ad9652f124d5} - {0dd87cd5-7a05-4790-832e-39ccd7f6d589} + {39478ff4-d4af-4f07-9441-01ac0b03c3d4} @@ -60,9 +60,24 @@ SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files + + SSLCore\Header Files + + + SSLCore\Header Files + + + SSLCore\Header Files + SSLCore\Header Files @@ -131,6 +146,21 @@ SSLCore\Source Files + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + + + SSLCore\Source Files + SSLCore\Source Files diff --git a/NetSSL_Win/NetSSL_Win_x64_vs90.vcproj b/NetSSL_Win/NetSSL_Win_x64_vs90.vcproj index 023b66f0e..4ab5eedaf 100644 --- a/NetSSL_Win/NetSSL_Win_x64_vs90.vcproj +++ b/NetSSL_Win/NetSSL_Win_x64_vs90.vcproj @@ -411,8 +411,18 @@ RelativePath=".\include\Poco\Net\Context.h"/> + + + + + + + + + + #include #include +#ifndef SECURITY_WIN32 +#define SECURITY_WIN32 +#endif +#include +#include namespace Poco { @@ -108,11 +113,14 @@ public: OPT_USE_STRONG_CRYPTO = 0x08, /// Disable known weak cryptographic algorithms, cipher suites, and /// SSL/TLS protocol versions that may be otherwise enabled for better interoperability. + OPT_LOAD_CERT_FROM_FILE = 0x10, + /// Load certificate and private key from a PKCS #12 (.pfx) file, + /// and not from the certificate store. OPT_DEFAULTS = OPT_PERFORM_REVOCATION_CHECK | OPT_TRUST_ROOTS_WIN_CERT_STORE | OPT_USE_STRONG_CRYPTO }; Context(Usage usage, - const std::string& certificateName, + const std::string& certificateNameOrPath, VerificationMode verMode = VERIFY_RELAXED, int options = OPT_DEFAULTS, const std::string& certificateStoreName = CERT_STORE_MY); @@ -120,16 +128,21 @@ public: /// /// * usage specifies whether the context is used by a client or server, /// as well as which protocol to use. - /// * certificateName specifies the subject name of the certificate to use. + /// * certificateNameOrPath specifies either the subject name of the certificate to use, + /// or the path of a PKCS #12 file containing the certificate and corresponding private key. + /// If a subject name is specified, the certificate must be located in the certificate + /// store specified by certificateStoreName. If a path is given, the OPT_LOAD_CERT_FROM_FILE + /// option must be set. + /// * verificationMode specifies whether and how peer certificates are validated. /// * options is a combination of Option flags. /// * certificateStoreName specifies the name of the Windows certificate store - /// * to use for loading the certificate. You can use predefined constants - /// CERT_STORE_MY, CERT_STORE_ROOT, etc. - /// * verificationMode specifies whether and how peer certificates are validated. + /// to use for loading the certificate. Predefined constants + /// CERT_STORE_MY, CERT_STORE_ROOT, etc. can be used. /// - /// Note: If the private key is protected by a passphrase, a PrivateKeyPassphraseHandler - /// must have been setup with the SSLManager, or the SSLManager's PrivateKeyPassphraseRequired - /// event must be handled. + /// Note: you can use OpenSSL to convert a certificate and private key in PEM format + /// into PKCS #12 format required to import into the Context: + /// + /// openssl pkcs12 -export -inkey cert.key -in cert.crt -out cert.pfx ~Context(); /// Destroys the Context. @@ -150,37 +163,55 @@ public: int options() const; /// Returns the options flags. - const std::string& certificateName() const; - /// Returns the name of the certificate to use. - - const std::string& certificateStoreName() const; - /// Returns the name of the certificate store to use. - void addTrustedCert(const Poco::Net::X509Certificate& cert); /// Adds the certificate to the trusted certs. Takes ownership of pCert. + Poco::Net::X509Certificate certificate(); + /// Loads or imports and returns the certificate specified in the constructor. + /// + /// Throws a NoCertificateException if the certificate cannot + /// be found or no certificate name has been provided in the constructor. + /// + /// May also throw a filesystem-related exception if the certificate file + /// cannot be found. + HCERTSTORE certificateStore() const; /// Returns a handle to the certificate store. + CredHandle& credentials(); + /// Returns a reference to the Schannel credentials for this Context. + static const std::string CERT_STORE_MY; static const std::string CERT_STORE_ROOT; static const std::string CERT_STORE_TRUST; static const std::string CERT_STORE_CA; static const std::string CERT_STORE_USERDS; +protected: + void init(); + void loadCertificate(); + void importCertificate(); + void importCertificate(const char* pBuffer, std::size_t size); + void acquireSchannelCredentials(CredHandle& credHandle) const; + DWORD proto() const; + private: Context(const Context&); - Context& operator=(const Context&); + Context& operator = (const Context&); Usage _usage; Context::VerificationMode _mode; int _options; - std::string _certificateName; - std::string _certificateStoreName; + std::string _certNameOrPath; + std::string _certStoreName; HCERTSTORE _hMemCertStore; HCERTSTORE _hCollectionCertStore; HCERTSTORE _hRootCertStore; - Poco::FastMutex _mutex; + HCERTSTORE _hCertStore; + PCCERT_CONTEXT _pCert; + CredHandle _hCreds; + SecurityFunctionTableW& _securityFunctions; + mutable Poco::FastMutex _mutex; }; @@ -220,18 +251,6 @@ inline bool Context::sessionCacheEnabled() const } -inline const std::string& Context::certificateName() const -{ - return _certificateName; -} - - -inline const std::string& Context::certificateStoreName() const -{ - return _certificateStoreName; -} - - inline HCERTSTORE Context::certificateStore() const { return _hCollectionCertStore; diff --git a/NetSSL_Win/include/Poco/Net/InvalidCertificateHandler.h b/NetSSL_Win/include/Poco/Net/InvalidCertificateHandler.h index 152a34f39..088998b6a 100644 --- a/NetSSL_Win/include/Poco/Net/InvalidCertificateHandler.h +++ b/NetSSL_Win/include/Poco/Net/InvalidCertificateHandler.h @@ -1,7 +1,7 @@ // // InvalidCertificateHandler.h // -// $Id: //poco/1.4/NetSSL_Win/include/Poco/Net/InvalidCertificateHandler.h#1 $ +// $Id$ // // Library: NetSSL_Win // Package: SSLCore diff --git a/NetSSL_Win/include/Poco/Net/KeyConsoleHandler.h b/NetSSL_Win/include/Poco/Net/KeyConsoleHandler.h new file mode 100644 index 000000000..ae9ca9164 --- /dev/null +++ b/NetSSL_Win/include/Poco/Net/KeyConsoleHandler.h @@ -0,0 +1,49 @@ +// +// KeyConsoleHandler.h +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: KeyConsoleHandler +// +// Definition of the KeyConsoleHandler class. +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef NetSSL_KeyConsoleHandler_INCLUDED +#define NetSSL_KeyConsoleHandler_INCLUDED + + +#include "Poco/Net/NetSSL.h" +#include "Poco/Net/PrivateKeyPassphraseHandler.h" + + +namespace Poco { +namespace Net { + + +class NetSSL_Win_API KeyConsoleHandler: public PrivateKeyPassphraseHandler + /// An implementation of PrivateKeyPassphraseHandler that + /// reads the key for a certificate from the console. +{ +public: + KeyConsoleHandler(bool server); + /// Creates the KeyConsoleHandler. + + ~KeyConsoleHandler(); + /// Destroys the KeyConsoleHandler. + + void onPrivateKeyRequested(const void* pSender, std::string& privateKey); +}; + + +} } // namespace Poco::Net + + +#endif // NetSSL_KeyConsoleHandler_INCLUDED diff --git a/NetSSL_Win/include/Poco/Net/KeyFileHandler.h b/NetSSL_Win/include/Poco/Net/KeyFileHandler.h new file mode 100644 index 000000000..9ac09b049 --- /dev/null +++ b/NetSSL_Win/include/Poco/Net/KeyFileHandler.h @@ -0,0 +1,53 @@ +// +// KeyFileHandler.h +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: KeyFileHandler +// +// Definition of the KeyFileHandler class. +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef NetSSL_KeyFileHandler_INCLUDED +#define NetSSL_KeyFileHandler_INCLUDED + + +#include "Poco/Net/NetSSL.h" +#include "Poco/Net/PrivateKeyPassphraseHandler.h" + + +namespace Poco { +namespace Net { + + +class NetSSL_Win_API KeyFileHandler: public PrivateKeyPassphraseHandler + /// An implementation of PrivateKeyPassphraseHandler that + /// reads the key for a certificate from a configuration file + /// under the path "openSSL.privateKeyPassphraseHandler.options.password". +{ +public: + KeyFileHandler(bool server); + /// Creates the KeyFileHandler. + + virtual ~KeyFileHandler(); + /// Destroys the KeyFileHandler. + + void onPrivateKeyRequested(const void* pSender, std::string& privateKey); + +private: + static const std::string CFG_PRIV_KEY_FILE; +}; + + +} } // namespace Poco::Net + + +#endif // NetSSL_KeyFileHandler_INCLUDED diff --git a/NetSSL_Win/include/Poco/Net/PrivateKeyFactory.h b/NetSSL_Win/include/Poco/Net/PrivateKeyFactory.h new file mode 100644 index 000000000..c0ef9b8d8 --- /dev/null +++ b/NetSSL_Win/include/Poco/Net/PrivateKeyFactory.h @@ -0,0 +1,97 @@ +// +// PrivateKeyFactory.h +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: PrivateKeyFactory +// +// Definition of the PrivateKeyFactory class. +// +// Copyright (c) 2006-214, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef NetSSL_PrivateKeyFactory_INCLUDED +#define NetSSL_PrivateKeyFactory_INCLUDED + + +#include "Poco/Net/NetSSL.h" + + +namespace Poco { +namespace Net { + + +class PrivateKeyPassphraseHandler; + + +class NetSSL_Win_API PrivateKeyFactory + /// A PrivateKeyFactory is responsible for creating PrivateKeyPassphraseHandlers. + /// + /// You don't need to access this class directly. Use the macro + /// POCO_REGISTER_KEYFACTORY(namespace, PrivateKeyPassphraseHandlerName) + /// instead (see the documentation of PrivateKeyPassphraseHandler for an example). +{ +public: + PrivateKeyFactory(); + /// Creates the PrivateKeyFactory. + + virtual ~PrivateKeyFactory(); + /// Destroys the PrivateKeyFactory. + + virtual PrivateKeyPassphraseHandler* create(bool onServer) const = 0; + /// Creates a new PrivateKeyPassphraseHandler +}; + + +class NetSSL_Win_API PrivateKeyFactoryRegistrar + /// Registrar class which automatically registers PrivateKeyFactories at the PrivateKeyFactoryMgr. + /// + /// You don't need to access this class directly. Use the macro + /// POCO_REGISTER_KEYFACTORY(namespace, PrivateKeyPassphraseHandlerName) + /// instead (see the documentation of PrivateKeyPassphraseHandler for an example). + +{ +public: + PrivateKeyFactoryRegistrar(const std::string& name, PrivateKeyFactory* pFactory); + /// Registers the PrivateKeyFactory with the given name at the factory manager. + + virtual ~PrivateKeyFactoryRegistrar(); + /// Destroys the PrivateKeyFactoryRegistrar. +}; + + +template +class PrivateKeyFactoryImpl: public Poco::Net::PrivateKeyFactory +{ +public: + PrivateKeyFactoryImpl() + { + } + + ~PrivateKeyFactoryImpl() + { + } + + PrivateKeyPassphraseHandler* create(bool server) const + { + return new T(server); + } +}; + + +} } // namespace Poco::Net + + +// DEPRECATED: register the factory directly at the FactoryMgr: +// Poco::Net::SSLManager::instance().privateKeyFactoryMgr().setFactory(name, new Poco::Net::PrivateKeyFactoryImpl()); +#define POCO_REGISTER_KEYFACTORY(API, PKCLS) \ + static Poco::Net::PrivateKeyFactoryRegistrar aRegistrar(std::string(#PKCLS), new Poco::Net::PrivateKeyFactoryImpl()); + + +#endif // NetSSL_PrivateKeyFactory_INCLUDED diff --git a/NetSSL_Win/include/Poco/Net/PrivateKeyFactoryMgr.h b/NetSSL_Win/include/Poco/Net/PrivateKeyFactoryMgr.h new file mode 100644 index 000000000..21a9d846f --- /dev/null +++ b/NetSSL_Win/include/Poco/Net/PrivateKeyFactoryMgr.h @@ -0,0 +1,66 @@ +// +// PrivateKeyFactoryMgr.h +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: PrivateKeyFactoryMgr +// +// Definition of the PrivateKeyFactoryMgr class. +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef NetSSL_PrivateKeyFactoryMgr_INCLUDED +#define NetSSL_PrivateKeyFactoryMgr_INCLUDED + + +#include "Poco/Net/NetSSL.h" +#include "Poco/Net/PrivateKeyFactory.h" +#include "Poco/SharedPtr.h" +#include + + +namespace Poco { +namespace Net { + + +class NetSSL_Win_API PrivateKeyFactoryMgr + /// A PrivateKeyFactoryMgr manages all existing PrivateKeyFactories. +{ +public: + typedef std::map > FactoriesMap; + + PrivateKeyFactoryMgr(); + /// Creates the PrivateKeyFactoryMgr. + + ~PrivateKeyFactoryMgr(); + /// Destroys the PrivateKeyFactoryMgr. + + void setFactory(const std::string& name, PrivateKeyFactory* pFactory); + /// Registers the factory. Class takes ownership of the pointer. + /// If a factory with the same name already exists, an exception is thrown. + + bool hasFactory(const std::string& name) const; + /// Returns true if for the given name a factory is already registered + + const PrivateKeyFactory* getFactory(const std::string& name) const; + /// Returns NULL if for the given name a factory does not exist, otherwise the factory is returned + + void removeFactory(const std::string& name); + /// Removes the factory from the manager. + +private: + FactoriesMap _factories; +}; + + +} } // namespace Poco::Net + + +#endif // NetSSL_PrivateKeyFactoryMgr_INCLUDED diff --git a/NetSSL_Win/include/Poco/Net/PrivateKeyPassphraseHandler.h b/NetSSL_Win/include/Poco/Net/PrivateKeyPassphraseHandler.h new file mode 100644 index 000000000..288c1bf78 --- /dev/null +++ b/NetSSL_Win/include/Poco/Net/PrivateKeyPassphraseHandler.h @@ -0,0 +1,86 @@ +// +// PrivateKeyPassphraseHandler.h +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: PrivateKeyPassphraseHandler +// +// Definition of the PrivateKeyPassphraseHandler class. +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef NetSSL_PrivateKeyPassphraseHandler_INCLUDED +#define NetSSL_PrivateKeyPassphraseHandler_INCLUDED + + +#include "Poco/Net/NetSSL.h" + + +namespace Poco { +namespace Net { + + +class NetSSL_Win_API PrivateKeyPassphraseHandler + /// A passphrase handler is needed whenever the private key of a certificate is loaded and the certificate is protected + /// by a passphrase. The PrivateKeyPassphraseHandler's task is to provide that passphrase. + /// One can install one's own PrivateKeyPassphraseHandler by implementing this interface. Note that + /// in the implementation file of the subclass the following code must be present (assuming you use the namespace My_API + /// and the name of your handler class is MyGuiHandler): + /// + /// #include "Poco/Net/PrivateKeyFactory.h" + /// ... + /// POCO_REGISTER_KEYFACTORY(My_API, MyGuiHandler) + /// + /// One can either set the handler directly in the startup code of the main method of ones application by calling + /// + /// SSLManager::instance().initialize(myguiHandler, myInvalidCertificateHandler, mySSLContext) + /// + /// or in case one's application extends Poco::Util::Application one can use an XML configuration and put the following entry + /// under the path openSSL.privateKeyPassphraseHandler: + /// + /// + /// MyGuiHandler + /// + /// [...] // Put optional config params for the handler here + /// + /// + /// + /// Note that the name of the passphrase handler must be same as the one provided to the POCO_REGISTER_KEYFACTORY macro. +{ +public: + PrivateKeyPassphraseHandler(bool onServerSide); + /// Creates the PrivateKeyPassphraseHandler. Automatically registers at the SSLManager::PrivateKeyPassword event. + + virtual ~PrivateKeyPassphraseHandler(); + /// Destroys the PrivateKeyPassphraseHandler. + + virtual void onPrivateKeyRequested(const void* pSender, std::string& privateKey) = 0; + /// Returns the requested private key in the parameter privateKey. + + bool serverSide() const; + +private: + bool _serverSide; +}; + + +// +// inlines +// +inline bool PrivateKeyPassphraseHandler::serverSide() const +{ + return _serverSide; +} + + +} } // namespace Poco::Net + + +#endif // NetSSL_PrivateKeyPassphraseHandler_INCLUDED diff --git a/NetSSL_Win/include/Poco/Net/SSLException.h b/NetSSL_Win/include/Poco/Net/SSLException.h index 0456d6d13..c26924cfa 100644 --- a/NetSSL_Win/include/Poco/Net/SSLException.h +++ b/NetSSL_Win/include/Poco/Net/SSLException.h @@ -1,7 +1,7 @@ // // SSLException.h // -// $Id: //poco/1.4/NetSSL_Win/include/Poco/Net/SSLException.h#1 $ +// $Id$ // // Library: NetSSL_Win // Package: SSLCore @@ -30,8 +30,10 @@ namespace Net { POCO_DECLARE_EXCEPTION(NetSSL_Win_API, SSLException, NetException) POCO_DECLARE_EXCEPTION(NetSSL_Win_API, SSLContextException, SSLException) -POCO_DECLARE_EXCEPTION(NetSSL_Win_API, InvalidCertificateException, SSLException) -POCO_DECLARE_EXCEPTION(NetSSL_Win_API, CertificateValidationException, SSLException) +POCO_DECLARE_EXCEPTION(NetSSL_Win_API, CertificateException, SSLException) +POCO_DECLARE_EXCEPTION(NetSSL_Win_API, NoCertificateException, CertificateException) +POCO_DECLARE_EXCEPTION(NetSSL_Win_API, InvalidCertificateException, CertificateException) +POCO_DECLARE_EXCEPTION(NetSSL_Win_API, CertificateValidationException, CertificateException) POCO_DECLARE_EXCEPTION(NetSSL_Win_API, SSLConnectionUnexpectedlyClosedException, SSLException) diff --git a/NetSSL_Win/include/Poco/Net/SSLManager.h b/NetSSL_Win/include/Poco/Net/SSLManager.h index 8c33a9942..608b99e47 100644 --- a/NetSSL_Win/include/Poco/Net/SSLManager.h +++ b/NetSSL_Win/include/Poco/Net/SSLManager.h @@ -1,9 +1,9 @@ // // SSLManager.h // -// $Id: //poco/1.4/NetSSL_Schannel/include/Poco/Net/SSLManager.h#1 $ +// $Id$ // -// Library: NetSSL_Schannel +// Library: NetSSL_Win // Package: SSLCore // Module: SSLManager // @@ -23,8 +23,10 @@ #include "Poco/Net/NetSSL.h" #include "Poco/Net/VerificationErrorArgs.h" #include "Poco/Net/Context.h" +#include "Poco/Net/PrivateKeyFactoryMgr.h" #include "Poco/Net/CertificateHandlerFactoryMgr.h" #include "Poco/Net/InvalidCertificateHandler.h" +#include "Poco/Util/AbstractConfiguration.h" #include "Poco/BasicEvent.h" #include "Poco/SharedPtr.h" #include @@ -77,6 +79,12 @@ class NetSSL_Win_API SSLManager /// true|false /// true|false /// true|false + /// + /// KeyFileHandler + /// + /// s3cr3t + /// + /// /// /// ConsoleCertificateHandler /// @@ -93,8 +101,9 @@ class NetSSL_Win_API SSLManager /// be prefixed with openSSL.server or openSSL.client. Some properties are only supported /// for servers. /// - /// - certificateName (string): The subject name of the certificate to use. The certificate myst + /// - certificateName (string): The subject name of the certificate to use. The certificate must /// be available in the Windows user or machine certificate store. + /// - certificatePath (string): The path of a certificate and private key file in PKCS #12 format. /// - certificateStore (string): The certificate store location to use. /// Valid values are "MY", "Root", "Trust" or "CA". Defaults to "MY". /// - verificationMode (string): Specifies whether and how peer certificates are validated (see @@ -107,6 +116,9 @@ class NetSSL_Win_API SSLManager /// - useStrongCrypto (boolean): Disable known weak cryptographic algorithms, cipher suites, and /// SSL/TLS protocol versions that may be otherwise enabled for better interoperability. /// Defaults to true. + /// - privateKeyPassphraseHandler.name (string): The name of the class (subclass of PrivateKeyPassphraseHandler) + /// used for obtaining the passphrase for accessing the private key. + /// - privateKeyPassphraseHandler.options.password (string): The password to be used by KeyFileHandler. /// - invalidCertificateHandler.name: The name of the class (subclass of CertificateHandler) /// used for confirming invalid certificates. /// - requireTLSv1 (boolean): Require a TLSv1 connection. @@ -114,6 +126,7 @@ class NetSSL_Win_API SSLManager /// - requireTLSv1_2 (boolean): Require a TLSv1.2 connection. Not supported on Windows Embedded Compact. { public: + typedef Poco::SharedPtr PrivateKeyPassphraseHandlerPtr; typedef Poco::SharedPtr InvalidCertificateHandlerPtr; Poco::BasicEvent ServerVerificationError; @@ -122,10 +135,14 @@ public: Poco::BasicEvent ClientVerificationError; /// Fired whenever a certificate verification error is detected by the client during a handshake. + Poco::BasicEvent PrivateKeyPassphraseRequired; + /// Fired when a encrypted certificate is loaded. Not setting the password + /// in the event parameter will result in a failure to load the certificate. + static SSLManager& instance(); /// Returns the instance of the SSLManager singleton. - void initializeServer(InvalidCertificateHandlerPtr& pCertificateHandler, Context::Ptr pContext); + void initializeServer(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr pCertificateHandler, Context::Ptr pContext); /// Initializes the server side of the SSLManager with a default invalid certificate handler and a default context. If this method /// is never called the SSLmanager will try to initialize its members from an application configuration. /// @@ -140,7 +157,7 @@ public: /// Context::Ptr pContext = new Context(Context::SERVER_USE, "mycert"); /// SSLManager::instance().initializeServer(pInvalidCertHandler, pContext); - void initializeClient(InvalidCertificateHandlerPtr& pCertificateHandler, Context::Ptr ptrContext); + void initializeClient(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr pCertificateHandler, Context::Ptr ptrContext); /// Initializes the client side of the SSLManager with a default invalid certificate handler and a default context. If this method /// is never called the SSLmanager will try to initialize its members from an application configuration. /// @@ -167,14 +184,26 @@ public: /// Unless initializeClient() has been called, the first call to this method initializes the default Context /// from the application configuration. + PrivateKeyPassphraseHandlerPtr serverPassphraseHandler(); + /// Returns the configured passphrase handler of the server. If none is set, the method will create a default one + /// from an application configuration. + InvalidCertificateHandlerPtr serverCertificateHandler(); /// Returns an initialized certificate handler (used by the server to verify client cert) which determines how invalid certificates are treated. /// If none is set, it will try to auto-initialize one from an application configuration. + PrivateKeyPassphraseHandlerPtr clientPassphraseHandler(); + /// Returns the configured passphrase handler of the client. If none is set, the method will create a default one + /// from an application configuration. + InvalidCertificateHandlerPtr clientCertificateHandler(); /// Returns an initialized certificate handler (used by the client to verify server cert) which determines how invalid certificates are treated. /// If none is set, it will try to auto-initialize one from an application configuration. + PrivateKeyFactoryMgr& privateKeyFactoryMgr(); + /// Returns the private key factory manager which stores the + /// factories for the different registered passphrase handlers for private keys. + CertificateHandlerFactoryMgr& certificateHandlerFactoryMgr(); /// Returns the CertificateHandlerFactoryMgr which stores the /// factories for the different registered certificate handlers. @@ -207,6 +236,9 @@ private: void initEvents(bool server); /// Registers delegates at the events according to the configuration. + void initPassphraseHandler(bool server); + /// Inits the passphrase handler. + void initCertificateHandler(bool server); /// Inits the certificate handler. @@ -216,18 +248,29 @@ private: void unloadSecurityLibrary(); /// Unloads the Windows security DLL. + static Poco::Util::AbstractConfiguration& appConfig(); + /// Returns the application configuration. + /// + /// Throws a InvalidStateException if not application instance + /// is available. + HMODULE _hSecurityModule; SecurityFunctionTableW _securityFunctions; + PrivateKeyFactoryMgr _factoryMgr; CertificateHandlerFactoryMgr _certHandlerFactoryMgr; Context::Ptr _ptrDefaultServerContext; + PrivateKeyPassphraseHandlerPtr _ptrServerPassphraseHandler; InvalidCertificateHandlerPtr _ptrServerCertificateHandler; Context::Ptr _ptrDefaultClientContext; + PrivateKeyPassphraseHandlerPtr _ptrClientPassphraseHandler; InvalidCertificateHandlerPtr _ptrClientCertificateHandler; Poco::FastMutex _mutex; static const std::string CFG_CERT_NAME; static const std::string VAL_CERT_NAME; + static const std::string CFG_CERT_PATH; + static const std::string VAL_CERT_PATH; static const std::string CFG_CERT_STORE; static const std::string VAL_CERT_STORE; static const std::string CFG_VER_MODE; @@ -252,12 +295,19 @@ private: friend class Poco::SingletonHolder; friend class SecureSocketImpl; + friend class Context; }; // // inlines // +inline PrivateKeyFactoryMgr& SSLManager::privateKeyFactoryMgr() +{ + return _factoryMgr; +} + + inline CertificateHandlerFactoryMgr& SSLManager::certificateHandlerFactoryMgr() { return _certHandlerFactoryMgr; diff --git a/NetSSL_Win/include/Poco/Net/SecureSocketImpl.h b/NetSSL_Win/include/Poco/Net/SecureSocketImpl.h index 32e05942a..e42cf3a7f 100644 --- a/NetSSL_Win/include/Poco/Net/SecureSocketImpl.h +++ b/NetSSL_Win/include/Poco/Net/SecureSocketImpl.h @@ -1,9 +1,9 @@ // // SecureSocketImpl.h // -// $Id: //poco/1.4/NetSSL_Schannel/include/Poco/Net/SecureSocketImpl.h#1 $ +// $Id$ // -// Library: NetSSL_Schannel +// Library: NetSSL_Win // Package: SSLSockets // Module: SecureSocketImpl // @@ -194,8 +194,7 @@ protected: bool loadSecurityLibrary(); void initClientContext(); void initServerContext(); - PCCERT_CONTEXT loadCertificate(const std::string& certStore, const std::string& certName, bool useMachineStore, bool mustFindCertificate); - void acquireSchannelContext(Mode mode, PCCERT_CONTEXT pCertContext, CredHandle& outHandle); + PCCERT_CONTEXT loadCertificate(bool mustFindCertificate); void initCommon(); void cleanup(); void performClientHandshake(); @@ -217,7 +216,6 @@ protected: void stateConnected(); void acceptSSL(); void connectSSL(bool completeHandshake); - DWORD proto() const; static int lastError(); void stateMachine(); void setState(State st); @@ -232,7 +230,6 @@ private: std::string _peerHostName; bool _useMachineStore; bool _clientAuthRequired; - HCERTSTORE _hCertificateStore; PCCERT_CONTEXT _pServerCertificate; PCCERT_CONTEXT _pPeerCertificate; diff --git a/NetSSL_Win/include/Poco/Net/Utility.h b/NetSSL_Win/include/Poco/Net/Utility.h index 1aee6e262..b82b7086e 100644 --- a/NetSSL_Win/include/Poco/Net/Utility.h +++ b/NetSSL_Win/include/Poco/Net/Utility.h @@ -1,9 +1,9 @@ // // Utility.h // -// $Id: //poco/1.4/NetSSL_Schannel/include/Poco/Net/Utility.h#1 $ +// $Id$ // -// Library: NetSSL_Schannel +// Library: NetSSL_Win // Package: SSLCore // Module: Utility // diff --git a/NetSSL_Win/include/Poco/Net/X509Certificate.h b/NetSSL_Win/include/Poco/Net/X509Certificate.h index 561653f79..7deab4049 100644 --- a/NetSSL_Win/include/Poco/Net/X509Certificate.h +++ b/NetSSL_Win/include/Poco/Net/X509Certificate.h @@ -1,7 +1,7 @@ // // X509Certificate.h // -// $Id: //poco/1.4/Crypto/include/Poco/Crypto/X509Certificate.h#2 $ +// $Id$ // // Library: Crypto // Package: Certificate @@ -47,13 +47,16 @@ public: NID_ORGANIZATION_UNIT_NAME }; - explicit X509Certificate(std::istream& istr); + explicit X509Certificate(const std::string& certPath); /// Creates the X509Certificate object by reading - /// a certificate in PEM format from a stream. + /// a certificate in PEM or DER format from a file. - explicit X509Certificate(const std::string& path); - /// Creates the X509Certificate object by reading - /// a certificate in PEM format from a file. + X509Certificate(const std::string& certName, const std::string& certStoreName, bool useMachineStore = false); + /// Creates the X509Certificate object by loading + /// a certificate from the specified certificate store. + /// + /// If useSystemStore is true, the machine's certificate store is used, + /// otherwise the user's certificate store. explicit X509Certificate(PCCERT_CONTEXT pCert); /// Creates the X509Certificate from an existing @@ -108,14 +111,6 @@ public: Poco::DateTime expiresOn() const; /// Returns the date and time the certificate expires. - void save(std::ostream& stream) const; - /// Writes the certificate to the given stream. - /// The certificate is written in PEM format. - - void save(const std::string& path) const; - /// Writes the certificate to the file given by path. - /// The certificate is written in PEM format. - bool issuedBy(const X509Certificate& issuerCertificate) const; /// Checks whether the certificate has been issued by /// the issuer given by issuerCertificate. This can be @@ -132,20 +127,18 @@ public: /// Returns the underlying WinCrypt certificate. protected: - void load(std::istream& stream); - /// Loads the certificate from the given stream. The - /// certificate must be in PEM format. - - void load(const std::string& path); - /// Loads the certificate from the given file. The - /// certificate must be in PEM format. - void init(); /// Extracts issuer and subject name from the certificate. static void* nid2oid(NID nid); /// Returns the OID for the given NID. + void loadCertificate(const std::string& certName, const std::string& certStoreName, bool useMachineStore); + void importCertificate(const std::string& certPath); + void importCertificate(const char* pBuffer, std::size_t size); + void importPEMCertificate(const char* pBuffer, std::size_t size); + void importDERCertificate(const char* pBuffer, std::size_t size); + private: enum { diff --git a/NetSSL_Win/src/AcceptCertificateHandler.cpp b/NetSSL_Win/src/AcceptCertificateHandler.cpp index 923e6b318..53dc712cf 100644 --- a/NetSSL_Win/src/AcceptCertificateHandler.cpp +++ b/NetSSL_Win/src/AcceptCertificateHandler.cpp @@ -1,7 +1,7 @@ // // AcceptCertificateHandler.cpp // -// $Id: //poco/1.4/NetSSL_Win/src/AcceptCertificateHandler.cpp#1 $ +// $Id$ // // Library: NetSSL_Win // Package: SSLCore diff --git a/NetSSL_Win/src/Context.cpp b/NetSSL_Win/src/Context.cpp index 9fdfc1cde..30f89ec23 100644 --- a/NetSSL_Win/src/Context.cpp +++ b/NetSSL_Win/src/Context.cpp @@ -1,9 +1,9 @@ // // Context.cpp // -// $Id: //poco/1.4/NetSSL_Schannel/src/Context.cpp#1 $ +// $Id$ // -// Library: NetSSL_Schannel +// Library: NetSSL_Win // Package: SSLCore // Module: Context // @@ -17,7 +17,16 @@ #include "Poco/Net/Context.h" #include "Poco/Net/SSLManager.h" #include "Poco/Net/SSLException.h" +#include "Poco/Net/Utility.h" #include "Poco/UnicodeConverter.h" +#include "Poco/Format.h" +#include "Poco/File.h" +#include "Poco/FileStream.h" +#include "Poco/MemoryStream.h" +#include "Poco/Base64Decoder.h" +#include "Poco/Buffer.h" +#include +#include namespace Poco { @@ -32,20 +41,54 @@ const std::string Context::CERT_STORE_USERDS("USERDS"); Context::Context(Usage usage, - const std::string& certName, + const std::string& certNameOrPath, VerificationMode verMode, int options, const std::string& certStore): _usage(usage), _mode(verMode), _options(options), - _certificateName(certName), - _certificateStoreName(certStore), + _certNameOrPath(certNameOrPath), + _certStoreName(certStore), _hMemCertStore(0), _hCollectionCertStore(0), _hRootCertStore(0), - _mutex() + _hCertStore(0), + _pCert(0), + _securityFunctions(SSLManager::instance().securityFunctions()) { + init(); +} + + +Context::~Context() +{ + if (_pCert) + { + CertFreeCertificateContext(_pCert); + } + if (_hCertStore) + { + CertCloseStore(_hCertStore, 0); + } + CertCloseStore(_hCollectionCertStore, 0); + CertCloseStore(_hMemCertStore, 0); + if (_hRootCertStore) + { + CertCloseStore(_hRootCertStore, 0); + } + if (_hCreds.dwLower != 0 && _hCreds.dwUpper != 0) + { + _securityFunctions.FreeCredentialsHandle(&_hCreds); + } +} + + +void Context::init() +{ + _hCreds.dwLower = 0; + _hCreds.dwUpper = 0; + _hMemCertStore = CertOpenStore( CERT_STORE_PROV_MEMORY, // The memory provider type 0, // The encoding type is not needed @@ -83,22 +126,229 @@ Context::Context(Usage usage, } -Context::~Context() +void Context::addTrustedCert(const Poco::Net::X509Certificate& cert) { - CertCloseStore(_hCollectionCertStore, 0); - CertCloseStore(_hMemCertStore, 0); - if (_hRootCertStore) + Poco::FastMutex::ScopedLock lock(_mutex); + if (!CertAddCertificateContextToStore(_hMemCertStore, cert.system(), CERT_STORE_ADD_REPLACE_EXISTING, 0)) + throw CertificateException("Failed to add certificate to store", GetLastError()); +} + + +Poco::Net::X509Certificate Context::certificate() +{ + if (_pCert) + return Poco::Net::X509Certificate(_pCert, true); + + if (_certNameOrPath.empty()) + throw NoCertificateException("Certificate requested, but no certificate name or path provided"); + + if (_options & OPT_LOAD_CERT_FROM_FILE) { - CertCloseStore(_hRootCertStore, 0); + importCertificate(); + } + else + { + loadCertificate(); + } + + return Poco::Net::X509Certificate(_pCert, true); +} + + +void Context::loadCertificate() +{ + std::wstring wcertStore; + Poco::UnicodeConverter::convert(_certStoreName, wcertStore); + if (!_hCertStore) + { + if (_options & OPT_USE_MACHINE_STORE) + _hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, _certStoreName.c_str()); + else + _hCertStore = CertOpenSystemStoreW(0, wcertStore.c_str()); + } + if (!_hCertStore) throw CertificateException("Failed to open certificate store", _certStoreName, GetLastError()); + + CERT_RDN_ATTR cert_rdn_attr; + cert_rdn_attr.pszObjId = szOID_COMMON_NAME; + cert_rdn_attr.dwValueType = CERT_RDN_ANY_TYPE; + cert_rdn_attr.Value.cbData = (DWORD) _certNameOrPath.size(); + cert_rdn_attr.Value.pbData = (BYTE *) _certNameOrPath.c_str(); + + CERT_RDN cert_rdn; + cert_rdn.cRDNAttr = 1; + cert_rdn.rgRDNAttr = &cert_rdn_attr; + + _pCert = CertFindCertificateInStore(_hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR, &cert_rdn, NULL); + if (!_pCert) throw NoCertificateException(Poco::format("Failed to find certificate %s in store %s", _certNameOrPath, _certStoreName)); +} + + +void Context::importCertificate() +{ + Poco::File certFile(_certNameOrPath); + if (!certFile.exists()) throw Poco::FileNotFoundException(_certNameOrPath); + Poco::File::FileSize size = certFile.getSize(); + if (size > 4096) throw Poco::DataFormatException("PKCS #12 certificate file too large", _certNameOrPath); + Poco::Buffer buffer(static_cast(size)); + Poco::FileInputStream istr(_certNameOrPath); + istr.read(buffer.begin(), buffer.size()); + if (istr.gcount() != size) throw Poco::IOException("error reading PKCS #12 certificate file"); + importCertificate(buffer.begin(), buffer.size()); +} + + +void Context::importCertificate(const char* pBuffer, std::size_t size) +{ + std::string password; + SSLManager::instance().PrivateKeyPassphraseRequired.notify(&SSLManager::instance(), password); + std::wstring wpassword; + Poco::UnicodeConverter::toUTF16(password, wpassword); + + // clear UTF-8 password + std::fill(const_cast(password.data()), const_cast(password.data() + password.size()), 'X'); + + CRYPT_DATA_BLOB blob; + blob.cbData = static_cast(size); + blob.pbData = reinterpret_cast(const_cast(pBuffer)); + + HCERTSTORE hTempStore = PFXImportCertStore(&blob, wpassword.data(), PKCS12_ALLOW_OVERWRITE_KEY | PKCS12_INCLUDE_EXTENDED_PROPERTIES); + + // clear UTF-16 password + std::fill(const_cast(wpassword.data()), const_cast(wpassword.data() + password.size()), L'X'); + + if (hTempStore) + { + PCCERT_CONTEXT pCert = 0; + pCert = CertEnumCertificatesInStore(hTempStore, pCert); + while (pCert) + { + PCCERT_CONTEXT pStoreCert = 0; + BOOL res = CertAddCertificateContextToStore(_hMemCertStore, pCert, CERT_STORE_ADD_REPLACE_EXISTING, &pStoreCert); + if (res) + { + if (!_pCert) + { + _pCert = pStoreCert; + } + else + { + CertFreeCertificateContext(pStoreCert); + pStoreCert = 0; + } + } + pCert = CertEnumCertificatesInStore(hTempStore, pCert); + } + CertCloseStore(hTempStore, 0); + } + else throw CertificateException("failed to import certificate", GetLastError()); +} + + +CredHandle& Context::credentials() +{ + Poco::FastMutex::ScopedLock lock(_mutex); + + if (_hCreds.dwLower == 0 && _hCreds.dwUpper == 0) + { + acquireSchannelCredentials(_hCreds); + } + return _hCreds; +} + + +void Context::acquireSchannelCredentials(CredHandle& credHandle) const +{ + SCHANNEL_CRED schannelCred; + ZeroMemory(&schannelCred, sizeof(schannelCred)); + schannelCred.dwVersion = SCHANNEL_CRED_VERSION; + + if (_pCert) + { + schannelCred.cCreds = 1; // how many cred are stored in &pCertContext + schannelCred.paCred = &const_cast(_pCert); + } + + schannelCred.grbitEnabledProtocols = proto(); + + // Windows NT and Windows Me/98/95: revocation checking not supported via flags + if (_options & Context::OPT_PERFORM_REVOCATION_CHECK) + schannelCred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + else + schannelCred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; + + if (isForServerUse()) + { + if (_mode == Context::VERIFY_STRICT) + schannelCred.dwFlags |= SCH_CRED_NO_SYSTEM_MAPPER; + + if (_mode == Context::VERIFY_NONE) + schannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; + } + else + { + if (_mode == Context::VERIFY_STRICT) + schannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; + else + schannelCred.dwFlags |= SCH_CRED_USE_DEFAULT_CREDS; + + if (_mode == Context::VERIFY_NONE) + schannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_SERVERNAME_CHECK; + } + +#if defined(SCH_USE_STRONG_CRYPTO) + if (_options & Context::OPT_USE_STRONG_CRYPTO) + schannelCred.dwFlags |= SCH_USE_STRONG_CRYPTO; +#endif + + schannelCred.hRootStore = _hCollectionCertStore; + + TimeStamp tsExpiry; + tsExpiry.LowPart = tsExpiry.HighPart = 0; + SECURITY_STATUS status = _securityFunctions.AcquireCredentialsHandleW( + NULL, + UNISP_NAME_W, + isForServerUse() ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, + NULL, + &schannelCred, + NULL, + NULL, + &credHandle, + &tsExpiry); + + if (status != SEC_E_OK) + { + throw SSLException("Failed to acquire Schannel credentials", Utility::formatError(status)); } } -void Context::addTrustedCert(const Poco::Net::X509Certificate& cert) +DWORD Context::proto() const { - Poco::FastMutex::ScopedLock lock(_mutex); - CertAddCertificateContextToStore(_hMemCertStore, cert.system(), CERT_STORE_ADD_REPLACE_EXISTING, 0); + switch (_usage) + { + case Context::CLIENT_USE: + return SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT; + case Context::SERVER_USE: + return SP_PROT_SSL3_SERVER | SP_PROT_TLS1_SERVER; + case Context::TLSV1_CLIENT_USE: + return SP_PROT_TLS1_CLIENT; + case Context::TLSV1_SERVER_USE: + return SP_PROT_TLS1_SERVER; +#if defined(SP_PROT_TLS1_1) + case Context::TLSV1_1_CLIENT_USE: + return SP_PROT_TLS1_1_CLIENT; + case Context::TLSV1_1_SERVER_USE: + return SP_PROT_TLS1_1_SERVER; +#endif +#if defined(SP_PROT_TLS1_2) + case Context::TLSV1_2_CLIENT_USE: + return SP_PROT_TLS1_2_CLIENT; + case Context::TLSV1_2_SERVER_USE: + return SP_PROT_TLS1_2_SERVER; +#endif + default: + throw Poco::InvalidArgumentException("Unsupported SSL/TLS protocol version"); + } } - } } // namespace Poco::Net diff --git a/NetSSL_Win/src/InvalidCertificateHandler.cpp b/NetSSL_Win/src/InvalidCertificateHandler.cpp index 8397ecff9..07d7fc55e 100644 --- a/NetSSL_Win/src/InvalidCertificateHandler.cpp +++ b/NetSSL_Win/src/InvalidCertificateHandler.cpp @@ -37,10 +37,17 @@ InvalidCertificateHandler::InvalidCertificateHandler(bool handleErrorsOnServerSi InvalidCertificateHandler::~InvalidCertificateHandler() { - if (_handleErrorsOnServerSide) - SSLManager::instance().ServerVerificationError -= Delegate(this, &InvalidCertificateHandler::onInvalidCertificate); - else - SSLManager::instance().ClientVerificationError -= Delegate(this, &InvalidCertificateHandler::onInvalidCertificate); + try + { + if (_handleErrorsOnServerSide) + SSLManager::instance().ServerVerificationError -= Delegate(this, &InvalidCertificateHandler::onInvalidCertificate); + else + SSLManager::instance().ClientVerificationError -= Delegate(this, &InvalidCertificateHandler::onInvalidCertificate); + } + catch (...) + { + poco_unexpected(); + } } diff --git a/NetSSL_Win/src/KeyConsoleHandler.cpp b/NetSSL_Win/src/KeyConsoleHandler.cpp new file mode 100644 index 000000000..6e1d1a0e4 --- /dev/null +++ b/NetSSL_Win/src/KeyConsoleHandler.cpp @@ -0,0 +1,42 @@ +// +// KeyConsoleHandler.cpp +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: KeyConsoleHandler +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/KeyConsoleHandler.h" +#include + + +namespace Poco { +namespace Net { + + +KeyConsoleHandler::KeyConsoleHandler(bool server):PrivateKeyPassphraseHandler(server) +{ +} + + +KeyConsoleHandler::~KeyConsoleHandler() +{ +} + + +void KeyConsoleHandler::onPrivateKeyRequested(const void* pSender, std::string& privateKey) +{ + std::cout << "Please enter the passphrase for the private key: "; + std::cin >> privateKey; +} + + +} } // namespace Poco::Net diff --git a/NetSSL_Win/src/KeyFileHandler.cpp b/NetSSL_Win/src/KeyFileHandler.cpp new file mode 100644 index 000000000..1efeaf9aa --- /dev/null +++ b/NetSSL_Win/src/KeyFileHandler.cpp @@ -0,0 +1,63 @@ +// +// KeyFileHandler.cpp +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: KeyFileHandler +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/KeyFileHandler.h" +#include "Poco/Net/SSLManager.h" +#include "Poco/File.h" +#include "Poco/Util/AbstractConfiguration.h" +#include "Poco/Util/Application.h" +#include "Poco/Util/OptionException.h" + + +namespace Poco { +namespace Net { + + +const std::string KeyFileHandler::CFG_PRIV_KEY_FILE("privateKeyPassphraseHandler.options.password"); + + +KeyFileHandler::KeyFileHandler(bool server):PrivateKeyPassphraseHandler(server) +{ +} + + +KeyFileHandler::~KeyFileHandler() +{ +} + + +void KeyFileHandler::onPrivateKeyRequested(const void* pSender, std::string& privateKey) +{ + try + { + Poco::Util::AbstractConfiguration& config = Poco::Util::Application::instance().config(); + std::string prefix = serverSide() ? SSLManager::CFG_SERVER_PREFIX : SSLManager::CFG_CLIENT_PREFIX; + if (!config.hasProperty(prefix + CFG_PRIV_KEY_FILE)) + throw Poco::Util::EmptyOptionException(std::string("Missing Configuration Entry: ") + prefix + CFG_PRIV_KEY_FILE); + + privateKey = config.getString(prefix + CFG_PRIV_KEY_FILE); + } + catch (Poco::NullPointerException&) + { + throw Poco::IllegalStateException( + "An application configuration is required to obtain the private key passphrase, " + "but no Poco::Util::Application instance is available." + ); + } +} + + +} } // namespace Poco::Net diff --git a/NetSSL_Win/src/PrivateKeyFactory.cpp b/NetSSL_Win/src/PrivateKeyFactory.cpp new file mode 100644 index 000000000..e75f586f0 --- /dev/null +++ b/NetSSL_Win/src/PrivateKeyFactory.cpp @@ -0,0 +1,46 @@ +// +// PrivateKeyFactory.cpp +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: PrivateKeyFactory +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/PrivateKeyFactory.h" +#include "Poco/Net/SSLManager.h" + + +namespace Poco { +namespace Net { + + +PrivateKeyFactory::PrivateKeyFactory() +{ +} + + +PrivateKeyFactory::~PrivateKeyFactory() +{ +} + + +PrivateKeyFactoryRegistrar::PrivateKeyFactoryRegistrar(const std::string& name, PrivateKeyFactory* pFactory) +{ + SSLManager::instance().privateKeyFactoryMgr().setFactory(name, pFactory); +} + + +PrivateKeyFactoryRegistrar::~PrivateKeyFactoryRegistrar() +{ +} + + +} } // namespace Poco::Net diff --git a/NetSSL_Win/src/PrivateKeyFactoryMgr.cpp b/NetSSL_Win/src/PrivateKeyFactoryMgr.cpp new file mode 100644 index 000000000..3886728d6 --- /dev/null +++ b/NetSSL_Win/src/PrivateKeyFactoryMgr.cpp @@ -0,0 +1,69 @@ +// +// PrivateKeyFactoryMgr.cpp +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: PrivateKeyFactoryMgr +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/PrivateKeyFactoryMgr.h" +#include "Poco/Net/KeyFileHandler.h" +#include "Poco/Net/KeyConsoleHandler.h" + + +namespace Poco { +namespace Net { + + +PrivateKeyFactoryMgr::PrivateKeyFactoryMgr() +{ + setFactory("KeyFileHandler", new PrivateKeyFactoryImpl()); + setFactory("KeyConsoleHandler", new PrivateKeyFactoryImpl()); +} + + +PrivateKeyFactoryMgr::~PrivateKeyFactoryMgr() +{ +} + + +void PrivateKeyFactoryMgr::setFactory(const std::string& name, PrivateKeyFactory* pFactory) +{ + bool success = _factories.insert(make_pair(name, Poco::SharedPtr(pFactory))).second; + if (!success) + delete pFactory; + poco_assert(success); +} + + +bool PrivateKeyFactoryMgr::hasFactory(const std::string& name) const +{ + return _factories.find(name) != _factories.end(); +} + + +const PrivateKeyFactory* PrivateKeyFactoryMgr::getFactory(const std::string& name) const +{ + FactoriesMap::const_iterator it = _factories.find(name); + if (it != _factories.end()) + return it->second; + else + return 0; +} + + +void PrivateKeyFactoryMgr::removeFactory(const std::string& name) +{ + _factories.erase(name); +} + + +} } // namespace Poco::Net diff --git a/NetSSL_Win/src/PrivateKeyPassphraseHandler.cpp b/NetSSL_Win/src/PrivateKeyPassphraseHandler.cpp new file mode 100644 index 000000000..fccbb85c9 --- /dev/null +++ b/NetSSL_Win/src/PrivateKeyPassphraseHandler.cpp @@ -0,0 +1,48 @@ +// +// PrivateKeyPassphraseHandler.cpp +// +// $Id$ +// +// Library: NetSSL_Win +// Package: SSLCore +// Module: PrivateKeyPassphraseHandler +// +// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/PrivateKeyPassphraseHandler.h" +#include "Poco/Net/SSLManager.h" +#include "Poco/Delegate.h" + + +using Poco::Delegate; + + +namespace Poco { +namespace Net { + + +PrivateKeyPassphraseHandler::PrivateKeyPassphraseHandler(bool onServerSide): _serverSide(onServerSide) +{ + SSLManager::instance().PrivateKeyPassphraseRequired += Delegate(this, &PrivateKeyPassphraseHandler::onPrivateKeyRequested); +} + + +PrivateKeyPassphraseHandler::~PrivateKeyPassphraseHandler() +{ + try + { + SSLManager::instance().PrivateKeyPassphraseRequired -= Delegate(this, &PrivateKeyPassphraseHandler::onPrivateKeyRequested); + } + catch (...) + { + poco_unexpected(); + } +} + + +} } // namespace Poco::Net diff --git a/NetSSL_Win/src/SSLException.cpp b/NetSSL_Win/src/SSLException.cpp index 4fb128caa..6a313da3d 100644 --- a/NetSSL_Win/src/SSLException.cpp +++ b/NetSSL_Win/src/SSLException.cpp @@ -1,7 +1,7 @@ // // SSLException.cpp // -// $Id: //poco/1.4/NetSSL_Win/src/SSLException.cpp#1 $ +// $Id$ // // Library: NetSSL_Win // Package: SSLCore @@ -24,8 +24,10 @@ namespace Net { POCO_IMPLEMENT_EXCEPTION(SSLException, NetException, "SSL Exception") POCO_IMPLEMENT_EXCEPTION(SSLContextException, SSLException, "SSL context exception") -POCO_IMPLEMENT_EXCEPTION(InvalidCertificateException, SSLException, "Invalid certficate") -POCO_IMPLEMENT_EXCEPTION(CertificateValidationException, SSLException, "Certificate validation error") +POCO_IMPLEMENT_EXCEPTION(CertificateException, SSLException, "Certificate exception") +POCO_IMPLEMENT_EXCEPTION(NoCertificateException, CertificateException, "No certificate") +POCO_IMPLEMENT_EXCEPTION(InvalidCertificateException, CertificateException, "Invalid certficate") +POCO_IMPLEMENT_EXCEPTION(CertificateValidationException, CertificateException, "Certificate validation error") POCO_IMPLEMENT_EXCEPTION(SSLConnectionUnexpectedlyClosedException, SSLException, "SSL connection unexpectedly closed") diff --git a/NetSSL_Win/src/SSLManager.cpp b/NetSSL_Win/src/SSLManager.cpp index 63317406f..ef08481a3 100644 --- a/NetSSL_Win/src/SSLManager.cpp +++ b/NetSSL_Win/src/SSLManager.cpp @@ -1,9 +1,9 @@ // // SSLManager.cpp // -// $Id: //poco/1.4/NetSSL_Schannel/src/SSLManager.cpp#1 $ +// $Id$ // -// Library: NetSSL_Schannel +// Library: NetSSL_Win // Package: SSLCore // Module: SSLManager // @@ -17,11 +17,11 @@ #include "Poco/Net/SSLManager.h" #include "Poco/Net/Context.h" #include "Poco/Net/Utility.h" +#include "Poco/Net/PrivateKeyPassphraseHandler.h" #include "Poco/SingletonHolder.h" #include "Poco/Delegate.h" #include "Poco/Util/Application.h" #include "Poco/Util/OptionException.h" -#include "Poco/Util/LayeredConfiguration.h" namespace Poco { @@ -30,6 +30,8 @@ namespace Net { const std::string SSLManager::CFG_CERT_NAME("certificateName"); const std::string SSLManager::VAL_CERT_NAME(""); +const std::string SSLManager::CFG_CERT_PATH("certificatePath"); +const std::string SSLManager::VAL_CERT_PATH(""); const std::string SSLManager::CFG_CERT_STORE("certificateStore"); const std::string SSLManager::VAL_CERT_STORE("MY"); const std::string SSLManager::CFG_VER_MODE("verificationMode"); @@ -42,6 +44,8 @@ const std::string SSLManager::CFG_USE_MACHINE_STORE("useMachineStore"); const bool SSLManager::VAL_USE_MACHINE_STORE(false); const std::string SSLManager::CFG_USE_STRONG_CRYPTO("useStrongCrypto"); const bool SSLManager::VAL_USE_STRONG_CRYPTO(true); +const std::string SSLManager::CFG_DELEGATE_HANDLER("privateKeyPassphraseHandler.name"); +const std::string SSLManager::VAL_DELEGATE_HANDLER("KeyConsoleHandler"); const std::string SSLManager::CFG_CERTIFICATE_HANDLER("invalidCertificateHandler.name"); const std::string SSLManager::VAL_CERTIFICATE_HANDLER("ConsoleCertificateHandler"); const std::string SSLManager::CFG_SERVER_PREFIX("schannel.server."); @@ -60,7 +64,15 @@ SSLManager::SSLManager(): SSLManager::~SSLManager() { - shutdown(); + try + { + shutdown(); + + } + catch (...) + { + poco_unexpected(); + } } @@ -76,17 +88,19 @@ SSLManager& SSLManager::instance() } -void SSLManager::initializeServer(InvalidCertificateHandlerPtr& ptrHandler, Context::Ptr ptrContext) +void SSLManager::initializeServer(PrivateKeyPassphraseHandlerPtr pPassphraseHandler, InvalidCertificateHandlerPtr pCertHandler, Context::Ptr pContext) { - _ptrServerCertificateHandler = ptrHandler; - _ptrDefaultServerContext = ptrContext; + _ptrServerPassphraseHandler = pPassphraseHandler; + _ptrServerCertificateHandler = pCertHandler; + _ptrDefaultServerContext = pContext; } -void SSLManager::initializeClient(InvalidCertificateHandlerPtr& ptrHandler, Context::Ptr ptrContext) +void SSLManager::initializeClient(PrivateKeyPassphraseHandlerPtr pPassphraseHandler, InvalidCertificateHandlerPtr pCertHandler, Context::Ptr pContext) { - _ptrClientCertificateHandler = ptrHandler; - _ptrDefaultClientContext = ptrContext; + _ptrClientPassphraseHandler = pPassphraseHandler; + _ptrClientCertificateHandler = pCertHandler; + _ptrDefaultClientContext = pContext; } @@ -112,6 +126,28 @@ Context::Ptr SSLManager::defaultClientContext() } +SSLManager::PrivateKeyPassphraseHandlerPtr SSLManager::serverPassphraseHandler() +{ + Poco::FastMutex::ScopedLock lock(_mutex); + + if (!_ptrServerPassphraseHandler) + initPassphraseHandler(true); + + return _ptrServerPassphraseHandler; +} + + +SSLManager::PrivateKeyPassphraseHandlerPtr SSLManager::clientPassphraseHandler() +{ + Poco::FastMutex::ScopedLock lock(_mutex); + + if (!_ptrClientPassphraseHandler) + initPassphraseHandler(false); + + return _ptrClientPassphraseHandler; +} + + SSLManager::InvalidCertificateHandlerPtr SSLManager::serverCertificateHandler() { Poco::FastMutex::ScopedLock lock(_mutex); @@ -142,8 +178,9 @@ void SSLManager::initDefaultContext(bool server) initEvents(server); const std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX; - Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config(); + Poco::Util::AbstractConfiguration& config = appConfig(); std::string certName = config.getString(prefix + CFG_CERT_NAME, VAL_CERT_NAME); + std::string certPath = config.getString(prefix + CFG_CERT_PATH, VAL_CERT_PATH); std::string certStore = config.getString(prefix + CFG_CERT_STORE, VAL_CERT_STORE); bool requireTLSv1 = config.getBool(prefix + CFG_REQUIRE_TLSV1, false); @@ -168,6 +205,11 @@ void SSLManager::initDefaultContext(bool server) if (trustRoots) options |= Context::OPT_TRUST_ROOTS_WIN_CERT_STORE; if (useMachineStore) options |= Context::OPT_USE_MACHINE_STORE; if (useStrongCrypto) options |= Context::OPT_USE_STRONG_CRYPTO; + if (!certPath.empty()) + { + options |= Context::OPT_LOAD_CERT_FROM_FILE; + certName = certPath; + } Context::Usage usage; if (server) @@ -199,17 +241,45 @@ void SSLManager::initDefaultContext(bool server) void SSLManager::initEvents(bool server) { + initPassphraseHandler(server); initCertificateHandler(server); } +void SSLManager::initPassphraseHandler(bool server) +{ + if (server && _ptrServerPassphraseHandler) return; + if (!server && _ptrClientPassphraseHandler) return; + + std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX; + Poco::Util::AbstractConfiguration& config = appConfig(); + + std::string className(config.getString(prefix + CFG_DELEGATE_HANDLER, VAL_DELEGATE_HANDLER)); + + const PrivateKeyFactory* pFactory = 0; + if (privateKeyFactoryMgr().hasFactory(className)) + { + pFactory = privateKeyFactoryMgr().getFactory(className); + } + + if (pFactory) + { + if (server) + _ptrServerPassphraseHandler = pFactory->create(server); + else + _ptrClientPassphraseHandler = pFactory->create(server); + } + else throw Poco::Util::UnknownOptionException(std::string("No passphrase handler known with the name ") + className); +} + + void SSLManager::initCertificateHandler(bool server) { if (server && _ptrServerCertificateHandler) return; if (!server && _ptrClientCertificateHandler) return; std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX; - Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config(); + Poco::Util::AbstractConfiguration& config = appConfig(); std::string className(config.getString(prefix + CFG_CERTIFICATE_HANDLER, VAL_CERTIFICATE_HANDLER)); @@ -234,8 +304,10 @@ void SSLManager::shutdown() { ClientVerificationError.clear(); ServerVerificationError.clear(); + _ptrServerPassphraseHandler = 0; _ptrServerCertificateHandler = 0; _ptrDefaultServerContext = 0; + _ptrClientPassphraseHandler = 0; _ptrClientCertificateHandler = 0; _ptrDefaultClientContext = 0; @@ -321,6 +393,22 @@ void SSLManager::unloadSecurityLibrary() } +Poco::Util::AbstractConfiguration& SSLManager::appConfig() +{ + try + { + return Poco::Util::Application::instance().config(); + } + catch (Poco::NullPointerException&) + { + throw Poco::IllegalStateException( + "An application configuration is required to initialize the Poco::Net::SSLManager, " + "but no Poco::Util::Application instance is available." + ); + } +} + + void initializeSSL() { } diff --git a/NetSSL_Win/src/SecureSocketImpl.cpp b/NetSSL_Win/src/SecureSocketImpl.cpp index cd8150d21..270ff009a 100644 --- a/NetSSL_Win/src/SecureSocketImpl.cpp +++ b/NetSSL_Win/src/SecureSocketImpl.cpp @@ -1,9 +1,9 @@ // // SecureSocketImpl.cpp // -// $Id: //poco/1.4/NetSSL_Schannel/src/SecureSocketImpl.cpp#1 $ +// $Id$ // -// Library: NetSSL_Schannel +// Library: NetSSL_Win // Package: SSLSockets // Module: SecureSocketImpl // @@ -75,9 +75,7 @@ SecureSocketImpl::SecureSocketImpl(Poco::AutoPtr pSocketImpl, Contex _pSocket(pSocketImpl), _pContext(pContext), _mode(pContext->isForServerUse() ? MODE_SERVER : MODE_CLIENT), - _useMachineStore((pContext->options() & Context::OPT_USE_MACHINE_STORE) != 0), _clientAuthRequired(pContext->verificationMode() >= Context::VERIFY_STRICT), - _hCertificateStore(0), _pServerCertificate(0), _pPeerCertificate(0), _hCreds(), @@ -155,7 +153,6 @@ void SecureSocketImpl::cleanup() if (_hCreds.dwLower != 0 && _hCreds.dwUpper != 0) { - _securityFunctions.FreeCredentialsHandle(&_hCreds); _hCreds.dwLower = 0; _hCreds.dwUpper = 0; } @@ -179,12 +176,6 @@ void SecureSocketImpl::cleanup() _pPeerCertificate = 0; } - if (_hCertificateStore) - { - CertCloseStore(_hCertificateStore, 0); - _hCertificateStore = 0; - } - // must release buffers before unloading library _outSecBuffer.release(); _inSecBuffer.release(); @@ -657,116 +648,22 @@ void SecureSocketImpl::setPeerHostName(const std::string& peerHostName) } -PCCERT_CONTEXT SecureSocketImpl::loadCertificate(const std::string& certStore, const std::string& certName, bool useMachineStore, bool mustFindCertificate) +PCCERT_CONTEXT SecureSocketImpl::loadCertificate(bool mustFindCertificate) { - if (mustFindCertificate && certName.empty()) - throw SSLException("Certificate required, but no certificate name provided"); - - PCCERT_CONTEXT pCert = 0; - - std::wstring wcertStore; - Poco::UnicodeConverter::convert(certStore, wcertStore); - if (!_hCertificateStore) + try { - if (useMachineStore) - _hCertificateStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, certStore.c_str()); + Poco::Net::X509Certificate cert = _pContext->certificate(); + PCCERT_CONTEXT pCert = cert.system(); + // TODO: avoid use of PCCERT_CONTEXT + CertDuplicateCertificateContext(pCert); + return pCert; + } + catch (...) + { + if (mustFindCertificate) + throw; else - _hCertificateStore = CertOpenSystemStoreW(0, wcertStore.c_str()); - } - if (!_hCertificateStore) - { - throw SSLException("Failed to open certificate store", certStore, GetLastError()); - } - if (!certName.empty()) - { - CERT_RDN_ATTR cert_rdn_attr; - cert_rdn_attr.pszObjId = szOID_COMMON_NAME; - cert_rdn_attr.dwValueType = CERT_RDN_ANY_TYPE; - cert_rdn_attr.Value.cbData = (DWORD) certName.size(); - cert_rdn_attr.Value.pbData = (BYTE *) certName.c_str(); - - CERT_RDN cert_rdn; - cert_rdn.cRDNAttr = 1; - cert_rdn.rgRDNAttr = &cert_rdn_attr; - - pCert = CertFindCertificateInStore(_hCertificateStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR, &cert_rdn, NULL); - if (!pCert) - { - // we throw independently of mustFind. If a name is specified we consider it an error - // if we don't find the given certificate - throw SSLException(Poco::format("Failed to find certificate %s in store %s", certName, certStore)); - } - } - - if (mustFindCertificate && !pCert) - throw SSLException(Poco::format("Failed to find certificate %s in store %s", certName, certStore)); - - return pCert; -} - - -void SecureSocketImpl::acquireSchannelContext(Mode mode, PCCERT_CONTEXT pCertContext, CredHandle& outHandle) -{ - SCHANNEL_CRED schannelCred; - ZeroMemory(&schannelCred, sizeof(schannelCred)); - schannelCred.dwVersion = SCHANNEL_CRED_VERSION; - - if (pCertContext != 0) - { - schannelCred.cCreds = 1; // how many cred are stored in &pCertContext - schannelCred.paCred = &pCertContext; - } - - schannelCred.grbitEnabledProtocols = proto(); - - // Windows NT and Windows Me/98/95: revocation checking not supported via flags - if (_pContext->options() & Context::OPT_PERFORM_REVOCATION_CHECK) - schannelCred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; - else - schannelCred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; - - if (mode == MODE_SERVER) - { - if (_pContext->verificationMode() == Context::VERIFY_STRICT) - schannelCred.dwFlags |= SCH_CRED_NO_SYSTEM_MAPPER; - - if (_pContext->verificationMode() == Context::VERIFY_NONE) - schannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; - } - else - { - if (_pContext->verificationMode() == Context::VERIFY_STRICT) - schannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; - else - schannelCred.dwFlags |= SCH_CRED_USE_DEFAULT_CREDS; - - if (_pContext->verificationMode() == Context::VERIFY_NONE) - schannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_SERVERNAME_CHECK; - } - -#if defined(SCH_USE_STRONG_CRYPTO) - if (_pContext->options() & Context::OPT_USE_STRONG_CRYPTO) - schannelCred.dwFlags |= SCH_USE_STRONG_CRYPTO; -#endif - - schannelCred.hRootStore = _pContext->certificateStore(); - - TimeStamp tsExpiry; - tsExpiry.LowPart = tsExpiry.HighPart = 0; - SECURITY_STATUS status = _securityFunctions.AcquireCredentialsHandleW( - NULL, - UNISP_NAME_W, - mode == MODE_SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, - NULL, - &schannelCred, - NULL, - NULL, - &outHandle, - &tsExpiry); - - if (status != SEC_E_OK) - { - throw SSLException("Failed to acquire Schannel credentials", Utility::formatError(status)); + return 0; } } @@ -818,8 +715,8 @@ void SecureSocketImpl::clientConnectVerify() void SecureSocketImpl::initClientContext() { - _pServerCertificate = loadCertificate(_pContext->certificateStoreName(), _pContext->certificateName(), _useMachineStore, false); - acquireSchannelContext(MODE_CLIENT, _pServerCertificate, _hCreds); + _pServerCertificate = loadCertificate(false); + _hCreds = _pContext->credentials(); } @@ -1104,8 +1001,8 @@ void SecureSocketImpl::performClientHandshakeLoopIncompleteMessage() void SecureSocketImpl::initServerContext() { - _pServerCertificate = loadCertificate(_pContext->certificateStoreName(), _pContext->certificateName(), _useMachineStore, true); - acquireSchannelContext(MODE_SERVER, _pServerCertificate, _hCreds); + _pServerCertificate = loadCertificate(true); + _hCreds = _pContext->credentials(); } @@ -1593,36 +1490,6 @@ LONG SecureSocketImpl::serverDisconnect(PCredHandle phCreds, CtxtHandle *phConte } -DWORD SecureSocketImpl::proto() const -{ - switch (_pContext->usage()) - { - case Context::CLIENT_USE: - return SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT; - case Context::SERVER_USE: - return SP_PROT_SSL3_SERVER | SP_PROT_TLS1_SERVER; - case Context::TLSV1_CLIENT_USE: - return SP_PROT_TLS1_CLIENT; - case Context::TLSV1_SERVER_USE: - return SP_PROT_TLS1_SERVER; -#if defined(SP_PROT_TLS1_1) - case Context::TLSV1_1_CLIENT_USE: - return SP_PROT_TLS1_1_CLIENT; - case Context::TLSV1_1_SERVER_USE: - return SP_PROT_TLS1_1_SERVER; -#endif -#if defined(SP_PROT_TLS1_2) - case Context::TLSV1_2_CLIENT_USE: - return SP_PROT_TLS1_2_CLIENT; - case Context::TLSV1_2_SERVER_USE: - return SP_PROT_TLS1_2_SERVER; -#endif - default: - throw Poco::InvalidArgumentException("Unsupported SSL/TLS protocol version"); - } -} - - void SecureSocketImpl::stateIllegal() { throw Poco::IllegalStateException("SSL state machine"); diff --git a/NetSSL_Win/src/Utility.cpp b/NetSSL_Win/src/Utility.cpp index 524cfffd8..11de03169 100644 --- a/NetSSL_Win/src/Utility.cpp +++ b/NetSSL_Win/src/Utility.cpp @@ -1,9 +1,9 @@ // // Utility.cpp // -// $Id: //poco/1.4/NetSSL_Schannel/src/Utility.cpp#1 $ +// $Id$ // -// Library: NetSSL_Schannel +// Library: NetSSL_Win // Package: SSLCore // Module: Utility // diff --git a/NetSSL_Win/src/X509Certificate.cpp b/NetSSL_Win/src/X509Certificate.cpp index 5e4f54395..817113fde 100644 --- a/NetSSL_Win/src/X509Certificate.cpp +++ b/NetSSL_Win/src/X509Certificate.cpp @@ -1,7 +1,7 @@ // // X509Certificate.cpp // -// $Id: //poco/1.4/Crypto/src/X509Certificate.cpp#1 $ +// $Id$ // // Library: Crypto // Package: Certificate @@ -15,13 +15,18 @@ #include "Poco/Net/X509Certificate.h" +#include "Poco/Net/SSLException.h" #include "Poco/StreamCopier.h" #include "Poco/String.h" #include "Poco/DateTimeParser.h" #include "Poco/Base64Encoder.h" #include "Poco/Base64Decoder.h" +#include "Poco/File.h" #include "Poco/FileStream.h" +#include "Poco/MemoryStream.h" +#include "Poco/Buffer.h" #include "Poco/UnicodeConverter.h" +#include "Poco/Format.h" #include @@ -29,17 +34,17 @@ namespace Poco { namespace Net { -X509Certificate::X509Certificate(std::istream& istr): - _pCert(0) -{ - load(istr); -} - - X509Certificate::X509Certificate(const std::string& path): _pCert(0) { - load(path); + importCertificate(path); +} + + +X509Certificate::X509Certificate(const std::string& certName, const std::string& certStoreName, bool useMachineStore): + _pCert(0) +{ + loadCertificate(certName, certStoreName, useMachineStore); } @@ -98,36 +103,6 @@ X509Certificate::~X509Certificate() } -void X509Certificate::load(std::istream& istr) -{ - poco_assert (!_pCert); - - // TODO - - init(); -} - - -void X509Certificate::load(const std::string& path) -{ - Poco::FileInputStream istr(path); - load(istr); -} - - -void X509Certificate::save(std::ostream& stream) const -{ - // TODO -} - - -void X509Certificate::save(const std::string& path) const -{ - Poco::FileOutputStream ostr(path); - save(ostr); -} - - void X509Certificate::init() { wchar_t data[256]; @@ -253,4 +228,97 @@ void* X509Certificate::nid2oid(NID nid) } +void X509Certificate::loadCertificate(const std::string& certName, const std::string& certStoreName, bool useMachineStore) +{ + std::wstring wcertStore; + Poco::UnicodeConverter::convert(certStoreName, wcertStore); + HCERTSTORE hCertStore; + if (useMachineStore) + hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, certStoreName.c_str()); + else + hCertStore = CertOpenSystemStoreW(0, wcertStore.c_str()); + + if (!hCertStore) throw CertificateException("Failed to open certificate store", certStoreName, GetLastError()); + + CERT_RDN_ATTR cert_rdn_attr; + cert_rdn_attr.pszObjId = szOID_COMMON_NAME; + cert_rdn_attr.dwValueType = CERT_RDN_ANY_TYPE; + cert_rdn_attr.Value.cbData = (DWORD) certName.size(); + cert_rdn_attr.Value.pbData = (BYTE *) certName.c_str(); + + CERT_RDN cert_rdn; + cert_rdn.cRDNAttr = 1; + cert_rdn.rgRDNAttr = &cert_rdn_attr; + + _pCert = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR, &cert_rdn, NULL); + if (!_pCert) + { + CertCloseStore(hCertStore, 0); + throw NoCertificateException(Poco::format("Failed to find certificate %s in store %s", certName, certStoreName)); + } + CertCloseStore(hCertStore, 0); +} + + +void X509Certificate::importCertificate(const std::string& certPath) +{ + Poco::File certFile(certPath); + if (!certFile.exists()) throw Poco::FileNotFoundException(certPath); + Poco::File::FileSize size = certFile.getSize(); + if (size > 4096) throw Poco::DataFormatException("certificate file too large", certPath); + if (size < 32) throw Poco::DataFormatException("certificate file too small", certPath); + Poco::Buffer buffer(static_cast(size)); + Poco::FileInputStream istr(certPath); + istr.read(buffer.begin(), buffer.size()); + if (istr.gcount() != size) throw Poco::IOException("error reading certificate file"); + importCertificate(buffer.begin(), buffer.size()); +} + + +void X509Certificate::importCertificate(const char* pBuffer, std::size_t size) +{ + if (std::memcmp(pBuffer, "-----BEGIN CERTIFICATE-----", 27) == 0) + importPEMCertificate(pBuffer + 27, size - 27); + else + importDERCertificate(pBuffer, size); +} + + +void X509Certificate::importPEMCertificate(const char* pBuffer, std::size_t size) +{ + Poco::Buffer derBuffer(size); + std::size_t derSize = 0; + + const char* pemBegin = pBuffer; + const char* pemEnd = pemBegin + (size - 25); + while (pemEnd > pemBegin && std::memcmp(pemEnd, "-----END CERTIFICATE-----", 25) != 0) --pemEnd; + if (pemEnd == pemBegin) throw Poco::DataFormatException("Not a valid PEM file - end marker missing"); + + Poco::MemoryInputStream istr(pemBegin, pemEnd - pemBegin); + Poco::Base64Decoder dec(istr); + + char* derBegin = derBuffer.begin(); + char* derEnd = derBegin; + + int ch = dec.get(); + while (ch != -1) + { + *derEnd++ = static_cast(ch); + ch = dec.get(); + } + + importDERCertificate(derBegin, derEnd - derBegin); +} + + +void X509Certificate::importDERCertificate(const char* pBuffer, std::size_t size) +{ + _pCert = CertCreateCertificateContext(X509_ASN_ENCODING, reinterpret_cast(pBuffer), static_cast(size)); + if (!_pCert) + { + throw Poco::DataFormatException("Failed to load certificate from file", GetLastError()); + } +} + + } } // namespace Poco::Net diff --git a/NetSSL_Win/testsuite/TestSuite.xml b/NetSSL_Win/testsuite/TestSuite.xml index 2c03eb7be..8f78c9490 100644 --- a/NetSSL_Win/testsuite/TestSuite.xml +++ b/NetSSL_Win/testsuite/TestSuite.xml @@ -1,9 +1,15 @@ - ${system.nodeName} + any.pfx none false + + KeyFileHandler + + secret + + AcceptCertificateHandler @@ -13,6 +19,12 @@ relaxed false + + KeyFileHandler + + secret + + AcceptCertificateHandler diff --git a/NetSSL_Win/testsuite/any.pfx b/NetSSL_Win/testsuite/any.pfx new file mode 100644 index 0000000000000000000000000000000000000000..cc0ad5d17ffb7165f9990d7ffb0c7a9aa6172544 GIT binary patch literal 2653 zcmY+^cQ_P|9|!Pr?r@iJisWQdXT;en*)wPF(aFimI8ydH<7X$%g@n3P$jpd1!a3=r zjBK6t&5AM-j()z+^P7Ksp3n2V-_P^@^M%Agoq!CCNE}p<2_l(doU+fxz|2sFgTg>K zDC=p=g2aJ3|64JY;Xrk#(JLSW;PjRMw_!kDWP<){ft7&?$qr)aHETw3+kl8bAPXQK z2MSm6kD-UJd^>D;3x)~EvSy=v&noUkn1^mT^*_g2O8eJu`@1`T^PwpgkDb5x;(q&F zZ@&FWnnD`O1u~flCRm5li>J9fo!(wTb%o1{M=mV^(-wG-E0Jw!B8T_%!*-Vaxhz(D zc|C^B11sZ~kH~~keNuTz>Q$pfgzE-(>gC`d(~k*7S&}{cUN;U@FO$+wc69MM`s!Dn zI7np>J^*xYbBZ~GC>*T6eh6u6DbPqsaS%OGL~>4$2vvDyaDLA1Q^QM$Kwl9wqo-^K zNSQZO8^N&Ws;yQf$J|ZqOU_yCvVS=|ex2Pr!Ne2vI=Avp8;Ky4t*_Nx@spP@LN|IC zA9ru=o;c#AsIb~tF22dr1b3tC=rDlUZahTa4k{_D_2tp;JBY6QjE^jmtryMiTtGa` znx2;CSdC3Ig@uM-ELwPffP3j~YK+|5uTp%Uva9dH(ep_ju2=dDi`TG4IfSCf2A4mi z>bCuTe0WRM(DSed>fFr(KM4nuw2spbH_cH9mvAs!jKt4u{ zuhc^s_sVkQ;M%A1{rthgt2%~njwP7>0x<<&D#u|_9x z?N!(MyeYr50L)lYY(r>9sH(+8wXs{x-F7L(*{E&GUq5_o8EdKU<=9n;C#i;i>#v)rU&!krw^CR2in1RTKt=MhTZeD|#hbd2=v88QBWJMV zgF0cWd;6ZdP?Rg*pVUV?phf>y@dg) zs~@q_(pA)SrAx9R0OCRylPr+%J3ohAlR7-^I60f4P`Bgw=B&)7M+`0X6`o}6GumaI zlbrq={rt^YHuKWm@8sK-*7>s$-3vf=ez$!*L%DnV#>G-5WJcj53h}_BN=4%&BA^eNJZ*8XWcAaaOL)% zXR0&3#rRLhAVGw(M^hCVbP;K3rfOcXc#Q&gjfyc``znrX+ z_B(y~IVIZX=cIbo5VZ+GLQ)aoNyYrjOXrfRzcW}9pAa$<*PlDpzSRbnPKZ}k#Vi<$ zyUI#ZP>TH>J)!`warf`;M9QK0XWrudTsh<7K2H4S+6&FKE4rGl^}!2EY<5QNueCdn zIIzzDKvjkV%Y$%WnbTPE^e!=-`8Qio2H>f0o2Rg?{hwxxe`}^l@ED`6nb!ZU83+gJ zw`sHO8=|wxoUlE%^+2Md?6w!LoCm44H!`gC9B>(ze0c%V9C!!O`{Pakw24Nx?$-H!fb~#K|H1chFW9wa<2BSlrl7FcVj zfjfj2sf8S#(lPw>M$!_iVIA!*@#(}MMRDC!Vz+(5S%Y0$Wk(YgFL#`7CF4mRBjmoF zV&$|Edp0o1zKA(6DBTb7xGd`IBaFE94;u^Gqs&qt0f_R)<~QwGzLHJy{fn`==6Iv1 zXocVwa1Hf=upcr*H(F;f_0M&=L7r^w%(|-_eUWqPZERa_v*pX#cq3mHVt<5tzk4DA zK5kR!Pf6@*(Sf;a=?Cxjar6;X8U;0#-KXH&`!g0d_9aIP`h)^`nx;jY>?44BAyCF| z4Msn;+Eci5G&KWYW&hjO@RxHe+urB6A6y4(<~@s z+T(nl*{@7SS#w&|5j+M*LA5j1XOR!d6c$)_+{QId4MWZJ-bU4KX_W6nqBtR%yK|Iz zr1MyJ4LuMyOne{1+|S4WNvap8DiwBS<4;!h=4A|B9BM)rD(yEWt0y>urvbuLaPdhy zdN;5|Ib1re;u1tzc}oR!v}bX-HFs)_&LQ5cV{c8{{8(%A{=qYf22L?%Brab<_S39V znjUMSupu;AbL`J&?$%F|Q6?WCCf9le@$)(MwoozeZYR9-h5O5gci(=ot)l61X&&Wj z|EfSE=mV904NBe)i6pi~a^*18Zm__qq(}MIXKZf^y#YuY;g#qlgrPN9gYS*MoQ5R zeVHwJI&M78yuK0X{t&DL09Z4&H!M3(+ALqy4_ z?OEbFQVuDMgfM}n*cpLvFaX3gFMw-m=6`8(QnK4DY}M6}-aVQHVo5B;?|<}`7x`Ps Fe*!8&;bi~- literal 0 HcmV?d00001 diff --git a/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp b/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp index 8ccf04948..08f5d9eb7 100644 --- a/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp +++ b/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp @@ -1,7 +1,7 @@ // // HTTPSServerTest.cpp // -// $Id: //poco/1.4/NetSSL_Win/testsuite/src/HTTPSServerTest.cpp#1 $ +// $Id$ // // Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH. // and Contributors. @@ -27,6 +27,7 @@ #include +using Poco::Net::Context; using Poco::Net::HTTPServer; using Poco::Net::HTTPServerParams; using Poco::Net::HTTPRequestHandler; diff --git a/NetSSL_Win/testsuite/src/HTTPSServerTest.h b/NetSSL_Win/testsuite/src/HTTPSServerTest.h index 9ba28c2c7..dd3062e81 100644 --- a/NetSSL_Win/testsuite/src/HTTPSServerTest.h +++ b/NetSSL_Win/testsuite/src/HTTPSServerTest.h @@ -1,7 +1,7 @@ // // HTTPSServerTest.h // -// $Id: //poco/1.4/NetSSL_Win/testsuite/src/HTTPSServerTest.h#1 $ +// $Id$ // // Definition of the HTTPSServerTest class. // diff --git a/NetSSL_Win/testsuite/testrunner.xml b/NetSSL_Win/testsuite/testrunner.xml index 2c03eb7be..8f78c9490 100644 --- a/NetSSL_Win/testsuite/testrunner.xml +++ b/NetSSL_Win/testsuite/testrunner.xml @@ -1,9 +1,15 @@ - ${system.nodeName} + any.pfx none false + + KeyFileHandler + + secret + + AcceptCertificateHandler @@ -13,6 +19,12 @@ relaxed false + + KeyFileHandler + + secret + + AcceptCertificateHandler