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; | ||||
| } | ||||
| 
 | ||||
| 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 = { | ||||
| 	.get = con_get, | ||||
| 	.put = con_put, | ||||
|  | @ -3753,6 +3767,8 @@ static const struct ceph_connection_operations mds_con_ops = { | |||
| 	.invalidate_authorizer = invalidate_authorizer, | ||||
| 	.peer_reset = peer_reset, | ||||
| 	.alloc_msg = mds_alloc_msg, | ||||
| 	.sign_message = sign_message, | ||||
| 	.check_message_signature = check_message_signature, | ||||
| }; | ||||
| 
 | ||||
| /* eof */ | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| 
 | ||||
| struct ceph_auth_client; | ||||
| struct ceph_authorizer; | ||||
| struct ceph_msg; | ||||
| 
 | ||||
| struct ceph_auth_handshake { | ||||
| 	struct ceph_authorizer *authorizer; | ||||
|  | @ -20,6 +21,10 @@ struct ceph_auth_handshake { | |||
| 	size_t authorizer_buf_len; | ||||
| 	void *authorizer_reply_buf; | ||||
| 	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 { | ||||
|  | @ -66,6 +71,11 @@ struct ceph_auth_client_ops { | |||
| 	void (*reset)(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 { | ||||
|  | @ -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, | ||||
| 					    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 | ||||
|  |  | |||
|  | @ -84,6 +84,7 @@ static inline u64 ceph_sanitize_features(u64 features) | |||
| 	 CEPH_FEATURE_PGPOOL3 |			\ | ||||
| 	 CEPH_FEATURE_OSDENC |			\ | ||||
| 	 CEPH_FEATURE_CRUSH_TUNABLES |		\ | ||||
| 	 CEPH_FEATURE_MSG_AUTH |		\ | ||||
| 	 CEPH_FEATURE_CRUSH_TUNABLES2 |		\ | ||||
| 	 CEPH_FEATURE_REPLY_CREATE_INODE |	\ | ||||
| 	 CEPH_FEATURE_OSDHASHPSPOOL |		\ | ||||
|  |  | |||
|  | @ -42,6 +42,10 @@ struct ceph_connection_operations { | |||
| 	struct ceph_msg * (*alloc_msg) (struct ceph_connection *con, | ||||
| 					struct ceph_msg_header *hdr, | ||||
| 					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 */ | ||||
|  | @ -142,7 +146,10 @@ struct ceph_msg_data_cursor { | |||
|  */ | ||||
| struct ceph_msg { | ||||
| 	struct ceph_msg_header hdr;	/* header */ | ||||
| 	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 ceph_buffer *middle; | ||||
| 
 | ||||
|  |  | |||
|  | @ -164,13 +164,21 @@ struct ceph_msg_header { | |||
| /*
 | ||||
|  * follows data payload | ||||
|  */ | ||||
| struct ceph_msg_footer_old { | ||||
| 	__le32 front_crc, middle_crc, data_crc; | ||||
| 	__u8 flags; | ||||
| } __attribute__ ((packed)); | ||||
| 
 | ||||
| struct ceph_msg_footer { | ||||
| 	__le32 front_crc, middle_crc, data_crc; | ||||
| 	// sig holds the 64 bits of the digital signature for the message PLR
 | ||||
| 	__le64  sig; | ||||
| 	__u8 flags; | ||||
| } __attribute__ ((packed)); | ||||
| 
 | ||||
| #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_SIGNED	  (1<<2)   /* msg was signed */ | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| 
 | ||||
| #include <linux/ceph/decode.h> | ||||
| #include <linux/ceph/auth.h> | ||||
| #include <linux/ceph/messenger.h> | ||||
| 
 | ||||
| #include "crypto.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_reply_buf = 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; | ||||
| } | ||||
|  | @ -667,6 +670,59 @@ static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac, | |||
| 		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 = { | ||||
| 	.name = "x", | ||||
|  | @ -681,6 +737,8 @@ static const struct ceph_auth_client_ops ceph_x_ops = { | |||
| 	.invalidate_authorizer = ceph_x_invalidate_authorizer, | ||||
| 	.reset =  ceph_x_reset, | ||||
| 	.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); | ||||
| 	con->out_kvec_is_msg = true; | ||||
| 	con->out_kvec[v].iov_base = &m->footer; | ||||
| 	if (con->peer_features & CEPH_FEATURE_MSG_AUTH) { | ||||
| 		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_more = m->more_to_follow; | ||||
| 	con->out_msg_done = true; | ||||
|  | @ -2249,6 +2259,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 	int ret; | ||||
| 	unsigned int front_len, middle_len, data_len; | ||||
| 	bool do_datacrc = !con->msgr->nocrc; | ||||
| 	bool need_sign = (con->peer_features & CEPH_FEATURE_MSG_AUTH); | ||||
| 	u64 seq; | ||||
| 	u32 crc; | ||||
| 
 | ||||
|  | @ -2361,12 +2372,21 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 	} | ||||
| 
 | ||||
| 	/* footer */ | ||||
| 	size = sizeof (m->footer); | ||||
| 	if (need_sign) | ||||
| 		size = sizeof(m->footer); | ||||
| 	else | ||||
| 		size = sizeof(m->old_footer); | ||||
| 
 | ||||
| 	end += size; | ||||
| 	ret = read_partial(con, end, size, &m->footer); | ||||
| 	if (ret <= 0) | ||||
| 		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", | ||||
| 	     m, front_len, m->footer.front_crc, middle_len, | ||||
| 	     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; | ||||
| 	} | ||||
| 
 | ||||
| 	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! */ | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2920,6 +2920,20 @@ static int invalidate_authorizer(struct ceph_connection *con) | |||
| 	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 = { | ||||
| 	.get = get_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, | ||||
| 	.invalidate_authorizer = invalidate_authorizer, | ||||
| 	.alloc_msg = alloc_msg, | ||||
| 	.sign_message = sign_message, | ||||
| 	.check_message_signature = check_message_signature, | ||||
| 	.fault = osd_reset, | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Yan, Zheng
				Yan, Zheng