const string& bucket_name = s->init_state.url_bucket;
/* TempURL requires that bucket and object names are specified. */
- if (bucket_name.empty() || s->object->empty()) {
+ if (bucket_name.empty() || rgw::sal::Object::empty(s->object)) {
throw -EPERM;
}
}
}
-class TempURLEngine::SignatureHelper
-{
-private:
- static constexpr uint32_t output_size =
- CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2 + 1;
-
- unsigned char dest[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE]; // 20
- char dest_str[output_size];
-
+template <class HASHFLAVOR, SignatureFlavor SIGNATUREFLAVOR>
+class TempURLSignatureT : public rgw::auth::swift::FormatSignature<HASHFLAVOR,SIGNATUREFLAVOR> {
+ using UCHARPTR = const unsigned char*;
+ using base_t = SignatureHelperT<HASHFLAVOR>;
+ using format_signature_t = rgw::auth::swift::FormatSignature<HASHFLAVOR,SIGNATUREFLAVOR>;
public:
- SignatureHelper() = default;
-
const char* calc(const std::string& key,
const std::string_view& method,
const std::string_view& path,
const std::string& expires) {
+ HASHFLAVOR hmac((UCHARPTR) key.data(), key.size());
- using ceph::crypto::HMACSHA1;
- using UCHARPTR = const unsigned char*;
-
- HMACSHA1 hmac((UCHARPTR) key.c_str(), key.size());
hmac.Update((UCHARPTR) method.data(), method.size());
hmac.Update((UCHARPTR) "\n", 1);
hmac.Update((UCHARPTR) expires.c_str(), expires.size());
hmac.Update((UCHARPTR) "\n", 1);
hmac.Update((UCHARPTR) path.data(), path.size());
- hmac.Final(dest);
+ hmac.Final(base_t::dest);
- buf_to_hex((UCHARPTR) dest, sizeof(dest), dest_str);
-
- return dest_str;
+ return format_signature_t::result();
}
-
- bool is_equal_to(const std::string& rhs) const {
- /* never allow out-of-range exception */
- if (rhs.size() < (output_size - 1)) {
- return false;
+}; /* TempURLSignatureT */
+class TempURLEngine::SignatureHelper {
+public:
+ SignatureHelper() {};
+ virtual ~SignatureHelper() {};
+ virtual const char* calc(const std::string& key,
+ const std::string_view& method,
+ const std::string_view& path,
+ const std::string& expires) {
+ return nullptr;
+ }
+ virtual bool is_equal_to(const std::string& rhs) {
+ return false;
+ };
+ static std::unique_ptr<SignatureHelper> get_sig_helper(std::string_view x);
+};
+class TempURLSignature {
+ friend TempURLEngine;
+ using BadSignatureHelper = TempURLEngine::SignatureHelper;
+ template<typename HASHFLAVOR, SignatureFlavor SIGNATUREFLAVOR>
+ class SignatureHelper_x : public TempURLEngine::SignatureHelper
+ {
+ friend TempURLEngine;
+ TempURLSignatureT<HASHFLAVOR,SIGNATUREFLAVOR> d;
+ public:
+ SignatureHelper_x() {};
+ ~SignatureHelper_x() { };
+ virtual const char* calc(const std::string& key,
+ const std::string_view& method,
+ const std::string_view& path,
+ const std::string& expires) {
+ return d.calc(key,method,path,expires);
}
- return rhs.compare(0 /* pos */, output_size, dest_str) == 0;
+ virtual bool is_equal_to(const std::string& rhs) {
+ return d.is_equal_to(rhs);
+ };
+ };
+};
+
+std::unique_ptr<TempURLEngine::SignatureHelper> TempURLEngine::SignatureHelper::get_sig_helper(std::string_view x) {
+ size_t pos = x.find(':');
+ if (pos == x.npos || pos <= 0) {
+ switch(x.length()) {
+ case CEPH_CRYPTO_HMACSHA1_DIGESTSIZE*2:
+ return std::make_unique<TempURLSignature::SignatureHelper_x<ceph::crypto::HMACSHA1,rgw::auth::swift::SignatureFlavor::BARE_HEX>>();
+ case CEPH_CRYPTO_HMACSHA256_DIGESTSIZE*2:
+ return std::make_unique<TempURLSignature::SignatureHelper_x<ceph::crypto::HMACSHA256,rgw::auth::swift::SignatureFlavor::BARE_HEX>>();
+ case CEPH_CRYPTO_HMACSHA512_DIGESTSIZE*2:
+ return std::make_unique<TempURLSignature::SignatureHelper_x<ceph::crypto::HMACSHA512,rgw::auth::swift::SignatureFlavor::BARE_HEX>>();
+ }
+ return std::make_unique<TempURLSignature::BadSignatureHelper>();
}
+ std::string_view type { x.substr(0,pos) };
+ if (type == "sha1") {
+ return std::make_unique<TempURLSignature::SignatureHelper_x<ceph::crypto::HMACSHA1,rgw::auth::swift::SignatureFlavor::NAMED_BASE64>>();
+ } else if (type == "sha256") {
+ return std::make_unique<TempURLSignature::SignatureHelper_x<ceph::crypto::HMACSHA256,rgw::auth::swift::SignatureFlavor::NAMED_BASE64>>();
+ } else if (type == "sha512") {
+ return std::make_unique<TempURLSignature::SignatureHelper_x<ceph::crypto::HMACSHA512,rgw::auth::swift::SignatureFlavor::NAMED_BASE64>>();
+ }
+ return std::make_unique<TempURLSignature::BadSignatureHelper>();
+};
-}; /* TempURLEngine::SignatureHelper */
-
-class TempURLEngine::PrefixableSignatureHelper
- : private TempURLEngine::SignatureHelper {
- using base_t = SignatureHelper;
+class TempURLEngine::PrefixableSignatureHelper {
const std::string_view decoded_uri;
const std::string_view object_name;
std::string_view no_obj_uri;
const boost::optional<const std::string&> prefix;
+ std::unique_ptr<SignatureHelper> base_sig_helper;
public:
- PrefixableSignatureHelper(const std::string& _decoded_uri,
+ PrefixableSignatureHelper(const std::string_view sig,
+ const std::string& _decoded_uri,
const std::string& object_name,
const boost::optional<const std::string&> prefix)
: decoded_uri(_decoded_uri),
object_name(object_name),
- prefix(prefix) {
+ prefix(prefix),
+ base_sig_helper(TempURLEngine::SignatureHelper::get_sig_helper(sig)) {
/* Transform: v1/acct/cont/obj - > v1/acct/cont/
*
* NOTE(rzarzynski): we really want to substr() on std::string_view,
* a temporary. */
no_obj_uri = \
decoded_uri.substr(0, decoded_uri.length() - object_name.length());
- }
+ };
const char* calc(const std::string& key,
const std::string_view& method,
const std::string_view& path,
const std::string& expires) {
if (!prefix) {
- return base_t::calc(key, method, path, expires);
+ return base_sig_helper->calc(key, method, path, expires);
} else {
const auto prefixed_path = \
string_cat_reserve("prefix:", no_obj_uri, *prefix);
- return base_t::calc(key, method, prefixed_path, expires);
+ return base_sig_helper->calc(key, method, prefixed_path, expires);
}
}
bool is_equal_to(const std::string& rhs) const {
- bool is_auth_ok = base_t::is_equal_to(rhs);
+ bool is_auth_ok = base_sig_helper->is_equal_to(rhs);
if (prefix && is_auth_ok) {
const auto prefix_uri = string_cat_reserve(no_obj_uri, *prefix);
/* Need to try each combination of keys, allowed path and methods. */
PrefixableSignatureHelper sig_helper {
+ temp_url_sig,
s->decoded_uri,
s->object->get_name(),
temp_url_prefix
{
return new RGW_SWIFT_Auth_Get;
}
-
#include "rgw_auth_keystone.h"
#include "rgw_auth_filters.h"
#include "rgw_sal.h"
+#include "rgw_b64.h"
#define RGW_SWIFT_TOKEN_EXPIRATION (15 * 60)
/* TempURL: engine */
class TempURLEngine : public rgw::auth::Engine {
+ friend class TempURLSignature;
using result_t = rgw::auth::Engine::result_t;
CephContext* const cct;
}
};
+// shared logic for swift tempurl and formpost signatures
+template <class HASHFLAVOR>
+inline constexpr uint32_t signature_hash_size = -1;
+template <>
+inline constexpr uint32_t signature_hash_size<ceph::crypto::HMACSHA1> = CEPH_CRYPTO_HMACSHA1_DIGESTSIZE;
+template<>
+inline constexpr uint32_t signature_hash_size<ceph::crypto::HMACSHA256> = CEPH_CRYPTO_HMACSHA256_DIGESTSIZE;
+template<>
+inline constexpr uint32_t signature_hash_size<ceph::crypto::HMACSHA512> = CEPH_CRYPTO_HMACSHA512_DIGESTSIZE;
+
+const char sha1_name[] = "sha1";
+const char sha256_name[] = "sha256";
+const char sha512_name[] = "sha512";
+
+template <class HASHFLAVOR>
+const char * signature_hash_name;
+template<>
+inline constexpr const char * signature_hash_name<ceph::crypto::HMACSHA1> = sha1_name;;
+template<>
+inline constexpr const char * signature_hash_name<ceph::crypto::HMACSHA256> = sha256_name;
+template<>
+inline constexpr const char * signature_hash_name<ceph::crypto::HMACSHA512> = sha512_name;
+
+template <class HASHFLAVOR>
+inline const uint32_t signature_hash_name_size = -1;
+template<>
+inline constexpr uint32_t signature_hash_name_size<ceph::crypto::HMACSHA1> = sizeof sha1_name;;
+template<>
+inline constexpr uint32_t signature_hash_name_size<ceph::crypto::HMACSHA256> = sizeof sha256_name;
+template<>
+inline constexpr uint32_t signature_hash_name_size<ceph::crypto::HMACSHA512> = sizeof sha512_name;
+
+template <class HASHFLAVOR>
+class SignatureHelperT {
+protected:
+ static constexpr uint32_t hash_size = signature_hash_size<HASHFLAVOR>;
+ static constexpr uint32_t output_size = hash_size * 2 + 1;
+ const char * signature_name = signature_hash_name<HASHFLAVOR>;
+ uint32_t signature_name_size = signature_hash_name_size<HASHFLAVOR>;
+ char dest_str[output_size];
+ uint32_t dest_size = 0;
+ unsigned char dest[hash_size];
+
+public:
+ ~SignatureHelperT() { };
+
+ void Update(const unsigned char *input, size_t length);
+
+ const char* get_signature() const {
+ return dest_str;
+ }
+
+ bool is_equal_to(const std::string& rhs) const {
+ /* never allow out-of-range exception */
+ if (!dest_size || rhs.size() < dest_size) {
+ return false;
+ }
+ return rhs.compare(0 /* pos */, dest_size + 1, dest_str) == 0;
+ }
+};
+
+enum class SignatureFlavor {
+ BARE_HEX,
+ NAMED_BASE64
+};
+
+template <typename HASHFLAVOR, SignatureFlavor SIGNATUREFLAVOR>
+class FormatSignature {
+};
+
+// hexadecimal
+template <typename HASHFLAVOR>
+class FormatSignature<HASHFLAVOR, SignatureFlavor::BARE_HEX> : public SignatureHelperT<HASHFLAVOR> {
+ using UCHARPTR = const unsigned char*;
+ using base_t = SignatureHelperT<HASHFLAVOR>;
+public:
+ const char *result() {
+ buf_to_hex((UCHARPTR) base_t::dest,
+ signature_hash_size<HASHFLAVOR>,
+ base_t::dest_str);
+ base_t::dest_size = strlen(base_t::dest_str);
+ return base_t::dest_str;
+ };
+};
+
+// prefix:base64
+template <typename HASHFLAVOR>
+class FormatSignature<HASHFLAVOR, SignatureFlavor::NAMED_BASE64> : public SignatureHelperT<HASHFLAVOR> {
+ using UCHARPTR = const unsigned char*;
+ using base_t = SignatureHelperT<HASHFLAVOR>;
+public:
+ char * const result() {
+ const char *prefix = base_t::signature_name;
+ const int prefix_size = base_t::signature_name_size;
+ std::string_view dest_view((char*)base_t::dest, sizeof base_t::dest);
+ auto b { rgw::to_base64(dest_view) };
+ for (auto &v: b ) { // translate to "url safe" (rfc 4648 section 5)
+ switch(v) {
+ case '+': v = '-'; break;
+ case '/': v = '_'; break;
+ }
+ }
+ base_t::dest_size = prefix_size + b.length();
+ if (base_t::dest_size < base_t::output_size) {
+ ::memcpy(base_t::dest_str, prefix, prefix_size - 1);
+ base_t::dest_str[prefix_size-1] = ':';
+ ::strcpy(base_t::dest_str + prefix_size, b.c_str());
+ } else {
+ base_t::dest_size = 0;
+ }
+ return base_t::dest_str;
+ };
+};
+
} /* namespace swift */
} /* namespace auth */
} /* namespace rgw */