Browse Source

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: Yehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: Sage Weil <sage@newdream.net>
Sage Weil 15 years ago
parent
commit
9bd2e6f8ba
10 changed files with 144 additions and 33 deletions
  1. 43 18
      fs/ceph/auth.c
  2. 7 0
      fs/ceph/auth.h
  3. 13 0
      fs/ceph/mds_client.c
  4. 9 0
      fs/ceph/messenger.c
  5. 1 0
      fs/ceph/messenger.h
  6. 48 7
      fs/ceph/mon_client.c
  7. 3 0
      fs/ceph/mon_client.h
  8. 12 0
      fs/ceph/osd_client.c
  9. 6 6
      fs/ceph/super.c
  10. 2 2
      fs/ceph/super.h

+ 43 - 18
fs/ceph/auth.c

@@ -125,6 +125,30 @@ bad:
 	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 @@ out:
 	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
fs/ceph/auth.h

@@ -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
fs/ceph/mds_client.c

@@ -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
fs/ceph/messenger.c

@@ -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
fs/ceph/messenger.h

@@ -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);

+ 48 - 7
fs/ceph/mon_client.c

@@ -29,6 +29,8 @@
 
 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).
  */
@@ -103,6 +105,7 @@ static void __close_session(struct ceph_mon_client *monc)
 		ceph_con_revoke(monc->con, monc->m_auth);
 		ceph_con_close(monc->con);
 		monc->cur_mon = -1;
+		monc->pending_auth = 0;
 		ceph_auth_reset(monc->auth);
 	}
 }
@@ -334,7 +337,7 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
 
 out:
 	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)
 		__open_session(monc);  /* continue hunting */
 	} else {
 		ceph_con_keepalive(monc->con);
+		mutex_unlock(&monc->mutex);
+
+		__validate_auth(monc);
+
+		mutex_lock(&monc->mutex);
 		if (monc->auth->ops->is_authenticated(monc->auth))
 			__send_subscribe(monc);
 	}
@@ -557,6 +565,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
 		goto out_pool2;
 
 	monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, 0, 0, NULL);
+	monc->pending_auth = 0;
 	if (IS_ERR(monc->m_auth)) {
 		err = PTR_ERR(monc->m_auth);
 		monc->m_auth = NULL;
@@ -614,6 +623,15 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
 	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,
 			      struct ceph_msg *msg)
@@ -621,18 +639,16 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
 	int ret;
 
 	mutex_lock(&monc->mutex);
+	monc->pending_auth = 0;
 	ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
 				     msg->front.iov_len,
 				     monc->m_auth->front.iov_base,
 				     monc->m_auth->front_max);
 	if (ret < 0) {
-		monc->client->mount_err = ret;
-		wake_up(&monc->client->mount_wq);
+		monc->client->auth_err = ret;
+		wake_up(&monc->client->auth_wq);
 	} else if (ret > 0) {
-		monc->m_auth->front.iov_len = 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);
+		__send_prepared_auth_request(monc, ret);
 	} else if (monc->auth->ops->is_authenticated(monc->auth)) {
 		dout("authenticated, starting session\n");
 
@@ -645,6 +661,31 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
 	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
  */

+ 3 - 0
fs/ceph/mon_client.h

@@ -61,6 +61,7 @@ struct ceph_mon_client {
 
 	struct ceph_auth_client *auth;
 	struct ceph_msg *m_auth;
+	int pending_auth;
 
 	bool hunting;
 	int cur_mon;                       /* last monitor i contacted */
@@ -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_validate_auth(struct ceph_mon_client *monc);
+
 
 
 #endif

+ 12 - 0
fs/ceph/osd_client.c

@@ -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);
 }
 
+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 = {
 	.get = get_osd_con,
@@ -1455,6 +1466,7 @@ const static struct ceph_connection_operations osd_con_ops = {
 	.dispatch = dispatch,
 	.get_authorizer = get_authorizer,
 	.verify_authorizer_reply = verify_authorizer_reply,
+	.invalidate_authorizer = invalidate_authorizer,
 	.alloc_msg = alloc_msg,
 	.fault = osd_reset,
 };

+ 6 - 6
fs/ceph/super.c

@@ -542,7 +542,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
 
 	mutex_init(&client->mount_mutex);
 
-	init_waitqueue_head(&client->mount_wq);
+	init_waitqueue_head(&client->auth_wq);
 
 	client->sb = NULL;
 	client->mount_state = CEPH_MOUNT_MOUNTING;
@@ -550,7 +550,7 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
 
 	client->msgr = NULL;
 
-	client->mount_err = 0;
+	client->auth_err = 0;
 	atomic_long_set(&client->writeback_count, 0);
 
 	err = bdi_init(&client->backing_dev_info);
@@ -742,13 +742,13 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
 
 		/* wait */
 		dout("mount waiting for mon_map\n");
-		err = wait_event_interruptible_timeout(client->mount_wq, /* FIXME */
-			       have_mon_map(client) || (client->mount_err < 0),
+		err = wait_event_interruptible_timeout(client->auth_wq,
+			       have_mon_map(client) || (client->auth_err < 0),
 			       timeout);
 		if (err == -EINTR || err == -ERESTARTSYS)
 			goto out;
-		if (client->mount_err < 0) {
-			err = client->mount_err;
+		if (client->auth_err < 0) {
+			err = client->auth_err;
 			goto out;
 		}
 	}

+ 2 - 2
fs/ceph/super.h

@@ -123,9 +123,9 @@ struct ceph_client {
 	struct super_block *sb;
 
 	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_mon_client monc;