libceph: message signature support
Signed-off-by: Yan, Zheng <zyan@redhat.com>
This commit is contained in:
parent
ae385eaf24
commit
33d0733796
@ -3744,6 +3744,20 @@ static struct ceph_msg *mds_alloc_msg(struct ceph_connection *con,
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sign_message(struct ceph_connection *con, struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
struct ceph_mds_session *s = con->private;
|
||||||
|
struct ceph_auth_handshake *auth = &s->s_auth;
|
||||||
|
return ceph_auth_sign_message(auth, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
struct ceph_mds_session *s = con->private;
|
||||||
|
struct ceph_auth_handshake *auth = &s->s_auth;
|
||||||
|
return ceph_auth_check_message_signature(auth, msg);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ceph_connection_operations mds_con_ops = {
|
static const struct ceph_connection_operations mds_con_ops = {
|
||||||
.get = con_get,
|
.get = con_get,
|
||||||
.put = con_put,
|
.put = con_put,
|
||||||
@ -3753,6 +3767,8 @@ static const struct ceph_connection_operations mds_con_ops = {
|
|||||||
.invalidate_authorizer = invalidate_authorizer,
|
.invalidate_authorizer = invalidate_authorizer,
|
||||||
.peer_reset = peer_reset,
|
.peer_reset = peer_reset,
|
||||||
.alloc_msg = mds_alloc_msg,
|
.alloc_msg = mds_alloc_msg,
|
||||||
|
.sign_message = sign_message,
|
||||||
|
.check_message_signature = check_message_signature,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* eof */
|
/* eof */
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
struct ceph_auth_client;
|
struct ceph_auth_client;
|
||||||
struct ceph_authorizer;
|
struct ceph_authorizer;
|
||||||
|
struct ceph_msg;
|
||||||
|
|
||||||
struct ceph_auth_handshake {
|
struct ceph_auth_handshake {
|
||||||
struct ceph_authorizer *authorizer;
|
struct ceph_authorizer *authorizer;
|
||||||
@ -20,6 +21,10 @@ struct ceph_auth_handshake {
|
|||||||
size_t authorizer_buf_len;
|
size_t authorizer_buf_len;
|
||||||
void *authorizer_reply_buf;
|
void *authorizer_reply_buf;
|
||||||
size_t authorizer_reply_buf_len;
|
size_t authorizer_reply_buf_len;
|
||||||
|
int (*sign_message)(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg);
|
||||||
|
int (*check_message_signature)(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ceph_auth_client_ops {
|
struct ceph_auth_client_ops {
|
||||||
@ -66,6 +71,11 @@ struct ceph_auth_client_ops {
|
|||||||
void (*reset)(struct ceph_auth_client *ac);
|
void (*reset)(struct ceph_auth_client *ac);
|
||||||
|
|
||||||
void (*destroy)(struct ceph_auth_client *ac);
|
void (*destroy)(struct ceph_auth_client *ac);
|
||||||
|
|
||||||
|
int (*sign_message)(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg);
|
||||||
|
int (*check_message_signature)(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ceph_auth_client {
|
struct ceph_auth_client {
|
||||||
@ -113,4 +123,20 @@ extern int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
|
|||||||
extern void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac,
|
extern void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac,
|
||||||
int peer_type);
|
int peer_type);
|
||||||
|
|
||||||
|
static inline int ceph_auth_sign_message(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
if (auth->sign_message)
|
||||||
|
return auth->sign_message(auth, msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ceph_auth_check_message_signature(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
if (auth->check_message_signature)
|
||||||
|
return auth->check_message_signature(auth, msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,6 +84,7 @@ static inline u64 ceph_sanitize_features(u64 features)
|
|||||||
CEPH_FEATURE_PGPOOL3 | \
|
CEPH_FEATURE_PGPOOL3 | \
|
||||||
CEPH_FEATURE_OSDENC | \
|
CEPH_FEATURE_OSDENC | \
|
||||||
CEPH_FEATURE_CRUSH_TUNABLES | \
|
CEPH_FEATURE_CRUSH_TUNABLES | \
|
||||||
|
CEPH_FEATURE_MSG_AUTH | \
|
||||||
CEPH_FEATURE_CRUSH_TUNABLES2 | \
|
CEPH_FEATURE_CRUSH_TUNABLES2 | \
|
||||||
CEPH_FEATURE_REPLY_CREATE_INODE | \
|
CEPH_FEATURE_REPLY_CREATE_INODE | \
|
||||||
CEPH_FEATURE_OSDHASHPSPOOL | \
|
CEPH_FEATURE_OSDHASHPSPOOL | \
|
||||||
|
@ -42,6 +42,10 @@ struct ceph_connection_operations {
|
|||||||
struct ceph_msg * (*alloc_msg) (struct ceph_connection *con,
|
struct ceph_msg * (*alloc_msg) (struct ceph_connection *con,
|
||||||
struct ceph_msg_header *hdr,
|
struct ceph_msg_header *hdr,
|
||||||
int *skip);
|
int *skip);
|
||||||
|
int (*sign_message) (struct ceph_connection *con, struct ceph_msg *msg);
|
||||||
|
|
||||||
|
int (*check_message_signature) (struct ceph_connection *con,
|
||||||
|
struct ceph_msg *msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* use format string %s%d */
|
/* use format string %s%d */
|
||||||
@ -142,7 +146,10 @@ struct ceph_msg_data_cursor {
|
|||||||
*/
|
*/
|
||||||
struct ceph_msg {
|
struct ceph_msg {
|
||||||
struct ceph_msg_header hdr; /* header */
|
struct ceph_msg_header hdr; /* header */
|
||||||
struct ceph_msg_footer footer; /* footer */
|
union {
|
||||||
|
struct ceph_msg_footer footer; /* footer */
|
||||||
|
struct ceph_msg_footer_old old_footer; /* old format footer */
|
||||||
|
};
|
||||||
struct kvec front; /* unaligned blobs of message */
|
struct kvec front; /* unaligned blobs of message */
|
||||||
struct ceph_buffer *middle;
|
struct ceph_buffer *middle;
|
||||||
|
|
||||||
|
@ -164,13 +164,21 @@ struct ceph_msg_header {
|
|||||||
/*
|
/*
|
||||||
* follows data payload
|
* follows data payload
|
||||||
*/
|
*/
|
||||||
|
struct ceph_msg_footer_old {
|
||||||
|
__le32 front_crc, middle_crc, data_crc;
|
||||||
|
__u8 flags;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct ceph_msg_footer {
|
struct ceph_msg_footer {
|
||||||
__le32 front_crc, middle_crc, data_crc;
|
__le32 front_crc, middle_crc, data_crc;
|
||||||
|
// sig holds the 64 bits of the digital signature for the message PLR
|
||||||
|
__le64 sig;
|
||||||
__u8 flags;
|
__u8 flags;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define CEPH_MSG_FOOTER_COMPLETE (1<<0) /* msg wasn't aborted */
|
#define CEPH_MSG_FOOTER_COMPLETE (1<<0) /* msg wasn't aborted */
|
||||||
#define CEPH_MSG_FOOTER_NOCRC (1<<1) /* no data crc */
|
#define CEPH_MSG_FOOTER_NOCRC (1<<1) /* no data crc */
|
||||||
|
#define CEPH_MSG_FOOTER_SIGNED (1<<2) /* msg was signed */
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/ceph/decode.h>
|
#include <linux/ceph/decode.h>
|
||||||
#include <linux/ceph/auth.h>
|
#include <linux/ceph/auth.h>
|
||||||
|
#include <linux/ceph/messenger.h>
|
||||||
|
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "auth_x.h"
|
#include "auth_x.h"
|
||||||
@ -567,6 +568,8 @@ static int ceph_x_create_authorizer(
|
|||||||
auth->authorizer_buf_len = au->buf->vec.iov_len;
|
auth->authorizer_buf_len = au->buf->vec.iov_len;
|
||||||
auth->authorizer_reply_buf = au->reply_buf;
|
auth->authorizer_reply_buf = au->reply_buf;
|
||||||
auth->authorizer_reply_buf_len = sizeof (au->reply_buf);
|
auth->authorizer_reply_buf_len = sizeof (au->reply_buf);
|
||||||
|
auth->sign_message = ac->ops->sign_message;
|
||||||
|
auth->check_message_signature = ac->ops->check_message_signature;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -667,6 +670,59 @@ static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac,
|
|||||||
memset(&th->validity, 0, sizeof(th->validity));
|
memset(&th->validity, 0, sizeof(th->validity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int calcu_signature(struct ceph_x_authorizer *au,
|
||||||
|
struct ceph_msg *msg, __le64 *sig)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char tmp_enc[40];
|
||||||
|
__le32 tmp[5] = {
|
||||||
|
16u, msg->hdr.crc, msg->footer.front_crc,
|
||||||
|
msg->footer.middle_crc, msg->footer.data_crc,
|
||||||
|
};
|
||||||
|
ret = ceph_x_encrypt(&au->session_key, &tmp, sizeof(tmp),
|
||||||
|
tmp_enc, sizeof(tmp_enc));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
*sig = *(__le64*)(tmp_enc + 4);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ceph_x_sign_message(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if (!auth->authorizer)
|
||||||
|
return 0;
|
||||||
|
ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
|
||||||
|
msg, &msg->footer.sig);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
msg->footer.flags |= CEPH_MSG_FOOTER_SIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ceph_x_check_message_signature(struct ceph_auth_handshake *auth,
|
||||||
|
struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
__le64 sig_check;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!auth->authorizer)
|
||||||
|
return 0;
|
||||||
|
ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
|
||||||
|
msg, &sig_check);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (sig_check == msg->footer.sig)
|
||||||
|
return 0;
|
||||||
|
if (msg->footer.flags & CEPH_MSG_FOOTER_SIGNED)
|
||||||
|
dout("ceph_x_check_message_signature %p has signature %llx "
|
||||||
|
"expect %llx\n", msg, msg->footer.sig, sig_check);
|
||||||
|
else
|
||||||
|
dout("ceph_x_check_message_signature %p sender did not set "
|
||||||
|
"CEPH_MSG_FOOTER_SIGNED\n", msg);
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ceph_auth_client_ops ceph_x_ops = {
|
static const struct ceph_auth_client_ops ceph_x_ops = {
|
||||||
.name = "x",
|
.name = "x",
|
||||||
@ -681,6 +737,8 @@ static const struct ceph_auth_client_ops ceph_x_ops = {
|
|||||||
.invalidate_authorizer = ceph_x_invalidate_authorizer,
|
.invalidate_authorizer = ceph_x_invalidate_authorizer,
|
||||||
.reset = ceph_x_reset,
|
.reset = ceph_x_reset,
|
||||||
.destroy = ceph_x_destroy,
|
.destroy = ceph_x_destroy,
|
||||||
|
.sign_message = ceph_x_sign_message,
|
||||||
|
.check_message_signature = ceph_x_check_message_signature,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1196,8 +1196,18 @@ static void prepare_write_message_footer(struct ceph_connection *con)
|
|||||||
dout("prepare_write_message_footer %p\n", con);
|
dout("prepare_write_message_footer %p\n", con);
|
||||||
con->out_kvec_is_msg = true;
|
con->out_kvec_is_msg = true;
|
||||||
con->out_kvec[v].iov_base = &m->footer;
|
con->out_kvec[v].iov_base = &m->footer;
|
||||||
con->out_kvec[v].iov_len = sizeof(m->footer);
|
if (con->peer_features & CEPH_FEATURE_MSG_AUTH) {
|
||||||
con->out_kvec_bytes += sizeof(m->footer);
|
if (con->ops->sign_message)
|
||||||
|
con->ops->sign_message(con, m);
|
||||||
|
else
|
||||||
|
m->footer.sig = 0;
|
||||||
|
con->out_kvec[v].iov_len = sizeof(m->footer);
|
||||||
|
con->out_kvec_bytes += sizeof(m->footer);
|
||||||
|
} else {
|
||||||
|
m->old_footer.flags = m->footer.flags;
|
||||||
|
con->out_kvec[v].iov_len = sizeof(m->old_footer);
|
||||||
|
con->out_kvec_bytes += sizeof(m->old_footer);
|
||||||
|
}
|
||||||
con->out_kvec_left++;
|
con->out_kvec_left++;
|
||||||
con->out_more = m->more_to_follow;
|
con->out_more = m->more_to_follow;
|
||||||
con->out_msg_done = true;
|
con->out_msg_done = true;
|
||||||
@ -2249,6 +2259,7 @@ static int read_partial_message(struct ceph_connection *con)
|
|||||||
int ret;
|
int ret;
|
||||||
unsigned int front_len, middle_len, data_len;
|
unsigned int front_len, middle_len, data_len;
|
||||||
bool do_datacrc = !con->msgr->nocrc;
|
bool do_datacrc = !con->msgr->nocrc;
|
||||||
|
bool need_sign = (con->peer_features & CEPH_FEATURE_MSG_AUTH);
|
||||||
u64 seq;
|
u64 seq;
|
||||||
u32 crc;
|
u32 crc;
|
||||||
|
|
||||||
@ -2361,12 +2372,21 @@ static int read_partial_message(struct ceph_connection *con)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* footer */
|
/* footer */
|
||||||
size = sizeof (m->footer);
|
if (need_sign)
|
||||||
|
size = sizeof(m->footer);
|
||||||
|
else
|
||||||
|
size = sizeof(m->old_footer);
|
||||||
|
|
||||||
end += size;
|
end += size;
|
||||||
ret = read_partial(con, end, size, &m->footer);
|
ret = read_partial(con, end, size, &m->footer);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (!need_sign) {
|
||||||
|
m->footer.flags = m->old_footer.flags;
|
||||||
|
m->footer.sig = 0;
|
||||||
|
}
|
||||||
|
|
||||||
dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n",
|
dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n",
|
||||||
m, front_len, m->footer.front_crc, middle_len,
|
m, front_len, m->footer.front_crc, middle_len,
|
||||||
m->footer.middle_crc, data_len, m->footer.data_crc);
|
m->footer.middle_crc, data_len, m->footer.data_crc);
|
||||||
@ -2390,6 +2410,12 @@ static int read_partial_message(struct ceph_connection *con)
|
|||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (need_sign && con->ops->check_message_signature &&
|
||||||
|
con->ops->check_message_signature(con, m)) {
|
||||||
|
pr_err("read_partial_message %p signature check failed\n", m);
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
|
||||||
return 1; /* done! */
|
return 1; /* done! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2920,6 +2920,20 @@ static int invalidate_authorizer(struct ceph_connection *con)
|
|||||||
return ceph_monc_validate_auth(&osdc->client->monc);
|
return ceph_monc_validate_auth(&osdc->client->monc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sign_message(struct ceph_connection *con, struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
struct ceph_osd *o = con->private;
|
||||||
|
struct ceph_auth_handshake *auth = &o->o_auth;
|
||||||
|
return ceph_auth_sign_message(auth, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg)
|
||||||
|
{
|
||||||
|
struct ceph_osd *o = con->private;
|
||||||
|
struct ceph_auth_handshake *auth = &o->o_auth;
|
||||||
|
return ceph_auth_check_message_signature(auth, msg);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ceph_connection_operations osd_con_ops = {
|
static const struct ceph_connection_operations osd_con_ops = {
|
||||||
.get = get_osd_con,
|
.get = get_osd_con,
|
||||||
.put = put_osd_con,
|
.put = put_osd_con,
|
||||||
@ -2928,5 +2942,7 @@ static const struct ceph_connection_operations osd_con_ops = {
|
|||||||
.verify_authorizer_reply = verify_authorizer_reply,
|
.verify_authorizer_reply = verify_authorizer_reply,
|
||||||
.invalidate_authorizer = invalidate_authorizer,
|
.invalidate_authorizer = invalidate_authorizer,
|
||||||
.alloc_msg = alloc_msg,
|
.alloc_msg = alloc_msg,
|
||||||
|
.sign_message = sign_message,
|
||||||
|
.check_message_signature = check_message_signature,
|
||||||
.fault = osd_reset,
|
.fault = osd_reset,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user