Commit 9bd2e6f8 authored by Sage Weil's avatar Sage Weil

ceph: allow renewal of auth credentials

Add infrastructure to allow the mon_client to periodically renew its auth
credentials.  Also add a messenger callback that will force such a renewal
if a peer rejects our authenticator.
Signed-off-by: default avatarYehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent 8b6e4f2d
...@@ -125,6 +125,30 @@ bad: ...@@ -125,6 +125,30 @@ bad:
return -ERANGE; return -ERANGE;
} }
int ceph_build_auth_request(struct ceph_auth_client *ac,
void *msg_buf, size_t msg_len)
{
struct ceph_mon_request_header *monhdr = msg_buf;
void *p = monhdr + 1;
void *end = msg_buf + msg_len;
int ret;
monhdr->have_version = 0;
monhdr->session_mon = cpu_to_le16(-1);
monhdr->session_mon_tid = 0;
ceph_encode_32(&p, ac->protocol);
ret = ac->ops->build_request(ac, p + sizeof(u32), end);
if (ret < 0) {
pr_err("error %d building request\n", ret);
return ret;
}
dout(" built request %d bytes\n", ret);
ceph_encode_32(&p, ret);
return p + ret - msg_buf;
}
/* /*
* Handle auth message from monitor. * Handle auth message from monitor.
*/ */
...@@ -188,28 +212,13 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac, ...@@ -188,28 +212,13 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
goto out; goto out;
} }
} }
ac->negotiating = false;
} }
ret = ac->ops->handle_reply(ac, result, payload, payload_end); ret = ac->ops->handle_reply(ac, result, payload, payload_end);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
struct ceph_mon_request_header *monhdr = reply_buf; return ceph_build_auth_request(ac, reply_buf, reply_len);
void *p = reply_buf + 1;
void *end = reply_buf + reply_len;
monhdr->have_version = 0;
monhdr->session_mon = cpu_to_le16(-1);
monhdr->session_mon_tid = 0;
ceph_encode_32(&p, ac->protocol);
ret = ac->ops->build_request(ac, p + sizeof(u32), end);
if (ret < 0) {
pr_err("error %d building request\n", ret);
goto out;
}
dout(" built request %d bytes\n", ret);
ceph_encode_32(&p, ret);
return p + ret - reply_buf;
} else if (ret) { } else if (ret) {
pr_err("authentication error %d\n", ret); pr_err("authentication error %d\n", ret);
return ret; return ret;
...@@ -222,4 +231,20 @@ out: ...@@ -222,4 +231,20 @@ out:
return ret; return ret;
} }
int ceph_build_auth(struct ceph_auth_client *ac,
void *msg_buf, size_t msg_len)
{
if (!ac->protocol)
return ceph_auth_build_hello(ac, msg_buf, msg_len);
BUG_ON(!ac->ops);
if (!ac->ops->is_authenticated(ac))
return ceph_build_auth_request(ac, msg_buf, msg_len);
return 0;
}
int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
{
if (!ac->ops)
return 0;
return ac->ops->is_authenticated(ac);
}
...@@ -42,6 +42,8 @@ struct ceph_auth_client_ops { ...@@ -42,6 +42,8 @@ struct ceph_auth_client_ops {
struct ceph_authorizer *a, size_t len); struct ceph_authorizer *a, size_t len);
void (*destroy_authorizer)(struct ceph_auth_client *ac, void (*destroy_authorizer)(struct ceph_auth_client *ac,
struct ceph_authorizer *a); struct ceph_authorizer *a);
void (*invalidate_authorizer)(struct ceph_auth_client *ac,
int peer_type);
/* reset when we (re)connect to a monitor */ /* reset when we (re)connect to a monitor */
void (*reset)(struct ceph_auth_client *ac); void (*reset)(struct ceph_auth_client *ac);
...@@ -74,4 +76,9 @@ extern int ceph_handle_auth_reply(struct ceph_auth_client *ac, ...@@ -74,4 +76,9 @@ extern int ceph_handle_auth_reply(struct ceph_auth_client *ac,
void *reply_buf, size_t reply_len); void *reply_buf, size_t reply_len);
extern int ceph_entity_name_encode(const char *name, void **p, void *end); extern int ceph_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);
#endif #endif
...@@ -2946,12 +2946,25 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) ...@@ -2946,12 +2946,25 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len)
return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len); return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len);
} }
static int invalidate_authorizer(struct ceph_connection *con)
{
struct ceph_mds_session *s = con->private;
struct ceph_mds_client *mdsc = s->s_mdsc;
struct ceph_auth_client *ac = mdsc->client->monc.auth;
if (ac->ops->invalidate_authorizer)
ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS);
return ceph_monc_validate_auth(&mdsc->client->monc);
}
const static struct ceph_connection_operations mds_con_ops = { const static struct ceph_connection_operations mds_con_ops = {
.get = con_get, .get = con_get,
.put = con_put, .put = con_put,
.dispatch = dispatch, .dispatch = dispatch,
.get_authorizer = get_authorizer, .get_authorizer = get_authorizer,
.verify_authorizer_reply = verify_authorizer_reply, .verify_authorizer_reply = verify_authorizer_reply,
.invalidate_authorizer = invalidate_authorizer,
.peer_reset = peer_reset, .peer_reset = peer_reset,
}; };
......
...@@ -1849,6 +1849,15 @@ static void ceph_fault(struct ceph_connection *con) ...@@ -1849,6 +1849,15 @@ static void ceph_fault(struct ceph_connection *con)
con->in_msg = NULL; con->in_msg = NULL;
} }
/*
* in case we faulted due to authentication, invalidate our
* current tickets so that we can get new ones.
*/
if (con->auth_retry && con->ops->invalidate_authorizer) {
dout("calling invalidate_authorizer()\n");
con->ops->invalidate_authorizer(con);
}
/* If there are no messages in the queue, place the connection /* If there are no messages in the queue, place the connection
* in a STANDBY state (i.e., don't try to reconnect just yet). */ * in a STANDBY state (i.e., don't try to reconnect just yet). */
if (list_empty(&con->out_queue) && !con->out_keepalive_pending) { if (list_empty(&con->out_queue) && !con->out_keepalive_pending) {
......
...@@ -32,6 +32,7 @@ struct ceph_connection_operations { ...@@ -32,6 +32,7 @@ struct ceph_connection_operations {
void **buf, int *len, int *proto, void **buf, int *len, int *proto,
void **reply_buf, int *reply_len, int force_new); void **reply_buf, int *reply_len, int force_new);
int (*verify_authorizer_reply) (struct ceph_connection *con, int len); int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
int (*invalidate_authorizer)(struct ceph_connection *con);
/* protocol version mismatch */ /* protocol version mismatch */
void (*bad_proto) (struct ceph_connection *con); void (*bad_proto) (struct ceph_connection *con);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
const static struct ceph_connection_operations mon_con_ops; const static struct ceph_connection_operations mon_con_ops;
static int __validate_auth(struct ceph_mon_client *monc);
/* /*
* Decode a monmap blob (e.g., during mount). * Decode a monmap blob (e.g., during mount).
*/ */
...@@ -103,6 +105,7 @@ static void __close_session(struct ceph_mon_client *monc) ...@@ -103,6 +105,7 @@ static void __close_session(struct ceph_mon_client *monc)
ceph_con_revoke(monc->con, monc->m_auth); ceph_con_revoke(monc->con, monc->m_auth);
ceph_con_close(monc->con); ceph_con_close(monc->con);
monc->cur_mon = -1; monc->cur_mon = -1;
monc->pending_auth = 0;
ceph_auth_reset(monc->auth); ceph_auth_reset(monc->auth);
} }
} }
...@@ -334,7 +337,7 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, ...@@ -334,7 +337,7 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
out: out:
mutex_unlock(&monc->mutex); mutex_unlock(&monc->mutex);
wake_up(&client->mount_wq); wake_up(&client->auth_wq);
} }
/* /*
...@@ -477,6 +480,11 @@ static void delayed_work(struct work_struct *work) ...@@ -477,6 +480,11 @@ static void delayed_work(struct work_struct *work)
__open_session(monc); /* continue hunting */ __open_session(monc); /* continue hunting */
} else { } else {
ceph_con_keepalive(monc->con); ceph_con_keepalive(monc->con);
mutex_unlock(&monc->mutex);
__validate_auth(monc);
mutex_lock(&monc->mutex);
if (monc->auth->ops->is_authenticated(monc->auth)) if (monc->auth->ops->is_authenticated(monc->auth))
__send_subscribe(monc); __send_subscribe(monc);
} }
...@@ -557,6 +565,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) ...@@ -557,6 +565,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
goto out_pool2; goto out_pool2;
monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, 0, 0, NULL); monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, 0, 0, NULL);
monc->pending_auth = 0;
if (IS_ERR(monc->m_auth)) { if (IS_ERR(monc->m_auth)) {
err = PTR_ERR(monc->m_auth); err = PTR_ERR(monc->m_auth);
monc->m_auth = NULL; monc->m_auth = NULL;
...@@ -614,6 +623,15 @@ void ceph_monc_stop(struct ceph_mon_client *monc) ...@@ -614,6 +623,15 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
kfree(monc->monmap); kfree(monc->monmap);
} }
static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len)
{
monc->pending_auth = 1;
monc->m_auth->front.iov_len = len;
monc->m_auth->hdr.front_len = cpu_to_le32(len);
ceph_msg_get(monc->m_auth); /* keep our ref */
ceph_con_send(monc->con, monc->m_auth);
}
static void handle_auth_reply(struct ceph_mon_client *monc, static void handle_auth_reply(struct ceph_mon_client *monc,
struct ceph_msg *msg) struct ceph_msg *msg)
...@@ -621,18 +639,16 @@ static void handle_auth_reply(struct ceph_mon_client *monc, ...@@ -621,18 +639,16 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
int ret; int ret;
mutex_lock(&monc->mutex); mutex_lock(&monc->mutex);
monc->pending_auth = 0;
ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base, ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
msg->front.iov_len, msg->front.iov_len,
monc->m_auth->front.iov_base, monc->m_auth->front.iov_base,
monc->m_auth->front_max); monc->m_auth->front_max);
if (ret < 0) { if (ret < 0) {
monc->client->mount_err = ret; monc->client->auth_err = ret;
wake_up(&monc->client->mount_wq); wake_up(&monc->client->auth_wq);
} else if (ret > 0) { } else if (ret > 0) {
monc->m_auth->front.iov_len = ret; __send_prepared_auth_request(monc, ret);
monc->m_auth->hdr.front_len = cpu_to_le32(ret);
ceph_msg_get(monc->m_auth); /* keep our ref */
ceph_con_send(monc->con, monc->m_auth);
} else if (monc->auth->ops->is_authenticated(monc->auth)) { } else if (monc->auth->ops->is_authenticated(monc->auth)) {
dout("authenticated, starting session\n"); dout("authenticated, starting session\n");
...@@ -645,6 +661,31 @@ static void handle_auth_reply(struct ceph_mon_client *monc, ...@@ -645,6 +661,31 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
mutex_unlock(&monc->mutex); mutex_unlock(&monc->mutex);
} }
static int __validate_auth(struct ceph_mon_client *monc)
{
int ret;
if (monc->pending_auth)
return 0;
ret = ceph_build_auth(monc->auth, monc->m_auth->front.iov_base,
monc->m_auth->front_max);
if (ret <= 0)
return ret; /* either an error, or no need to authenticate */
__send_prepared_auth_request(monc, ret);
return 0;
}
int ceph_monc_validate_auth(struct ceph_mon_client *monc)
{
int ret;
mutex_lock(&monc->mutex);
ret = __validate_auth(monc);
mutex_unlock(&monc->mutex);
return ret;
}
/* /*
* handle incoming message * handle incoming message
*/ */
......
...@@ -61,6 +61,7 @@ struct ceph_mon_client { ...@@ -61,6 +61,7 @@ struct ceph_mon_client {
struct ceph_auth_client *auth; struct ceph_auth_client *auth;
struct ceph_msg *m_auth; struct ceph_msg *m_auth;
int pending_auth;
bool hunting; bool hunting;
int cur_mon; /* last monitor i contacted */ int cur_mon; /* last monitor i contacted */
...@@ -110,6 +111,8 @@ extern int ceph_monc_do_statfs(struct ceph_mon_client *monc, ...@@ -110,6 +111,8 @@ extern int ceph_monc_do_statfs(struct ceph_mon_client *monc,
extern int ceph_monc_open_session(struct ceph_mon_client *monc); extern int ceph_monc_open_session(struct ceph_mon_client *monc);
extern int ceph_monc_validate_auth(struct ceph_mon_client *monc);
#endif #endif
...@@ -1448,6 +1448,17 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) ...@@ -1448,6 +1448,17 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len)
return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len); return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len);
} }
static int invalidate_authorizer(struct ceph_connection *con)
{
struct ceph_osd *o = con->private;
struct ceph_osd_client *osdc = o->o_osdc;
struct ceph_auth_client *ac = osdc->client->monc.auth;
if (ac->ops->invalidate_authorizer)
ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
return ceph_monc_validate_auth(&osdc->client->monc);
}
const static struct ceph_connection_operations osd_con_ops = { const static struct ceph_connection_operations osd_con_ops = {
.get = get_osd_con, .get = get_osd_con,
...@@ -1455,6 +1466,7 @@ const static struct ceph_connection_operations osd_con_ops = { ...@@ -1455,6 +1466,7 @@ const static struct ceph_connection_operations osd_con_ops = {
.dispatch = dispatch, .dispatch = dispatch,
.get_authorizer = get_authorizer, .get_authorizer = get_authorizer,
.verify_authorizer_reply = verify_authorizer_reply, .verify_authorizer_reply = verify_authorizer_reply,
.invalidate_authorizer = invalidate_authorizer,
.alloc_msg = alloc_msg, .alloc_msg = alloc_msg,
.fault = osd_reset, .fault = osd_reset,
}; };
...@@ -542,7 +542,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args) ...@@ -542,7 +542,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
mutex_init(&client->mount_mutex); mutex_init(&client->mount_mutex);
init_waitqueue_head(&client->mount_wq); init_waitqueue_head(&client->auth_wq);
client->sb = NULL; client->sb = NULL;
client->mount_state = CEPH_MOUNT_MOUNTING; client->mount_state = CEPH_MOUNT_MOUNTING;
...@@ -550,7 +550,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args) ...@@ -550,7 +550,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
client->msgr = NULL; client->msgr = NULL;
client->mount_err = 0; client->auth_err = 0;
atomic_long_set(&client->writeback_count, 0); atomic_long_set(&client->writeback_count, 0);
err = bdi_init(&client->backing_dev_info); err = bdi_init(&client->backing_dev_info);
...@@ -742,13 +742,13 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt, ...@@ -742,13 +742,13 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
/* wait */ /* wait */
dout("mount waiting for mon_map\n"); dout("mount waiting for mon_map\n");
err = wait_event_interruptible_timeout(client->mount_wq, /* FIXME */ err = wait_event_interruptible_timeout(client->auth_wq,
have_mon_map(client) || (client->mount_err < 0), have_mon_map(client) || (client->auth_err < 0),
timeout); timeout);
if (err == -EINTR || err == -ERESTARTSYS) if (err == -EINTR || err == -ERESTARTSYS)
goto out; goto out;
if (client->mount_err < 0) { if (client->auth_err < 0) {
err = client->mount_err; err = client->auth_err;
goto out; goto out;
} }
} }
......
...@@ -123,9 +123,9 @@ struct ceph_client { ...@@ -123,9 +123,9 @@ struct ceph_client {
struct super_block *sb; struct super_block *sb;
unsigned long mount_state; unsigned long mount_state;
wait_queue_head_t mount_wq; wait_queue_head_t auth_wq;
int mount_err; int auth_err;
struct ceph_messenger *msgr; /* messenger instance */ struct ceph_messenger *msgr; /* messenger instance */
struct ceph_mon_client monc; struct ceph_mon_client monc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment