C12F19791E1AE3C30005E93F /* upnperrors.c in Sources */ = {isa = PBXBuildFile; fileRef = C12F19771E1AE3C30005E93F /* upnperrors.c */; };
C12F197B1E1AE4460005E93F /* upnperrors.h in Headers */ = {isa = PBXBuildFile; fileRef = C12F197A1E1AE4460005E93F /* upnperrors.h */; };
C1305EBE186A13B100F03351 /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = C1305EB8186A134000F03351 /* file.c */; };
+ C139E3B122BE70FB0007870C /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C139E3B022BE70FA0007870C /* libssl.dylib */; };
+ C139E3B222BE71030007870C /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C139E3B022BE70FA0007870C /* libssl.dylib */; };
+ C139E3B322BE71180007870C /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C139E3B022BE70FA0007870C /* libssl.dylib */; };
+ C139E3B422BE71250007870C /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C139E3B022BE70FA0007870C /* libssl.dylib */; };
+ C139E3B522BE712C0007870C /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C139E3B022BE70FA0007870C /* libssl.dylib */; };
C1425B351EE9C5F5001DB85F /* tr-assert.c in Sources */ = {isa = PBXBuildFile; fileRef = C1425B321EE9C5EA001DB85F /* tr-assert.c */; };
C1425B361EE9C605001DB85F /* tr-assert.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B331EE9C5EA001DB85F /* tr-assert.h */; };
C1425B371EE9C705001DB85F /* tr-macros.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B341EE9C5EA001DB85F /* tr-macros.h */; };
C12F19771E1AE3C30005E93F /* upnperrors.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = upnperrors.c; path = "third-party/miniupnpc/upnperrors.c"; sourceTree = "<group>"; };
C12F197A1E1AE4460005E93F /* upnperrors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = upnperrors.h; path = "third-party/miniupnpc/upnperrors.h"; sourceTree = "<group>"; };
C1305EB8186A134000F03351 /* file.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = file.c; path = libtransmission/file.c; sourceTree = "<group>"; };
+ C139E3B022BE70FA0007870C /* libssl.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libssl.dylib; path = "third-party/openssl/lib/libssl.dylib"; sourceTree = "<group>"; };
C1425B321EE9C5EA001DB85F /* tr-assert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "tr-assert.c"; path = "libtransmission/tr-assert.c"; sourceTree = "<group>"; };
C1425B331EE9C5EA001DB85F /* tr-assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tr-assert.h"; path = "libtransmission/tr-assert.h"; sourceTree = "<group>"; };
C1425B341EE9C5EA001DB85F /* tr-macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tr-macros.h"; path = "libtransmission/tr-macros.h"; sourceTree = "<group>"; };
A296EF3C11E560BD004A2781 /* libiconv.dylib in Frameworks */,
A2290D1E14421CC100B95A09 /* libcrypto.dylib in Frameworks */,
A2290D2F1442B23200B95A09 /* libcurl.4.dylib in Frameworks */,
+ C139E3B322BE71180007870C /* libssl.dylib in Frameworks */,
A2B6141E1395B0EC000E0975 /* libz.dylib in Frameworks */,
A2B3FB4C0E59023000FF78FB /* Cocoa.framework in Frameworks */,
);
A296EF3B11E560A7004A2781 /* libiconv.dylib in Frameworks */,
A2290D2514421D1A00B95A09 /* libcrypto.dylib in Frameworks */,
A2290D2E1442B23200B95A09 /* libcurl.4.dylib in Frameworks */,
+ C139E3B122BE70FB0007870C /* libssl.dylib in Frameworks */,
A2B6141F1395B0F5000E0975 /* libz.dylib in Frameworks */,
A2E669790F5B8E5A00B4251A /* Security.framework in Frameworks */,
A22CFB820FB66EF30009BD3E /* Carbon.framework in Frameworks */,
A2F35BE315C5A7F900EBF632 /* Foundation.framework in Frameworks */,
A2F35BD415C5A19A00EBF632 /* libtransmission.a in Frameworks */,
A2F35BDB15C5A4A000EBF632 /* libiconv.dylib in Frameworks */,
- A2F35BDA15C5A49200EBF632 /* libz.dylib in Frameworks */,
A2F35BD715C5A46D00EBF632 /* libcrypto.dylib in Frameworks */,
A2AB76EA15D8130B009EFC95 /* libcurl.4.dylib in Frameworks */,
+ C139E3B222BE71030007870C /* libssl.dylib in Frameworks */,
+ A2F35BDA15C5A49200EBF632 /* libz.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A296EF3D11E560C3004A2781 /* libiconv.dylib in Frameworks */,
A2290D2014421CD000B95A09 /* libcrypto.dylib in Frameworks */,
A2290D301442B23200B95A09 /* libcurl.4.dylib in Frameworks */,
+ C139E3B422BE71250007870C /* libssl.dylib in Frameworks */,
A2B6141D1395B0E3000E0975 /* libz.dylib in Frameworks */,
A2B3FB530E59027100FF78FB /* Cocoa.framework in Frameworks */,
);
A296EF3E11E560D1004A2781 /* libiconv.dylib in Frameworks */,
A2290D2214421CD800B95A09 /* libcrypto.dylib in Frameworks */,
A2290D311442B23200B95A09 /* libcurl.4.dylib in Frameworks */,
+ C139E3B522BE712C0007870C /* libssl.dylib in Frameworks */,
A2B6141C1395ADE9000E0975 /* libz.dylib in Frameworks */,
A25E03D90E4015100086C225 /* Cocoa.framework in Frameworks */,
);
A2F35BBA15C5A0A100EBF632 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ C139E3B022BE70FA0007870C /* libssl.dylib */,
A2F35BBB15C5A0A100EBF632 /* QuickLook.framework */,
A2F35BE215C5A7F900EBF632 /* Foundation.framework */,
A2F35BE015C5A7ED00EBF632 /* Cocoa.framework */,
endif()
if(WIN32)
- target_link_libraries(${TR_NAME} shlwapi)
+ target_link_libraries(${TR_NAME} crypt32 shlwapi)
endif()
if(ENABLE_TESTS)
#define tr_rc4_ctx_t tr_rc4_ctx_t_
#define tr_dh_ctx_t tr_dh_ctx_t_
#define tr_dh_secret_t tr_dh_secret_t_
+#define tr_ssl_ctx_t tr_ssl_ctx_t_
+#define tr_x509_store_t tr_x509_store_t_
+#define tr_x509_cert_t tr_x509_cert_t_
#define tr_crypto tr_crypto_
#define tr_cryptoConstruct tr_cryptoConstruct_
#define tr_cryptoDestruct tr_cryptoDestruct_
#define tr_dh_secret_derive tr_dh_secret_derive_
#define tr_dh_secret_free tr_dh_secret_free_
#define tr_dh_align_key tr_dh_align_key_
+#define tr_ssl_get_x509_store tr_ssl_get_x509_store_
+#define tr_x509_store_add tr_x509_store_add_
+#define tr_x509_cert_new tr_x509_cert_new_
+#define tr_x509_cert_free tr_x509_cert_free_
#define tr_rand_int tr_rand_int_
#define tr_rand_int_weak tr_rand_int_weak_
#define tr_rand_buffer tr_rand_buffer_
#undef tr_rc4_ctx_t
#undef tr_dh_ctx_t
#undef tr_dh_secret_t
+#undef tr_ssl_ctx_t
+#undef tr_x509_store_t
+#undef tr_x509_cert_t
#undef tr_crypto
#undef tr_cryptoConstruct
#undef tr_cryptoDestruct
#undef tr_dh_secret_derive
#undef tr_dh_secret_free
#undef tr_dh_align_key
+#undef tr_ssl_get_x509_store
+#undef tr_x509_store_add
+#undef tr_x509_cert_new
+#undef tr_x509_cert_free
#undef tr_rand_int
#undef tr_rand_int_weak
#undef tr_rand_buffer
#define tr_rc4_ctx_t_ tr_rc4_ctx_t
#define tr_dh_ctx_t_ tr_dh_ctx_t
#define tr_dh_secret_t_ tr_dh_secret_t
+#define tr_ssl_ctx_t_ tr_ssl_ctx_t
+#define tr_x509_store_t_ tr_x509_store_t
+#define tr_x509_cert_t_ tr_x509_cert_t
#define tr_crypto_ tr_crypto
#define tr_cryptoConstruct_ tr_cryptoConstruct
#define tr_cryptoDestruct_ tr_cryptoDestruct
#define tr_dh_secret_derive_ tr_dh_secret_derive
#define tr_dh_secret_free_ tr_dh_secret_free
#define tr_dh_align_key_ tr_dh_align_key
+#define tr_ssl_get_x509_store_ tr_ssl_get_x509_store
+#define tr_x509_store_add_ tr_x509_store_add
+#define tr_x509_cert_new_ tr_x509_cert_new
+#define tr_x509_cert_free_ tr_x509_cert_free
#define tr_rand_int_ tr_rand_int
#define tr_rand_int_weak_ tr_rand_int_weak
#define tr_rand_buffer_ tr_rand_buffer
#include "utils.h"
#define TR_CRYPTO_DH_SECRET_FALLBACK
+#define TR_CRYPTO_X509_FALLBACK
#include "crypto-utils-fallback.c"
struct tr_dh_ctx
}
#endif /* TR_CRYPTO_DH_SECRET_FALLBACK */
+
+#ifdef TR_CRYPTO_X509_FALLBACK
+
+tr_x509_store_t tr_ssl_get_x509_store(tr_ssl_ctx_t handle)
+{
+ (void)handle;
+
+ return NULL;
+}
+
+bool tr_x509_store_add(tr_x509_store_t handle, tr_x509_cert_t cert)
+{
+ (void)handle;
+ (void)cert;
+
+ return false;
+}
+
+tr_x509_cert_t tr_x509_cert_new(void const* der, size_t der_length)
+{
+ (void)der;
+ (void)der_length;
+
+ return NULL;
+}
+
+void tr_x509_cert_free(tr_x509_cert_t handle)
+{
+ (void)handle;
+}
+
+#endif /* TR_CRYPTO_X509_FALLBACK */
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/evp.h>
-#include <openssl/rand.h>
#include <openssl/opensslv.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
#include "transmission.h"
#include "crypto-utils.h"
****
***/
+tr_x509_store_t tr_ssl_get_x509_store(tr_ssl_ctx_t handle)
+{
+ if (handle == NULL)
+ {
+ return NULL;
+ }
+
+ return SSL_CTX_get_cert_store(handle);
+}
+
+bool tr_x509_store_add(tr_x509_store_t handle, tr_x509_cert_t cert)
+{
+ TR_ASSERT(handle != NULL);
+ TR_ASSERT(cert != NULL);
+
+ return check_result(X509_STORE_add_cert(handle, cert));
+}
+
+tr_x509_cert_t tr_x509_cert_new(void const* der, size_t der_length)
+{
+ TR_ASSERT(der != NULL);
+
+ X509* const ret = d2i_X509(NULL, (unsigned char const**)&der, der_length);
+
+ if (ret == NULL)
+ {
+ log_error();
+ }
+
+ return ret;
+}
+
+void tr_x509_cert_free(tr_x509_cert_t handle)
+{
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ X509_free(handle);
+}
+
+/***
+****
+***/
+
bool tr_rand_buffer(void* buffer, size_t length)
{
TR_ASSERT(buffer != NULL);
#include "utils.h"
#define TR_CRYPTO_DH_SECRET_FALLBACK
+#define TR_CRYPTO_X509_FALLBACK
#include "crypto-utils-fallback.c"
/***
typedef void* tr_dh_ctx_t;
/** @brief Opaque DH secret key type. */
typedef void* tr_dh_secret_t;
+/** @brief Opaque SSL context type. */
+typedef void* tr_ssl_ctx_t;
+/** @brief Opaque X509 certificate store type. */
+typedef void* tr_x509_store_t;
+/** @brief Opaque X509 certificate type. */
+typedef void* tr_x509_cert_t;
/**
* @brief Generate a SHA1 hash from one or more chunks of memory.
*/
void tr_dh_align_key(uint8_t* key_buffer, size_t key_size, size_t buffer_size);
+/**
+ * @brief Get X509 certificate store from SSL context.
+ */
+tr_x509_store_t tr_ssl_get_x509_store(tr_ssl_ctx_t handle);
+
+/**
+ * @brief Add certificate to X509 certificate store.
+ */
+bool tr_x509_store_add(tr_x509_store_t handle, tr_x509_cert_t cert);
+
+/**
+ * @brief Allocate and initialize new X509 certificate from DER-encoded buffer.
+ */
+tr_x509_cert_t tr_x509_cert_new(void const* der_data, size_t der_data_size);
+
+/**
+ * @brief Free X509 certificate returned by @ref tr_x509_cert_new.
+ */
+void tr_x509_cert_free(tr_x509_cert_t handle);
+
/**
* @brief Returns a random number in the range of [0...upper_bound).
*/
#include <string.h> /* strlen(), strstr() */
#ifdef _WIN32
+#include <windows.h>
+#include <wincrypt.h>
#include <ws2tcpip.h>
#else
#include <sys/select.h>
#include <event2/buffer.h>
#include "transmission.h"
+#include "crypto-utils.h"
#include "file.h"
#include "list.h"
#include "log.h"
#endif
+static CURLcode ssl_context_func(CURL* curl, void* ssl_ctx, void* user_data)
+{
+ (void)curl;
+ (void)user_data;
+
+ tr_x509_store_t const cert_store = tr_ssl_get_x509_store(ssl_ctx);
+ if (cert_store == NULL)
+ {
+ return CURLE_OK;
+ }
+
+#ifdef _WIN32
+
+ curl_version_info_data const* const curl_ver = curl_version_info(CURLVERSION_NOW);
+ if (curl_ver->age >= 0 && strncmp(curl_ver->ssl_version, "Schannel", 8) == 0)
+ {
+ return CURLE_OK;
+ }
+
+ static LPCWSTR const sys_store_names[] =
+ {
+ L"CA",
+ L"ROOT"
+ };
+
+ for (size_t i = 0; i < TR_N_ELEMENTS(sys_store_names); ++i)
+ {
+ HCERTSTORE const sys_cert_store = CertOpenSystemStoreW(0, sys_store_names[i]);
+ if (sys_cert_store == NULL)
+ {
+ continue;
+ }
+
+ PCCERT_CONTEXT sys_cert = NULL;
+
+ while (true)
+ {
+ sys_cert = CertFindCertificateInStore(sys_cert_store, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, sys_cert);
+ if (sys_cert == NULL)
+ {
+ break;
+ }
+
+ tr_x509_cert_t const cert = tr_x509_cert_new(sys_cert->pbCertEncoded, sys_cert->cbCertEncoded);
+ if (cert == NULL)
+ {
+ continue;
+ }
+
+ tr_x509_store_add(cert_store, cert);
+ tr_x509_cert_free(cert);
+ }
+
+ CertCloseStore(sys_cert_store, 0);
+ }
+
+#endif
+
+ return CURLE_OK;
+}
+
static long getTimeoutFromURL(struct tr_web_task const* task)
{
long timeout;
{
curl_easy_setopt(e, CURLOPT_CAINFO, web->curl_ca_bundle);
}
+ else
+ {
+ curl_easy_setopt(e, CURLOPT_SSL_CTX_FUNCTION, ssl_context_func);
+ }
}
else
{