mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	libceph, ceph: implement msgr2.1 protocol (crc and secure modes)
Implement msgr2.1 wire protocol, available since nautilus 14.2.11 and octopus 15.2.5. msgr2.0 wire protocol is not implemented -- it has several security, integrity and robustness issues and therefore considered deprecated. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
		
							parent
							
								
									00498b9941
								
							
						
					
					
						commit
						cd1a677cad
					
				
					 15 changed files with 4356 additions and 31 deletions
				
			
		| 
						 | 
				
			
			@ -5014,7 +5014,7 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newmap = ceph_mdsmap_decode(&p, end, false);
 | 
			
		||||
	newmap = ceph_mdsmap_decode(&p, end, ceph_msgr2(mdsc->fsc->client));
 | 
			
		||||
	if (IS_ERR(newmap)) {
 | 
			
		||||
		err = PTR_ERR(newmap);
 | 
			
		||||
		goto bad_unlock;
 | 
			
		||||
| 
						 | 
				
			
			@ -5196,6 +5196,80 @@ static int invalidate_authorizer(struct ceph_connection *con)
 | 
			
		|||
	return ceph_monc_validate_auth(&mdsc->fsc->client->monc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mds_get_auth_request(struct ceph_connection *con,
 | 
			
		||||
				void *buf, int *buf_len,
 | 
			
		||||
				void **authorizer, int *authorizer_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mds_session *s = con->private;
 | 
			
		||||
	struct ceph_auth_client *ac = s->s_mdsc->fsc->client->monc.auth;
 | 
			
		||||
	struct ceph_auth_handshake *auth = &s->s_auth;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = ceph_auth_get_authorizer(ac, auth, CEPH_ENTITY_TYPE_MDS,
 | 
			
		||||
				       buf, buf_len);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	*authorizer = auth->authorizer_buf;
 | 
			
		||||
	*authorizer_len = auth->authorizer_buf_len;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mds_handle_auth_reply_more(struct ceph_connection *con,
 | 
			
		||||
				      void *reply, int reply_len,
 | 
			
		||||
				      void *buf, int *buf_len,
 | 
			
		||||
				      void **authorizer, int *authorizer_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mds_session *s = con->private;
 | 
			
		||||
	struct ceph_auth_client *ac = s->s_mdsc->fsc->client->monc.auth;
 | 
			
		||||
	struct ceph_auth_handshake *auth = &s->s_auth;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = ceph_auth_handle_svc_reply_more(ac, auth, reply, reply_len,
 | 
			
		||||
					      buf, buf_len);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	*authorizer = auth->authorizer_buf;
 | 
			
		||||
	*authorizer_len = auth->authorizer_buf_len;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mds_handle_auth_done(struct ceph_connection *con,
 | 
			
		||||
				u64 global_id, void *reply, int reply_len,
 | 
			
		||||
				u8 *session_key, int *session_key_len,
 | 
			
		||||
				u8 *con_secret, int *con_secret_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mds_session *s = con->private;
 | 
			
		||||
	struct ceph_auth_client *ac = s->s_mdsc->fsc->client->monc.auth;
 | 
			
		||||
	struct ceph_auth_handshake *auth = &s->s_auth;
 | 
			
		||||
 | 
			
		||||
	return ceph_auth_handle_svc_reply_done(ac, auth, reply, reply_len,
 | 
			
		||||
					       session_key, session_key_len,
 | 
			
		||||
					       con_secret, con_secret_len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mds_handle_auth_bad_method(struct ceph_connection *con,
 | 
			
		||||
				      int used_proto, int result,
 | 
			
		||||
				      const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				      const int *allowed_modes, int mode_cnt)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mds_session *s = con->private;
 | 
			
		||||
	struct ceph_mon_client *monc = &s->s_mdsc->fsc->client->monc;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (ceph_auth_handle_bad_authorizer(monc->auth, CEPH_ENTITY_TYPE_MDS,
 | 
			
		||||
					    used_proto, result,
 | 
			
		||||
					    allowed_protos, proto_cnt,
 | 
			
		||||
					    allowed_modes, mode_cnt)) {
 | 
			
		||||
		ret = ceph_monc_validate_auth(monc);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -EACCES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct ceph_msg *mds_alloc_msg(struct ceph_connection *con,
 | 
			
		||||
				struct ceph_msg_header *hdr, int *skip)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -5245,6 +5319,10 @@ static const struct ceph_connection_operations mds_con_ops = {
 | 
			
		|||
	.alloc_msg = mds_alloc_msg,
 | 
			
		||||
	.sign_message = mds_sign_message,
 | 
			
		||||
	.check_message_signature = mds_check_message_signature,
 | 
			
		||||
	.get_auth_request = mds_get_auth_request,
 | 
			
		||||
	.handle_auth_reply_more = mds_handle_auth_reply_more,
 | 
			
		||||
	.handle_auth_done = mds_handle_auth_done,
 | 
			
		||||
	.handle_auth_bad_method = mds_handle_auth_bad_method,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* eof */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,8 +120,12 @@ int ceph_auth_entity_name_encode(const char *name, void **p, void *end);
 | 
			
		|||
 | 
			
		||||
extern int ceph_build_auth(struct ceph_auth_client *ac,
 | 
			
		||||
		    void *msg_buf, size_t msg_len);
 | 
			
		||||
 | 
			
		||||
extern int ceph_auth_is_authenticated(struct ceph_auth_client *ac);
 | 
			
		||||
 | 
			
		||||
int __ceph_auth_get_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
			       struct ceph_auth_handshake *auth,
 | 
			
		||||
			       int peer_type, bool force_new,
 | 
			
		||||
			       int *proto, int *pref_mode, int *fallb_mode);
 | 
			
		||||
extern int ceph_auth_create_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
				       int peer_type,
 | 
			
		||||
				       struct ceph_auth_handshake *auth);
 | 
			
		||||
| 
						 | 
				
			
			@ -157,4 +161,34 @@ int ceph_auth_check_message_signature(struct ceph_auth_handshake *auth,
 | 
			
		|||
		return auth->check_message_signature(auth, msg);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len);
 | 
			
		||||
int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply,
 | 
			
		||||
				int reply_len, void *buf, int buf_len);
 | 
			
		||||
int ceph_auth_handle_reply_done(struct ceph_auth_client *ac,
 | 
			
		||||
				u64 global_id, void *reply, int reply_len,
 | 
			
		||||
				u8 *session_key, int *session_key_len,
 | 
			
		||||
				u8 *con_secret, int *con_secret_len);
 | 
			
		||||
bool ceph_auth_handle_bad_method(struct ceph_auth_client *ac,
 | 
			
		||||
				 int used_proto, int result,
 | 
			
		||||
				 const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				 const int *allowed_modes, int mode_cnt);
 | 
			
		||||
 | 
			
		||||
int ceph_auth_get_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
			     struct ceph_auth_handshake *auth,
 | 
			
		||||
			     int peer_type, void *buf, int *buf_len);
 | 
			
		||||
int ceph_auth_handle_svc_reply_more(struct ceph_auth_client *ac,
 | 
			
		||||
				    struct ceph_auth_handshake *auth,
 | 
			
		||||
				    void *reply, int reply_len,
 | 
			
		||||
				    void *buf, int *buf_len);
 | 
			
		||||
int ceph_auth_handle_svc_reply_done(struct ceph_auth_client *ac,
 | 
			
		||||
				    struct ceph_auth_handshake *auth,
 | 
			
		||||
				    void *reply, int reply_len,
 | 
			
		||||
				    u8 *session_key, int *session_key_len,
 | 
			
		||||
				    u8 *con_secret, int *con_secret_len);
 | 
			
		||||
bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
				     int peer_type, int used_proto, int result,
 | 
			
		||||
				     const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				     const int *allowed_modes, int mode_cnt);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,6 +93,10 @@ struct ceph_dir_layout {
 | 
			
		|||
#define CEPH_AUTH_NONE	 	0x1
 | 
			
		||||
#define CEPH_AUTH_CEPHX	 	0x2
 | 
			
		||||
 | 
			
		||||
#define CEPH_AUTH_MODE_NONE		0
 | 
			
		||||
#define CEPH_AUTH_MODE_AUTHORIZER	1
 | 
			
		||||
#define CEPH_AUTH_MODE_MON		10
 | 
			
		||||
 | 
			
		||||
/* msgr2 protocol modes */
 | 
			
		||||
#define CEPH_CON_MODE_UNKNOWN	0x0
 | 
			
		||||
#define CEPH_CON_MODE_CRC	0x1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -221,6 +221,7 @@ static inline void ceph_encode_timespec64(struct ceph_timespec *tv,
 | 
			
		|||
#define CEPH_ENTITY_ADDR_TYPE_NONE	0
 | 
			
		||||
#define CEPH_ENTITY_ADDR_TYPE_LEGACY	__cpu_to_le32(1)
 | 
			
		||||
#define CEPH_ENTITY_ADDR_TYPE_MSGR2	__cpu_to_le32(2)
 | 
			
		||||
#define CEPH_ENTITY_ADDR_TYPE_ANY	__cpu_to_le32(3)
 | 
			
		||||
 | 
			
		||||
static inline void ceph_encode_banner_addr(struct ceph_entity_addr *a)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -243,6 +244,9 @@ extern int ceph_decode_entity_addr(void **p, void *end,
 | 
			
		|||
int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2,
 | 
			
		||||
			       struct ceph_entity_addr *addr);
 | 
			
		||||
 | 
			
		||||
int ceph_entity_addr_encoding_len(const struct ceph_entity_addr *addr);
 | 
			
		||||
void ceph_encode_entity_addr(void **p, const struct ceph_entity_addr *addr);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * encoders
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,10 +31,10 @@
 | 
			
		|||
#define CEPH_OPT_FSID             (1<<0)
 | 
			
		||||
#define CEPH_OPT_NOSHARE          (1<<1) /* don't share client with other sbs */
 | 
			
		||||
#define CEPH_OPT_MYIP             (1<<2) /* specified my ip */
 | 
			
		||||
#define CEPH_OPT_NOCRC            (1<<3) /* no data crc on writes */
 | 
			
		||||
#define CEPH_OPT_NOCRC            (1<<3) /* no data crc on writes (msgr1) */
 | 
			
		||||
#define CEPH_OPT_NOMSGAUTH	  (1<<4) /* don't require msg signing feat */
 | 
			
		||||
#define CEPH_OPT_TCP_NODELAY	  (1<<5) /* TCP_NODELAY on TCP sockets */
 | 
			
		||||
#define CEPH_OPT_NOMSGSIGN	  (1<<6) /* don't sign msgs */
 | 
			
		||||
#define CEPH_OPT_NOMSGSIGN	  (1<<6) /* don't sign msgs (msgr1) */
 | 
			
		||||
#define CEPH_OPT_ABORT_ON_FULL	  (1<<7) /* abort w/ ENOSPC when full */
 | 
			
		||||
 | 
			
		||||
#define CEPH_OPT_DEFAULT   (CEPH_OPT_TCP_NODELAY)
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +84,7 @@ struct ceph_options {
 | 
			
		|||
#define CEPH_MONC_HUNT_BACKOFF		2
 | 
			
		||||
#define CEPH_MONC_HUNT_MAX_MULT		10
 | 
			
		||||
 | 
			
		||||
#define CEPH_MSG_MAX_CONTROL_LEN (16*1024*1024)
 | 
			
		||||
#define CEPH_MSG_MAX_FRONT_LEN	(16*1024*1024)
 | 
			
		||||
#define CEPH_MSG_MAX_MIDDLE_LEN	(16*1024*1024)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -152,6 +153,10 @@ struct ceph_client {
 | 
			
		|||
 | 
			
		||||
#define from_msgr(ms)	container_of(ms, struct ceph_client, msgr)
 | 
			
		||||
 | 
			
		||||
static inline bool ceph_msgr2(struct ceph_client *client)
 | 
			
		||||
{
 | 
			
		||||
	return client->options->con_modes[0] != CEPH_CON_MODE_UNKNOWN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * snapshots
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
#define __FS_CEPH_MESSENGER_H
 | 
			
		||||
 | 
			
		||||
#include <linux/bvec.h>
 | 
			
		||||
#include <linux/crypto.h>
 | 
			
		||||
#include <linux/kref.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/net.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +53,23 @@ struct ceph_connection_operations {
 | 
			
		|||
 | 
			
		||||
	int (*sign_message) (struct ceph_msg *msg);
 | 
			
		||||
	int (*check_message_signature) (struct ceph_msg *msg);
 | 
			
		||||
 | 
			
		||||
	/* msgr2 authentication exchange */
 | 
			
		||||
	int (*get_auth_request)(struct ceph_connection *con,
 | 
			
		||||
				void *buf, int *buf_len,
 | 
			
		||||
				void **authorizer, int *authorizer_len);
 | 
			
		||||
	int (*handle_auth_reply_more)(struct ceph_connection *con,
 | 
			
		||||
				      void *reply, int reply_len,
 | 
			
		||||
				      void *buf, int *buf_len,
 | 
			
		||||
				      void **authorizer, int *authorizer_len);
 | 
			
		||||
	int (*handle_auth_done)(struct ceph_connection *con,
 | 
			
		||||
				u64 global_id, void *reply, int reply_len,
 | 
			
		||||
				u8 *session_key, int *session_key_len,
 | 
			
		||||
				u8 *con_secret, int *con_secret_len);
 | 
			
		||||
	int (*handle_auth_bad_method)(struct ceph_connection *con,
 | 
			
		||||
				      int used_proto, int result,
 | 
			
		||||
				      const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				      const int *allowed_modes, int mode_cnt);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* use format string %s%lld */
 | 
			
		||||
| 
						 | 
				
			
			@ -246,8 +264,15 @@ struct ceph_msg {
 | 
			
		|||
#define CEPH_CON_S_PREOPEN		2
 | 
			
		||||
#define CEPH_CON_S_V1_BANNER		3
 | 
			
		||||
#define CEPH_CON_S_V1_CONNECT_MSG	4
 | 
			
		||||
#define CEPH_CON_S_OPEN			5
 | 
			
		||||
#define CEPH_CON_S_STANDBY		6
 | 
			
		||||
#define CEPH_CON_S_V2_BANNER_PREFIX	5
 | 
			
		||||
#define CEPH_CON_S_V2_BANNER_PAYLOAD	6
 | 
			
		||||
#define CEPH_CON_S_V2_HELLO		7
 | 
			
		||||
#define CEPH_CON_S_V2_AUTH		8
 | 
			
		||||
#define CEPH_CON_S_V2_AUTH_SIGNATURE	9
 | 
			
		||||
#define CEPH_CON_S_V2_SESSION_CONNECT	10
 | 
			
		||||
#define CEPH_CON_S_V2_SESSION_RECONNECT	11
 | 
			
		||||
#define CEPH_CON_S_OPEN			12
 | 
			
		||||
#define CEPH_CON_S_STANDBY		13
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ceph_connection flag bits
 | 
			
		||||
| 
						 | 
				
			
			@ -301,6 +326,99 @@ struct ceph_connection_v1_info {
 | 
			
		|||
	u32 peer_global_seq;  /* peer's global seq for this connection */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CEPH_CRC_LEN			4
 | 
			
		||||
#define CEPH_GCM_KEY_LEN		16
 | 
			
		||||
#define CEPH_GCM_IV_LEN			sizeof(struct ceph_gcm_nonce)
 | 
			
		||||
#define CEPH_GCM_BLOCK_LEN		16
 | 
			
		||||
#define CEPH_GCM_TAG_LEN		16
 | 
			
		||||
 | 
			
		||||
#define CEPH_PREAMBLE_LEN		32
 | 
			
		||||
#define CEPH_PREAMBLE_INLINE_LEN	48
 | 
			
		||||
#define CEPH_PREAMBLE_PLAIN_LEN		CEPH_PREAMBLE_LEN
 | 
			
		||||
#define CEPH_PREAMBLE_SECURE_LEN	(CEPH_PREAMBLE_LEN +		\
 | 
			
		||||
					 CEPH_PREAMBLE_INLINE_LEN +	\
 | 
			
		||||
					 CEPH_GCM_TAG_LEN)
 | 
			
		||||
#define CEPH_EPILOGUE_PLAIN_LEN		(1 + 3 * CEPH_CRC_LEN)
 | 
			
		||||
#define CEPH_EPILOGUE_SECURE_LEN	(CEPH_GCM_BLOCK_LEN + CEPH_GCM_TAG_LEN)
 | 
			
		||||
 | 
			
		||||
#define CEPH_FRAME_MAX_SEGMENT_COUNT	4
 | 
			
		||||
 | 
			
		||||
struct ceph_frame_desc {
 | 
			
		||||
	int fd_tag;  /* FRAME_TAG_* */
 | 
			
		||||
	int fd_seg_cnt;
 | 
			
		||||
	int fd_lens[CEPH_FRAME_MAX_SEGMENT_COUNT];  /* logical */
 | 
			
		||||
	int fd_aligns[CEPH_FRAME_MAX_SEGMENT_COUNT];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ceph_gcm_nonce {
 | 
			
		||||
	__le32 fixed;
 | 
			
		||||
	__le64 counter __packed;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ceph_connection_v2_info {
 | 
			
		||||
	struct iov_iter in_iter;
 | 
			
		||||
	struct kvec in_kvecs[5];  /* recvmsg */
 | 
			
		||||
	struct bio_vec in_bvec;  /* recvmsg (in_cursor) */
 | 
			
		||||
	int in_kvec_cnt;
 | 
			
		||||
	int in_state;  /* IN_S_* */
 | 
			
		||||
 | 
			
		||||
	struct iov_iter out_iter;
 | 
			
		||||
	struct kvec out_kvecs[8];  /* sendmsg */
 | 
			
		||||
	struct bio_vec out_bvec;  /* sendpage (out_cursor, out_zero),
 | 
			
		||||
				     sendmsg (out_enc_pages) */
 | 
			
		||||
	int out_kvec_cnt;
 | 
			
		||||
	int out_state;  /* OUT_S_* */
 | 
			
		||||
 | 
			
		||||
	int out_zero;  /* # of zero bytes to send */
 | 
			
		||||
	bool out_iter_sendpage;  /* use sendpage if possible */
 | 
			
		||||
 | 
			
		||||
	struct ceph_frame_desc in_desc;
 | 
			
		||||
	struct ceph_msg_data_cursor in_cursor;
 | 
			
		||||
	struct ceph_msg_data_cursor out_cursor;
 | 
			
		||||
 | 
			
		||||
	struct crypto_shash *hmac_tfm;  /* post-auth signature */
 | 
			
		||||
	struct crypto_aead *gcm_tfm;  /* on-wire encryption */
 | 
			
		||||
	struct aead_request *gcm_req;
 | 
			
		||||
	struct crypto_wait gcm_wait;
 | 
			
		||||
	struct ceph_gcm_nonce in_gcm_nonce;
 | 
			
		||||
	struct ceph_gcm_nonce out_gcm_nonce;
 | 
			
		||||
 | 
			
		||||
	struct page **out_enc_pages;
 | 
			
		||||
	int out_enc_page_cnt;
 | 
			
		||||
	int out_enc_resid;
 | 
			
		||||
	int out_enc_i;
 | 
			
		||||
 | 
			
		||||
	int con_mode;  /* CEPH_CON_MODE_* */
 | 
			
		||||
 | 
			
		||||
	void *conn_bufs[16];
 | 
			
		||||
	int conn_buf_cnt;
 | 
			
		||||
 | 
			
		||||
	struct kvec in_sign_kvecs[8];
 | 
			
		||||
	struct kvec out_sign_kvecs[8];
 | 
			
		||||
	int in_sign_kvec_cnt;
 | 
			
		||||
	int out_sign_kvec_cnt;
 | 
			
		||||
 | 
			
		||||
	u64 client_cookie;
 | 
			
		||||
	u64 server_cookie;
 | 
			
		||||
	u64 global_seq;
 | 
			
		||||
	u64 connect_seq;
 | 
			
		||||
	u64 peer_global_seq;
 | 
			
		||||
 | 
			
		||||
	u8 in_buf[CEPH_PREAMBLE_SECURE_LEN];
 | 
			
		||||
	u8 out_buf[CEPH_PREAMBLE_SECURE_LEN];
 | 
			
		||||
	struct {
 | 
			
		||||
		u8 late_status;  /* FRAME_LATE_STATUS_* */
 | 
			
		||||
		union {
 | 
			
		||||
			struct {
 | 
			
		||||
				u32 front_crc;
 | 
			
		||||
				u32 middle_crc;
 | 
			
		||||
				u32 data_crc;
 | 
			
		||||
			} __packed;
 | 
			
		||||
			u8 pad[CEPH_GCM_BLOCK_LEN - 1];
 | 
			
		||||
		};
 | 
			
		||||
	} out_epil;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A single connection with another host.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -346,7 +464,10 @@ struct ceph_connection {
 | 
			
		|||
	struct delayed_work work;	    /* send|recv work */
 | 
			
		||||
	unsigned long       delay;          /* current delay interval */
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct ceph_connection_v1_info v1;
 | 
			
		||||
		struct ceph_connection_v2_info v2;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct page *ceph_zero_page;
 | 
			
		||||
| 
						 | 
				
			
			@ -397,6 +518,15 @@ bool ceph_con_v1_opened(struct ceph_connection *con);
 | 
			
		|||
void ceph_con_v1_reset_session(struct ceph_connection *con);
 | 
			
		||||
void ceph_con_v1_reset_protocol(struct ceph_connection *con);
 | 
			
		||||
 | 
			
		||||
/* messenger_v2.c */
 | 
			
		||||
int ceph_con_v2_try_read(struct ceph_connection *con);
 | 
			
		||||
int ceph_con_v2_try_write(struct ceph_connection *con);
 | 
			
		||||
void ceph_con_v2_revoke(struct ceph_connection *con);
 | 
			
		||||
void ceph_con_v2_revoke_incoming(struct ceph_connection *con);
 | 
			
		||||
bool ceph_con_v2_opened(struct ceph_connection *con);
 | 
			
		||||
void ceph_con_v2_reset_session(struct ceph_connection *con);
 | 
			
		||||
void ceph_con_v2_reset_protocol(struct ceph_connection *con);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern const char *ceph_pr_addr(const struct ceph_entity_addr *addr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,9 +14,39 @@
 | 
			
		|||
 * constant.
 | 
			
		||||
 */
 | 
			
		||||
#define CEPH_BANNER "ceph v027"
 | 
			
		||||
#define CEPH_BANNER_LEN 9
 | 
			
		||||
#define CEPH_BANNER_MAX_LEN 30
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * messenger V2 connection banner prefix.
 | 
			
		||||
 * The full banner string should have the form: "ceph v2\n<le16>"
 | 
			
		||||
 * the 2 bytes are the length of the remaining banner.
 | 
			
		||||
 */
 | 
			
		||||
#define CEPH_BANNER_V2 "ceph v2\n"
 | 
			
		||||
#define CEPH_BANNER_V2_LEN 8
 | 
			
		||||
#define CEPH_BANNER_V2_PREFIX_LEN (CEPH_BANNER_V2_LEN + sizeof(__le16))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * messenger V2 features
 | 
			
		||||
 */
 | 
			
		||||
#define CEPH_MSGR2_INCARNATION_1 (0ull)
 | 
			
		||||
 | 
			
		||||
#define DEFINE_MSGR2_FEATURE(bit, incarnation, name)               \
 | 
			
		||||
	static const uint64_t CEPH_MSGR2_FEATURE_##name = (1ULL << bit); \
 | 
			
		||||
	static const uint64_t CEPH_MSGR2_FEATUREMASK_##name =            \
 | 
			
		||||
			(1ULL << bit | CEPH_MSGR2_INCARNATION_##incarnation);
 | 
			
		||||
 | 
			
		||||
#define HAVE_MSGR2_FEATURE(x, name) \
 | 
			
		||||
	(((x) & (CEPH_MSGR2_FEATUREMASK_##name)) == (CEPH_MSGR2_FEATUREMASK_##name))
 | 
			
		||||
 | 
			
		||||
DEFINE_MSGR2_FEATURE( 0, 1, REVISION_1)   // msgr2.1
 | 
			
		||||
 | 
			
		||||
#define CEPH_MSGR2_SUPPORTED_FEATURES (CEPH_MSGR2_FEATURE_REVISION_1)
 | 
			
		||||
 | 
			
		||||
#define CEPH_MSGR2_REQUIRED_FEATURES  (CEPH_MSGR2_FEATURE_REVISION_1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Rollover-safe type and comparator for 32-bit sequence numbers.
 | 
			
		||||
 * Comparator returns -1, 0, or 1.
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +188,24 @@ struct ceph_msg_header {
 | 
			
		|||
	__le32 crc;       /* header crc32c */
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct ceph_msg_header2 {
 | 
			
		||||
	__le64 seq;       /* message seq# for this session */
 | 
			
		||||
	__le64 tid;       /* transaction id */
 | 
			
		||||
	__le16 type;      /* message type */
 | 
			
		||||
	__le16 priority;  /* priority.  higher value == higher priority */
 | 
			
		||||
	__le16 version;   /* version of message encoding */
 | 
			
		||||
 | 
			
		||||
	__le32 data_pre_padding_len;
 | 
			
		||||
	__le16 data_off;  /* sender: include full offset;
 | 
			
		||||
			     receiver: mask against ~PAGE_MASK */
 | 
			
		||||
 | 
			
		||||
	__le64 ack_seq;
 | 
			
		||||
	__u8 flags;
 | 
			
		||||
	/* oldest code we think can decode this.  unknown if zero. */
 | 
			
		||||
	__le16 compat_version;
 | 
			
		||||
	__le16 reserved;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
#define CEPH_MSG_PRIO_LOW     64
 | 
			
		||||
#define CEPH_MSG_PRIO_DEFAULT 127
 | 
			
		||||
#define CEPH_MSG_PRIO_HIGH    196
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,9 @@ config CEPH_LIB
 | 
			
		|||
	select LIBCRC32C
 | 
			
		||||
	select CRYPTO_AES
 | 
			
		||||
	select CRYPTO_CBC
 | 
			
		||||
	select CRYPTO_GCM
 | 
			
		||||
	select CRYPTO_HMAC
 | 
			
		||||
	select CRYPTO_SHA256
 | 
			
		||||
	select CRYPTO
 | 
			
		||||
	select KEYS
 | 
			
		||||
	default n
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,4 +15,4 @@ libceph-y := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
 | 
			
		|||
	auth_x.o \
 | 
			
		||||
	ceph_strings.o ceph_hash.o \
 | 
			
		||||
	pagevec.o snapshot.o string_table.o \
 | 
			
		||||
	messenger_v1.o
 | 
			
		||||
	messenger_v1.o messenger_v2.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										309
									
								
								net/ceph/auth.c
									
									
									
									
									
								
							
							
						
						
									
										309
									
								
								net/ceph/auth.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -293,6 +293,39 @@ int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_auth_is_authenticated);
 | 
			
		||||
 | 
			
		||||
int __ceph_auth_get_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
			       struct ceph_auth_handshake *auth,
 | 
			
		||||
			       int peer_type, bool force_new,
 | 
			
		||||
			       int *proto, int *pref_mode, int *fallb_mode)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&ac->mutex);
 | 
			
		||||
	if (force_new && auth->authorizer) {
 | 
			
		||||
		ceph_auth_destroy_authorizer(auth->authorizer);
 | 
			
		||||
		auth->authorizer = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (!auth->authorizer)
 | 
			
		||||
		ret = ac->ops->create_authorizer(ac, peer_type, auth);
 | 
			
		||||
	else if (ac->ops->update_authorizer)
 | 
			
		||||
		ret = ac->ops->update_authorizer(ac, peer_type, auth);
 | 
			
		||||
	else
 | 
			
		||||
		ret = 0;
 | 
			
		||||
	if (ret)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	*proto = ac->protocol;
 | 
			
		||||
	if (pref_mode && fallb_mode) {
 | 
			
		||||
		*pref_mode = ac->preferred_mode;
 | 
			
		||||
		*fallb_mode = ac->fallback_mode;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(__ceph_auth_get_authorizer);
 | 
			
		||||
 | 
			
		||||
int ceph_auth_create_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
				int peer_type,
 | 
			
		||||
				struct ceph_auth_handshake *auth)
 | 
			
		||||
| 
						 | 
				
			
			@ -369,3 +402,279 @@ void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type)
 | 
			
		|||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_auth_invalidate_authorizer);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * msgr2 authentication
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static bool contains(const int *arr, int cnt, int val)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < cnt; i++) {
 | 
			
		||||
		if (arr[i] == val)
 | 
			
		||||
			return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode)
 | 
			
		||||
{
 | 
			
		||||
	WARN_ON(pref_mode == CEPH_CON_MODE_UNKNOWN);
 | 
			
		||||
	if (fallb_mode != CEPH_CON_MODE_UNKNOWN) {
 | 
			
		||||
		ceph_encode_32_safe(p, end, 2, e_range);
 | 
			
		||||
		ceph_encode_32_safe(p, end, pref_mode, e_range);
 | 
			
		||||
		ceph_encode_32_safe(p, end, fallb_mode, e_range);
 | 
			
		||||
	} else {
 | 
			
		||||
		ceph_encode_32_safe(p, end, 1, e_range);
 | 
			
		||||
		ceph_encode_32_safe(p, end, pref_mode, e_range);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
e_range:
 | 
			
		||||
	return -ERANGE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Similar to ceph_auth_build_hello().
 | 
			
		||||
 */
 | 
			
		||||
int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len)
 | 
			
		||||
{
 | 
			
		||||
	int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE;
 | 
			
		||||
	void *end = buf + buf_len;
 | 
			
		||||
	void *lenp;
 | 
			
		||||
	void *p;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&ac->mutex);
 | 
			
		||||
	if (ac->protocol == CEPH_AUTH_UNKNOWN) {
 | 
			
		||||
		ret = init_protocol(ac, proto);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			pr_err("auth protocol '%s' init failed: %d\n",
 | 
			
		||||
			       ceph_auth_proto_name(proto), ret);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		WARN_ON(ac->protocol != proto);
 | 
			
		||||
		ac->ops->reset(ac);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = buf;
 | 
			
		||||
	ceph_encode_32_safe(&p, end, ac->protocol, e_range);
 | 
			
		||||
	ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	lenp = p;
 | 
			
		||||
	p += 4;  /* space for len */
 | 
			
		||||
 | 
			
		||||
	ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range);
 | 
			
		||||
	ret = ceph_auth_entity_name_encode(ac->name, &p, end);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	ceph_encode_64_safe(&p, end, ac->global_id, e_range);
 | 
			
		||||
	ceph_encode_32(&lenp, p - lenp - 4);
 | 
			
		||||
	ret = p - buf;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return ret;
 | 
			
		||||
 | 
			
		||||
e_range:
 | 
			
		||||
	ret = -ERANGE;
 | 
			
		||||
	goto out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply,
 | 
			
		||||
				int reply_len, void *buf, int buf_len)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&ac->mutex);
 | 
			
		||||
	ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len,
 | 
			
		||||
				    NULL, NULL, NULL, NULL);
 | 
			
		||||
	if (ret == -EAGAIN)
 | 
			
		||||
		ret = build_request(ac, false, buf, buf_len);
 | 
			
		||||
	else
 | 
			
		||||
		WARN_ON(ret >= 0);
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ceph_auth_handle_reply_done(struct ceph_auth_client *ac,
 | 
			
		||||
				u64 global_id, void *reply, int reply_len,
 | 
			
		||||
				u8 *session_key, int *session_key_len,
 | 
			
		||||
				u8 *con_secret, int *con_secret_len)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&ac->mutex);
 | 
			
		||||
	if (global_id && ac->global_id != global_id) {
 | 
			
		||||
		dout("%s global_id %llu -> %llu\n", __func__, ac->global_id,
 | 
			
		||||
		     global_id);
 | 
			
		||||
		ac->global_id = global_id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len,
 | 
			
		||||
				    session_key, session_key_len,
 | 
			
		||||
				    con_secret, con_secret_len);
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ceph_auth_handle_bad_method(struct ceph_auth_client *ac,
 | 
			
		||||
				 int used_proto, int result,
 | 
			
		||||
				 const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				 const int *allowed_modes, int mode_cnt)
 | 
			
		||||
{
 | 
			
		||||
	mutex_lock(&ac->mutex);
 | 
			
		||||
	WARN_ON(used_proto != ac->protocol);
 | 
			
		||||
 | 
			
		||||
	if (result == -EOPNOTSUPP) {
 | 
			
		||||
		if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
 | 
			
		||||
			pr_err("auth protocol '%s' not allowed\n",
 | 
			
		||||
			       ceph_auth_proto_name(ac->protocol));
 | 
			
		||||
			goto not_allowed;
 | 
			
		||||
		}
 | 
			
		||||
		if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
 | 
			
		||||
		    (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
 | 
			
		||||
		     !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
 | 
			
		||||
			pr_err("preferred mode '%s' not allowed\n",
 | 
			
		||||
			       ceph_con_mode_name(ac->preferred_mode));
 | 
			
		||||
			if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
 | 
			
		||||
				pr_err("no fallback mode\n");
 | 
			
		||||
			else
 | 
			
		||||
				pr_err("fallback mode '%s' not allowed\n",
 | 
			
		||||
				       ceph_con_mode_name(ac->fallback_mode));
 | 
			
		||||
			goto not_allowed;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	WARN_ON(result == -EOPNOTSUPP || result >= 0);
 | 
			
		||||
	pr_err("auth protocol '%s' msgr authentication failed: %d\n",
 | 
			
		||||
	       ceph_auth_proto_name(ac->protocol), result);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return true;
 | 
			
		||||
 | 
			
		||||
not_allowed:
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ceph_auth_get_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
			     struct ceph_auth_handshake *auth,
 | 
			
		||||
			     int peer_type, void *buf, int *buf_len)
 | 
			
		||||
{
 | 
			
		||||
	void *end = buf + *buf_len;
 | 
			
		||||
	int pref_mode, fallb_mode;
 | 
			
		||||
	int proto;
 | 
			
		||||
	void *p;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto,
 | 
			
		||||
					 &pref_mode, &fallb_mode);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	p = buf;
 | 
			
		||||
	ceph_encode_32_safe(&p, end, proto, e_range);
 | 
			
		||||
	ret = encode_con_modes(&p, end, pref_mode, fallb_mode);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
 | 
			
		||||
	*buf_len = p - buf;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
e_range:
 | 
			
		||||
	return -ERANGE;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_auth_get_authorizer);
 | 
			
		||||
 | 
			
		||||
int ceph_auth_handle_svc_reply_more(struct ceph_auth_client *ac,
 | 
			
		||||
				    struct ceph_auth_handshake *auth,
 | 
			
		||||
				    void *reply, int reply_len,
 | 
			
		||||
				    void *buf, int *buf_len)
 | 
			
		||||
{
 | 
			
		||||
	void *end = buf + *buf_len;
 | 
			
		||||
	void *p;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer,
 | 
			
		||||
						 reply, reply_len);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	p = buf;
 | 
			
		||||
	ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
 | 
			
		||||
	*buf_len = p - buf;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
e_range:
 | 
			
		||||
	return -ERANGE;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more);
 | 
			
		||||
 | 
			
		||||
int ceph_auth_handle_svc_reply_done(struct ceph_auth_client *ac,
 | 
			
		||||
				    struct ceph_auth_handshake *auth,
 | 
			
		||||
				    void *reply, int reply_len,
 | 
			
		||||
				    u8 *session_key, int *session_key_len,
 | 
			
		||||
				    u8 *con_secret, int *con_secret_len)
 | 
			
		||||
{
 | 
			
		||||
	return ceph_auth_verify_authorizer_reply(ac, auth->authorizer,
 | 
			
		||||
		reply, reply_len, session_key, session_key_len,
 | 
			
		||||
		con_secret, con_secret_len);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done);
 | 
			
		||||
 | 
			
		||||
bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client *ac,
 | 
			
		||||
				     int peer_type, int used_proto, int result,
 | 
			
		||||
				     const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				     const int *allowed_modes, int mode_cnt)
 | 
			
		||||
{
 | 
			
		||||
	mutex_lock(&ac->mutex);
 | 
			
		||||
	WARN_ON(used_proto != ac->protocol);
 | 
			
		||||
 | 
			
		||||
	if (result == -EOPNOTSUPP) {
 | 
			
		||||
		if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
 | 
			
		||||
			pr_err("auth protocol '%s' not allowed by %s\n",
 | 
			
		||||
			       ceph_auth_proto_name(ac->protocol),
 | 
			
		||||
			       ceph_entity_type_name(peer_type));
 | 
			
		||||
			goto not_allowed;
 | 
			
		||||
		}
 | 
			
		||||
		if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
 | 
			
		||||
		    (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
 | 
			
		||||
		     !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
 | 
			
		||||
			pr_err("preferred mode '%s' not allowed by %s\n",
 | 
			
		||||
			       ceph_con_mode_name(ac->preferred_mode),
 | 
			
		||||
			       ceph_entity_type_name(peer_type));
 | 
			
		||||
			if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
 | 
			
		||||
				pr_err("no fallback mode\n");
 | 
			
		||||
			else
 | 
			
		||||
				pr_err("fallback mode '%s' not allowed by %s\n",
 | 
			
		||||
				       ceph_con_mode_name(ac->fallback_mode),
 | 
			
		||||
				       ceph_entity_type_name(peer_type));
 | 
			
		||||
			goto not_allowed;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	WARN_ON(result == -EOPNOTSUPP || result >= 0);
 | 
			
		||||
	pr_err("auth protocol '%s' authorization to %s failed: %d\n",
 | 
			
		||||
	       ceph_auth_proto_name(ac->protocol),
 | 
			
		||||
	       ceph_entity_type_name(peer_type), result);
 | 
			
		||||
 | 
			
		||||
	if (ac->ops->invalidate_authorizer)
 | 
			
		||||
		ac->ops->invalidate_authorizer(ac, peer_type);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return true;
 | 
			
		||||
 | 
			
		||||
not_allowed:
 | 
			
		||||
	mutex_unlock(&ac->mutex);
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
#include <linux/ceph/ceph_debug.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/inet.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/ceph/decode.h>
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
| 
						 | 
				
			
			@ -138,3 +140,46 @@ int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2,
 | 
			
		|||
	return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_decode_entity_addrvec);
 | 
			
		||||
 | 
			
		||||
static int get_sockaddr_encoding_len(sa_family_t family)
 | 
			
		||||
{
 | 
			
		||||
	union {
 | 
			
		||||
		struct sockaddr sa;
 | 
			
		||||
		struct sockaddr_in sin;
 | 
			
		||||
		struct sockaddr_in6 sin6;
 | 
			
		||||
	} u;
 | 
			
		||||
 | 
			
		||||
	switch (family) {
 | 
			
		||||
	case AF_INET:
 | 
			
		||||
		return sizeof(u.sin);
 | 
			
		||||
	case AF_INET6:
 | 
			
		||||
		return sizeof(u.sin6);
 | 
			
		||||
	default:
 | 
			
		||||
		return sizeof(u);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ceph_entity_addr_encoding_len(const struct ceph_entity_addr *addr)
 | 
			
		||||
{
 | 
			
		||||
	sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
 | 
			
		||||
	int addr_len = get_sockaddr_encoding_len(family);
 | 
			
		||||
 | 
			
		||||
	return 1 + CEPH_ENCODING_START_BLK_LEN + 4 + 4 + 4 + addr_len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ceph_encode_entity_addr(void **p, const struct ceph_entity_addr *addr)
 | 
			
		||||
{
 | 
			
		||||
	sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
 | 
			
		||||
	int addr_len = get_sockaddr_encoding_len(family);
 | 
			
		||||
 | 
			
		||||
	ceph_encode_8(p, 1);  /* marker */
 | 
			
		||||
	ceph_start_encoding(p, 1, 1, sizeof(addr->type) +
 | 
			
		||||
				     sizeof(addr->nonce) +
 | 
			
		||||
				     sizeof(u32) + addr_len);
 | 
			
		||||
	ceph_encode_copy(p, &addr->type, sizeof(addr->type));
 | 
			
		||||
	ceph_encode_copy(p, &addr->nonce, sizeof(addr->nonce));
 | 
			
		||||
 | 
			
		||||
	ceph_encode_32(p, addr_len);
 | 
			
		||||
	ceph_encode_16(p, family);
 | 
			
		||||
	ceph_encode_copy(p, addr->in_addr.__data, addr_len - sizeof(family));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -195,9 +195,12 @@ EXPORT_SYMBOL(ceph_pr_addr);
 | 
			
		|||
 | 
			
		||||
void ceph_encode_my_addr(struct ceph_messenger *msgr)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(&msgr->my_enc_addr, &msgr->inst.addr, sizeof(msgr->my_enc_addr));
 | 
			
		||||
	if (!ceph_msgr2(from_msgr(msgr))) {
 | 
			
		||||
		memcpy(&msgr->my_enc_addr, &msgr->inst.addr,
 | 
			
		||||
		       sizeof(msgr->my_enc_addr));
 | 
			
		||||
		ceph_encode_banner_addr(&msgr->my_enc_addr);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * work queue for all reading and writing to/from the socket.
 | 
			
		||||
| 
						 | 
				
			
			@ -513,6 +516,9 @@ static void ceph_con_reset_protocol(struct ceph_connection *con)
 | 
			
		|||
		con->out_msg = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ceph_msgr2(from_msgr(con->msgr)))
 | 
			
		||||
		ceph_con_v2_reset_protocol(con);
 | 
			
		||||
	else
 | 
			
		||||
		ceph_con_v1_reset_protocol(con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -526,6 +532,7 @@ static void ceph_msg_remove(struct ceph_msg *msg)
 | 
			
		|||
 | 
			
		||||
	ceph_msg_put(msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ceph_msg_remove_list(struct list_head *head)
 | 
			
		||||
{
 | 
			
		||||
	while (!list_empty(head)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -547,6 +554,9 @@ void ceph_con_reset_session(struct ceph_connection *con)
 | 
			
		|||
	con->in_seq = 0;
 | 
			
		||||
	con->in_seq_acked = 0;
 | 
			
		||||
 | 
			
		||||
	if (ceph_msgr2(from_msgr(con->msgr)))
 | 
			
		||||
		ceph_con_v2_reset_session(con);
 | 
			
		||||
	else
 | 
			
		||||
		ceph_con_v1_reset_session(con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -600,6 +610,9 @@ EXPORT_SYMBOL(ceph_con_open);
 | 
			
		|||
 */
 | 
			
		||||
bool ceph_con_opened(struct ceph_connection *con)
 | 
			
		||||
{
 | 
			
		||||
	if (ceph_msgr2(from_msgr(con->msgr)))
 | 
			
		||||
		return ceph_con_v2_opened(con);
 | 
			
		||||
 | 
			
		||||
	return ceph_con_v1_opened(con);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1302,7 +1315,16 @@ int ceph_parse_ips(const char *c, const char *end,
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		ceph_addr_set_port(&addr[i], port);
 | 
			
		||||
		/*
 | 
			
		||||
		 * We want the type to be set according to ms_mode
 | 
			
		||||
		 * option, but options are normally parsed after mon
 | 
			
		||||
		 * addresses.  Rather than complicating parsing, set
 | 
			
		||||
		 * to LEGACY and override in build_initial_monmap()
 | 
			
		||||
		 * for mon addresses and ceph_messenger_init() for
 | 
			
		||||
		 * ip option.
 | 
			
		||||
		 */
 | 
			
		||||
		addr[i].type = CEPH_ENTITY_ADDR_TYPE_LEGACY;
 | 
			
		||||
		addr[i].nonce = 0;
 | 
			
		||||
 | 
			
		||||
		dout("parse_ips got %s\n", ceph_pr_addr(&addr[i]));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1410,6 +1432,13 @@ static bool con_sock_closed(struct ceph_connection *con)
 | 
			
		|||
	CASE(PREOPEN);
 | 
			
		||||
	CASE(V1_BANNER);
 | 
			
		||||
	CASE(V1_CONNECT_MSG);
 | 
			
		||||
	CASE(V2_BANNER_PREFIX);
 | 
			
		||||
	CASE(V2_BANNER_PAYLOAD);
 | 
			
		||||
	CASE(V2_HELLO);
 | 
			
		||||
	CASE(V2_AUTH);
 | 
			
		||||
	CASE(V2_AUTH_SIGNATURE);
 | 
			
		||||
	CASE(V2_SESSION_CONNECT);
 | 
			
		||||
	CASE(V2_SESSION_RECONNECT);
 | 
			
		||||
	CASE(OPEN);
 | 
			
		||||
	CASE(STANDBY);
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			@ -1494,6 +1523,9 @@ static void ceph_con_workfn(struct work_struct *work)
 | 
			
		|||
			BUG_ON(con->sock);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (ceph_msgr2(from_msgr(con->msgr)))
 | 
			
		||||
			ret = ceph_con_v2_try_read(con);
 | 
			
		||||
		else
 | 
			
		||||
			ret = ceph_con_v1_try_read(con);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if (ret == -EAGAIN)
 | 
			
		||||
| 
						 | 
				
			
			@ -1504,6 +1536,9 @@ static void ceph_con_workfn(struct work_struct *work)
 | 
			
		|||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (ceph_msgr2(from_msgr(con->msgr)))
 | 
			
		||||
			ret = ceph_con_v2_try_write(con);
 | 
			
		||||
		else
 | 
			
		||||
			ret = ceph_con_v1_try_write(con);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if (ret == -EAGAIN)
 | 
			
		||||
| 
						 | 
				
			
			@ -1538,9 +1573,8 @@ static void con_fault(struct ceph_connection *con)
 | 
			
		|||
		ceph_pr_addr(&con->peer_addr), con->error_msg);
 | 
			
		||||
	con->error_msg = NULL;
 | 
			
		||||
 | 
			
		||||
	WARN_ON(con->state != CEPH_CON_S_V1_BANNER &&
 | 
			
		||||
	       con->state != CEPH_CON_S_V1_CONNECT_MSG &&
 | 
			
		||||
	       con->state != CEPH_CON_S_OPEN);
 | 
			
		||||
	WARN_ON(con->state == CEPH_CON_S_STANDBY ||
 | 
			
		||||
		con->state == CEPH_CON_S_CLOSED);
 | 
			
		||||
 | 
			
		||||
	ceph_con_reset_protocol(con);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1596,7 +1630,11 @@ void ceph_messenger_init(struct ceph_messenger *msgr,
 | 
			
		|||
		ceph_addr_set_port(&msgr->inst.addr, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgr->inst.addr.type = 0;
 | 
			
		||||
	/*
 | 
			
		||||
	 * Since nautilus, clients are identified using type ANY.
 | 
			
		||||
	 * For msgr1, ceph_encode_banner_addr() munges it to NONE.
 | 
			
		||||
	 */
 | 
			
		||||
	msgr->inst.addr.type = CEPH_ENTITY_ADDR_TYPE_ANY;
 | 
			
		||||
 | 
			
		||||
	/* generate a random non-zero nonce */
 | 
			
		||||
	do {
 | 
			
		||||
| 
						 | 
				
			
			@ -1706,6 +1744,9 @@ void ceph_msg_revoke(struct ceph_msg *msg)
 | 
			
		|||
	if (con->out_msg == msg) {
 | 
			
		||||
		WARN_ON(con->state != CEPH_CON_S_OPEN);
 | 
			
		||||
		dout("%s con %p msg %p was sending\n", __func__, con, msg);
 | 
			
		||||
		if (ceph_msgr2(from_msgr(con->msgr)))
 | 
			
		||||
			ceph_con_v2_revoke(con);
 | 
			
		||||
		else
 | 
			
		||||
			ceph_con_v1_revoke(con);
 | 
			
		||||
		ceph_msg_put(con->out_msg);
 | 
			
		||||
		con->out_msg = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -1732,6 +1773,9 @@ void ceph_msg_revoke_incoming(struct ceph_msg *msg)
 | 
			
		|||
	if (con->in_msg == msg) {
 | 
			
		||||
		WARN_ON(con->state != CEPH_CON_S_OPEN);
 | 
			
		||||
		dout("%s con %p msg %p was recving\n", __func__, con, msg);
 | 
			
		||||
		if (ceph_msgr2(from_msgr(con->msgr)))
 | 
			
		||||
			ceph_con_v2_revoke_incoming(con);
 | 
			
		||||
		else
 | 
			
		||||
			ceph_con_v1_revoke_incoming(con);
 | 
			
		||||
		ceph_msg_put(con->in_msg);
 | 
			
		||||
		con->in_msg = NULL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3443
									
								
								net/ceph/messenger_v2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3443
									
								
								net/ceph/messenger_v2.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -257,10 +257,16 @@ static void __open_session(struct ceph_mon_client *monc)
 | 
			
		|||
		      &monc->monmap->mon_inst[monc->cur_mon].addr);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * send an initial keepalive to ensure our timestamp is valid
 | 
			
		||||
	 * by the time we are in an OPENED state
 | 
			
		||||
	 * Queue a keepalive to ensure that in case of an early fault
 | 
			
		||||
	 * the messenger doesn't put us into STANDBY state and instead
 | 
			
		||||
	 * retries.  This also ensures that our timestamp is valid by
 | 
			
		||||
	 * the time we finish hunting and delayed_work() checks it.
 | 
			
		||||
	 */
 | 
			
		||||
	ceph_con_keepalive(&monc->con);
 | 
			
		||||
	if (ceph_msgr2(monc->client)) {
 | 
			
		||||
		monc->pending_auth = 1;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* initiate authentication handshake */
 | 
			
		||||
	ret = ceph_auth_build_hello(monc->auth,
 | 
			
		||||
| 
						 | 
				
			
			@ -543,7 +549,7 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
 | 
			
		|||
	p = msg->front.iov_base;
 | 
			
		||||
	end = p + msg->front.iov_len;
 | 
			
		||||
 | 
			
		||||
	monmap = ceph_monmap_decode(&p, end, false);
 | 
			
		||||
	monmap = ceph_monmap_decode(&p, end, ceph_msgr2(client));
 | 
			
		||||
	if (IS_ERR(monmap)) {
 | 
			
		||||
		pr_err("problem decoding monmap, %d\n",
 | 
			
		||||
		       (int)PTR_ERR(monmap));
 | 
			
		||||
| 
						 | 
				
			
			@ -1119,8 +1125,9 @@ static void delayed_work(struct work_struct *work)
 | 
			
		|||
 */
 | 
			
		||||
static int build_initial_monmap(struct ceph_mon_client *monc)
 | 
			
		||||
{
 | 
			
		||||
	__le32 my_type = ceph_msgr2(monc->client) ?
 | 
			
		||||
		CEPH_ENTITY_ADDR_TYPE_MSGR2 : CEPH_ENTITY_ADDR_TYPE_LEGACY;
 | 
			
		||||
	struct ceph_options *opt = monc->client->options;
 | 
			
		||||
	struct ceph_entity_addr *mon_addr = opt->mon_addr;
 | 
			
		||||
	int num_mon = opt->num_mon;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1129,12 +1136,16 @@ static int build_initial_monmap(struct ceph_mon_client *monc)
 | 
			
		|||
			       GFP_KERNEL);
 | 
			
		||||
	if (!monc->monmap)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_mon; i++) {
 | 
			
		||||
		monc->monmap->mon_inst[i].addr = mon_addr[i];
 | 
			
		||||
		monc->monmap->mon_inst[i].addr.nonce = 0;
 | 
			
		||||
		monc->monmap->mon_inst[i].name.type =
 | 
			
		||||
			CEPH_ENTITY_TYPE_MON;
 | 
			
		||||
		monc->monmap->mon_inst[i].name.num = cpu_to_le64(i);
 | 
			
		||||
		struct ceph_entity_inst *inst = &monc->monmap->mon_inst[i];
 | 
			
		||||
 | 
			
		||||
		memcpy(&inst->addr.in_addr, &opt->mon_addr[i].in_addr,
 | 
			
		||||
		       sizeof(inst->addr.in_addr));
 | 
			
		||||
		inst->addr.type = my_type;
 | 
			
		||||
		inst->addr.nonce = 0;
 | 
			
		||||
		inst->name.type = CEPH_ENTITY_TYPE_MON;
 | 
			
		||||
		inst->name.num = cpu_to_le64(i);
 | 
			
		||||
	}
 | 
			
		||||
	monc->monmap->num_mon = num_mon;
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1337,6 +1348,88 @@ int ceph_monc_validate_auth(struct ceph_mon_client *monc)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_monc_validate_auth);
 | 
			
		||||
 | 
			
		||||
static int mon_get_auth_request(struct ceph_connection *con,
 | 
			
		||||
				void *buf, int *buf_len,
 | 
			
		||||
				void **authorizer, int *authorizer_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mon_client *monc = con->private;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&monc->mutex);
 | 
			
		||||
	ret = ceph_auth_get_request(monc->auth, buf, *buf_len);
 | 
			
		||||
	mutex_unlock(&monc->mutex);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	*buf_len = ret;
 | 
			
		||||
	*authorizer = NULL;
 | 
			
		||||
	*authorizer_len = 0;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mon_handle_auth_reply_more(struct ceph_connection *con,
 | 
			
		||||
				      void *reply, int reply_len,
 | 
			
		||||
				      void *buf, int *buf_len,
 | 
			
		||||
				      void **authorizer, int *authorizer_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mon_client *monc = con->private;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&monc->mutex);
 | 
			
		||||
	ret = ceph_auth_handle_reply_more(monc->auth, reply, reply_len,
 | 
			
		||||
					  buf, *buf_len);
 | 
			
		||||
	mutex_unlock(&monc->mutex);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	*buf_len = ret;
 | 
			
		||||
	*authorizer = NULL;
 | 
			
		||||
	*authorizer_len = 0;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mon_handle_auth_done(struct ceph_connection *con,
 | 
			
		||||
				u64 global_id, void *reply, int reply_len,
 | 
			
		||||
				u8 *session_key, int *session_key_len,
 | 
			
		||||
				u8 *con_secret, int *con_secret_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mon_client *monc = con->private;
 | 
			
		||||
	bool was_authed;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&monc->mutex);
 | 
			
		||||
	WARN_ON(!monc->hunting);
 | 
			
		||||
	was_authed = ceph_auth_is_authenticated(monc->auth);
 | 
			
		||||
	ret = ceph_auth_handle_reply_done(monc->auth, global_id,
 | 
			
		||||
					  reply, reply_len,
 | 
			
		||||
					  session_key, session_key_len,
 | 
			
		||||
					  con_secret, con_secret_len);
 | 
			
		||||
	finish_auth(monc, ret, was_authed);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		finish_hunting(monc);
 | 
			
		||||
	mutex_unlock(&monc->mutex);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mon_handle_auth_bad_method(struct ceph_connection *con,
 | 
			
		||||
				      int used_proto, int result,
 | 
			
		||||
				      const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				      const int *allowed_modes, int mode_cnt)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_mon_client *monc = con->private;
 | 
			
		||||
	bool was_authed;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&monc->mutex);
 | 
			
		||||
	WARN_ON(!monc->hunting);
 | 
			
		||||
	was_authed = ceph_auth_is_authenticated(monc->auth);
 | 
			
		||||
	ceph_auth_handle_bad_method(monc->auth, used_proto, result,
 | 
			
		||||
				    allowed_protos, proto_cnt,
 | 
			
		||||
				    allowed_modes, mode_cnt);
 | 
			
		||||
	finish_auth(monc, -EACCES, was_authed);
 | 
			
		||||
	mutex_unlock(&monc->mutex);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * handle incoming message
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -1487,4 +1580,8 @@ static const struct ceph_connection_operations mon_con_ops = {
 | 
			
		|||
	.dispatch = dispatch,
 | 
			
		||||
	.fault = mon_fault,
 | 
			
		||||
	.alloc_msg = mon_alloc_msg,
 | 
			
		||||
	.get_auth_request = mon_get_auth_request,
 | 
			
		||||
	.handle_auth_reply_more = mon_handle_auth_reply_more,
 | 
			
		||||
	.handle_auth_done = mon_handle_auth_done,
 | 
			
		||||
	.handle_auth_bad_method = mon_handle_auth_bad_method,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3918,9 +3918,11 @@ static int handle_one_map(struct ceph_osd_client *osdc,
 | 
			
		|||
	set_pool_was_full(osdc);
 | 
			
		||||
 | 
			
		||||
	if (incremental)
 | 
			
		||||
		newmap = osdmap_apply_incremental(&p, end, false, osdc->osdmap);
 | 
			
		||||
		newmap = osdmap_apply_incremental(&p, end,
 | 
			
		||||
						  ceph_msgr2(osdc->client),
 | 
			
		||||
						  osdc->osdmap);
 | 
			
		||||
	else
 | 
			
		||||
		newmap = ceph_osdmap_decode(&p, end, false);
 | 
			
		||||
		newmap = ceph_osdmap_decode(&p, end, ceph_msgr2(osdc->client));
 | 
			
		||||
	if (IS_ERR(newmap))
 | 
			
		||||
		return PTR_ERR(newmap);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5575,6 +5577,7 @@ static void put_osd_con(struct ceph_connection *con)
 | 
			
		|||
/*
 | 
			
		||||
 * authentication
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Note: returned pointer is the address of a structure that's
 | 
			
		||||
 * managed separately.  Caller must *not* attempt to free it.
 | 
			
		||||
| 
						 | 
				
			
			@ -5640,6 +5643,80 @@ static int invalidate_authorizer(struct ceph_connection *con)
 | 
			
		|||
	return ceph_monc_validate_auth(&osdc->client->monc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int osd_get_auth_request(struct ceph_connection *con,
 | 
			
		||||
				void *buf, int *buf_len,
 | 
			
		||||
				void **authorizer, int *authorizer_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_osd *o = con->private;
 | 
			
		||||
	struct ceph_auth_client *ac = o->o_osdc->client->monc.auth;
 | 
			
		||||
	struct ceph_auth_handshake *auth = &o->o_auth;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = ceph_auth_get_authorizer(ac, auth, CEPH_ENTITY_TYPE_OSD,
 | 
			
		||||
				       buf, buf_len);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	*authorizer = auth->authorizer_buf;
 | 
			
		||||
	*authorizer_len = auth->authorizer_buf_len;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int osd_handle_auth_reply_more(struct ceph_connection *con,
 | 
			
		||||
				      void *reply, int reply_len,
 | 
			
		||||
				      void *buf, int *buf_len,
 | 
			
		||||
				      void **authorizer, int *authorizer_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_osd *o = con->private;
 | 
			
		||||
	struct ceph_auth_client *ac = o->o_osdc->client->monc.auth;
 | 
			
		||||
	struct ceph_auth_handshake *auth = &o->o_auth;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = ceph_auth_handle_svc_reply_more(ac, auth, reply, reply_len,
 | 
			
		||||
					      buf, buf_len);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	*authorizer = auth->authorizer_buf;
 | 
			
		||||
	*authorizer_len = auth->authorizer_buf_len;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int osd_handle_auth_done(struct ceph_connection *con,
 | 
			
		||||
				u64 global_id, void *reply, int reply_len,
 | 
			
		||||
				u8 *session_key, int *session_key_len,
 | 
			
		||||
				u8 *con_secret, int *con_secret_len)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_osd *o = con->private;
 | 
			
		||||
	struct ceph_auth_client *ac = o->o_osdc->client->monc.auth;
 | 
			
		||||
	struct ceph_auth_handshake *auth = &o->o_auth;
 | 
			
		||||
 | 
			
		||||
	return ceph_auth_handle_svc_reply_done(ac, auth, reply, reply_len,
 | 
			
		||||
					       session_key, session_key_len,
 | 
			
		||||
					       con_secret, con_secret_len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int osd_handle_auth_bad_method(struct ceph_connection *con,
 | 
			
		||||
				      int used_proto, int result,
 | 
			
		||||
				      const int *allowed_protos, int proto_cnt,
 | 
			
		||||
				      const int *allowed_modes, int mode_cnt)
 | 
			
		||||
{
 | 
			
		||||
	struct ceph_osd *o = con->private;
 | 
			
		||||
	struct ceph_mon_client *monc = &o->o_osdc->client->monc;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (ceph_auth_handle_bad_authorizer(monc->auth, CEPH_ENTITY_TYPE_OSD,
 | 
			
		||||
					    used_proto, result,
 | 
			
		||||
					    allowed_protos, proto_cnt,
 | 
			
		||||
					    allowed_modes, mode_cnt)) {
 | 
			
		||||
		ret = ceph_monc_validate_auth(monc);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -EACCES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void osd_reencode_message(struct ceph_msg *msg)
 | 
			
		||||
{
 | 
			
		||||
	int type = le16_to_cpu(msg->hdr.type);
 | 
			
		||||
| 
						 | 
				
			
			@ -5677,4 +5754,8 @@ static const struct ceph_connection_operations osd_con_ops = {
 | 
			
		|||
	.sign_message = osd_sign_message,
 | 
			
		||||
	.check_message_signature = osd_check_message_signature,
 | 
			
		||||
	.fault = osd_fault,
 | 
			
		||||
	.get_auth_request = osd_get_auth_request,
 | 
			
		||||
	.handle_auth_reply_more = osd_handle_auth_reply_more,
 | 
			
		||||
	.handle_auth_done = osd_handle_auth_done,
 | 
			
		||||
	.handle_auth_bad_method = osd_handle_auth_bad_method,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue