diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index a54ebdcf388e..b09bbe0d091a 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -316,7 +316,9 @@ struct curlFileTransfer : public FileTransfer curl_easy_setopt(req, CURLOPT_PIPEWAIT, 1); #endif #if LIBCURL_VERSION_NUM >= 0x072f00 - if (fileTransferSettings.enableHttp2) + // Our writeCallbackWrapper does not support rewinding which breaks + // negotiate/kerberos auth over http/2. + if (fileTransferSettings.enableHttp2 && request.authmethod != HttpAuthMethod::NEGOTIATE) curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); else curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); @@ -353,6 +355,8 @@ struct curlFileTransfer : public FileTransfer curl_easy_setopt(req, CURLOPT_SSL_VERIFYHOST, 0); } + curl_easy_setopt(req, CURLOPT_HTTPAUTH, request.authmethod); + curl_easy_setopt(req, CURLOPT_CONNECTTIMEOUT, fileTransferSettings.connectTimeout.get()); curl_easy_setopt(req, CURLOPT_LOW_SPEED_LIMIT, 1L); diff --git a/src/libstore/filetransfer.hh b/src/libstore/filetransfer.hh index 1c271cbec03f..8fa20b610087 100644 --- a/src/libstore/filetransfer.hh +++ b/src/libstore/filetransfer.hh @@ -4,6 +4,7 @@ #include "types.hh" #include "hash.hh" #include "config.hh" +#include "http-binary-cache-store.hh" #include #include @@ -56,6 +57,8 @@ struct FileTransferRequest std::string expectedETag; bool verifyTLS = true; bool head = false; + HttpAuthMethod authmethod = HttpAuthMethod::BASIC; + std::string bearer_token; size_t tries = fileTransferSettings.tries; unsigned int baseRetryTimeMs = 250; ActivityId parentAct; diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index 3328caef9c4d..588496bc6d07 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -1,4 +1,5 @@ #include "binary-cache-store.hh" +#include "http-binary-cache-store.hh" #include "filetransfer.hh" #include "globals.hh" #include "nar-info-disk-cache.hh" @@ -8,12 +9,38 @@ namespace nix { MakeError(UploadToHTTP, Error); +HttpAuthMethod parseHttpAuthMethod(const std::string &str) { + static const std::map map = { + {"none", HttpAuthMethod::NONE}, + {"basic", HttpAuthMethod::BASIC}, + {"digest", HttpAuthMethod::DIGEST}, + {"negotiate", HttpAuthMethod::NEGOTIATE}, + {"ntlm", HttpAuthMethod::NTLM}, + {"bearer", HttpAuthMethod::BEARER}, + {"any", HttpAuthMethod::ANY}, + {"anysafe", HttpAuthMethod::ANYSAFE}}; + auto it = map.find(str); + if (it == map.end()) { + throw UsageError("option authmethod has invalid value '%s'", str); + } + return it->second; +} + struct HttpBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig { using BinaryCacheStoreConfig::BinaryCacheStoreConfig; const std::string name() override { return "HTTP Binary Cache Store"; } + const Setting authmethod{this, "basic", "authmethod", + R"( + libcurl auth method to use (`none`, `basic`, `digest`, `bearer`, `negotiate`, `ntlm`, `any`, or `anysafe`). + See https://curl.se/libcurl/c/CURLOPT_HTTPAUTH.html for more info. + )"}; + + const Setting bearer_token{this, "", "bearer-token", + "Bearer token to use for authentication. Requires `authmethod` to be set to `bearer`."}; + std::string doc() override { return @@ -149,11 +176,13 @@ class HttpBinaryCacheStore : public virtual HttpBinaryCacheStoreConfig, public v FileTransferRequest makeRequest(const std::string & path) { - return FileTransferRequest( + auto request = FileTransferRequest( hasPrefix(path, "https://") || hasPrefix(path, "http://") || hasPrefix(path, "file://") ? path : cacheUri + "/" + path); - + request.authmethod = parseHttpAuthMethod(authmethod); + request.bearer_token = bearer_token; + return request; } void getFile(const std::string & path, Sink & sink) override diff --git a/src/libstore/http-binary-cache-store.hh b/src/libstore/http-binary-cache-store.hh new file mode 100644 index 000000000000..7c5e76880fc6 --- /dev/null +++ b/src/libstore/http-binary-cache-store.hh @@ -0,0 +1,19 @@ +#pragma once +///@file + +#include "types.hh" + +#include "curl/curl.h" + +namespace nix { + enum struct HttpAuthMethod : unsigned long { + NONE = CURLAUTH_NONE, + BASIC = CURLAUTH_BASIC, + DIGEST = CURLAUTH_DIGEST, + NEGOTIATE = CURLAUTH_NEGOTIATE, + NTLM = CURLAUTH_NTLM, + BEARER = CURLAUTH_BEARER, + ANY = CURLAUTH_ANY, + ANYSAFE = CURLAUTH_ANYSAFE + }; +}