mirror of
https://github.com/haiwen/seafile.git
synced 2025-01-09 04:17:30 +08:00
[win] Extract system CA certs to use with openssl.
This allows users to set custom CA to system repository while we use openssl for https sync.
This commit is contained in:
parent
c50132945b
commit
fb35ae8ca3
@ -192,6 +192,7 @@ if test "$bwin32" = true; then
|
||||
LIB_PSAPI=-lpsapi
|
||||
LIB_MAC=
|
||||
MSVC_CFLAGS="-D__MSVCRT__ -D__MSVCRT_VERSION__=0x0601"
|
||||
LIB_CRYPT32=-lcrypt32
|
||||
elif test "$bmac" = true ; then
|
||||
LIB_WS32=
|
||||
LIB_GDI32=
|
||||
@ -204,6 +205,7 @@ elif test "$bmac" = true ; then
|
||||
LIB_PSAPI=
|
||||
MSVC_CFLAGS=
|
||||
LIB_MAC="-framework CoreServices"
|
||||
LIB_CRYPT32=
|
||||
else
|
||||
LIB_WS32=
|
||||
LIB_GDI32=
|
||||
@ -216,6 +218,7 @@ else
|
||||
LIB_PSAPI=
|
||||
LIB_MAC=
|
||||
MSVC_CFLAGS=
|
||||
LIB_CRYPT32=
|
||||
fi
|
||||
|
||||
AC_SUBST(LIB_WS32)
|
||||
@ -229,6 +232,7 @@ AC_SUBST(LIB_SHELL32)
|
||||
AC_SUBST(LIB_PSAPI)
|
||||
AC_SUBST(LIB_MAC)
|
||||
AC_SUBST(MSVC_CFLAGS)
|
||||
AC_SUBST(LIB_CRYPT32)
|
||||
|
||||
|
||||
LIBEVENT_REQUIRED=2.0
|
||||
|
@ -128,7 +128,7 @@ seaf_daemon_LDADD = $(top_builddir)/lib/libseafile_common.la \
|
||||
@LIB_INTL@ \
|
||||
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \
|
||||
$(top_builddir)/common/cdc/libcdc.la \
|
||||
$(top_builddir)/common/index/libindex.la ${LIB_WS32} \
|
||||
$(top_builddir)/common/index/libindex.la @LIB_WS32@ @LIB_CRYPT32@ \
|
||||
@SEARPC_LIBS@ @CCNET_LIBS@ @GNOME_KEYRING_LIBS@ @JANSSON_LIBS@ @LIB_MAC@ @ZLIB_LIBS@ @CURL_LIBS@
|
||||
|
||||
seaf_daemon_LDFLAGS = @STATIC_COMPILE@ @CONSOLE@
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
@ -5,6 +7,13 @@
|
||||
#include <jansson.h>
|
||||
#include <event2/buffer.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
#endif
|
||||
|
||||
#include <ccnet/ccnet-client.h>
|
||||
|
||||
#include "seafile-config.h"
|
||||
@ -66,6 +75,8 @@ struct _HttpTxPriv {
|
||||
pthread_mutex_t pools_lock;
|
||||
|
||||
CcnetTimer *reset_bytes_timer;
|
||||
|
||||
char *ca_bundle_path;
|
||||
};
|
||||
typedef struct _HttpTxPriv HttpTxPriv;
|
||||
|
||||
@ -235,6 +246,8 @@ http_tx_manager_new (struct _SeafileSession *seaf)
|
||||
priv->connection_pools = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
pthread_mutex_init (&priv->pools_lock, NULL);
|
||||
|
||||
priv->ca_bundle_path = g_build_filename (seaf->seaf_dir, "ca-bundle.pem", NULL);
|
||||
|
||||
mgr->priv = priv;
|
||||
|
||||
return mgr;
|
||||
@ -271,6 +284,11 @@ http_tx_manager_start (HttpTxManager *mgr)
|
||||
{
|
||||
curl_global_init (CURL_GLOBAL_ALL);
|
||||
|
||||
#ifdef WIN32
|
||||
/* Remove existing ca-bundle file on start. */
|
||||
g_unlink (mgr->priv->ca_bundle_path);
|
||||
#endif
|
||||
|
||||
/* TODO: add a timer to clean up unused Http connections. */
|
||||
|
||||
mgr->priv->reset_bytes_timer = ccnet_timer_new (reset_bytes,
|
||||
@ -282,6 +300,118 @@ http_tx_manager_start (HttpTxManager *mgr)
|
||||
|
||||
/* Common Utility Functions. */
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
static void
|
||||
write_cert_name_to_pem_file (FILE *f, PCCERT_CONTEXT pc)
|
||||
{
|
||||
char *name;
|
||||
DWORD size;
|
||||
|
||||
fprintf (f, "\n");
|
||||
|
||||
if (!CertGetCertificateContextProperty(pc,
|
||||
CERT_FRIENDLY_NAME_PROP_ID,
|
||||
NULL, &size)) {
|
||||
seaf_warning ("Failed to get cert name: %lu\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
name = g_malloc ((gsize)size);
|
||||
if (!name) {
|
||||
seaf_warning ("Failed to alloc memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CertGetCertificateContextProperty(pc,
|
||||
CERT_FRIENDLY_NAME_PROP_ID,
|
||||
name, &size)) {
|
||||
seaf_warning ("Failed to get cert name: %lu\n", GetLastError());
|
||||
g_free (name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrite(name, (size_t)size, 1, f) != 1) {
|
||||
seaf_warning ("Failed to write pem file.\n");
|
||||
g_free (name);
|
||||
return;
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
static void
|
||||
write_cert_to_pem_file (FILE *f, PCCERT_CONTEXT pc)
|
||||
{
|
||||
const unsigned char *der = pc->pbCertEncoded;
|
||||
X509 *cert;
|
||||
|
||||
write_cert_name_to_pem_file (f, pc);
|
||||
|
||||
cert = d2i_X509 (NULL, &der, (int)pc->cbCertEncoded);
|
||||
if (!cert) {
|
||||
seaf_warning ("Failed to parse certificate from DER.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PEM_write_X509 (f, cert)) {
|
||||
seaf_warning ("Failed to write certificate.\n");
|
||||
X509_free (cert);
|
||||
return;
|
||||
}
|
||||
|
||||
X509_free (cert);
|
||||
}
|
||||
|
||||
static int
|
||||
create_ca_bundle (const char *ca_bundle_path)
|
||||
{
|
||||
HCERTSTORE store;
|
||||
FILE *f;
|
||||
|
||||
store = CertOpenSystemStoreW (0, L"ROOT");
|
||||
if (!store) {
|
||||
seaf_warning ("Failed to open system cert store: %lu\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = g_fopen (ca_bundle_path, "w+");
|
||||
if (!f) {
|
||||
seaf_warning ("Failed to open cabundle file\n");
|
||||
CertCloseStore(store, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PCCERT_CONTEXT pc = NULL;
|
||||
while (1) {
|
||||
pc = CertFindCertificateInStore (store, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
|
||||
if (!pc)
|
||||
break;
|
||||
write_cert_to_pem_file (f, pc);
|
||||
}
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
fclose (f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
load_ca_bundle (CURL *curl)
|
||||
{
|
||||
char *ca_bundle_path = seaf->http_tx_mgr->priv->ca_bundle_path;
|
||||
|
||||
if (!seaf_util_exists (ca_bundle_path)) {
|
||||
if (create_ca_bundle (ca_bundle_path) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
curl_easy_setopt (curl, CURLOPT_CAINFO, ca_bundle_path);
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
static void
|
||||
set_proxy (CURL *curl, gboolean is_https)
|
||||
{
|
||||
@ -399,6 +529,10 @@ http_get (CURL *curl, const char *url, const char *token,
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
#ifdef WIN32
|
||||
load_ca_bundle (curl);
|
||||
#endif
|
||||
|
||||
int rc = curl_easy_perform (curl);
|
||||
if (rc != 0) {
|
||||
seaf_warning ("libcurl failed to GET %s: %s.\n",
|
||||
@ -518,6 +652,10 @@ http_put (CURL *curl, const char *url, const char *token,
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
#ifdef WIN32
|
||||
load_ca_bundle (curl);
|
||||
#endif
|
||||
|
||||
int rc = curl_easy_perform (curl);
|
||||
if (rc != 0) {
|
||||
seaf_warning ("libcurl failed to PUT %s: %s.\n",
|
||||
@ -600,6 +738,10 @@ http_post (CURL *curl, const char *url, const char *token,
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rsp);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
load_ca_bundle (curl);
|
||||
#endif
|
||||
|
||||
gboolean is_https = (strncasecmp(url, "https", strlen("https")) == 0);
|
||||
set_proxy (curl, is_https);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user