]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: crypto: throw DigestException from Digest and HMAC
authorMatt Benjamin <mbenjamin@redhat.com>
Wed, 24 Apr 2019 20:44:51 +0000 (16:44 -0400)
committerMatt Benjamin <mbenjamin@redhat.com>
Thu, 25 Apr 2019 15:01:24 +0000 (11:01 -0400)
Fixes: http://tracker.ceph.com/issues/39456
Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
src/common/ceph_crypto.h
src/rgw/librgw.cc
src/rgw/rgw_process.cc

index 1189ae54cbd8b363ee91ff5d347aafe0f0484505..30206c65702a5182397d6c8c75912894ffa7b309 100644 (file)
@@ -3,6 +3,7 @@
 #define CEPH_CRYPTO_H
 
 #include "acconfig.h"
+#include <stdexcept>
 
 #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, &param);
-       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
index f94f241569ae1d79a11f2dc2b64c59ea2d7017c0..95692aa7c460c2711973b862106f7ee28c6a60a9 100644 (file)
@@ -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 {
index b96020d91dab69096dc0937f33a7c84bdb4e7ac1..ad43b5d33d641b74fb92e55820fbf00257dc17be 100644 (file)
@@ -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();