From: Yehuda Sadeh Date: Wed, 27 Nov 2013 01:49:27 +0000 (-0800) Subject: rgw: handle temp url key authorization X-Git-Tag: v0.78~333^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=56e4015cf4f2917b13c9f017e09ec47581ee4867;p=ceph.git rgw: handle temp url key authorization Fixes: #3454 Implement auth handling code that checks temp url signature and expiration. The key that is used for the signature is the bucket owner's temp url key. Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index daeb7760130..68626b8a6f5 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -743,7 +743,7 @@ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_options() int RGWHandler_ObjStore_SWIFT::authorize() { - if (!s->os_auth_token) { + if (!s->os_auth_token && s->info.args.get("temp_url_sig").empty()) { /* anonymous access */ rgw_get_anon_user(s->user); s->perm_mask = RGW_PERM_FULL_CONTROL; @@ -869,6 +869,12 @@ int RGWHandler_ObjStore_SWIFT::init_from_header(struct req_state *s) string ver; next_tok(req, ver, '/'); + + string tenant; + if (!tenant_path.empty()) { + next_tok(req, tenant, '/'); + } + s->os_auth_token = s->info.env->get("HTTP_X_AUTH_TOKEN"); next_tok(req, first, '/'); diff --git a/src/rgw/rgw_swift.cc b/src/rgw/rgw_swift.cc index 89b86fdfe8f..3ad422c9632 100644 --- a/src/rgw/rgw_swift.cc +++ b/src/rgw/rgw_swift.cc @@ -522,11 +522,84 @@ int RGWSwift::validate_keystone_token(RGWRados *store, const string& token, stru return 0; } +int authenticate_temp_url(RGWRados *store, req_state *s) +{ + /* temp url requires bucket and object specified in the requets */ + if (s->bucket_name_str.empty()) + return -EPERM; + + if (s->object_str.empty()) + return -EPERM; + + string temp_url_sig = s->info.args.get("temp_url_sig"); + if (temp_url_sig.empty()) + return -EPERM; + + string temp_url_expires = s->info.args.get("temp_url_expires"); + if (temp_url_expires.empty()) + return -EPERM; + + /* need to get user info of bucket owner */ + RGWBucketInfo bucket_info; + + int ret = store->get_bucket_info(NULL, s->bucket_name_str, bucket_info, NULL); + if (ret < 0) + return -EPERM; + + dout(20) << "temp url user (bucket owner): " << bucket_info.owner << dendl; + if (rgw_get_user_info_by_uid(store, bucket_info.owner, s->user) < 0) { + return -EPERM; + } + + if (s->user.temp_url_key.empty()) { + dout(5) << "user does not have temp url key set, aborting" << dendl; + return -EPERM; + } + + if (!s->info.method) + return -EPERM; + + utime_t now = ceph_clock_now(g_ceph_context); + + string err; + uint64_t expiration = (uint64_t)strict_strtoll(temp_url_expires.c_str(), 10, &err); + if (!err.empty()) { + dout(5) << "failed to parse temp_url_expires: " << err << dendl; + return -EPERM; + } + if (expiration <= (uint64_t)now.sec()) { + dout(5) << "temp url expired: " << expiration << " <= " << now.sec() << dendl; + return -EPERM; + } + + /* strip the swift prefix from the uri */ + int pos = g_conf->rgw_swift_url_prefix.find_last_not_of('/') + 1; + string object_path = s->info.request_uri.substr(pos + 1); + string str = string(s->info.method) + "\n" + temp_url_expires + "\n" + object_path; + + dout(20) << "temp url signature (plain text): " << str << dendl; + char dest[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE]; + calc_hmac_sha1(s->user.temp_url_key.c_str(), s->user.temp_url_key.size(), + str.c_str(), str.size(), dest); + + char dest_str[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2 + 1]; + buf_to_hex((const unsigned char *)dest, sizeof(dest), dest_str); + dout(20) << "temp url signature (calculated): " << dest_str << dendl; + + if (dest_str != temp_url_sig) { + dout(5) << "temp url signature mismatch: " << dest_str << " != " << temp_url_sig << dendl; + return -EPERM; + } + + return 0; +} bool RGWSwift::verify_swift_token(RGWRados *store, req_state *s) { - if (!s->os_auth_token) - return false; + if (!s->os_auth_token) { + int ret = authenticate_temp_url(store, s); + return (ret >= 0); + } if (strncmp(s->os_auth_token, "AUTH_rgwtk", 10) == 0) { int ret = rgw_swift_verify_signed_token(s->cct, store, s->os_auth_token, s->user);