mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00: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
@ -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 */
|
||||
|
||||
struct ceph_connection_v1_info v1;
|
||||
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,8 +195,11 @@ 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));
|
||||
ceph_encode_banner_addr(&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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -513,7 +516,10 @@ static void ceph_con_reset_protocol(struct ceph_connection *con)
|
||||
con->out_msg = NULL;
|
||||
}
|
||||
|
||||
ceph_con_v1_reset_protocol(con);
|
||||
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,7 +554,10 @@ void ceph_con_reset_session(struct ceph_connection *con)
|
||||
con->in_seq = 0;
|
||||
con->in_seq_acked = 0;
|
||||
|
||||
ceph_con_v1_reset_session(con);
|
||||
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,7 +1523,10 @@ static void ceph_con_workfn(struct work_struct *work)
|
||||
BUG_ON(con->sock);
|
||||
}
|
||||
|
||||
ret = ceph_con_v1_try_read(con);
|
||||
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)
|
||||
continue;
|
||||
@ -1504,7 +1536,10 @@ static void ceph_con_workfn(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ceph_con_v1_try_write(con);
|
||||
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)
|
||||
continue;
|
||||
@ -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,7 +1744,10 @@ 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);
|
||||
ceph_con_v1_revoke(con);
|
||||
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;
|
||||
} else {
|
||||
@ -1732,7 +1773,10 @@ 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);
|
||||
ceph_con_v1_revoke_incoming(con);
|
||||
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;
|
||||
} else {
|
||||
|
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 New Issue
Block a user