From: Matt Benjamin Date: Wed, 24 Apr 2019 20:44:51 +0000 (-0400) Subject: rgw: crypto: throw DigestException from Digest and HMAC X-Git-Tag: v15.1.0~2723^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=8be1ffc936b01c95f28d19ca6deb4fe5c5916fc0;p=ceph-ci.git rgw: crypto: throw DigestException from Digest and HMAC Fixes: http://tracker.ceph.com/issues/39456 Signed-off-by: Matt Benjamin --- diff --git a/src/common/ceph_crypto.h b/src/common/ceph_crypto.h index 1189ae54cbd..30206c65702 100644 --- a/src/common/ceph_crypto.h +++ b/src/common/ceph_crypto.h @@ -3,6 +3,7 @@ #define CEPH_CRYPTO_H #include "acconfig.h" +#include #define CEPH_CRYPTO_MD5_DIGESTSIZE 16 #define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20 @@ -46,7 +47,16 @@ namespace ceph { #ifdef USE_NSS namespace ceph { namespace crypto { + + class DigestException : public std::runtime_error + { + public: + DigestException(const char* what_arg) : runtime_error(what_arg) + {} + }; + namespace nss { + class NSSDigest { private: PK11Context *ctx; @@ -55,7 +65,9 @@ namespace ceph { NSSDigest (SECOidTag _type, size_t _digest_size) : digest_size(_digest_size) { ctx = PK11_CreateDigestContext(_type); - ceph_assert_always(ctx); + if (! ctx) { + throw DigestException("PK11_CreateDigestContext() failed"); + } Restart(); } ~NSSDigest () { @@ -64,21 +76,27 @@ namespace ceph { void Restart() { SECStatus s; s = PK11_DigestBegin(ctx); - ceph_assert_always(s == SECSuccess); + if (s != SECSuccess) { + throw DigestException("PK11_DigestBegin() failed"); + } } void Update (const unsigned char *input, size_t length) { if (length) { SECStatus s; s = PK11_DigestOp(ctx, input, length); - ceph_assert_always(s == SECSuccess); + if (s != SECSuccess) { + throw DigestException("PK11_DigestOp() failed"); + } } } void Final (unsigned char *digest) { SECStatus s; unsigned int dummy; s = PK11_DigestFinal(ctx, digest, &dummy, digest_size); - ceph_assert_always(s == SECSuccess); - ceph_assert_always(dummy == digest_size); + if (! (s == SECSuccess) && + (dummy == digest_size)) { + throw DigestException("PK11_DigestFinal() failed"); + } Restart(); } }; @@ -151,39 +169,51 @@ namespace ceph { HMAC (CK_MECHANISM_TYPE cktype, unsigned int digestsize, const unsigned char *key, size_t length) { digest_size = digestsize; slot = PK11_GetBestSlot(cktype, NULL); - ceph_assert_always(slot); + if (! slot) { + throw DigestException("PK11_GetBestSlot() failed"); + } SECItem keyItem; keyItem.type = siBuffer; keyItem.data = (unsigned char*)key; keyItem.len = length; symkey = PK11_ImportSymKey(slot, cktype, PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL); - ceph_assert_always(symkey); + if (! symkey) { + throw DigestException("PK11_ImportSymKey() failed"); + } SECItem param; param.type = siBuffer; param.data = NULL; param.len = 0; ctx = PK11_CreateContextBySymKey(cktype, CKA_SIGN, symkey, ¶m); - ceph_assert_always(ctx); + if (! ctx) { + throw DigestException("PK11_CreateContextBySymKey() failed"); + } Restart(); } ~HMAC (); void Restart() { SECStatus s; s = PK11_DigestBegin(ctx); - ceph_assert_always(s == SECSuccess); + if (s != SECSuccess) { + throw DigestException("PK11_DigestBegin() failed"); + } } void Update (const unsigned char *input, size_t length) { SECStatus s; s = PK11_DigestOp(ctx, input, length); - ceph_assert_always(s == SECSuccess); + if (s != SECSuccess) { + throw DigestException("PK11_DigestOp() failed"); + } } void Final (unsigned char *digest) { SECStatus s; unsigned int dummy; s = PK11_DigestFinal(ctx, digest, &dummy, digest_size); - ceph_assert_always(s == SECSuccess); - ceph_assert_always(dummy == digest_size); + if (! (s == SECSuccess) && + (dummy == digest_size)) { + throw DigestException("PK11_DigestFinal() failed"); + } Restart(); } }; @@ -214,7 +244,9 @@ namespace ceph::crypto::ssl { : mpType(type) { ::memset(&mContext, 0, sizeof(mContext)); const auto r = HMAC_Init_ex(&mContext, key, length, mpType, nullptr); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Init_ex() failed"); + } } ~HMAC () { HMAC_CTX_cleanup(&mContext); @@ -222,18 +254,24 @@ namespace ceph::crypto::ssl { void Restart () { const auto r = HMAC_Init_ex(&mContext, nullptr, 0, mpType, nullptr); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Init_ex() failed"); + } } void Update (const unsigned char *input, size_t length) { if (length) { const auto r = HMAC_Update(&mContext, input, length); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Update() failed"); + } } } void Final (unsigned char *digest) { unsigned int s; const auto r = HMAC_Final(&mContext, digest, &s); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Final() failed"); + } } }; # else @@ -245,7 +283,9 @@ namespace ceph::crypto::ssl { HMAC (const EVP_MD *type, const unsigned char *key, size_t length) : mpContext(HMAC_CTX_new()) { const auto r = HMAC_Init_ex(mpContext, key, length, type, nullptr); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Init_ex() failed"); + } } ~HMAC () { HMAC_CTX_free(mpContext); @@ -254,18 +294,24 @@ namespace ceph::crypto::ssl { void Restart () { const EVP_MD * const type = HMAC_CTX_get_md(mpContext); const auto r = HMAC_Init_ex(mpContext, nullptr, 0, type, nullptr); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Init_ex() failed"); + } } void Update (const unsigned char *input, size_t length) { if (length) { const auto r = HMAC_Update(mpContext, input, length); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Update() failed"); + } } } void Final (unsigned char *digest) { unsigned int s; const auto r = HMAC_Final(mpContext, digest, &s); - ceph_assert_always(r == 1); + if (r != 1) { + throw DigestException("HMAC_Final() failed"); + } } }; # endif // OPENSSL_VERSION_NUMBER < 0x10100000L diff --git a/src/rgw/librgw.cc b/src/rgw/librgw.cc index f94f241569a..95692aa7c46 100644 --- a/src/rgw/librgw.cc +++ b/src/rgw/librgw.cc @@ -259,67 +259,73 @@ namespace rgw { rgw_env.set("REQUEST_URI", s->info.request_uri); rgw_env.set("QUERY_STRING", ""); - /* XXX authorize does less here then in the REST path, e.g., - * the user's info is cached, but still incomplete */ - ldpp_dout(s, 2) << "authorizing" << dendl; - ret = req->authorize(op); - if (ret < 0) { - dout(10) << "failed to authorize request" << dendl; - abort_req(s, op, ret); - goto done; - } + try { + /* XXX authorize does less here then in the REST path, e.g., + * the user's info is cached, but still incomplete */ + ldpp_dout(s, 2) << "authorizing" << dendl; + ret = req->authorize(op); + if (ret < 0) { + dout(10) << "failed to authorize request" << dendl; + abort_req(s, op, ret); + goto done; + } - /* FIXME: remove this after switching all handlers to the new authentication - * infrastructure. */ - if (! s->auth.identity) { - s->auth.identity = rgw::auth::transform_old_authinfo(s); - } + /* FIXME: remove this after switching all handlers to the new + * authentication infrastructure. */ + if (! s->auth.identity) { + s->auth.identity = rgw::auth::transform_old_authinfo(s); + } - ldpp_dout(s, 2) << "reading op permissions" << dendl; - ret = req->read_permissions(op); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + ldpp_dout(s, 2) << "reading op permissions" << dendl; + ret = req->read_permissions(op); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - ldpp_dout(s, 2) << "init op" << dendl; - ret = op->init_processing(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + ldpp_dout(s, 2) << "init op" << dendl; + ret = op->init_processing(); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - ldpp_dout(s, 2) << "verifying op mask" << dendl; - ret = op->verify_op_mask(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + ldpp_dout(s, 2) << "verifying op mask" << dendl; + ret = op->verify_op_mask(); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - ldpp_dout(s, 2) << "verifying op permissions" << dendl; - ret = op->verify_permission(); - if (ret < 0) { - if (s->system_request) { - dout(2) << "overriding permissions due to system operation" << dendl; - } else if (s->auth.identity->is_admin_of(s->user->user_id)) { - dout(2) << "overriding permissions due to admin operation" << dendl; - } else { + ldpp_dout(s, 2) << "verifying op permissions" << dendl; + ret = op->verify_permission(); + if (ret < 0) { + if (s->system_request) { + dout(2) << "overriding permissions due to system operation" << dendl; + } else if (s->auth.identity->is_admin_of(s->user->user_id)) { + dout(2) << "overriding permissions due to admin operation" << dendl; + } else { + abort_req(s, op, ret); + goto done; + } + } + + ldpp_dout(s, 2) << "verifying op params" << dendl; + ret = op->verify_params(); + if (ret < 0) { abort_req(s, op, ret); goto done; } - } - ldpp_dout(s, 2) << "verifying op params" << dendl; - ret = op->verify_params(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + ldpp_dout(s, 2) << "executing" << dendl; + op->pre_exec(); + op->execute(); + op->complete(); - ldpp_dout(s, 2) << "executing" << dendl; - op->pre_exec(); - op->execute(); - op->complete(); + } catch (const ceph::crypto::DigestException& e) { + dout(0) << "authentication failed" << e.what() << dendl; + abort_req(s, op, -ERR_INVALID_SECRET_KEY); + } done: try { diff --git a/src/rgw/rgw_process.cc b/src/rgw/rgw_process.cc index b96020d91da..ad43b5d33d6 100644 --- a/src/rgw/rgw_process.cc +++ b/src/rgw/rgw_process.cc @@ -246,39 +246,45 @@ int process_request(RGWRados* const store, s->op_type = op->get_type(); - ldpp_dout(op, 2) << "verifying requester" << dendl; - ret = op->verify_requester(auth_registry); - if (ret < 0) { - dout(10) << "failed to authorize request" << dendl; - abort_early(s, op, ret, handler); - goto done; - } + try { + ldpp_dout(op, 2) << "verifying requester" << dendl; + ret = op->verify_requester(auth_registry); + if (ret < 0) { + dout(10) << "failed to authorize request" << dendl; + abort_early(s, op, ret, handler); + goto done; + } - /* FIXME: remove this after switching all handlers to the new authentication - * infrastructure. */ - if (nullptr == s->auth.identity) { - s->auth.identity = rgw::auth::transform_old_authinfo(s); - } + /* FIXME: remove this after switching all handlers to the new authentication + * infrastructure. */ + if (nullptr == s->auth.identity) { + s->auth.identity = rgw::auth::transform_old_authinfo(s); + } - ldpp_dout(op, 2) << "normalizing buckets and tenants" << dendl; - ret = handler->postauth_init(); - if (ret < 0) { - dout(10) << "failed to run post-auth init" << dendl; - abort_early(s, op, ret, handler); - goto done; - } + ldpp_dout(op, 2) << "normalizing buckets and tenants" << dendl; + ret = handler->postauth_init(); + if (ret < 0) { + dout(10) << "failed to run post-auth init" << dendl; + abort_early(s, op, ret, handler); + goto done; + } - if (s->user->suspended) { - dout(10) << "user is suspended, uid=" << s->user->user_id << dendl; - abort_early(s, op, -ERR_USER_SUSPENDED, handler); - goto done; - } + if (s->user->suspended) { + dout(10) << "user is suspended, uid=" << s->user->user_id << dendl; + abort_early(s, op, -ERR_USER_SUSPENDED, handler); + goto done; + } - ret = rgw_process_authenticated(handler, op, req, s); - if (ret < 0) { - abort_early(s, op, ret, handler); - goto done; + ret = rgw_process_authenticated(handler, op, req, s); + if (ret < 0) { + abort_early(s, op, ret, handler); + goto done; + } + } catch (const ceph::crypto::DigestException& e) { + dout(0) << "authentication failed" << e.what() << dendl; + abort_early(s, op, -ERR_INVALID_SECRET_KEY, handler); } + done: try { client_io->complete_request();