aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-02-02 19:21:06 -0500
committerSage Weil <sage@newdream.net>2010-02-10 18:04:47 -0500
commit9bd2e6f8ba71facf1cadb7154a7e0e4d345a6aba (patch)
tree1c1bb4d2f769eca05443b98334fe0fbdb3b977c2
parent8b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522 (diff)
ceph: allow renewal of auth credentials
Add infrastructure to allow the mon_client to periodically renew its auth credentials. Also add a messenger callback that will force such a renewal if a peer rejects our authenticator. Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net> Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--fs/ceph/auth.c61
-rw-r--r--fs/ceph/auth.h7
-rw-r--r--fs/ceph/mds_client.c13
-rw-r--r--fs/ceph/messenger.c9
-rw-r--r--fs/ceph/messenger.h1
-rw-r--r--fs/ceph/mon_client.c55
-rw-r--r--fs/ceph/mon_client.h3
-rw-r--r--fs/ceph/osd_client.c12
-rw-r--r--fs/ceph/super.c12
-rw-r--r--fs/ceph/super.h4
10 files changed, 144 insertions, 33 deletions
diff --git a/fs/ceph/auth.c b/fs/ceph/auth.c
index 32f2e2a021ab..d5872d4f92bf 100644
--- a/fs/ceph/auth.c
+++ b/fs/ceph/auth.c
@@ -125,6 +125,30 @@ bad:
125 return -ERANGE; 125 return -ERANGE;
126} 126}
127 127
128int ceph_build_auth_request(struct ceph_auth_client *ac,
129 void *msg_buf, size_t msg_len)
130{
131 struct ceph_mon_request_header *monhdr = msg_buf;
132 void *p = monhdr + 1;
133 void *end = msg_buf + msg_len;
134 int ret;
135
136 monhdr->have_version = 0;
137 monhdr->session_mon = cpu_to_le16(-1);
138 monhdr->session_mon_tid = 0;
139
140 ceph_encode_32(&p, ac->protocol);
141
142 ret = ac->ops->build_request(ac, p + sizeof(u32), end);
143 if (ret < 0) {
144 pr_err("error %d building request\n", ret);
145 return ret;
146 }
147 dout(" built request %d bytes\n", ret);
148 ceph_encode_32(&p, ret);
149 return p + ret - msg_buf;
150}
151
128/* 152/*
129 * Handle auth message from monitor. 153 * Handle auth message from monitor.
130 */ 154 */
@@ -188,28 +212,13 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
188 goto out; 212 goto out;
189 } 213 }
190 } 214 }
215
216 ac->negotiating = false;
191 } 217 }
192 218
193 ret = ac->ops->handle_reply(ac, result, payload, payload_end); 219 ret = ac->ops->handle_reply(ac, result, payload, payload_end);
194 if (ret == -EAGAIN) { 220 if (ret == -EAGAIN) {
195 struct ceph_mon_request_header *monhdr = reply_buf; 221 return ceph_build_auth_request(ac, reply_buf, reply_len);
196 void *p = reply_buf + 1;
197 void *end = reply_buf + reply_len;
198
199 monhdr->have_version = 0;
200 monhdr->session_mon = cpu_to_le16(-1);
201 monhdr->session_mon_tid = 0;
202
203 ceph_encode_32(&p, ac->protocol);
204
205 ret = ac->ops->build_request(ac, p + sizeof(u32), end);
206 if (ret < 0) {
207 pr_err("error %d building request\n", ret);
208 goto out;
209 }
210 dout(" built request %d bytes\n", ret);
211 ceph_encode_32(&p, ret);
212 return p + ret - reply_buf;
213 } else if (ret) { 222 } else if (ret) {
214 pr_err("authentication error %d\n", ret); 223 pr_err("authentication error %d\n", ret);
215 return ret; 224 return ret;
@@ -222,4 +231,20 @@ out:
222 return ret; 231 return ret;
223} 232}
224 233
234int ceph_build_auth(struct ceph_auth_client *ac,
235 void *msg_buf, size_t msg_len)
236{
237 if (!ac->protocol)
238 return ceph_auth_build_hello(ac, msg_buf, msg_len);
239 BUG_ON(!ac->ops);
240 if (!ac->ops->is_authenticated(ac))
241 return ceph_build_auth_request(ac, msg_buf, msg_len);
242 return 0;
243}
225 244
245int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
246{
247 if (!ac->ops)
248 return 0;
249 return ac->ops->is_authenticated(ac);
250}
diff --git a/fs/ceph/auth.h b/fs/ceph/auth.h
index 4d8cdf6bb3b6..ca4f57cfb267 100644
--- a/fs/ceph/auth.h
+++ b/fs/ceph/auth.h
@@ -42,6 +42,8 @@ struct ceph_auth_client_ops {
42 struct ceph_authorizer *a, size_t len); 42 struct ceph_authorizer *a, size_t len);
43 void (*destroy_authorizer)(struct ceph_auth_client *ac, 43 void (*destroy_authorizer)(struct ceph_auth_client *ac,
44 struct ceph_authorizer *a); 44 struct ceph_authorizer *a);
45 void (*invalidate_authorizer)(struct ceph_auth_client *ac,
46 int peer_type);
45 47
46 /* reset when we (re)connect to a monitor */ 48 /* reset when we (re)connect to a monitor */
47 void (*reset)(struct ceph_auth_client *ac); 49 void (*reset)(struct ceph_auth_client *ac);
@@ -74,4 +76,9 @@ extern int ceph_handle_auth_reply(struct ceph_auth_client *ac,
74 void *reply_buf, size_t reply_len); 76 void *reply_buf, size_t reply_len);
75extern int ceph_entity_name_encode(const char *name, void **p, void *end); 77extern int ceph_entity_name_encode(const char *name, void **p, void *end);
76 78
79extern int ceph_build_auth(struct ceph_auth_client *ac,
80 void *msg_buf, size_t msg_len);
81
82extern int ceph_auth_is_authenticated(struct ceph_auth_client *ac);
83
77#endif 84#endif
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 4e3e8b229e67..aa8506bad42d 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2946,12 +2946,25 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len)
2946 return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len); 2946 return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len);
2947} 2947}
2948 2948
2949static int invalidate_authorizer(struct ceph_connection *con)
2950{
2951 struct ceph_mds_session *s = con->private;
2952 struct ceph_mds_client *mdsc = s->s_mdsc;
2953 struct ceph_auth_client *ac = mdsc->client->monc.auth;
2954
2955 if (ac->ops->invalidate_authorizer)
2956 ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS);
2957
2958 return ceph_monc_validate_auth(&mdsc->client->monc);
2959}
2960
2949const static struct ceph_connection_operations mds_con_ops = { 2961const static struct ceph_connection_operations mds_con_ops = {
2950 .get = con_get, 2962 .get = con_get,
2951 .put = con_put, 2963 .put = con_put,
2952 .dispatch = dispatch, 2964 .dispatch = dispatch,
2953 .get_authorizer = get_authorizer, 2965 .get_authorizer = get_authorizer,
2954 .verify_authorizer_reply = verify_authorizer_reply, 2966 .verify_authorizer_reply = verify_authorizer_reply,
2967 .invalidate_authorizer = invalidate_authorizer,
2955 .peer_reset = peer_reset, 2968 .peer_reset = peer_reset,
2956}; 2969};
2957 2970
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
index e4e8d4439d3a..c4341784ec8f 100644
--- a/fs/ceph/messenger.c
+++ b/fs/ceph/messenger.c
@@ -1849,6 +1849,15 @@ static void ceph_fault(struct ceph_connection *con)
1849 con->in_msg = NULL; 1849 con->in_msg = NULL;
1850 } 1850 }
1851 1851
1852 /*
1853 * in case we faulted due to authentication, invalidate our
1854 * current tickets so that we can get new ones.
1855 */
1856 if (con->auth_retry && con->ops->invalidate_authorizer) {
1857 dout("calling invalidate_authorizer()\n");
1858 con->ops->invalidate_authorizer(con);
1859 }
1860
1852 /* If there are no messages in the queue, place the connection 1861 /* If there are no messages in the queue, place the connection
1853 * in a STANDBY state (i.e., don't try to reconnect just yet). */ 1862 * in a STANDBY state (i.e., don't try to reconnect just yet). */
1854 if (list_empty(&con->out_queue) && !con->out_keepalive_pending) { 1863 if (list_empty(&con->out_queue) && !con->out_keepalive_pending) {
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h
index c26a3d8aa78c..c9735378be3f 100644
--- a/fs/ceph/messenger.h
+++ b/fs/ceph/messenger.h
@@ -32,6 +32,7 @@ struct ceph_connection_operations {
32 void **buf, int *len, int *proto, 32 void **buf, int *len, int *proto,
33 void **reply_buf, int *reply_len, int force_new); 33 void **reply_buf, int *reply_len, int force_new);
34 int (*verify_authorizer_reply) (struct ceph_connection *con, int len); 34 int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
35 int (*invalidate_authorizer)(struct ceph_connection *con);
35 36
36 /* protocol version mismatch */ 37 /* protocol version mismatch */
37 void (*bad_proto) (struct ceph_connection *con); 38 void (*bad_proto) (struct ceph_connection *con);
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
index 3f7ae7f73c50..fec41a0eff86 100644
--- a/fs/ceph/mon_client.c
+++ b/fs/ceph/mon_client.c
@@ -29,6 +29,8 @@
29 29
30const static struct ceph_connection_operations mon_con_ops; 30const static struct ceph_connection_operations mon_con_ops;
31 31
32static int __validate_auth(struct ceph_mon_client *monc);
33
32/* 34/*
33 * Decode a monmap blob (e.g., during mount). 35 * Decode a monmap blob (e.g., during mount).
34 */ 36 */
@@ -103,6 +105,7 @@ static void __close_session(struct ceph_mon_client *monc)
103 ceph_con_revoke(monc->con, monc->m_auth); 105 ceph_con_revoke(monc->con, monc->m_auth);
104 ceph_con_close(monc->con); 106 ceph_con_close(monc->con);
105 monc->cur_mon = -1; 107 monc->cur_mon = -1;
108 monc->pending_auth = 0;
106 ceph_auth_reset(monc->auth); 109 ceph_auth_reset(monc->auth);
107 } 110 }
108} 111}
@@ -334,7 +337,7 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
334 337
335out: 338out:
336 mutex_unlock(&monc->mutex); 339 mutex_unlock(&monc->mutex);
337 wake_up(&client->mount_wq); 340 wake_up(&client->auth_wq);
338} 341}
339 342
340/* 343/*
@@ -477,6 +480,11 @@ static void delayed_work(struct work_struct *work)
477 __open_session(monc); /* continue hunting */ 480 __open_session(monc); /* continue hunting */
478 } else { 481 } else {
479 ceph_con_keepalive(monc->con); 482 ceph_con_keepalive(monc->con);
483 mutex_unlock(&monc->mutex);
484
485 __validate_auth(monc);
486
487 mutex_lock(&monc->mutex);
480 if (monc->auth->ops->is_authenticated(monc->auth)) 488 if (monc->auth->ops->is_authenticated(monc->auth))
481 __send_subscribe(monc); 489 __send_subscribe(monc);
482 } 490 }
@@ -557,6 +565,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
557 goto out_pool2; 565 goto out_pool2;
558 566
559 monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, 0, 0, NULL); 567 monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, 0, 0, NULL);
568 monc->pending_auth = 0;
560 if (IS_ERR(monc->m_auth)) { 569 if (IS_ERR(monc->m_auth)) {
561 err = PTR_ERR(monc->m_auth); 570 err = PTR_ERR(monc->m_auth);
562 monc->m_auth = NULL; 571 monc->m_auth = NULL;
@@ -614,6 +623,15 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
614 kfree(monc->monmap); 623 kfree(monc->monmap);
615} 624}
616 625
626static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len)
627{
628 monc->pending_auth = 1;
629 monc->m_auth->front.iov_len = len;
630 monc->m_auth->hdr.front_len = cpu_to_le32(len);
631 ceph_msg_get(monc->m_auth); /* keep our ref */
632 ceph_con_send(monc->con, monc->m_auth);
633}
634
617 635
618static void handle_auth_reply(struct ceph_mon_client *monc, 636static void handle_auth_reply(struct ceph_mon_client *monc,
619 struct ceph_msg *msg) 637 struct ceph_msg *msg)
@@ -621,18 +639,16 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
621 int ret; 639 int ret;
622 640
623 mutex_lock(&monc->mutex); 641 mutex_lock(&monc->mutex);
642 monc->pending_auth = 0;
624 ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base, 643 ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
625 msg->front.iov_len, 644 msg->front.iov_len,
626 monc->m_auth->front.iov_base, 645 monc->m_auth->front.iov_base,
627 monc->m_auth->front_max); 646 monc->m_auth->front_max);
628 if (ret < 0) { 647 if (ret < 0) {
629 monc->client->mount_err = ret; 648 monc->client->auth_err = ret;
630 wake_up(&monc->client->mount_wq); 649 wake_up(&monc->client->auth_wq);
631 } else if (ret > 0) { 650 } else if (ret > 0) {
632 monc->m_auth->front.iov_len = ret; 651 __send_prepared_auth_request(monc, ret);
633 monc->m_auth->hdr.front_len = cpu_to_le32(ret);
634 ceph_msg_get(monc->m_auth); /* keep our ref */
635 ceph_con_send(monc->con, monc->m_auth);
636 } else if (monc->auth->ops->is_authenticated(monc->auth)) { 652 } else if (monc->auth->ops->is_authenticated(monc->auth)) {
637 dout("authenticated, starting session\n"); 653 dout("authenticated, starting session\n");
638 654
@@ -645,6 +661,31 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
645 mutex_unlock(&monc->mutex); 661 mutex_unlock(&monc->mutex);
646} 662}
647 663
664static int __validate_auth(struct ceph_mon_client *monc)
665{
666 int ret;
667
668 if (monc->pending_auth)
669 return 0;
670
671 ret = ceph_build_auth(monc->auth, monc->m_auth->front.iov_base,
672 monc->m_auth->front_max);
673 if (ret <= 0)
674 return ret; /* either an error, or no need to authenticate */
675 __send_prepared_auth_request(monc, ret);
676 return 0;
677}
678
679int ceph_monc_validate_auth(struct ceph_mon_client *monc)
680{
681 int ret;
682
683 mutex_lock(&monc->mutex);
684 ret = __validate_auth(monc);
685 mutex_unlock(&monc->mutex);
686 return ret;
687}
688
648/* 689/*
649 * handle incoming message 690 * handle incoming message
650 */ 691 */
diff --git a/fs/ceph/mon_client.h b/fs/ceph/mon_client.h
index c75b53302ecc..5ca8e48d4379 100644
--- a/fs/ceph/mon_client.h
+++ b/fs/ceph/mon_client.h
@@ -61,6 +61,7 @@ struct ceph_mon_client {
61 61
62 struct ceph_auth_client *auth; 62 struct ceph_auth_client *auth;
63 struct ceph_msg *m_auth; 63 struct ceph_msg *m_auth;
64 int pending_auth;
64 65
65 bool hunting; 66 bool hunting;
66 int cur_mon; /* last monitor i contacted */ 67 int cur_mon; /* last monitor i contacted */
@@ -110,6 +111,8 @@ extern int ceph_monc_do_statfs(struct ceph_mon_client *monc,
110 111
111extern int ceph_monc_open_session(struct ceph_mon_client *monc); 112extern int ceph_monc_open_session(struct ceph_mon_client *monc);
112 113
114extern int ceph_monc_validate_auth(struct ceph_mon_client *monc);
115
113 116
114 117
115#endif 118#endif
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c
index 944759b3079f..35c8afea13ec 100644
--- a/fs/ceph/osd_client.c
+++ b/fs/ceph/osd_client.c
@@ -1448,6 +1448,17 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len)
1448 return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len); 1448 return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len);
1449} 1449}
1450 1450
1451static int invalidate_authorizer(struct ceph_connection *con)
1452{
1453 struct ceph_osd *o = con->private;
1454 struct ceph_osd_client *osdc = o->o_osdc;
1455 struct ceph_auth_client *ac = osdc->client->monc.auth;
1456
1457 if (ac->ops->invalidate_authorizer)
1458 ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
1459
1460 return ceph_monc_validate_auth(&osdc->client->monc);
1461}
1451 1462
1452const static struct ceph_connection_operations osd_con_ops = { 1463const static struct ceph_connection_operations osd_con_ops = {
1453 .get = get_osd_con, 1464 .get = get_osd_con,
@@ -1455,6 +1466,7 @@ const static struct ceph_connection_operations osd_con_ops = {
1455 .dispatch = dispatch, 1466 .dispatch = dispatch,
1456 .get_authorizer = get_authorizer, 1467 .get_authorizer = get_authorizer,
1457 .verify_authorizer_reply = verify_authorizer_reply, 1468 .verify_authorizer_reply = verify_authorizer_reply,
1469 .invalidate_authorizer = invalidate_authorizer,
1458 .alloc_msg = alloc_msg, 1470 .alloc_msg = alloc_msg,
1459 .fault = osd_reset, 1471 .fault = osd_reset,
1460}; 1472};
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index cd81c84e96fc..3a2548951fe6 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -542,7 +542,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
542 542
543 mutex_init(&client->mount_mutex); 543 mutex_init(&client->mount_mutex);
544 544
545 init_waitqueue_head(&client->mount_wq); 545 init_waitqueue_head(&client->auth_wq);
546 546
547 client->sb = NULL; 547 client->sb = NULL;
548 client->mount_state = CEPH_MOUNT_MOUNTING; 548 client->mount_state = CEPH_MOUNT_MOUNTING;
@@ -550,7 +550,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
550 550
551 client->msgr = NULL; 551 client->msgr = NULL;
552 552
553 client->mount_err = 0; 553 client->auth_err = 0;
554 atomic_long_set(&client->writeback_count, 0); 554 atomic_long_set(&client->writeback_count, 0);
555 555
556 err = bdi_init(&client->backing_dev_info); 556 err = bdi_init(&client->backing_dev_info);
@@ -742,13 +742,13 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
742 742
743 /* wait */ 743 /* wait */
744 dout("mount waiting for mon_map\n"); 744 dout("mount waiting for mon_map\n");
745 err = wait_event_interruptible_timeout(client->mount_wq, /* FIXME */ 745 err = wait_event_interruptible_timeout(client->auth_wq,
746 have_mon_map(client) || (client->mount_err < 0), 746 have_mon_map(client) || (client->auth_err < 0),
747 timeout); 747 timeout);
748 if (err == -EINTR || err == -ERESTARTSYS) 748 if (err == -EINTR || err == -ERESTARTSYS)
749 goto out; 749 goto out;
750 if (client->mount_err < 0) { 750 if (client->auth_err < 0) {
751 err = client->mount_err; 751 err = client->auth_err;
752 goto out; 752 goto out;
753 } 753 }
754 } 754 }
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 62d9ae482d72..770f7b507fce 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -123,9 +123,9 @@ struct ceph_client {
123 struct super_block *sb; 123 struct super_block *sb;
124 124
125 unsigned long mount_state; 125 unsigned long mount_state;
126 wait_queue_head_t mount_wq; 126 wait_queue_head_t auth_wq;
127 127
128 int mount_err; 128 int auth_err;
129 129
130 struct ceph_messenger *msgr; /* messenger instance */ 130 struct ceph_messenger *msgr; /* messenger instance */
131 struct ceph_mon_client monc; 131 struct ceph_mon_client monc;