aboutsummaryrefslogtreecommitdiffstats
path: root/ydb/library/http_proxy/authorization/signature.cpp
diff options
context:
space:
mode:
authorradix <radix@yandex-team.ru>2022-02-10 16:49:44 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:49:44 +0300
commit24658cfd172ef5de124df383c334079783154fbf (patch)
treebccc29f3945c7245036b5973bcc7358a760fcc25 /ydb/library/http_proxy/authorization/signature.cpp
parentceabccd128eb94ed6566936fcab2093ec62aa84a (diff)
downloadydb-24658cfd172ef5de124df383c334079783154fbf.tar.gz
Restoring authorship annotation for <radix@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'ydb/library/http_proxy/authorization/signature.cpp')
-rw-r--r--ydb/library/http_proxy/authorization/signature.cpp498
1 files changed, 249 insertions, 249 deletions
diff --git a/ydb/library/http_proxy/authorization/signature.cpp b/ydb/library/http_proxy/authorization/signature.cpp
index 60368c0614..5abef495d6 100644
--- a/ydb/library/http_proxy/authorization/signature.cpp
+++ b/ydb/library/http_proxy/authorization/signature.cpp
@@ -1,262 +1,262 @@
-#include "auth_helpers.h"
-#include "signature.h"
-
+#include "auth_helpers.h"
+#include "signature.h"
+
#include <library/cpp/http/io/stream.h>
#include <library/cpp/http/misc/parsed_request.h>
-
+
#include <contrib/libs/openssl/include/openssl/evp.h>
#include <contrib/libs/openssl/include/openssl/hmac.h>
#include <contrib/libs/openssl/include/openssl/sha.h>
-
-#include <util/generic/algorithm.h>
-#include <util/stream/str.h>
-#include <util/string/builder.h>
+
+#include <util/generic/algorithm.h>
+#include <util/stream/str.h>
+#include <util/string/builder.h>
#include <library/cpp/cgiparam/cgiparam.h>
-#include <util/string/hex.h>
-#include <util/string/join.h>
-#include <util/string/strip.h>
-
+#include <util/string/hex.h>
+#include <util/string/join.h>
+#include <util/string/strip.h>
+
namespace NKikimr::NSQS {
-
-static TString HmacSHA256(TStringBuf key, TStringBuf data) {
- unsigned char hash[SHA256_DIGEST_LENGTH];
- ui32 hl = SHA256_DIGEST_LENGTH;
+
+static TString HmacSHA256(TStringBuf key, TStringBuf data) {
+ unsigned char hash[SHA256_DIGEST_LENGTH];
+ ui32 hl = SHA256_DIGEST_LENGTH;
const auto* res = HMAC(EVP_sha256(), key.data(), key.size(), reinterpret_cast<const unsigned char*>(data.data()), data.size(), hash, &hl);
- Y_ENSURE(res);
- Y_ENSURE(hl == SHA256_DIGEST_LENGTH);
- return TString{reinterpret_cast<const char*>(res), hl};
-}
-
-static TString HashSHA256(IInputStream& stream) {
- SHA256_CTX hasher;
- SHA256_Init(&hasher);
- char buf[4096];
- size_t read = 0;
- while ((read = stream.Read(buf, sizeof(buf))) != 0) {
- SHA256_Update(&hasher, buf, read);
- }
- unsigned char hash[SHA256_DIGEST_LENGTH];
- SHA256_Final(hash, &hasher);
- return to_lower(HexEncode(hash, SHA256_DIGEST_LENGTH));
-}
-
-static TString HashSHA256(TStringBuf data) {
- TMemoryInput in{data};
- return HashSHA256(in);
-}
-
-static const char newline = '\n';
-static const char pathDelim = '/';
-
+ Y_ENSURE(res);
+ Y_ENSURE(hl == SHA256_DIGEST_LENGTH);
+ return TString{reinterpret_cast<const char*>(res), hl};
+}
+
+static TString HashSHA256(IInputStream& stream) {
+ SHA256_CTX hasher;
+ SHA256_Init(&hasher);
+ char buf[4096];
+ size_t read = 0;
+ while ((read = stream.Read(buf, sizeof(buf))) != 0) {
+ SHA256_Update(&hasher, buf, read);
+ }
+ unsigned char hash[SHA256_DIGEST_LENGTH];
+ SHA256_Final(hash, &hasher);
+ return to_lower(HexEncode(hash, SHA256_DIGEST_LENGTH));
+}
+
+static TString HashSHA256(TStringBuf data) {
+ TMemoryInput in{data};
+ return HashSHA256(in);
+}
+
+static const char newline = '\n';
+static const char pathDelim = '/';
+
constexpr TStringBuf AUTHORIZATION_HEADER = "authorization";
-
-static const TString SIGNED_HEADERS_PARAM = "signedheaders";
-static const TString SIGNATURE_PARAM = "signature";
-static const TString CREDENTIAL_PARAM = "credential";
-
-TAwsRequestSignV4::TAwsRequestSignV4(const TString& request) {
- // special standalone ctor for tests
- TStringInput si(request);
- THttpInput input(&si);
- TParsedHttpFull parsed(input.FirstLine());
-
- TMaybe<TBuffer> inputData;
- ui64 contentLength = 0;
- if (parsed.Method == "POST") {
- if (input.GetContentLength(contentLength)) {
- inputData.ConstructInPlace();
- inputData->Resize(contentLength);
- if (input.Load(inputData->Data(), (size_t)contentLength) != contentLength) {
- Y_VERIFY(false);
- }
- }
- }
-
- Process(input, parsed, inputData);
-}
-
-TAwsRequestSignV4::TAwsRequestSignV4(const THttpInput& input, const TParsedHttpFull& parsed, const TMaybe<TBuffer>& inputData) {
- Process(input, parsed, inputData);
-}
-
-const TString& TAwsRequestSignV4::GetCanonicalRequest() const {
- return CanonicalRequestStr_;
-}
-
-const TString& TAwsRequestSignV4::GetStringToSign() const {
- return FinalStringToSignStr_;
-}
-
-const TString& TAwsRequestSignV4::GetParsedSignature() const {
- return ParsedSignature_;
-}
-
-const TString& TAwsRequestSignV4::GetSigningTimestamp() const {
- return AwsTimestamp_;
-}
-
-const TString& TAwsRequestSignV4::GetRegion() const {
- return AwsRegion_;
-}
-
-const TString& TAwsRequestSignV4::GetAccessKeyId() const {
- return AccessKeyId_;
-}
-
-void TAwsRequestSignV4::Process(const THttpInput& input, const TParsedHttpFull& parsed, const TMaybe<TBuffer>& inputData) {
- ParseAuthorization(input);
- MakeCanonicalRequest(input, parsed, inputData);
- MakeFinalStringToSign();
-}
-
-TString TAwsRequestSignV4::CalcSignature(const TString& secretKey) const {
- const auto dateKey = HmacSHA256(TString::Join("AWS4", secretKey), AwsDate_);
- const auto dateRegionKey = HmacSHA256(dateKey, AwsRegion_);
- const auto dateRegionServiceKey = HmacSHA256(dateRegionKey, AwsService_);
- const auto signingKey = HmacSHA256(dateRegionServiceKey, AwsRequest_);
- const auto signatureHmac = HmacSHA256(signingKey, FinalStringToSignStr_);
-
+
+static const TString SIGNED_HEADERS_PARAM = "signedheaders";
+static const TString SIGNATURE_PARAM = "signature";
+static const TString CREDENTIAL_PARAM = "credential";
+
+TAwsRequestSignV4::TAwsRequestSignV4(const TString& request) {
+ // special standalone ctor for tests
+ TStringInput si(request);
+ THttpInput input(&si);
+ TParsedHttpFull parsed(input.FirstLine());
+
+ TMaybe<TBuffer> inputData;
+ ui64 contentLength = 0;
+ if (parsed.Method == "POST") {
+ if (input.GetContentLength(contentLength)) {
+ inputData.ConstructInPlace();
+ inputData->Resize(contentLength);
+ if (input.Load(inputData->Data(), (size_t)contentLength) != contentLength) {
+ Y_VERIFY(false);
+ }
+ }
+ }
+
+ Process(input, parsed, inputData);
+}
+
+TAwsRequestSignV4::TAwsRequestSignV4(const THttpInput& input, const TParsedHttpFull& parsed, const TMaybe<TBuffer>& inputData) {
+ Process(input, parsed, inputData);
+}
+
+const TString& TAwsRequestSignV4::GetCanonicalRequest() const {
+ return CanonicalRequestStr_;
+}
+
+const TString& TAwsRequestSignV4::GetStringToSign() const {
+ return FinalStringToSignStr_;
+}
+
+const TString& TAwsRequestSignV4::GetParsedSignature() const {
+ return ParsedSignature_;
+}
+
+const TString& TAwsRequestSignV4::GetSigningTimestamp() const {
+ return AwsTimestamp_;
+}
+
+const TString& TAwsRequestSignV4::GetRegion() const {
+ return AwsRegion_;
+}
+
+const TString& TAwsRequestSignV4::GetAccessKeyId() const {
+ return AccessKeyId_;
+}
+
+void TAwsRequestSignV4::Process(const THttpInput& input, const TParsedHttpFull& parsed, const TMaybe<TBuffer>& inputData) {
+ ParseAuthorization(input);
+ MakeCanonicalRequest(input, parsed, inputData);
+ MakeFinalStringToSign();
+}
+
+TString TAwsRequestSignV4::CalcSignature(const TString& secretKey) const {
+ const auto dateKey = HmacSHA256(TString::Join("AWS4", secretKey), AwsDate_);
+ const auto dateRegionKey = HmacSHA256(dateKey, AwsRegion_);
+ const auto dateRegionServiceKey = HmacSHA256(dateRegionKey, AwsService_);
+ const auto signingKey = HmacSHA256(dateRegionServiceKey, AwsRequest_);
+ const auto signatureHmac = HmacSHA256(signingKey, FinalStringToSignStr_);
+
return to_lower(HexEncode(signatureHmac.data(), signatureHmac.size()));
-}
-
-void TAwsRequestSignV4::ParseAuthorization(const THttpInput& input) {
- for (const auto& header : input.Headers()) {
- if (AsciiEqualsIgnoreCase(header.Name(), AUTHORIZATION_HEADER)) {
- auto params = ParseAuthorizationParams(header.Value());
-
- SignedHeadersList_ = TString(params[SIGNED_HEADERS_PARAM]);
- ParsedSignature_ = TString(params[SIGNATURE_PARAM]);
-
- TStringBuf credential = params[CREDENTIAL_PARAM];
- AccessKeyId_ = TString(credential.NextTok(pathDelim));
- AwsDate_ = TString(credential.NextTok(pathDelim));
- AwsRegion_ = TString(credential.NextTok(pathDelim));
- AwsService_ = TString(credential.NextTok(pathDelim));
- break;
- }
- }
-}
-
-static TString UriEncode(const TStringBuf input, bool encodeSlash = false) {
- TStringStream result;
- for (const char ch : input) {
- if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' ||
- ch == '-' || ch == '~' || ch == '.') {
- result << ch;
- } else if (ch == '/') {
- if (encodeSlash) {
- result << "%2F";
- } else {
- result << ch;
- }
- } else {
- result << "%" << HexEncode(&ch, 1);
- }
- }
- return result.Str();
-}
-
-void TAwsRequestSignV4::MakeCanonicalRequest(const THttpInput& input, const TParsedHttpFull& parsed, const TMaybe<TBuffer>& inputData) {
- TStringStream canonicalRequest;
- // METHOD
- canonicalRequest << parsed.Method << newline;
- // PATH
- canonicalRequest << UriEncode(parsed.Path) << newline;
- // CGI
- TCgiParameters cgi(parsed.Cgi);
- TMap<TString, TVector<TString>> sortedCgi;
-
- for (const auto& [key, value] : cgi) {
- sortedCgi[key].push_back(value);
- }
-
- for (auto& pair : sortedCgi) {
- ::Sort(pair.second.begin(), pair.second.end());
- }
-
- if (sortedCgi.size()) {
- TStringStream canonicalCgi;
-
- auto printSingleParam = [&canonicalCgi](const TString& key, const TVector<TString>& values) {
- auto it = values.begin();
- canonicalCgi << UriEncode(key) << "=" << UriEncode(*it);
- while (++it != values.end()) {
- canonicalCgi << "&" << UriEncode(key) << "=" << UriEncode(*it);
- }
-
- };
-
- auto it = sortedCgi.begin();
- printSingleParam(it->first, it->second);
- while (++it != sortedCgi.end()) {
- canonicalCgi << "&";
- printSingleParam(it->first, it->second);
- }
-
- canonicalRequest << canonicalCgi.Str() << newline;
- } else {
- canonicalRequest << newline;
- }
- // CANONICAL HEADERS
- TMap<TStringBuf, TVector<TString>> canonicalHeaders;
-
- TStringBuf headersList = SignedHeadersList_;
- while (TStringBuf headerName = headersList.NextTok(';')) {
- canonicalHeaders[headerName] = {};
- }
-
- for (const auto& header : input.Headers()) {
- const auto lowercaseHeaderName = to_lower(header.Name());
- auto it = canonicalHeaders.find(lowercaseHeaderName);
- if (it != canonicalHeaders.end()) {
- it->second.push_back(Strip(header.Value()));
- }
- }
-
- for (const auto& [key, value] : canonicalHeaders) {
+}
+
+void TAwsRequestSignV4::ParseAuthorization(const THttpInput& input) {
+ for (const auto& header : input.Headers()) {
+ if (AsciiEqualsIgnoreCase(header.Name(), AUTHORIZATION_HEADER)) {
+ auto params = ParseAuthorizationParams(header.Value());
+
+ SignedHeadersList_ = TString(params[SIGNED_HEADERS_PARAM]);
+ ParsedSignature_ = TString(params[SIGNATURE_PARAM]);
+
+ TStringBuf credential = params[CREDENTIAL_PARAM];
+ AccessKeyId_ = TString(credential.NextTok(pathDelim));
+ AwsDate_ = TString(credential.NextTok(pathDelim));
+ AwsRegion_ = TString(credential.NextTok(pathDelim));
+ AwsService_ = TString(credential.NextTok(pathDelim));
+ break;
+ }
+ }
+}
+
+static TString UriEncode(const TStringBuf input, bool encodeSlash = false) {
+ TStringStream result;
+ for (const char ch : input) {
+ if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' ||
+ ch == '-' || ch == '~' || ch == '.') {
+ result << ch;
+ } else if (ch == '/') {
+ if (encodeSlash) {
+ result << "%2F";
+ } else {
+ result << ch;
+ }
+ } else {
+ result << "%" << HexEncode(&ch, 1);
+ }
+ }
+ return result.Str();
+}
+
+void TAwsRequestSignV4::MakeCanonicalRequest(const THttpInput& input, const TParsedHttpFull& parsed, const TMaybe<TBuffer>& inputData) {
+ TStringStream canonicalRequest;
+ // METHOD
+ canonicalRequest << parsed.Method << newline;
+ // PATH
+ canonicalRequest << UriEncode(parsed.Path) << newline;
+ // CGI
+ TCgiParameters cgi(parsed.Cgi);
+ TMap<TString, TVector<TString>> sortedCgi;
+
+ for (const auto& [key, value] : cgi) {
+ sortedCgi[key].push_back(value);
+ }
+
+ for (auto& pair : sortedCgi) {
+ ::Sort(pair.second.begin(), pair.second.end());
+ }
+
+ if (sortedCgi.size()) {
+ TStringStream canonicalCgi;
+
+ auto printSingleParam = [&canonicalCgi](const TString& key, const TVector<TString>& values) {
+ auto it = values.begin();
+ canonicalCgi << UriEncode(key) << "=" << UriEncode(*it);
+ while (++it != values.end()) {
+ canonicalCgi << "&" << UriEncode(key) << "=" << UriEncode(*it);
+ }
+
+ };
+
+ auto it = sortedCgi.begin();
+ printSingleParam(it->first, it->second);
+ while (++it != sortedCgi.end()) {
+ canonicalCgi << "&";
+ printSingleParam(it->first, it->second);
+ }
+
+ canonicalRequest << canonicalCgi.Str() << newline;
+ } else {
+ canonicalRequest << newline;
+ }
+ // CANONICAL HEADERS
+ TMap<TStringBuf, TVector<TString>> canonicalHeaders;
+
+ TStringBuf headersList = SignedHeadersList_;
+ while (TStringBuf headerName = headersList.NextTok(';')) {
+ canonicalHeaders[headerName] = {};
+ }
+
+ for (const auto& header : input.Headers()) {
+ const auto lowercaseHeaderName = to_lower(header.Name());
+ auto it = canonicalHeaders.find(lowercaseHeaderName);
+ if (it != canonicalHeaders.end()) {
+ it->second.push_back(Strip(header.Value()));
+ }
+ }
+
+ for (const auto& [key, value] : canonicalHeaders) {
canonicalRequest << key << ":"sv << JoinRange(",", value.begin(), value.end()) << newline;
- }
-
- canonicalRequest << newline; // skip additional line after headers
- // SIGNED HEADERS
- canonicalRequest << SignedHeadersList_ << newline;
-
- static const TStringBuf hashedContentHeader = "x-amz-content-sha256";
-
- // PAYLOAD
- auto contentIt = canonicalHeaders.find(hashedContentHeader);
- static const TStringBuf unsignedPayloadLiteral = "UNSIGNED-PAYLOAD";
- if (contentIt != canonicalHeaders.end() && !contentIt->second.empty() && contentIt->second[0] == unsignedPayloadLiteral) {
- canonicalRequest << unsignedPayloadLiteral;
- } else {
- if (inputData) {
- canonicalRequest << HashSHA256(TStringBuf(inputData->Data(), inputData->Size()));
- } else {
- static const TStringBuf emptyStringSHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
- canonicalRequest << emptyStringSHA256;
- }
- }
-
- auto amzDateIt = canonicalHeaders.find("x-amz-date");
- if (amzDateIt != canonicalHeaders.end() && !amzDateIt->second.empty()) {
- AwsTimestamp_ = amzDateIt->second[0];
- }
-
- CanonicalRequestStr_ = canonicalRequest.Str();
-}
-
-void TAwsRequestSignV4::MakeFinalStringToSign() {
- TStringStream finalStringToSign;
+ }
+
+ canonicalRequest << newline; // skip additional line after headers
+ // SIGNED HEADERS
+ canonicalRequest << SignedHeadersList_ << newline;
+
+ static const TStringBuf hashedContentHeader = "x-amz-content-sha256";
+
+ // PAYLOAD
+ auto contentIt = canonicalHeaders.find(hashedContentHeader);
+ static const TStringBuf unsignedPayloadLiteral = "UNSIGNED-PAYLOAD";
+ if (contentIt != canonicalHeaders.end() && !contentIt->second.empty() && contentIt->second[0] == unsignedPayloadLiteral) {
+ canonicalRequest << unsignedPayloadLiteral;
+ } else {
+ if (inputData) {
+ canonicalRequest << HashSHA256(TStringBuf(inputData->Data(), inputData->Size()));
+ } else {
+ static const TStringBuf emptyStringSHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+ canonicalRequest << emptyStringSHA256;
+ }
+ }
+
+ auto amzDateIt = canonicalHeaders.find("x-amz-date");
+ if (amzDateIt != canonicalHeaders.end() && !amzDateIt->second.empty()) {
+ AwsTimestamp_ = amzDateIt->second[0];
+ }
+
+ CanonicalRequestStr_ = canonicalRequest.Str();
+}
+
+void TAwsRequestSignV4::MakeFinalStringToSign() {
+ TStringStream finalStringToSign;
finalStringToSign << "AWS4-HMAC-SHA256"sv << newline;
- finalStringToSign << AwsTimestamp_ << newline;
-
- finalStringToSign << AwsDate_ << pathDelim;
- finalStringToSign << AwsRegion_ << pathDelim;
- finalStringToSign << AwsService_ << pathDelim;
- finalStringToSign << AwsRequest_ << newline;
-
- finalStringToSign << HashSHA256(CanonicalRequestStr_);
- FinalStringToSignStr_ = finalStringToSign.Str();
-}
-
+ finalStringToSign << AwsTimestamp_ << newline;
+
+ finalStringToSign << AwsDate_ << pathDelim;
+ finalStringToSign << AwsRegion_ << pathDelim;
+ finalStringToSign << AwsService_ << pathDelim;
+ finalStringToSign << AwsRequest_ << newline;
+
+ finalStringToSign << HashSHA256(CanonicalRequestStr_);
+ FinalStringToSignStr_ = finalStringToSign.Str();
+}
+
} // namespace NKikimr::NSQS