aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-03-25 13:26:01 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:17:13 -0400
commit0bed9b5c523d577378b6f83eab5835fe30c27208 (patch)
treeab35e0fdeedf883e029cedab7a0ecbce71376426
parent4b8e8b5d78b8322351d44487c1b76f7e9d3412bc (diff)
libceph: add update_authorizer auth method
Currently the messenger calls out to a get_authorizer con op, which will create a new authorizer if it doesn't yet have one. In the meantime, when we rotate our service keys, the authorizer doesn't get updated. Eventually it will be rejected by the server on a new connection attempt and get invalidated, and we will then rebuild a new authorizer, but this is not ideal. Instead, if we do have an authorizer, call a new update_authorizer op that will verify that the current authorizer is using the latest secret. If it is not, we will build a new one that does. This avoids the transient failure. This fixes one of the sorry sequence of events for bug http://tracker.ceph.com/issues/4282 Signed-off-by: Sage Weil <sage@inktank.com> Reviewed-by: Alex Elder <elder@inktank.com>
-rw-r--r--fs/ceph/mds_client.c7
-rw-r--r--include/linux/ceph/auth.h3
-rw-r--r--net/ceph/auth_x.c23
-rw-r--r--net/ceph/auth_x.h1
-rw-r--r--net/ceph/osd_client.c5
5 files changed, 38 insertions, 1 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 0db6f5206d11..010ff83d640b 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -3445,7 +3445,12 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
3445 } 3445 }
3446 if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { 3446 if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
3447 int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, 3447 int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS,
3448 auth); 3448 auth);
3449 if (ret)
3450 return ERR_PTR(ret);
3451 } else if (ac->ops && ac->ops_update_authorizer) {
3452 int ret = ac->ops->update_authorizer(ac, CEPH_ENTITY_TYPE_MDS,
3453 auth);
3449 if (ret) 3454 if (ret)
3450 return ERR_PTR(ret); 3455 return ERR_PTR(ret);
3451 } 3456 }
diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h
index d4080f309b56..73e973e70026 100644
--- a/include/linux/ceph/auth.h
+++ b/include/linux/ceph/auth.h
@@ -52,6 +52,9 @@ struct ceph_auth_client_ops {
52 */ 52 */
53 int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type, 53 int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type,
54 struct ceph_auth_handshake *auth); 54 struct ceph_auth_handshake *auth);
55 /* ensure that an existing authorizer is up to date */
56 int (*update_authorizer)(struct ceph_auth_client *ac, int peer_type,
57 struct ceph_auth_handshake *auth);
55 int (*verify_authorizer_reply)(struct ceph_auth_client *ac, 58 int (*verify_authorizer_reply)(struct ceph_auth_client *ac,
56 struct ceph_authorizer *a, size_t len); 59 struct ceph_authorizer *a, size_t len);
57 void (*destroy_authorizer)(struct ceph_auth_client *ac, 60 void (*destroy_authorizer)(struct ceph_auth_client *ac,
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
index bd8758dbfded..2d5981555cd6 100644
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -298,6 +298,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
298 return -ENOMEM; 298 return -ENOMEM;
299 } 299 }
300 au->service = th->service; 300 au->service = th->service;
301 au->secret_id = th->secret_id;
301 302
302 msg_a = au->buf->vec.iov_base; 303 msg_a = au->buf->vec.iov_base;
303 msg_a->struct_v = 1; 304 msg_a->struct_v = 1;
@@ -555,6 +556,27 @@ static int ceph_x_create_authorizer(
555 return 0; 556 return 0;
556} 557}
557 558
559static int ceph_x_update_authorizer(
560 struct ceph_auth_client *ac, int peer_type,
561 struct ceph_auth_handshake *auth)
562{
563 struct ceph_x_authorizer *au;
564 struct ceph_x_ticket_handler *th;
565 int ret;
566
567 th = get_ticket_handler(ac, peer_type);
568 if (IS_ERR(th))
569 return PTR_ERR(th);
570
571 au = (struct ceph_x_authorizer *)auth->authorizer;
572 if (au->secret_id < th->secret_id) {
573 dout("ceph_x_update_authorizer service %u secret %llu < %llu\n",
574 au->service, au->secret_id, th->secret_id);
575 return ceph_x_build_authorizer(ac, th, au);
576 }
577 return 0;
578}
579
558static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, 580static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
559 struct ceph_authorizer *a, size_t len) 581 struct ceph_authorizer *a, size_t len)
560{ 582{
@@ -641,6 +663,7 @@ static const struct ceph_auth_client_ops ceph_x_ops = {
641 .build_request = ceph_x_build_request, 663 .build_request = ceph_x_build_request,
642 .handle_reply = ceph_x_handle_reply, 664 .handle_reply = ceph_x_handle_reply,
643 .create_authorizer = ceph_x_create_authorizer, 665 .create_authorizer = ceph_x_create_authorizer,
666 .update_authorizer = ceph_x_update_authorizer,
644 .verify_authorizer_reply = ceph_x_verify_authorizer_reply, 667 .verify_authorizer_reply = ceph_x_verify_authorizer_reply,
645 .destroy_authorizer = ceph_x_destroy_authorizer, 668 .destroy_authorizer = ceph_x_destroy_authorizer,
646 .invalidate_authorizer = ceph_x_invalidate_authorizer, 669 .invalidate_authorizer = ceph_x_invalidate_authorizer,
diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h
index f459e93b774f..c5a058da7ac8 100644
--- a/net/ceph/auth_x.h
+++ b/net/ceph/auth_x.h
@@ -29,6 +29,7 @@ struct ceph_x_authorizer {
29 struct ceph_buffer *buf; 29 struct ceph_buffer *buf;
30 unsigned int service; 30 unsigned int service;
31 u64 nonce; 31 u64 nonce;
32 u64 secret_id;
32 char reply_buf[128]; /* big enough for encrypted blob */ 33 char reply_buf[128]; /* big enough for encrypted blob */
33}; 34};
34 35
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index cb14db8496bd..5ef24e3e1627 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2220,6 +2220,11 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
2220 auth); 2220 auth);
2221 if (ret) 2221 if (ret)
2222 return ERR_PTR(ret); 2222 return ERR_PTR(ret);
2223 } else if (ac->ops && ac->ops->update_authorizer) {
2224 int ret = ac->ops->update_authorizer(ac, CEPH_ENTITY_TYPE_OSD,
2225 auth);
2226 if (ret)
2227 return ERR_PTR(ret);
2223 } 2228 }
2224 *proto = ac->protocol; 2229 *proto = ac->protocol;
2225 2230