[PATCH] chunkd: change net protocol to support arbitrary keys

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Incompatible network protocol change just committed...



commit 6fb485cbffcf61d73b0cfe7effbf88c9e0b48377
Author: Jeff Garzik <jeff@xxxxxxxxxx>
Date:   Thu Nov 5 00:06:16 2009 -0500

    Change protocol to permit arbitrary binary keys, up to 1K in size.
    
    Also,
    - remove several unused struct members from struct chunksrv_resp.
    - improve client disconnect logging
    
    Signed-off-by: Jeff Garzik <jgarzik@xxxxxxxxxx>

diff --git a/include/chunk_msg.h b/include/chunk_msg.h
index 4222f27..0efe7a3 100644
--- a/include/chunk_msg.h
+++ b/include/chunk_msg.h
@@ -8,7 +8,7 @@
 enum {
 	CHD_MAGIC_SZ		= 8,
 	CHD_USER_SZ		= 64,
-	CHD_KEY_SZ		= 64,
+	CHD_KEY_SZ		= 1024,
 	CHD_CSUM_SZ		= 64,
 	CHD_SIG_SZ		= 64,
 };
@@ -38,23 +38,22 @@ enum errcode {
 struct chunksrv_req {
 	uint8_t			magic[CHD_MAGIC_SZ];	/* CHUNKD_MAGIC */
 	uint8_t			op;			/* CHO_xxx */
-	uint8_t			rsv1[3];
+	uint8_t			rsv1[1];
+	uint16_t		key_len;
 	uint32_t		nonce;	/* random number, to stir checksum */
 	uint64_t		data_len;		/* len of addn'l data */
 	char			user[CHD_USER_SZ];	/* username */
-	char			key[CHD_KEY_SZ];	/* object id */
 	char			sig[CHD_SIG_SZ];	/* HMAC signature */
+
+	/* variable-length key */
 };
 
 struct chunksrv_resp {
 	uint8_t			magic[CHD_MAGIC_SZ];	/* CHUNKD_MAGIC */
-	uint8_t			op;			/* CHO_xxx */
 	uint8_t			resp_code;		/* errcode's */
-	uint8_t			rsv1[2];
-	uint32_t		nonce;	/* random number, to stir checksum */
+	uint8_t			rsv1[3];
+	uint32_t		nonce;	/* txn id, copied from request */
 	uint64_t		data_len;		/* len of addn'l data */
-	char			user[CHD_USER_SZ];	/* username */
-	char			key[CHD_KEY_SZ];	/* object id */
 	char			checksum[CHD_CSUM_SZ];	/* SHA1 checksum */
 };
 
diff --git a/include/chunkc.h b/include/chunkc.h
index d815ce0..1cc8cc7 100644
--- a/include/chunkc.h
+++ b/include/chunkc.h
@@ -32,7 +32,7 @@ struct st_client {
 	SSL_CTX		*ssl_ctx;
 	SSL		*ssl;
 
-	char		req_buf[sizeof(struct chunksrv_req)];
+	char		req_buf[sizeof(struct chunksrv_req) + CHD_KEY_SZ];
 };
 
 extern void stc_free(struct st_client *stc);
diff --git a/lib/chunkdc.c b/lib/chunkdc.c
index a2df1e0..73731d4 100644
--- a/lib/chunkdc.c
+++ b/lib/chunkdc.c
@@ -45,12 +45,10 @@ static void req_init(struct st_client *stc, struct chunksrv_req *req)
 }
 
 static void req_set_key(struct chunksrv_req *req, const void *key,
-			size_t key_len)
+			uint16_t key_len)
 {
-	/* length must include nul, and already be checked for range
-	 * validity
-	 */
-	memcpy(req->key, key, key_len);
+	req->key_len = GUINT16_TO_LE(key_len);
+	memcpy((req + 1), key, key_len);
 }
 
 static bool net_read(struct st_client *stc, void *data, size_t datalen)
