aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-11-04 03:33:37 -0500
committerIlya Dryomov <idryomov@redhat.com>2014-12-17 12:09:50 -0500
commit33d07337962c7bbd2fd5cf7f1106735c9507fbe2 (patch)
tree93a95e7d02db4d7ba7d282483e32fd0627a3c281
parentae385eaf24dc39c1703049112e4265b9f93b7d86 (diff)
libceph: message signature support
Signed-off-by: Yan, Zheng <zyan@redhat.com>
-rw-r--r--fs/ceph/mds_client.c16
-rw-r--r--include/linux/ceph/auth.h26
-rw-r--r--include/linux/ceph/ceph_features.h1
-rw-r--r--include/linux/ceph/messenger.h9
-rw-r--r--include/linux/ceph/msgr.h8
-rw-r--r--net/ceph/auth_x.c58
-rw-r--r--net/ceph/messenger.c32
-rw-r--r--net/ceph/osd_client.c16
8 files changed, 162 insertions, 4 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index fc74617069a3..9f00853f6d42 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -3744,6 +3744,20 @@ static struct ceph_msg *mds_alloc_msg(struct ceph_connection *con,
3744 return msg; 3744 return msg;
3745} 3745}
3746 3746
3747static int sign_message(struct ceph_connection *con, struct ceph_msg *msg)
3748{
3749 struct ceph_mds_session *s = con->private;
3750 struct ceph_auth_handshake *auth = &s->s_auth;
3751 return ceph_auth_sign_message(auth, msg);
3752}
3753
3754static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg)
3755{
3756 struct ceph_mds_session *s = con->private;
3757 struct ceph_auth_handshake *auth = &s->s_auth;
3758 return ceph_auth_check_message_signature(auth, msg);
3759}
3760
3747static const struct ceph_connection_operations mds_con_ops = { 3761static const struct ceph_connection_operations mds_con_ops = {
3748 .get = con_get, 3762 .get = con_get,
3749 .put = con_put, 3763 .put = con_put,
@@ -3753,6 +3767,8 @@ static const struct ceph_connection_operations mds_con_ops = {
3753 .invalidate_authorizer = invalidate_authorizer, 3767 .invalidate_authorizer = invalidate_authorizer,
3754 .peer_reset = peer_reset, 3768 .peer_reset = peer_reset,
3755 .alloc_msg = mds_alloc_msg, 3769 .alloc_msg = mds_alloc_msg,
3770 .sign_message = sign_message,
3771 .check_message_signature = check_message_signature,
3756}; 3772};
3757 3773
3758/* eof */ 3774/* eof */
diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h
index 5f3386844134..260d78b587c4 100644
--- a/include/linux/ceph/auth.h
+++ b/include/linux/ceph/auth.h
@@ -13,6 +13,7 @@
13 13
14struct ceph_auth_client; 14struct ceph_auth_client;
15struct ceph_authorizer; 15struct ceph_authorizer;
16struct ceph_msg;
16 17
17struct ceph_auth_handshake { 18struct ceph_auth_handshake {
18 struct ceph_authorizer *authorizer; 19 struct ceph_authorizer *authorizer;
@@ -20,6 +21,10 @@ struct ceph_auth_handshake {
20 size_t authorizer_buf_len; 21 size_t authorizer_buf_len;
21 void *authorizer_reply_buf; 22 void *authorizer_reply_buf;
22 size_t authorizer_reply_buf_len; 23 size_t authorizer_reply_buf_len;
24 int (*sign_message)(struct ceph_auth_handshake *auth,
25 struct ceph_msg *msg);
26 int (*check_message_signature)(struct ceph_auth_handshake *auth,
27 struct ceph_msg *msg);
23}; 28};
24 29
25struct ceph_auth_client_ops { 30struct ceph_auth_client_ops {
@@ -66,6 +71,11 @@ struct ceph_auth_client_ops {
66 void (*reset)(struct ceph_auth_client *ac); 71 void (*reset)(struct ceph_auth_client *ac);
67 72
68 void (*destroy)(struct ceph_auth_client *ac); 73 void (*destroy)(struct ceph_auth_client *ac);
74
75 int (*sign_message)(struct ceph_auth_handshake *auth,
76 struct ceph_msg *msg);
77 int (*check_message_signature)(struct ceph_auth_handshake *auth,
78 struct ceph_msg *msg);
69}; 79};
70 80
71struct ceph_auth_client { 81struct ceph_auth_client {
@@ -113,4 +123,20 @@ extern int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
113extern void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, 123extern void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac,
114 int peer_type); 124 int peer_type);
115 125
126static inline int ceph_auth_sign_message(struct ceph_auth_handshake *auth,
127 struct ceph_msg *msg)
128{
129 if (auth->sign_message)
130 return auth->sign_message(auth, msg);
131 return 0;
132}
133
134static inline
135int ceph_auth_check_message_signature(struct ceph_auth_handshake *auth,
136 struct ceph_msg *msg)
137{
138 if (auth->check_message_signature)
139 return auth->check_message_signature(auth, msg);
140 return 0;
141}
116#endif 142#endif
diff --git a/include/linux/ceph/ceph_features.h b/include/linux/ceph/ceph_features.h
index d12659ce550d..71e05bbf8ceb 100644
--- a/include/linux/ceph/ceph_features.h
+++ b/include/linux/ceph/ceph_features.h
@@ -84,6 +84,7 @@ static inline u64 ceph_sanitize_features(u64 features)
84 CEPH_FEATURE_PGPOOL3 | \ 84 CEPH_FEATURE_PGPOOL3 | \
85 CEPH_FEATURE_OSDENC | \ 85 CEPH_FEATURE_OSDENC | \
86 CEPH_FEATURE_CRUSH_TUNABLES | \ 86 CEPH_FEATURE_CRUSH_TUNABLES | \
87 CEPH_FEATURE_MSG_AUTH | \
87 CEPH_FEATURE_CRUSH_TUNABLES2 | \ 88 CEPH_FEATURE_CRUSH_TUNABLES2 | \
88 CEPH_FEATURE_REPLY_CREATE_INODE | \ 89 CEPH_FEATURE_REPLY_CREATE_INODE | \
89 CEPH_FEATURE_OSDHASHPSPOOL | \ 90 CEPH_FEATURE_OSDHASHPSPOOL | \
diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h
index 40ae58e3e9db..d9d396c16503 100644
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -42,6 +42,10 @@ struct ceph_connection_operations {
42 struct ceph_msg * (*alloc_msg) (struct ceph_connection *con, 42 struct ceph_msg * (*alloc_msg) (struct ceph_connection *con,
43 struct ceph_msg_header *hdr, 43 struct ceph_msg_header *hdr,
44 int *skip); 44 int *skip);
45 int (*sign_message) (struct ceph_connection *con, struct ceph_msg *msg);
46
47 int (*check_message_signature) (struct ceph_connection *con,
48 struct ceph_msg *msg);
45}; 49};
46 50
47/* use format string %s%d */ 51/* use format string %s%d */
@@ -142,7 +146,10 @@ struct ceph_msg_data_cursor {
142 */ 146 */
143struct ceph_msg { 147struct ceph_msg {
144 struct ceph_msg_header hdr; /* header */ 148 struct ceph_msg_header hdr; /* header */
145 struct ceph_msg_footer footer; /* footer */ 149 union {
150 struct ceph_msg_footer footer; /* footer */
151 struct ceph_msg_footer_old old_footer; /* old format footer */
152 };
146 struct kvec front; /* unaligned blobs of message */ 153 struct kvec front; /* unaligned blobs of message */
147 struct ceph_buffer *middle; 154 struct ceph_buffer *middle;
148 155
diff --git a/include/linux/ceph/msgr.h b/include/linux/ceph/msgr.h
index 3d94a73b5f30..cac4b28ac1c0 100644
--- a/include/linux/ceph/msgr.h
+++ b/include/linux/ceph/msgr.h
@@ -164,13 +164,21 @@ struct ceph_msg_header {
164/* 164/*
165 * follows data payload 165 * follows data payload
166 */ 166 */
167struct ceph_msg_footer_old {
168 __le32 front_crc, middle_crc, data_crc;
169 __u8 flags;
170} __attribute__ ((packed));
171
167struct ceph_msg_footer { 172struct ceph_msg_footer {
168 __le32 front_crc, middle_crc, data_crc; 173 __le32 front_crc, middle_crc, data_crc;
174 // sig holds the 64 bits of the digital signature for the message PLR
175 __le64 sig;
169 __u8 flags; 176 __u8 flags;
170} __attribute__ ((packed)); 177} __attribute__ ((packed));
171 178
172#define CEPH_MSG_FOOTER_COMPLETE (1<<0) /* msg wasn't aborted */ 179#define CEPH_MSG_FOOTER_COMPLETE (1<<0) /* msg wasn't aborted */
173#define CEPH_MSG_FOOTER_NOCRC (1<<1) /* no data crc */ 180#define CEPH_MSG_FOOTER_NOCRC (1<<1) /* no data crc */
181#define CEPH_MSG_FOOTER_SIGNED (1<<2) /* msg was signed */
174 182
175 183
176#endif 184#endif
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
index 77f3885c16bc..15845814a0f2 100644
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/ceph/decode.h> 9#include <linux/ceph/decode.h>
10#include <linux/ceph/auth.h> 10#include <linux/ceph/auth.h>
11#include <linux/ceph/messenger.h>
11 12
12#include "crypto.h" 13#include "crypto.h"
13#include "auth_x.h" 14#include "auth_x.h"
@@ -567,6 +568,8 @@ static int ceph_x_create_authorizer(
567 auth->authorizer_buf_len = au->buf->vec.iov_len; 568 auth->authorizer_buf_len = au->buf->vec.iov_len;
568 auth->authorizer_reply_buf = au->reply_buf; 569 auth->authorizer_reply_buf = au->reply_buf;
569 auth->authorizer_reply_buf_len = sizeof (au->reply_buf); 570 auth->authorizer_reply_buf_len = sizeof (au->reply_buf);
571 auth->sign_message = ac->ops->sign_message;
572 auth->check_message_signature = ac->ops->check_message_signature;
570 573
571 return 0; 574 return 0;
572} 575}
@@ -667,6 +670,59 @@ static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac,
667 memset(&th->validity, 0, sizeof(th->validity)); 670 memset(&th->validity, 0, sizeof(th->validity));
668} 671}
669 672
673static int calcu_signature(struct ceph_x_authorizer *au,
674 struct ceph_msg *msg, __le64 *sig)
675{
676 int ret;
677 char tmp_enc[40];
678 __le32 tmp[5] = {
679 16u, msg->hdr.crc, msg->footer.front_crc,
680 msg->footer.middle_crc, msg->footer.data_crc,
681 };
682 ret = ceph_x_encrypt(&au->session_key, &tmp, sizeof(tmp),
683 tmp_enc, sizeof(tmp_enc));
684 if (ret < 0)
685 return ret;
686 *sig = *(__le64*)(tmp_enc + 4);
687 return 0;
688}
689
690static int ceph_x_sign_message(struct ceph_auth_handshake *auth,
691 struct ceph_msg *msg)
692{
693 int ret;
694 if (!auth->authorizer)
695 return 0;
696 ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
697 msg, &msg->footer.sig);
698 if (ret < 0)
699 return ret;
700 msg->footer.flags |= CEPH_MSG_FOOTER_SIGNED;
701 return 0;
702}
703
704static int ceph_x_check_message_signature(struct ceph_auth_handshake *auth,
705 struct ceph_msg *msg)
706{
707 __le64 sig_check;
708 int ret;
709
710 if (!auth->authorizer)
711 return 0;
712 ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
713 msg, &sig_check);
714 if (ret < 0)
715 return ret;
716 if (sig_check == msg->footer.sig)
717 return 0;
718 if (msg->footer.flags & CEPH_MSG_FOOTER_SIGNED)
719 dout("ceph_x_check_message_signature %p has signature %llx "
720 "expect %llx\n", msg, msg->footer.sig, sig_check);
721 else
722 dout("ceph_x_check_message_signature %p sender did not set "
723 "CEPH_MSG_FOOTER_SIGNED\n", msg);
724 return -EBADMSG;
725}
670 726
671static const struct ceph_auth_client_ops ceph_x_ops = { 727static const struct ceph_auth_client_ops ceph_x_ops = {
672 .name = "x", 728 .name = "x",
@@ -681,6 +737,8 @@ static const struct ceph_auth_client_ops ceph_x_ops = {
681 .invalidate_authorizer = ceph_x_invalidate_authorizer, 737 .invalidate_authorizer = ceph_x_invalidate_authorizer,
682 .reset = ceph_x_reset, 738 .reset = ceph_x_reset,
683 .destroy = ceph_x_destroy, 739 .destroy = ceph_x_destroy,
740 .sign_message = ceph_x_sign_message,
741 .check_message_signature = ceph_x_check_message_signature,
684}; 742};
685 743
686 744
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 863d07ab2129..33a2f201e460 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1196,8 +1196,18 @@ static void prepare_write_message_footer(struct ceph_connection *con)
1196 dout("prepare_write_message_footer %p\n", con); 1196 dout("prepare_write_message_footer %p\n", con);
1197 con->out_kvec_is_msg = true; 1197 con->out_kvec_is_msg = true;
1198 con->out_kvec[v].iov_base = &m->footer; 1198 con->out_kvec[v].iov_base = &m->footer;
1199 con->out_kvec[v].iov_len = sizeof(m->footer); 1199 if (con->peer_features & CEPH_FEATURE_MSG_AUTH) {
1200 con->out_kvec_bytes += sizeof(m->footer); 1200 if (con->ops->sign_message)
1201 con->ops->sign_message(con, m);
1202 else
1203 m->footer.sig = 0;
1204 con->out_kvec[v].iov_len = sizeof(m->footer);
1205 con->out_kvec_bytes += sizeof(m->footer);
1206 } else {
1207 m->old_footer.flags = m->footer.flags;
1208 con->out_kvec[v].iov_len = sizeof(m->old_footer);
1209 con->out_kvec_bytes += sizeof(m->old_footer);
1210 }
1201 con->out_kvec_left++; 1211 con->out_kvec_left++;
1202 con->out_more = m->more_to_follow; 1212 con->out_more = m->more_to_follow;
1203 con->out_msg_done = true; 1213 con->out_msg_done = true;
@@ -2249,6 +2259,7 @@ static int read_partial_message(struct ceph_connection *con)
2249 int ret; 2259 int ret;
2250 unsigned int front_len, middle_len, data_len; 2260 unsigned int front_len, middle_len, data_len;
2251 bool do_datacrc = !con->msgr->nocrc; 2261 bool do_datacrc = !con->msgr->nocrc;
2262 bool need_sign = (con->peer_features & CEPH_FEATURE_MSG_AUTH);
2252 u64 seq; 2263 u64 seq;
2253 u32 crc; 2264 u32 crc;
2254 2265
@@ -2361,12 +2372,21 @@ static int read_partial_message(struct ceph_connection *con)
2361 } 2372 }
2362 2373
2363 /* footer */ 2374 /* footer */
2364 size = sizeof (m->footer); 2375 if (need_sign)
2376 size = sizeof(m->footer);
2377 else
2378 size = sizeof(m->old_footer);
2379
2365 end += size; 2380 end += size;
2366 ret = read_partial(con, end, size, &m->footer); 2381 ret = read_partial(con, end, size, &m->footer);
2367 if (ret <= 0) 2382 if (ret <= 0)
2368 return ret; 2383 return ret;
2369 2384
2385 if (!need_sign) {
2386 m->footer.flags = m->old_footer.flags;
2387 m->footer.sig = 0;
2388 }
2389
2370 dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n", 2390 dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n",
2371 m, front_len, m->footer.front_crc, middle_len, 2391 m, front_len, m->footer.front_crc, middle_len,
2372 m->footer.middle_crc, data_len, m->footer.data_crc); 2392 m->footer.middle_crc, data_len, m->footer.data_crc);
@@ -2390,6 +2410,12 @@ static int read_partial_message(struct ceph_connection *con)
2390 return -EBADMSG; 2410 return -EBADMSG;
2391 } 2411 }
2392 2412
2413 if (need_sign && con->ops->check_message_signature &&
2414 con->ops->check_message_signature(con, m)) {
2415 pr_err("read_partial_message %p signature check failed\n", m);
2416 return -EBADMSG;
2417 }
2418
2393 return 1; /* done! */ 2419 return 1; /* done! */
2394} 2420}
2395 2421
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 6f164289bde8..1f6c4055adaf 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2920,6 +2920,20 @@ static int invalidate_authorizer(struct ceph_connection *con)
2920 return ceph_monc_validate_auth(&osdc->client->monc); 2920 return ceph_monc_validate_auth(&osdc->client->monc);
2921} 2921}
2922 2922
2923static int sign_message(struct ceph_connection *con, struct ceph_msg *msg)
2924{
2925 struct ceph_osd *o = con->private;
2926 struct ceph_auth_handshake *auth = &o->o_auth;
2927 return ceph_auth_sign_message(auth, msg);
2928}
2929
2930static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg)
2931{
2932 struct ceph_osd *o = con->private;
2933 struct ceph_auth_handshake *auth = &o->o_auth;
2934 return ceph_auth_check_message_signature(auth, msg);
2935}
2936
2923static const struct ceph_connection_operations osd_con_ops = { 2937static const struct ceph_connection_operations osd_con_ops = {
2924 .get = get_osd_con, 2938 .get = get_osd_con,
2925 .put = put_osd_con, 2939 .put = put_osd_con,
@@ -2928,5 +2942,7 @@ static const struct ceph_connection_operations osd_con_ops = {
2928 .verify_authorizer_reply = verify_authorizer_reply, 2942 .verify_authorizer_reply = verify_authorizer_reply,
2929 .invalidate_authorizer = invalidate_authorizer, 2943 .invalidate_authorizer = invalidate_authorizer,
2930 .alloc_msg = alloc_msg, 2944 .alloc_msg = alloc_msg,
2945 .sign_message = sign_message,
2946 .check_message_signature = check_message_signature,
2931 .fault = osd_reset, 2947 .fault = osd_reset,
2932}; 2948};