diff --git a/configure.ac b/configure.ac index bf054e1e3b..db85794167 100644 --- a/configure.ac +++ b/configure.ac @@ -1044,7 +1044,7 @@ if test x$unbound = xtrue; then fi if test x$soup = xtrue; then - PKG_CHECK_MODULES(soup, [libsoup-2.4]) + PKG_CHECK_MODULES(soup, [libsoup-3.0]) AC_SUBST(soup_CFLAGS) AC_SUBST(soup_LIBS) fi diff --git a/scripts/test.sh b/scripts/test.sh index 65545ea0dd..3adce6c005 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -305,7 +305,7 @@ all|alpine|codeql|coverage|sonarcloud|no-dbg|no-testable-ke) if [ "$TEST" = "no-testable-ke" ]; then CONFIG="$CONFIG --without-testable-ke" fi - DEPS="$DEPS libcurl4-gnutls-dev libsoup2.4-dev libunbound-dev libldns-dev + DEPS="$DEPS libcurl4-gnutls-dev libsoup-3.0-dev libunbound-dev libldns-dev libmysqlclient-dev libsqlite3-dev clearsilver-dev libfcgi-dev libldap2-dev libpcsclite-dev libpam0g-dev binutils-dev libnm-dev libgcrypt20-dev libjson-c-dev libtspi-dev libsystemd-dev @@ -318,11 +318,11 @@ all|alpine|codeql|coverage|sonarcloud|no-dbg|no-testable-ke) fi if [ "$TEST" = "alpine" ]; then # override the whole list for alpine - DEPS="git gmp-dev openldap-dev curl-dev ldns-dev unbound-dev libsoup-dev - tpm2-tss-dev tpm2-tss-sys mariadb-dev wolfssl-dev libgcrypt-dev - botan3-dev pcsc-lite-dev networkmanager-dev linux-pam-dev - iptables-dev libselinux-dev binutils-dev libunwind-dev ruby - py3-setuptools py3-build py3-tox" + DEPS="git gmp-dev openldap-dev curl-dev ldns-dev unbound-dev libsoup3-dev + libxml2-dev tpm2-tss-dev tpm2-tss-sys mariadb-dev wolfssl-dev + libgcrypt-dev botan3-dev pcsc-lite-dev networkmanager-dev + linux-pam-dev iptables-dev libselinux-dev binutils-dev libunwind-dev + ruby py3-setuptools py3-build py3-tox" # musl does not provide backtrace(), so use libunwind CONFIG="$CONFIG --enable-unwind-backtraces" # alpine doesn't have systemd diff --git a/src/libstrongswan/fetcher/fetcher.h b/src/libstrongswan/fetcher/fetcher.h index b4bd78809f..dc8e16a73d 100644 --- a/src/libstrongswan/fetcher/fetcher.h +++ b/src/libstrongswan/fetcher/fetcher.h @@ -69,12 +69,6 @@ enum fetcher_option_t { */ FETCH_REQUEST_HEADER, - /** - * Use HTTP Version 1.0 instead of 1.1. - * No additional argument is needed. - */ - FETCH_HTTP_VERSION_1_0, - /** * Timeout to use for fetch, in seconds. * Additional argument is u_int diff --git a/src/libstrongswan/fetcher/fetcher_manager.c b/src/libstrongswan/fetcher/fetcher_manager.c index fe371a6d61..cd636f45a1 100644 --- a/src/libstrongswan/fetcher/fetcher_manager.c +++ b/src/libstrongswan/fetcher/fetcher_manager.c @@ -103,9 +103,6 @@ METHOD(fetcher_manager_t, fetch, status_t, good = fetcher->set_option(fetcher, opt, va_arg(args, char*)); continue; - case FETCH_HTTP_VERSION_1_0: - good = fetcher->set_option(fetcher, opt); - continue; case FETCH_TIMEOUT: good = fetcher->set_option(fetcher, opt, va_arg(args, u_int)); diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c index c788e3f682..80d989c2d0 100644 --- a/src/libstrongswan/plugins/curl/curl_fetcher.c +++ b/src/libstrongswan/plugins/curl/curl_fetcher.c @@ -205,12 +205,6 @@ METHOD(fetcher_t, set_option, bool, this->headers = curl_slist_append(this->headers, header); break; } - case FETCH_HTTP_VERSION_1_0: - { - curl_easy_setopt(this->curl, CURLOPT_HTTP_VERSION, - CURL_HTTP_VERSION_1_0); - break; - } case FETCH_TIMEOUT: { this->timeout = va_arg(args, u_int); diff --git a/src/libstrongswan/plugins/soup/soup_fetcher.c b/src/libstrongswan/plugins/soup/soup_fetcher.c index 072dfd7b25..6c0cba2cb9 100644 --- a/src/libstrongswan/plugins/soup/soup_fetcher.c +++ b/src/libstrongswan/plugins/soup/soup_fetcher.c @@ -55,11 +55,6 @@ struct private_soup_fetcher_t { */ u_int timeout; - /** - * HTTP request version - */ - SoupHTTPVersion version; - /** * Fetcher callback function */ @@ -71,36 +66,13 @@ struct private_soup_fetcher_t { u_int *result; }; -/** - * Data to pass to soup callback - */ -typedef struct { - fetcher_callback_t cb; - void *user; - SoupSession *session; -} cb_data_t; - -/** - * Soup callback invoking our callback - */ -static void soup_cb(SoupMessage *message, SoupBuffer *chunk, cb_data_t *data) -{ - if (!data->cb(data->user, chunk_create((u_char*)chunk->data, chunk->length))) - { - soup_session_cancel_message(data->session, message, - SOUP_STATUS_CANCELLED); - } -} - METHOD(fetcher_t, fetch, status_t, private_soup_fetcher_t *this, char *uri, void *userdata) { SoupMessage *message; status_t status = FAILED; - cb_data_t data = { - .cb = this->cb, - .user = userdata, - }; + GBytes *request_body, *res; + SoupSession *session; message = soup_message_new(this->method, uri); if (!message) @@ -113,32 +85,43 @@ METHOD(fetcher_t, fetch, status_t, } if (this->type) { - soup_message_set_request(message, this->type, SOUP_MEMORY_STATIC, - this->data.ptr, this->data.len); + request_body = g_bytes_new_static(this->data.ptr, this->data.len); + soup_message_set_request_body_from_bytes(message, this->type, + request_body); + g_bytes_unref(request_body); } - soup_message_set_http_version(message, this->version); - soup_message_body_set_accumulate(message->response_body, FALSE); - g_signal_connect(message, "got-chunk", G_CALLBACK(soup_cb), &data); - data.session = soup_session_new(); - g_object_set(G_OBJECT(data.session), - SOUP_SESSION_TIMEOUT, (guint)this->timeout, NULL); + session = soup_session_new_with_options("timeout", (guint)this->timeout, + NULL); DBG2(DBG_LIB, "sending http request to '%s'...", uri); - soup_session_send_message(data.session, message); + res = soup_session_send_and_read(session, message, NULL, NULL); if (this->result) { - *this->result = message->status_code; + *this->result = soup_message_get_status(message); } - if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + if (SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(message))) { status = SUCCESS; } else if (!this->result) { /* only log an error if the code is not returned */ - DBG1(DBG_LIB, "HTTP request failed: %s", message->reason_phrase); + DBG1(DBG_LIB, "HTTP request failed: %s", + soup_message_get_reason_phrase(message)); + } + if (res) + { + gpointer data; + gsize data_len; + + data = g_bytes_unref_to_data(res, &data_len); + if (!this->cb(userdata, chunk_create(data, data_len))) + { + status = FAILED; + } + g_free(data); } g_object_unref(G_OBJECT(message)); - g_object_unref(G_OBJECT(data.session)); + g_object_unref(G_OBJECT(session)); return status; } @@ -158,9 +141,6 @@ METHOD(fetcher_t, set_option, bool, case FETCH_REQUEST_TYPE: this->type = va_arg(args, char*); break; - case FETCH_HTTP_VERSION_1_0: - this->version = SOUP_HTTP_1_0; - break; case FETCH_TIMEOUT: this->timeout = va_arg(args, u_int); break; @@ -200,7 +180,6 @@ soup_fetcher_t *soup_fetcher_create() }, }, .method = SOUP_METHOD_GET, - .version = SOUP_HTTP_1_1, .timeout = DEFAULT_TIMEOUT, .cb = fetcher_default_callback, ); diff --git a/src/libstrongswan/plugins/winhttp/winhttp_fetcher.c b/src/libstrongswan/plugins/winhttp/winhttp_fetcher.c index e387bbb937..0be9b3eff6 100644 --- a/src/libstrongswan/plugins/winhttp/winhttp_fetcher.c +++ b/src/libstrongswan/plugins/winhttp/winhttp_fetcher.c @@ -54,11 +54,6 @@ struct private_winhttp_fetcher_t { */ chunk_t request; - /** - * HTTP version string to use - */ - LPWSTR version; - /** * Optional HTTP headers, as allocated LPWSTR */ @@ -264,7 +259,7 @@ METHOD(fetcher_t, fetch, status_t, connection = WinHttpConnect(this->session, host, port, 0); if (connection) { - request = WinHttpOpenRequest(connection, method, path, this->version, + request = WinHttpOpenRequest(connection, method, path, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, flags); if (request) @@ -334,9 +329,6 @@ METHOD(fetcher_t, set_option, bool, case FETCH_REQUEST_HEADER: supported = append_header(this, va_arg(args, char*)); break; - case FETCH_HTTP_VERSION_1_0: - this->version = L"HTTP/1.0"; - break; case FETCH_TIMEOUT: this->timeout = va_arg(args, u_int) * 1000; break; @@ -381,7 +373,6 @@ winhttp_fetcher_t *winhttp_fetcher_create() .destroy = _destroy, }, }, - .version = L"HTTP/1.1", .cb = fetcher_default_callback, .headers = linked_list_create(), .session = WinHttpOpen(L"strongSwan WinHTTP fetcher", diff --git a/src/libstrongswan/tests/suites/test_fetch_http.c b/src/libstrongswan/tests/suites/test_fetch_http.c index b087a1e791..38460297c6 100644 --- a/src/libstrongswan/tests/suites/test_fetch_http.c +++ b/src/libstrongswan/tests/suites/test_fetch_http.c @@ -27,8 +27,6 @@ typedef struct { /* HTTP Method */ char *meth; - /* HTTP 1.x minor version */ - int minor; /* host to connect to */ char *host; /* HTTP service port */ @@ -117,8 +115,8 @@ static bool servicing(void *data, stream_t *stream) switch (nr++) { case 0: - snprintf(hdr, sizeof(hdr), "%s %s HTTP/1.%u", - test->meth, test->path, test->minor); + snprintf(hdr, sizeof(hdr), "%s %s HTTP/1.1", + test->meth, test->path); ck_assert_str_eq(hdr, start); break; default: @@ -158,7 +156,7 @@ static bool servicing(void *data, stream_t *stream) } /* response headers */ - snprintf(buf, sizeof(buf), "HTTP/1.%u %u OK\r\n", test->minor, test->code); + snprintf(buf, sizeof(buf), "HTTP/1.1 %u OK\r\n", test->code); ck_assert(stream->write_all(stream, buf, strlen(buf))); /* if the response code indicates an error the following write operations @@ -188,13 +186,13 @@ static bool servicing(void *data, stream_t *stream) } static test_service_t gtests[] = { - { "GET", 1, "127.0.0.1", 6543, "/a/test/?b=c", NULL, + { "GET", "127.0.0.1", 6543, "/a/test/?b=c", NULL, NULL, 0, "\x12\x34", 2, 0 }, - { "GET", 0, "localhost", 6543, "/", NULL, + { "GET", "localhost", 6543, "/", NULL, NULL, 0, NULL, 0, 0 }, - { "GET", 0, "127.0.0.1", 6543, "/largefile", NULL, + { "GET", "127.0.0.1", 6543, "/largefile", NULL, NULL, 0, large, sizeof(large), 0 }, - { "GET", 1, "[::1]", 6543, "/ipv6-url", NULL, + { "GET", "[::1]", 6543, "/ipv6-url", NULL, NULL, 0, "\x00\r\n\r\x00testdatablabla", 20, 0 }, }; @@ -214,9 +212,7 @@ START_TEST(test_get) snprintf(uri, sizeof(uri), "http://%s:%u%s", gtests[_i].host, gtests[_i].port, gtests[_i].path); - status = lib->fetcher->fetch(lib->fetcher, uri, &data, - !gtests[_i].minor ? FETCH_HTTP_VERSION_1_0 : FETCH_END, - FETCH_END); + status = lib->fetcher->fetch(lib->fetcher, uri, &data, FETCH_END); ck_assert_int_eq(status, SUCCESS); expected = chunk_create(gtests[_i].res, gtests[_i].res_len); ck_assert_msg(chunk_compare(expected, data) == 0, @@ -229,11 +225,11 @@ END_TEST static test_service_t ptests[] = { - { "POST", 1, "127.0.0.1", 6543, "/a/test/?b=c", "application/binary", + { "POST", "127.0.0.1", 6543, "/a/test/?b=c", "application/binary", "\x23\x45", 2, "\x12\x34", 2, 0 }, - { "POST", 0, "localhost", 6543, "/largefile", "application/x-large", + { "POST", "localhost", 6543, "/largefile", "application/x-large", large, sizeof(large), large, sizeof(large), 0 }, - { "POST", 1, "[::1]", 6543, "/ipv6-url", "text/plain", + { "POST", "[::1]", 6543, "/ipv6-url", "text/plain", "\x00\r\n\r\x00testdatablabla", 20, "\x00\r\n\r\x00testdatablabla", 20, 0 }, }; @@ -257,7 +253,6 @@ START_TEST(test_post) FETCH_REQUEST_TYPE, ptests[_i].type, FETCH_REQUEST_DATA, chunk_create(ptests[_i].req, ptests[_i].req_len), - !ptests[_i].minor ? FETCH_HTTP_VERSION_1_0 : FETCH_END, FETCH_END); ck_assert_int_eq(status, SUCCESS); expected = chunk_create(ptests[_i].res, ptests[_i].res_len); @@ -271,11 +266,11 @@ END_TEST static test_service_t rtests[] = { - { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 200 }, - { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 204 }, - { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 400 }, - { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 404 }, - { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 500 }, + { "GET", "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 200 }, + { "GET", "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 204 }, + { "GET", "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 400 }, + { "GET", "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 404 }, + { "GET", "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 500 }, }; START_TEST(test_response_code) diff --git a/src/libstrongswan/tests/tests.h b/src/libstrongswan/tests/tests.h index 9ad712d53d..bcd8dffd2c 100644 --- a/src/libstrongswan/tests/tests.h +++ b/src/libstrongswan/tests/tests.h @@ -44,7 +44,7 @@ TEST_SUITE_DEPEND(rsa_oaep_sha512_suite_create, PRIVKEY_DECRYPT, ENCRYPT_RSA_OAE TEST_SUITE_DEPEND(certpolicy_suite_create, CERT_ENCODE, CERT_X509) TEST_SUITE_DEPEND(certnames_suite_create, CERT_ENCODE, CERT_X509) TEST_SUITE_DEPEND(serial_gen_suite_create, CERT_ENCODE, CERT_X509) -TEST_SUITE(serial_parse_suite_create) +TEST_SUITE_DEPEND(serial_parse_suite_create, CERT_DECODE, CERT_X509) TEST_SUITE(host_suite_create) TEST_SUITE(printf_suite_create) TEST_SUITE(auth_cfg_suite_create) diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 999c391670..038cd0a0ce 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -563,16 +563,6 @@ static char *whitelist[] = { "xmlInitParserCtxt", /* libcurl */ "Curl_client_write", - /* libsoup */ - "soup_add_timeout", - "soup_headers_parse_response", - "soup_message_headers_append", - "soup_message_headers_clear", - "soup_message_headers_get_list", - "soup_message_headers_get_one", - "soup_session_abort", - "soup_session_get_type", - "soup_session_remove_feature", /* libldap */ "ldap_int_initialize", /* ClearSilver */