]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-11582: [mod_signalwire] Fix CA certificate detection on Windows.
authorAndrey Volk <andywolk@gmail.com>
Wed, 26 Dec 2018 23:17:31 +0000 (03:17 +0400)
committerAndrey Volk <andywolk@gmail.com>
Thu, 27 Dec 2018 00:57:04 +0000 (04:57 +0400)
src/mod/applications/mod_signalwire/cacert.cpp [new file with mode: 0644]
src/mod/applications/mod_signalwire/mod_signalwire.2017.vcxproj
src/mod/applications/mod_signalwire/mod_signalwire.c

diff --git a/src/mod/applications/mod_signalwire/cacert.cpp b/src/mod/applications/mod_signalwire/cacert.cpp
new file mode 100644 (file)
index 0000000..79f0d6e
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * cacert.cpp -- CA Certificate for cURL on Windows
+ *
+ * Copyright (c) 2018 SignalWire, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef WIN32
+
+#include <switch.h>
+#include <switch_curl.h>
+#include <switch_ssl.h>
+
+#include <vector>
+#include <wincrypt.h>
+
+std::vector<X509*> m_trustedCertificateList;
+
+SWITCH_BEGIN_EXTERN_C
+
+static void addCertificatesForStore(LPCSTR name)
+{
+       HCERTSTORE storeHandle = CertOpenSystemStore(NULL, name);
+
+       if (storeHandle == nullptr)     {
+               return;
+       }
+
+       PCCERT_CONTEXT windowsCertificate = CertEnumCertificatesInStore(storeHandle, nullptr);
+
+       while (windowsCertificate != nullptr) {
+               X509 *opensslCertificate = d2i_X509(nullptr, const_cast<unsigned char const **>(&windowsCertificate->pbCertEncoded), windowsCertificate->cbCertEncoded);
+               if (opensslCertificate == nullptr) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A certificate could not be converted.\n");
+               } else {
+                       m_trustedCertificateList.push_back(opensslCertificate);
+               }
+
+               windowsCertificate = CertEnumCertificatesInStore(storeHandle, windowsCertificate);
+       }
+
+       CertCloseStore(storeHandle, 0);
+}
+
+static void setupSslContext(SSL_CTX* context)
+{
+       X509_STORE* certStore = SSL_CTX_get_cert_store(context);
+       for (X509 *x509 : m_trustedCertificateList)     {
+               X509_STORE_add_cert(certStore, x509);
+       }
+}
+
+void sslLoadWindowsCACertificate() {
+       if (m_trustedCertificateList.empty()) {
+               addCertificatesForStore("CA");
+               addCertificatesForStore("AuthRoot");
+               addCertificatesForStore("ROOT");
+       }
+}
+
+void sslUnLoadWindowsCACertificate()
+{
+       for (X509 *x509 : m_trustedCertificateList) {
+               X509_free(x509);
+       }
+
+       m_trustedCertificateList.clear();
+}
+
+int sslContextFunction(void* curl, void* sslctx, void* userdata)
+{
+       setupSslContext(reinterpret_cast<SSL_CTX *>(sslctx));
+       return CURLE_OK;
+}
+
+SWITCH_END_EXTERN_C
+
+#endif
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
+ */
index 192c82d51dff629e1f08c485e47e19928e53bb60..c620dff061ae716501c8c13b001a75fbec982c47 100644 (file)
@@ -46,6 +46,7 @@
     <PlatformToolset>v141</PlatformToolset>\r
   </PropertyGroup>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="$(SolutionDir)\w32\curl.props" />\r
   <Import Project="$(SolutionDir)\w32\libks.props" Condition=" '$(libksPropsImported)' == '' " />\r
   <Import Project="$(SolutionDir)\w32\signalwire-client-c.props" Condition=" '$(signalwire-client-cPropsImported)' == '' " />\r
   <Import Project="$(SolutionDir)\w32\openssl.props" Condition=" '$(OpensslPropsImported)' == '' " />\r
@@ -77,6 +78,9 @@
       <PrecompiledHeader>\r
       </PrecompiledHeader>\r
     </ClCompile>\r
+    <Link>\r
+      <AdditionalDependencies>crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+    </Link>\r
   </ItemDefinitionGroup>\r
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
     <ClCompile>\r
     </Link>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="cacert.cpp" />\r
     <ClCompile Include="mod_signalwire.c" />\r
   </ItemGroup>\r
   <ItemGroup>\r
index 5fd2fe828e3d7caabf7b67c80249c0c9fe5aa472..ad2b15b3d3939b4e64f10dec45e645af6057df62 100644 (file)
 #include <sys/utsname.h>
 #endif
 
+#ifdef WIN32
+void sslLoadWindowsCACertificate();
+void sslUnLoadWindowsCACertificate();
+int sslContextFunction(void* curl, void* sslctx, void* userdata);
+#endif
+
 #define SW_KS_JSON_PRINT(_h, _j) do { \
                char *_json = ks_json_print(_j); \
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "--- %s ---\n%s\n---\n", _h, _json); \
@@ -356,6 +362,9 @@ static ks_status_t mod_signalwire_adoption_post(void)
        switch_curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
        switch_curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&rd);
        switch_curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, response_data_handler);
+#ifdef WIN32
+       curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslContextFunction);
+#endif
 
        if ((res = switch_curl_easy_perform(curl))) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Curl Result %d, Error: %s\n", res, errbuf);
@@ -861,6 +870,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_signalwire_load)
                ks_global_set_logger(mod_signalwire_kslogger);
        }
        
+#ifdef WIN32
+       sslLoadWindowsCACertificate();
+#endif
+
        // Configuration
        swclt_config_create(&globals.config);
        load_config();
@@ -967,6 +980,11 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_signalwire_shutdown)
        // shutdown libblade (but not libks?)
        swclt_shutdown();
 
+#ifdef WIN32
+       // free certificate pointers previously loaded
+       sslUnLoadWindowsCACertificate();
+#endif
+
        return SWITCH_STATUS_SUCCESS;
 }