From 7fb4f88ab9e534b7670c8b233f33787bd3c90071 Mon Sep 17 00:00:00 2001 From: Florian Bezannier Date: Fri, 15 Dec 2023 09:49:07 +0100 Subject: [PATCH] feat: add MTLS auth --- meson.build | 7 +++ src/caremote.c | 53 +++++++++++++++++ src/caremote.h | 2 + src/casync-http.c | 71 ++++++++++++++++++++--- src/casync-tool.c | 50 +++++++++++++++- src/casync.c | 21 +++++++ src/casync.h | 2 + test/http-server.py | 127 ++++++++++++++++++++++++++++++++++++++--- test/test-mtls.sh.in | 9 +++ test/test-script.sh.in | 29 ++++++---- 10 files changed, 341 insertions(+), 30 deletions(-) create mode 100755 test/test-mtls.sh.in diff --git a/meson.build b/meson.build index cc06a764..92d0e995 100644 --- a/meson.build +++ b/meson.build @@ -311,6 +311,13 @@ test_cache_sh = configure_file( test_cache = find_program(test_cache_sh) test('test-cache.sh', test_cache, timeout : 30 * 60) +test_mtls_sh = configure_file( + output : 'test-mtls.sh', + input : 'test/test-mtls.sh.in', + configuration : substs) +test_mtls = find_program(test_mtls_sh) +test('test-mtls.sh', test_mtls, + timeout : 30 * 60) udev_rule = configure_file( output : '75-casync.rules', diff --git a/src/caremote.c b/src/caremote.c index 63cb080e..b67be92c 100644 --- a/src/caremote.c +++ b/src/caremote.c @@ -51,6 +51,10 @@ struct CaRemote { char *wstore_url; /* The "primary" store, where we write to */ char **rstore_urls; /* Additional, "secondary" stores we check */ + char *arg_tls_cert; + char *arg_tls_ca ; + char *arg_tls_key; + char *cache_path; int cache_fd; bool remove_cache; @@ -674,6 +678,30 @@ int ca_remote_set_archive_fd(CaRemote *rr, int fd) { return ca_remote_file_set_fd(&rr->index_file, fd); } +int ca_remote_set_client_auth(CaRemote *rr, const char *client_cert, const char *client_key, const char *ca_cert) { + if (!rr) + return -EINVAL; + if (!client_cert||!client_key) + return -EINVAL; + + + rr->arg_tls_cert = strdup(client_cert); + if (!rr->arg_tls_cert) + return -ENOMEM; + + rr->arg_tls_key = strdup(client_key); + if (!rr->arg_tls_key) + return -ENOMEM; + + if(ca_cert){ + rr->arg_tls_ca = strdup(ca_cert); + if (!rr->arg_tls_ca) + return -ENOMEM; + } + + return 0; +} + static int ca_remote_init_cache(CaRemote *rr) { int r; @@ -1000,6 +1028,12 @@ static int ca_remote_start(CaRemote *rr) { if (rr->rate_limit_bps != UINT64_MAX) argc++; + if (rr->arg_tls_key&&rr->arg_tls_cert){ + argc+=2; + } + if(rr->arg_tls_ca){ + argc++; + } args = newa(char*, argc + 1); @@ -1045,6 +1079,25 @@ static int ca_remote_start(CaRemote *rr) { i++; } + if (rr->arg_tls_key&&rr->arg_tls_cert){ + r = asprintf(args + i, "--tls-client-cert=%s", rr->arg_tls_cert); + if (r < 0) + return log_oom(); + + i++; + r = asprintf(args + i, "--tls-client-key=%s", rr->arg_tls_key); + if (r < 0) + return log_oom(); + + i++; + } + if(rr->arg_tls_ca){ + r = asprintf(args + i, "--tls-ca-cert=%s", rr->arg_tls_ca); + if (r < 0) + return log_oom(); + + i++; + } args[i + CA_REMOTE_ARG_OPERATION] = (char*) ((rr->local_feature_flags & (CA_PROTOCOL_PUSH_CHUNKS|CA_PROTOCOL_PUSH_INDEX|CA_PROTOCOL_PUSH_ARCHIVE)) ? "push" : "pull"); args[i + CA_REMOTE_ARG_BASE_URL] = /* rr->base_url ? rr->base_url + skip :*/ (char*) "-"; diff --git a/src/caremote.h b/src/caremote.h index 818ab4f7..491b192e 100644 --- a/src/caremote.h +++ b/src/caremote.h @@ -72,6 +72,8 @@ int ca_remote_set_index_fd(CaRemote *rr, int fd); int ca_remote_set_archive_path(CaRemote *rr, const char *path); int ca_remote_set_archive_fd(CaRemote *rr, int fd); +int ca_remote_set_client_auth(CaRemote *rr, const char *client_cert, const char *client_key, const char *ca_cert); + int ca_remote_step(CaRemote *rr); int ca_remote_poll(CaRemote *rr, uint64_t timeout_nsec, const sigset_t *ss); diff --git a/src/casync-http.c b/src/casync-http.c index 28b2c541..4e4bc4a3 100644 --- a/src/casync-http.c +++ b/src/casync-http.c @@ -16,6 +16,9 @@ static volatile sig_atomic_t quit = false; static int arg_log_level = -1; static bool arg_verbose = false; static curl_off_t arg_rate_limit_bps = 0; +static char *arg_tls_cert = NULL; +static char *arg_tls_ca = NULL; +static char *arg_tls_key = NULL; static enum { ARG_PROTOCOL_HTTP, @@ -73,6 +76,28 @@ static CURLcode robust_curl_easy_perform(CURL *curl) { return c; } +static CURLcode set_curl_tls_opt(CURL *curl){ + CURLcode curLcode = CURLE_OK; + if(arg_tls_cert&&arg_tls_key){ + curLcode = curl_easy_setopt(curl, CURLOPT_SSLCERT, arg_tls_cert); + if (curLcode != CURLE_OK){ + log_error("Failed to add client certificate"); + return curLcode; + } + curLcode = curl_easy_setopt(curl, CURLOPT_SSLKEY, arg_tls_key); + if( curLcode != CURLE_OK){ + log_error("Failed to add client private key"); + return curLcode; + } + } + if(arg_tls_ca){ + curLcode = curl_easy_setopt(curl, CURLOPT_CAINFO, arg_tls_ca); + if (curLcode != CURLE_OK) + log_error("Failed to add certificate authority"); + } + return curLcode; +} + static int process_remote(CaRemote *rr, ProcessUntil until) { int r; @@ -293,6 +318,7 @@ static int acquire_file(CaRemote *rr, size_t (*callback)(const void *p, size_t size, size_t nmemb, void *userdata), void *userdata) { long protocol_status; + CURLcode curl_code; assert(curl); assert(url); @@ -313,11 +339,10 @@ static int acquire_file(CaRemote *rr, log_error("Failed to set CURL private data."); return -EIO; } - log_debug("Acquiring %s...", url); - - if (robust_curl_easy_perform(curl) != CURLE_OK) { - log_error("Failed to acquire %s", url); + curl_code = robust_curl_easy_perform(curl); + if ( curl_code != CURLE_OK) { + log_error("Failed to acquire %s %s", url, curl_easy_strerror(curl_code)); return -EIO; } @@ -373,6 +398,7 @@ static int run(int argc, char *argv[]) { const char *base_url, *archive_url, *index_url, *wstore_url; size_t n_stores = 0, current_store = 0; CURL *curl = NULL; + CURLcode curl_code; _cleanup_(ca_remote_unrefp) CaRemote *rr = NULL; _cleanup_(realloc_buffer_free) ReallocBuffer buffer = {}; _cleanup_free_ char *url_buffer = NULL; @@ -476,6 +502,10 @@ static int run(int argc, char *argv[]) { goto finish; } + if(set_curl_tls_opt(curl)!=CURLE_OK){ + return -EIO; + } + if (archive_url) { r = acquire_file(rr, curl, archive_url, write_archive, rr); if (r < 0) @@ -509,7 +539,6 @@ static int run(int argc, char *argv[]) { for (;;) { const char *store_url; CaChunkID id; - if (quit) { log_info("Got exit signal, quitting."); r = 0; @@ -587,10 +616,12 @@ static int run(int argc, char *argv[]) { goto finish; } - log_debug("Acquiring %s...", url_buffer); - if (robust_curl_easy_perform(curl) != CURLE_OK) { - log_error("Failed to acquire %s", url_buffer); + + log_debug("Acquiring %s...", url_buffer); + curl_code = robust_curl_easy_perform(curl); + if (curl_code != CURLE_OK) { + log_error("Failed to acquire %s a %s", url_buffer, curl_easy_strerror(curl_code)); r = -EIO; goto finish; } @@ -659,6 +690,9 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_RATE_LIMIT_BPS = 0x100, + ARG_TLS_KEY, + ARG_TLS_CERT, + ARG_TLS_CA }; static const struct option options[] = { @@ -666,6 +700,9 @@ static int parse_argv(int argc, char *argv[]) { { "log-level", required_argument, NULL, 'l' }, { "verbose", no_argument, NULL, 'v' }, { "rate-limit-bps", required_argument, NULL, ARG_RATE_LIMIT_BPS }, + { "tls-client-cert",required_argument, NULL, 't' }, + { "tls-client-key", required_argument, NULL, 'k' }, + { "tls-ca-cert", required_argument, NULL, 'c' }, {} }; @@ -715,6 +752,24 @@ static int parse_argv(int argc, char *argv[]) { arg_rate_limit_bps = strtoll(optarg, NULL, 10); break; + case 't': + r = free_and_strdup(&arg_tls_cert, optarg); + if (r < 0) + return log_oom(); + break; + + case 'k': + r = free_and_strdup(&arg_tls_key, optarg); + if (r < 0) + return log_oom(); + break; + + case 'c': + r = free_and_strdup(&arg_tls_ca, optarg); + if (r < 0) + return log_oom(); + break; + case '?': return -EINVAL; diff --git a/src/casync-tool.c b/src/casync-tool.c index ec21759d..cfbbf1e0 100644 --- a/src/casync-tool.c +++ b/src/casync-tool.c @@ -61,6 +61,9 @@ static char *arg_store = NULL; static char **arg_extra_stores = NULL; static char **arg_seeds = NULL; static char *arg_cache = NULL; +static char *arg_tls_cert = NULL; +static char *arg_tls_ca = NULL; +static char *arg_tls_key = NULL; static bool arg_cache_auto = false; static size_t arg_chunk_size_min = 0; static size_t arg_chunk_size_avg = 0; @@ -121,6 +124,9 @@ static void help(void) { " --seed-output=no Don't implicitly add pre-existing output as seed\n" " when extracting\n" " --recursive=no List non-recursively\n" + " --tls-ca-cert Certificate Authority to validate remote tls server\n" + " --tls-client-cert Client cert to authenticate to remote tls server\n" + " --tls-client-key Client key to authenticate to remote tls server\n" #if HAVE_FUSE " --mkdir=no Don't automatically create mount directory if it\n" " is missing\n" @@ -347,6 +353,9 @@ static int parse_argv(int argc, char *argv[]) { ARG_DIGEST, ARG_COMPRESSION, ARG_VERSION, + ARG_TLS_KEY, + ARG_TLS_CERT, + ARG_TLS_CA }; static const struct option options[] = { @@ -380,6 +389,9 @@ static int parse_argv(int argc, char *argv[]) { { "mkdir", required_argument, NULL, ARG_MKDIR }, { "digest", required_argument, NULL, ARG_DIGEST }, { "compression", required_argument, NULL, ARG_COMPRESSION }, + { "tls-client-cert", required_argument, NULL, ARG_TLS_CERT }, + { "tls-client-key", required_argument, NULL, ARG_TLS_KEY }, + { "tls-ca-cert", required_argument, NULL, ARG_TLS_CA }, {} }; @@ -666,6 +678,24 @@ static int parse_argv(int argc, char *argv[]) { break; } + case ARG_TLS_CERT: + r = free_and_strdup(&arg_tls_cert, optarg); + if (r < 0) + return log_oom(); + break; + + case ARG_TLS_KEY: + r = free_and_strdup(&arg_tls_key, optarg); + if (r < 0) + return log_oom(); + break; + + case ARG_TLS_CA: + r = free_and_strdup(&arg_tls_ca, optarg); + if (r < 0) + return log_oom(); + break; + case '?': return -EINVAL; @@ -1660,7 +1690,9 @@ static int verb_extract(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to set store: %m"); } - + if(arg_tls_key && arg_tls_cert){ + ca_sync_set_client_auth(s,arg_tls_cert,arg_tls_key,arg_tls_ca); + } r = load_seeds_and_extra_stores(s); if (r < 0) return r; @@ -2105,7 +2137,6 @@ static int verb_list(int argc, char *argv[]) { _cleanup_(ca_sync_unrefp) CaSync *s = NULL; bool toplevel_shown = false; int r; - if (argc > 3) { log_error("Input path/URL and subtree path expected."); return -EINVAL; @@ -2301,6 +2332,10 @@ static int verb_list(int argc, char *argv[]) { return log_error_errno(r, "Failed to enable hardlink digest: %m"); } + if(arg_tls_key && arg_tls_cert){ + ca_sync_set_client_auth(s,arg_tls_cert,arg_tls_key,arg_tls_ca); + } + (void) send_notify("READY=1"); for (;;) { @@ -2577,6 +2612,9 @@ static int verb_digest(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to set store: %m"); } + if(arg_tls_key && arg_tls_cert){ + ca_sync_set_client_auth(s,arg_tls_cert,arg_tls_key,arg_tls_ca); + } r = load_seeds_and_extra_stores(s); if (r < 0) @@ -3470,6 +3508,10 @@ static int verb_pull(int argc, char *argv[]) { return log_error_errno(r, "Failed to set rate limit: %m"); } + if(arg_tls_key && arg_tls_cert){ + ca_remote_set_client_auth(rr, arg_tls_cert, arg_tls_key, arg_tls_ca); + } + r = ca_remote_set_io_fds(rr, STDIN_FILENO, STDOUT_FILENO); if (r < 0) return log_error_errno(r, "Failed to set I/O file descriptors: %m"); @@ -3629,6 +3671,10 @@ static int verb_push(int argc, char *argv[]) { return log_error_errno(r, "Failed to set rate limit: %m"); } + if(arg_tls_key && arg_tls_cert){ + ca_remote_set_client_auth(rr, arg_tls_cert, arg_tls_key, arg_tls_ca); + } + r = ca_remote_set_io_fds(rr, STDIN_FILENO, STDOUT_FILENO); if (r < 0) return log_error_errno(r, "Failed to set I/O file descriptors: %m"); diff --git a/src/casync.c b/src/casync.c index 21b55419..579e0df5 100644 --- a/src/casync.c +++ b/src/casync.c @@ -1298,6 +1298,27 @@ static bool ca_sync_use_cache(CaSync *s) { return !!s->cache; } +int ca_sync_set_client_auth(CaSync *sync, const char *client_cert, const char *client_key, const char *ca_cert){ + int r; + if(sync->remote_index){ + r = ca_remote_set_client_auth(sync->remote_index, client_cert, client_key, ca_cert); + if (r < 0) + return r; + } + if(sync->remote_wstore){ + r = ca_remote_set_client_auth(sync->remote_wstore, client_cert, client_key, ca_cert); + if (r < 0) + return r; + } + if(sync->remote_archive){ + r = ca_remote_set_client_auth(sync->remote_archive, client_cert, client_key, ca_cert); + if (r < 0) + return r; + } + return 0; +} + + static int ca_sync_start(CaSync *s) { size_t i; int r; diff --git a/src/casync.h b/src/casync.h index c5b51b4c..fbfc16c3 100644 --- a/src/casync.h +++ b/src/casync.h @@ -93,6 +93,8 @@ int ca_sync_add_seed_path(CaSync *sync, const char *path); int ca_sync_set_cache_fd(CaSync *sync, int fd); int ca_sync_set_cache_path(CaSync *sync, const char *path); +int ca_sync_set_client_auth(CaSync *sync, const char *client_cert, const char *client_key, const char *ca_cert); + int ca_sync_step(CaSync *sync); int ca_sync_poll(CaSync *s, uint64_t timeout_nsec, const sigset_t *ss); diff --git a/test/http-server.py b/test/http-server.py index e8078787..11a189c6 100755 --- a/test/http-server.py +++ b/test/http-server.py @@ -1,21 +1,29 @@ #!/usr/bin/python3 # SPDX-License-Identifier: LGPL-2.1+ +import argparse +import ssl +import uuid +from datetime import datetime, timedelta +from os.path import exists, abspath -PORT = 4321 +from cryptography import x509 +from cryptography.hazmat._oid import NameOID +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization, hashes +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.x509 import ExtensionType + +DEFAULT_PORT = 4321 import http.server import os import socket import socketserver -import sys -import time -os.chdir(sys.argv[1]) -if len(sys.argv) >= 3: - PORT = int(sys.argv[2]) +CERT_VALIDITY = timedelta(31, 0, 0) -def send_notify(text): +def send_notify(text): if text is None or text == "": return @@ -30,6 +38,7 @@ def send_notify(text): fd.connect("\0" + e[1:] if e[0] == '@' else e) fd.send(bytes(text, 'utf-8')) + class AllowReuseAddressServer(socketserver.TCPServer): allow_reuse_address = True @@ -37,6 +46,106 @@ def server_activate(self): super().server_activate() send_notify("READY=1") -httpd = AllowReuseAddressServer(("", PORT), http.server.SimpleHTTPRequestHandler) -httpd.serve_forever() +def create_cert(subject_name, issuer_name, extval: ExtensionType, critical: bool, ca_key=None): + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=2048, + backend=default_backend() + ) + builder = x509.CertificateBuilder() + builder = builder.subject_name(subject_name) + builder = builder.issuer_name(issuer_name) + builder = builder.not_valid_before(datetime.today() - CERT_VALIDITY) + builder = builder.not_valid_after(datetime.today() + CERT_VALIDITY) + builder = builder.serial_number(int(uuid.uuid4())) + builder = builder.public_key(private_key.public_key()) + builder = builder.add_extension(extval, critical) + return builder.sign(private_key=ca_key if ca_key else private_key, algorithm=hashes.SHA256(), + backend=default_backend()), private_key + + +def create_certs(HostName, KeyFile, CertFile, ClientCertCAs): + ca_subject_name = x509.Name([ + x509.NameAttribute(NameOID.COMMON_NAME, "CA_TEST"), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'TEST ON'), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'TEST OUN'), + ]) + + ca_cert, ca_key = create_cert(ca_subject_name, ca_subject_name, x509.BasicConstraints(ca=True, path_length=None), + critical=False) + + server_cert, server_key = create_cert(x509.Name([ + x509.NameAttribute(NameOID.COMMON_NAME, HostName), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'TEST ON'), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'TEST OUN'), + ]), ca_subject_name, x509.ExtendedKeyUsage([x509.ExtendedKeyUsageOID.SERVER_AUTH]), False, ca_key) + + client_cert, client_key = create_cert(x509.Name([ + x509.NameAttribute(NameOID.COMMON_NAME, HostName), + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'TEST ON'), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'TEST OUN'), + ]), ca_subject_name, x509.ExtendedKeyUsage([x509.ExtendedKeyUsageOID.CLIENT_AUTH]), False, ca_key) + + open(KeyFile, "wb").write(server_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption() + )) + open(CertFile, "wb").write(server_cert.public_bytes( + encoding=serialization.Encoding.PEM, + )) + open("client.key", "wb").write(client_key.private_bytes(encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption())) + open("client.crt", "wb").write(client_cert.public_bytes( + encoding=serialization.Encoding.PEM, + )) + open(ClientCertCAs, "wb").write(ca_cert.public_bytes(encoding=serialization.Encoding.PEM)) + + +def run_server(https: bool, host_name, port, key_file=None, cert_file=None, client_cert_ca=None): + httpd = AllowReuseAddressServer((host_name, port), http.server.SimpleHTTPRequestHandler) + + if https: + if not exists(key_file) or not exists(cert_file) or not exists(client_cert_ca): + print("Generating Key and Certificate...") + create_certs(host_name, key_file, cert_file, client_cert_ca) + print("mtls server") + httpd.socket = ssl.wrap_socket(httpd.socket, keyfile=key_file, certfile=cert_file, server_side=True, + cert_reqs=ssl.CERT_REQUIRED, ca_certs=client_cert_ca, + ssl_version=ssl.PROTOCOL_TLSv1_2) + protocol = 'HTTPS' + print(" Cert:", abspath(cert_file)) + + else: + protocol = 'HTTP' + + sa = httpd.socket.getsockname() + print("Serving", protocol, "on", sa[0], "port", sa[1], "...") + httpd.serve_forever() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--ssl', action='store_true', dest='SSL', + help='Launches an SSL (HTTPS) server (default: False)', default=False) + parser.add_argument('--host', action='store', dest='HostName', default="localhost", + help='Sets the host name to listen on (default: localhost)') + parser.add_argument('--port', action='store', dest='Port', type=int, default=DEFAULT_PORT, + help='Sets the port to listen on (default for HTTPS)') + parser.add_argument('--key', action='store', dest='KeyFile', default="server.key", + help='Sets the private key to use for SSL.') + parser.add_argument('--cert', action='store', dest='CertFile', default="server.crt", + help='''Sets the public certificate to use for SSL. Implies --ssl + (default: Temp-generated certificate*)''') + parser.add_argument('--certbase', action='store', dest='CertBase', + help='Sets the base path to a certificate and key (default: None*)') + parser.add_argument('--cacert', action='store', dest='ClientCertCAs', default="ca.crt", + help='Sets the CA to use for authenticating client certs.') + parser.add_argument('workdir', action='store', help='workdir') + + args = parser.parse_args() + os.chdir(args.workdir) + + run_server(args.SSL, args.HostName, args.Port, args.KeyFile, args.CertFile, args.ClientCertCAs) diff --git a/test/test-mtls.sh.in b/test/test-mtls.sh.in new file mode 100755 index 00000000..14d6609b --- /dev/null +++ b/test/test-mtls.sh.in @@ -0,0 +1,9 @@ +#!/bin/bash -ex +# SPDX-License-Identifier: LGPL-2.1+ + +# This is the same as test-script.sh, except that we use mtls protocol +# algorithm to be gzip. +export REMOTE_OPTIONS="--tls-ca-cert ../ca.crt --tls-client-cert ../client.crt --tls-client-key ../client.key" +export REMOTE_PROTOCOL="https" + +exec @top_builddir@/test-script.sh default zstd diff --git a/test/test-script.sh.in b/test/test-script.sh.in index 59d46876..e8bfe08e 100755 --- a/test/test-script.sh.in +++ b/test/test-script.sh.in @@ -4,6 +4,9 @@ DIGEST=${1:-sha512-256} COMPRESSION=${2:-zstd} +REMOTE_PROTOCOL="${REMOTE_PROTOCOL:-http}" +REMOTE_OPTIONS="${REMOTE_OPTIONS}" + # Skip the test if given compressor is unavailable [ $COMPRESSION != "gzip" -o @HAVE_LIBZ@ = 1 ] || exit 77 [ $COMPRESSION != "xz" -o @HAVE_LIBLZMA@ = 1 ] || exit 77 @@ -67,7 +70,6 @@ diff -ur --no-dereference . $SCRATCH_DIR/extract-catar2 diff -ur --no-dereference . $SCRATCH_DIR/extract-catar3 diff -ur --no-dereference . $SCRATCH_DIR/extract-caidx diff -ur --no-dereference . $SCRATCH_DIR/extract-caidx2 - set -e @top_builddir@/casync $PARAMS list $SCRATCH_DIR/extract-catar >$SCRATCH_DIR/test.extract-catar.list @@ -173,16 +175,21 @@ diff -q $SCRATCH_DIR/test.digest $SCRATCH_DIR/test2.catar.digest HTTP_PORT=$((10000 + $$ % 10000)) export CASYNC_PROTOCOL_PATH=@top_builddir@ - -HTTP_PID=`@top_builddir@/notify-wait @top_srcdir@/test/http-server.py $SCRATCH_DIR $HTTP_PORT` - -@top_builddir@/casync $PARAMS list http://localhost:$HTTP_PORT/test2.caidx >$SCRATCH_DIR/test3.caidx.list -@top_builddir@/casync $PARAMS mtree http://localhost:$HTTP_PORT/test2.caidx >$SCRATCH_DIR/test3.caidx.mtree -@top_builddir@/casync $PARAMS digest http://localhost:$HTTP_PORT/test2.caidx >$SCRATCH_DIR/test3.caidx.digest - -@top_builddir@/casync $PARAMS list http://localhost:$HTTP_PORT/test2.catar >$SCRATCH_DIR/test3.catar.list -@top_builddir@/casync $PARAMS mtree http://localhost:$HTTP_PORT/test2.catar >$SCRATCH_DIR/test3.catar.mtree -@top_builddir@/casync $PARAMS digest http://localhost:$HTTP_PORT/test2.catar >$SCRATCH_DIR/test3.catar.digest +if [ "${REMOTE_PROTOCOL}" = "https" ]; then + HTTP_PID=`@top_builddir@/notify-wait @top_srcdir@/test/http-server.py $SCRATCH_DIR --port $HTTP_PORT --ssl` +else + HTTP_PID=`@top_builddir@/notify-wait @top_srcdir@/test/http-server.py $SCRATCH_DIR --port $HTTP_PORT` +fi +sleep 5 + +rm -rf $SCRATCH_DIR/extract-catar +@top_builddir@/casync $PARAMS $REMOTE_OPTIONS list ${REMOTE_PROTOCOL}://localhost:$HTTP_PORT/test2.caidx >$SCRATCH_DIR/test3.caidx.list +@top_builddir@/casync $PARAMS $REMOTE_OPTIONS mtree ${REMOTE_PROTOCOL}://localhost:$HTTP_PORT/test2.caidx >$SCRATCH_DIR/test3.caidx.mtree +@top_builddir@/casync $PARAMS $REMOTE_OPTIONS digest ${REMOTE_PROTOCOL}://localhost:$HTTP_PORT/test2.caidx >$SCRATCH_DIR/test3.caidx.digest +@top_builddir@/casync $PARAMS $REMOTE_OPTIONS list ${REMOTE_PROTOCOL}://localhost:$HTTP_PORT/test2.catar >$SCRATCH_DIR/test3.catar.list +@top_builddir@/casync $PARAMS $REMOTE_OPTIONS mtree ${REMOTE_PROTOCOL}://localhost:$HTTP_PORT/test2.catar >$SCRATCH_DIR/test3.catar.mtree +@top_builddir@/casync $PARAMS $REMOTE_OPTIONS digest ${REMOTE_PROTOCOL}://localhost:$HTTP_PORT/test2.catar >$SCRATCH_DIR/test3.catar.digest +@top_builddir@/casync $PARAMS $REMOTE_OPTIONS extract ${REMOTE_PROTOCOL}://localhost:$HTTP_PORT/test2.catar >$SCRATCH_DIR/extract-catar diff -q $SCRATCH_DIR/test.list $SCRATCH_DIR/test3.caidx.list diff -q $SCRATCH_DIR/test.mtree $SCRATCH_DIR/test3.caidx.mtree