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

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
Loading
Loading
Loading
Loading
+43 −18
Original line number Diff line number Diff line
@@ -125,6 +125,30 @@ int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
	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.
 */
@@ -188,28 +212,13 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
				goto out;
			}
		}

		ac->negotiating = false;
	}

	ret = ac->ops->handle_reply(ac, result, payload, payload_end);
	if (ret == -EAGAIN) {
		struct ceph_mon_request_header *monhdr = reply_buf;
		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;
		return ceph_build_auth_request(ac, reply_buf, reply_len);
	} else if (ret) {
		pr_err("authentication error %d\n", ret);
		return ret;
@@ -222,4 +231,20 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
	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);
}
+7 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ struct ceph_auth_client_ops {
				       struct ceph_authorizer *a, size_t len);
	void (*destroy_authorizer)(struct ceph_auth_client *ac,
				   struct ceph_authorizer *a);
	void (*invalidate_authorizer)(struct ceph_auth_client *ac,
				      int peer_type);

	/* reset when we (re)connect to a monitor */
	void (*reset)(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);
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
+13 −0
Original line number Diff line number Diff line
@@ -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);
}

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 = {
	.get = con_get,
	.put = con_put,
	.dispatch = dispatch,
	.get_authorizer = get_authorizer,
	.verify_authorizer_reply = verify_authorizer_reply,
	.invalidate_authorizer = invalidate_authorizer,
	.peer_reset = peer_reset,
};

+9 −0
Original line number Diff line number Diff line
@@ -1849,6 +1849,15 @@ static void ceph_fault(struct ceph_connection *con)
		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
	 * in a STANDBY state (i.e., don't try to reconnect just yet). */
	if (list_empty(&con->out_queue) && !con->out_keepalive_pending) {
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct ceph_connection_operations {
			       void **buf, int *len, int *proto,
			       void **reply_buf, int *reply_len, int force_new);
	int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
	int (*invalidate_authorizer)(struct ceph_connection *con);

	/* protocol version mismatch */
	void (*bad_proto) (struct ceph_connection *con);
Loading