libceph: message signature support
Signed-off-by: Yan, Zheng <zyan@redhat.com>
This commit is contained in:
		
					parent
					
						
							
								ae385eaf24
							
						
					
				
			
			
				commit
				
					
						33d0733796
					
				
			
		
					 8 changed files with 162 additions and 4 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Yan, Zheng
				Yan, Zheng