diff --git a/lib/chunksrv.c b/lib/chunksrv.c
index d6482b2..cd8a093 100644
--- a/lib/chunksrv.c
+++ b/lib/chunksrv.c
@@ -7,7 +7,11 @@
 
 size_t req_len(const struct chunksrv_req *req)
 {
-	return sizeof(*req);
+	size_t len;
+
+	len = sizeof(struct chunksrv_req) + GUINT16_FROM_LE(req->key_len);
+
+	return len;
 }
 
 void chreq_sign(struct chunksrv_req *req, const char *key, char *b64hmac_out)
@@ -17,7 +21,7 @@ void chreq_sign(struct chunksrv_req *req, const char *key, char *b64hmac_out)
 	int save = 0, state = 0, b64_len;
 	const void *p = req;
 
-	HMAC(EVP_sha1(), key, strlen(key), p, sizeof(*req), md, &len);
+	HMAC(EVP_sha1(), key, strlen(key), p, req_len(req), md, &len);
 
 	b64_len = g_base64_encode_step(md, len, FALSE, b64hmac_out,
 				       &state, &save);
diff --git a/server/chunkd.h b/server/chunkd.h
index 8e666e7..d56e5da 100644
--- a/server/chunkd.h
+++ b/server/chunkd.h
@@ -60,7 +60,8 @@ struct client_write {
 
 /* internal client socket state */
 enum client_state {
-	evt_read_req,				/* read request line */
+	evt_read_fixed,				/* read fixed-len rec */
+	evt_read_var,				/* read variable-len rec */
 	evt_exec_req,				/* execute request */
 	evt_data_in,				/* request's content */
 	evt_dispose,				/* dispose of client */
@@ -85,6 +86,7 @@ struct client {
 	struct chunksrv_req	creq;
 	unsigned int		req_used;	/* amount of req_buf in use */
 	void			*req_ptr;	/* start of unexamined data */
+	uint16_t		key_len;
 
 	char			*hdr_start;	/* current hdr start */
 	char			*hdr_end;	/* current hdr end (so far) */
@@ -103,6 +105,7 @@ struct client {
 
 	char			netbuf[CLI_DATA_BUF_SZ];
 	char			netbuf_out[CLI_DATA_BUF_SZ];
+	char			key[CHD_KEY_SZ];
 };
 
 struct backend_obj {
diff --git a/server/object.c b/server/object.c
index 0792b66..62a1acb 100644
--- a/server/object.c
+++ b/server/object.c
@@ -17,7 +17,6 @@ static bool object_get_more(struct client *cli, struct client_write *wr,
 
 bool object_del(struct client *cli)
 {
-	const char *obj_key = cli->creq.key;
 	int rc;
 	enum errcode err = InternalError;
 	bool rcb;
@@ -31,8 +30,7 @@ bool object_del(struct client *cli)
 
 	resp_init_req(resp, &cli->creq);
 
-	rcb = fs_obj_delete(cli->creq.user, obj_key,
-			    strnlen(obj_key, CHD_KEY_SZ), &err);
+	rcb = fs_obj_delete(cli->creq.user, cli->key, cli->key_len, &err);
 	if (!rcb)
 		return cli_err(cli, err, true);
 
@@ -192,14 +190,13 @@ bool cli_evt_data_in(struct client *cli, unsigned int events)
 bool object_put(struct client *cli)
 {
 	const char *user = cli->creq.user;
-	const char *key = cli->creq.key;
 	uint64_t content_len = le64_to_cpu(cli->creq.data_len);
 	enum errcode err;
 
 	if (!user)
 		return cli_err(cli, AccessDenied, true);
 
-	cli->out_bo = fs_obj_new(key, strnlen(key, CHD_KEY_SZ), &err);
+	cli->out_bo = fs_obj_new(cli->key, cli->key_len, &err);
 	if (!cli->out_bo)
 		return cli_err(cli, err, true);
 
@@ -277,7 +274,6 @@ err_out_buf:
 
 bool object_get(struct client *cli, bool want_body)
 {
-	const char *obj_key = cli->creq.key;
 	int rc;
 	enum errcode err = InternalError;
 	struct backend_obj *obj;
@@ -291,8 +287,8 @@ bool object_get(struct client *cli, bool want_body)
 
 	resp_init_req(&get_resp->resp, &cli->creq);
 
-	cli->in_obj = obj = fs_obj_open(cli->creq.user, obj_key,
-					strnlen(obj_key, CHD_KEY_SZ), &err);
+	cli->in_obj = obj = fs_obj_open(cli->creq.user, cli->key,
+					cli->key_len, &err);
 	if (!obj) {
 		free(get_resp);
 		return cli_err(cli, err, true);
diff --git a/server/server.c b/server/server.c
index b2911b2..0fc138e 100644
--- a/server/server.c
+++ b/server/server.c
@@ -274,11 +274,8 @@ void resp_init_req(struct chunksrv_resp *resp,
 {
 	memset(resp, 0, sizeof(*resp));
 	memcpy(resp->magic, req->magic, CHD_MAGIC_SZ);
-	resp->op = req->op;
 	resp->nonce = req->nonce;
 	resp->data_len = req->data_len;
-	strncpy(resp->user, req->user, CHD_USER_SZ);
-	strncpy(resp->key, req->key, CHD_KEY_SZ);
 }
 
 static bool cli_write_free(struct client *cli, struct client_write *tmp,
@@ -316,6 +313,8 @@ static void cli_write_free_all(struct client *cli)
 
 static void cli_free(struct client *cli)
 {
+	applog(LOG_INFO, "client %s disconnected", cli->addr_host);
+
 	cli_write_free_all(cli);
 
 	cli_out_end(cli);
@@ -325,8 +324,10 @@ static void cli_free(struct client *cli)
 	if (cli->fd >= 0) {
 		if (cli->ssl)
 			SSL_shutdown(cli->ssl);
-		srv_poll_del(cli->fd);
-		close(cli->fd);
+		if (!srv_poll_del(cli->fd))
+			applog(LOG_ERR, "TCP cli poll del failed");
+		if (close(cli->fd) < 0)
+			syslogerr("close(2) TCP client socket");
 	}
 
 	if (debugging)
@@ -356,7 +357,7 @@ static struct client *cli_alloc(bool use_ssl)
 		}
 	}
 
-	cli->state = evt_read_req;
+	cli->state = evt_read_fixed;
 	INIT_LIST_HEAD(&cli->write_q);
 	cli->req_ptr = &cli->creq;
 
@@ -378,7 +379,7 @@ static bool cli_evt_recycle(struct client *cli, unsigned int events)
 {
 	cli->req_ptr = &cli->creq;
 	cli->req_used = 0;
-	cli->state = evt_read_req;
+	cli->state = evt_read_fixed;
 
 	return true;
 }
@@ -793,18 +794,21 @@ static bool volume_list(struct client *cli)
 	return rcb;
 }
 
-static bool authcheck(const struct chunksrv_req *req)
+static bool authcheck(const struct chunksrv_req *req, const void *key,
+		      size_t key_len)
 {
-	struct chunksrv_req tmpreq;
+	char req_buf[sizeof(struct chunksrv_req) + CHD_KEY_SZ];
+	struct chunksrv_req *tmpreq = (struct chunksrv_req *) req_buf;
 	char hmac[64];
 
-	memcpy(&tmpreq, req, sizeof(tmpreq));
-	memset(&tmpreq.sig, 0, sizeof(tmpreq.sig));
+	memcpy(tmpreq, req, sizeof(*req));
+	memcpy((tmpreq + 1), key, key_len);
+	memset(tmpreq->sig, 0, sizeof(tmpreq->sig));
 
 	/* for lack of a better authentication scheme, we
 	 * supply the username as the secret key
 	 */
-	chreq_sign(&tmpreq, req->user, hmac);
+	chreq_sign(tmpreq, req->user, hmac);
 
 	return strcmp(req->sig, hmac) ? false : true;
 }
@@ -820,10 +824,6 @@ static bool valid_req_hdr(const struct chunksrv_req *req)
 	if (len < 1 || len == sizeof(req->user))
 		return false;
 
-	len = strnlen(req->key, sizeof(req->key));
-	if (len == sizeof(req->key))
-		return false;
-
 	len = strnlen(req->sig, sizeof(req->sig));
 	if (len < 1 || len == sizeof(req->sig))
 		return false;
@@ -862,7 +862,7 @@ static bool cli_evt_exec_req(struct client *cli, unsigned int events)
 	}
 
 	/* check authentication */
-	if (!authcheck(req)) {
+	if (!authcheck(req, cli->key, cli->key_len)) {
 		err = SignatureDoesNotMatch;
 		goto err_out;
 	}
@@ -870,9 +870,10 @@ static bool cli_evt_exec_req(struct client *cli, unsigned int events)
 	cli->state = evt_recycle;
 
 	if (debugging)
-		applog(LOG_DEBUG, "REQ(op %s, key %s, user %s) seq %x len %lld",
+		applog(LOG_DEBUG, "REQ(op %s, key %s (%u), user %s) seq %x len %lld",
 		       op2str(req->op),
-		       req->key,
+		       cli->key,
+		       cli->key_len,
 		       req->user,
 		       req->nonce,
 		       (long long) le64_to_cpu(req->data_len));
@@ -912,7 +913,7 @@ err_out:
 	goto out;
 }
 
-static bool cli_evt_read_req(struct client *cli, unsigned int events)
+static bool cli_evt_read_fixed(struct client *cli, unsigned int events)
 {
 	int rc = cli_read_data(cli, cli->req_ptr,
 			       sizeof(cli->creq) - cli->req_used);
@@ -928,6 +929,38 @@ static bool cli_evt_read_req(struct client *cli, unsigned int events)
 	if (cli->req_used < sizeof(struct chunksrv_req))
 		return false;
 
+	cli->key_len = GUINT16_FROM_LE(cli->creq.key_len);
+
+	/* if no key, skip to execute-request state */
+	if (cli->key_len == 0) {
+		cli->state = evt_exec_req;
+		return true;
+	}
+
+	/* otherwise, go to read-variable-len-record state */
+	cli->req_ptr = &cli->key;
+	cli->req_used = 0;
+	cli->state = evt_read_var;
+
+	return true;
+}
+
+static bool cli_evt_read_var(struct client *cli, unsigned int events)
+{
+	int rc = cli_read_data(cli, cli->req_ptr,
+			       cli->key_len - cli->req_used);
+	if (rc < 0) {
+		cli->state = evt_dispose;
+		return true;
+	}
+
+	cli->req_ptr += rc;
+	cli->req_used += rc;
+
+	/* poll for more, if variable-length record not yet received */
+	if (cli->req_used < cli->key_len)
+		return false;
+
 	cli->state = evt_exec_req;
 
 	return true;
@@ -939,7 +972,7 @@ static bool cli_evt_ssl_accept(struct client *cli, unsigned int events)
 
 	rc = SSL_accept(cli->ssl);
 	if (rc > 0) {
-		cli->state = evt_read_req;
+		cli->state = evt_read_fixed;
 		return true;
 	}
 
@@ -961,7 +994,8 @@ out:
 }
 
 static cli_evt_func state_funcs[] = {
-	[evt_read_req]		= cli_evt_read_req,
+	[evt_read_fixed]	= cli_evt_read_fixed,
+	[evt_read_var]		= cli_evt_read_var,
 	[evt_exec_req]		= cli_evt_exec_req,
 	[evt_data_in]		= cli_evt_data_in,
 	[evt_dispose]		= cli_evt_dispose,
--
To unsubscribe from this list: send the line "unsubscribe hail-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Fedora Clound]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux