mirror of
https://github.com/haiwen/seafile.git
synced 2025-01-09 12:27:32 +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_PSAPI=-lpsapi
|
||||||
LIB_MAC=
|
LIB_MAC=
|
||||||
MSVC_CFLAGS="-D__MSVCRT__ -D__MSVCRT_VERSION__=0x0601"
|
MSVC_CFLAGS="-D__MSVCRT__ -D__MSVCRT_VERSION__=0x0601"
|
||||||
|
LIB_CRYPT32=-lcrypt32
|
||||||
elif test "$bmac" = true ; then
|
elif test "$bmac" = true ; then
|
||||||
LIB_WS32=
|
LIB_WS32=
|
||||||
LIB_GDI32=
|
LIB_GDI32=
|
||||||
@ -204,6 +205,7 @@ elif test "$bmac" = true ; then
|
|||||||
LIB_PSAPI=
|
LIB_PSAPI=
|
||||||
MSVC_CFLAGS=
|
MSVC_CFLAGS=
|
||||||
LIB_MAC="-framework CoreServices"
|
LIB_MAC="-framework CoreServices"
|
||||||
|
LIB_CRYPT32=
|
||||||
else
|
else
|
||||||
LIB_WS32=
|
LIB_WS32=
|
||||||
LIB_GDI32=
|
LIB_GDI32=
|
||||||
@ -216,6 +218,7 @@ else
|
|||||||
LIB_PSAPI=
|
LIB_PSAPI=
|
||||||
LIB_MAC=
|
LIB_MAC=
|
||||||
MSVC_CFLAGS=
|
MSVC_CFLAGS=
|
||||||
|
LIB_CRYPT32=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(LIB_WS32)
|
AC_SUBST(LIB_WS32)
|
||||||
@ -229,6 +232,7 @@ AC_SUBST(LIB_SHELL32)
|
|||||||
AC_SUBST(LIB_PSAPI)
|
AC_SUBST(LIB_PSAPI)
|
||||||
AC_SUBST(LIB_MAC)
|
AC_SUBST(LIB_MAC)
|
||||||
AC_SUBST(MSVC_CFLAGS)
|
AC_SUBST(MSVC_CFLAGS)
|
||||||
|
AC_SUBST(LIB_CRYPT32)
|
||||||
|
|
||||||
|
|
||||||
LIBEVENT_REQUIRED=2.0
|
LIBEVENT_REQUIRED=2.0
|
||||||
|
@ -128,7 +128,7 @@ seaf_daemon_LDADD = $(top_builddir)/lib/libseafile_common.la \
|
|||||||
@LIB_INTL@ \
|
@LIB_INTL@ \
|
||||||
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \
|
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \
|
||||||
$(top_builddir)/common/cdc/libcdc.la \
|
$(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@
|
@SEARPC_LIBS@ @CCNET_LIBS@ @GNOME_KEYRING_LIBS@ @JANSSON_LIBS@ @LIB_MAC@ @ZLIB_LIBS@ @CURL_LIBS@
|
||||||
|
|
||||||
seaf_daemon_LDFLAGS = @STATIC_COMPILE@ @CONSOLE@
|
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 "common.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@ -5,6 +7,13 @@
|
|||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <event2/buffer.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 <ccnet/ccnet-client.h>
|
||||||
|
|
||||||
#include "seafile-config.h"
|
#include "seafile-config.h"
|
||||||
@ -66,6 +75,8 @@ struct _HttpTxPriv {
|
|||||||
pthread_mutex_t pools_lock;
|
pthread_mutex_t pools_lock;
|
||||||
|
|
||||||
CcnetTimer *reset_bytes_timer;
|
CcnetTimer *reset_bytes_timer;
|
||||||
|
|
||||||
|
char *ca_bundle_path;
|
||||||
};
|
};
|
||||||
typedef struct _HttpTxPriv HttpTxPriv;
|
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);
|
priv->connection_pools = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
pthread_mutex_init (&priv->pools_lock, NULL);
|
pthread_mutex_init (&priv->pools_lock, NULL);
|
||||||
|
|
||||||
|
priv->ca_bundle_path = g_build_filename (seaf->seaf_dir, "ca-bundle.pem", NULL);
|
||||||
|
|
||||||
mgr->priv = priv;
|
mgr->priv = priv;
|
||||||
|
|
||||||
return mgr;
|
return mgr;
|
||||||
@ -271,6 +284,11 @@ http_tx_manager_start (HttpTxManager *mgr)
|
|||||||
{
|
{
|
||||||
curl_global_init (CURL_GLOBAL_ALL);
|
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. */
|
/* TODO: add a timer to clean up unused Http connections. */
|
||||||
|
|
||||||
mgr->priv->reset_bytes_timer = ccnet_timer_new (reset_bytes,
|
mgr->priv->reset_bytes_timer = ccnet_timer_new (reset_bytes,
|
||||||
@ -282,6 +300,118 @@ http_tx_manager_start (HttpTxManager *mgr)
|
|||||||
|
|
||||||
/* Common Utility Functions. */
|
/* 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
|
static void
|
||||||
set_proxy (CURL *curl, gboolean is_https)
|
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);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
load_ca_bundle (curl);
|
||||||
|
#endif
|
||||||
|
|
||||||
int rc = curl_easy_perform (curl);
|
int rc = curl_easy_perform (curl);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
seaf_warning ("libcurl failed to GET %s: %s.\n",
|
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);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
load_ca_bundle (curl);
|
||||||
|
#endif
|
||||||
|
|
||||||
int rc = curl_easy_perform (curl);
|
int rc = curl_easy_perform (curl);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
seaf_warning ("libcurl failed to PUT %s: %s.\n",
|
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);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
load_ca_bundle (curl);
|
||||||
|
#endif
|
||||||
|
|
||||||
gboolean is_https = (strncasecmp(url, "https", strlen("https")) == 0);
|
gboolean is_https = (strncasecmp(url, "https", strlen("https")) == 0);
|
||||||
set_proxy (curl, is_https);
|
set_proxy (curl, is_https);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user