All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] chunkd: add LOGIN message, don't send username in each request
@ 2009-11-10  8:00 Jeff Garzik
  0 siblings, 0 replies; only message in thread
From: Jeff Garzik @ 2009-11-10  8:00 UTC (permalink / raw)
  To: hail-devel


Just committed...



commit 8ee54c1631af713bc11426400a405d948ce71ffc
Author: Jeff Garzik <jeff@garzik.org>
Date:   Tue Nov 10 02:56:17 2009 -0500

    Add LOGIN request, and stop sending username in each message.
    
    The per-request message header shrinks by 64 bytes.
    
    This is an incompatible network protocol change, but the programming
    API stays unchanged.
    
    Also,
    libchunkdc: better validation of stc_new() arguments
    
    Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

diff --git a/include/chunk_msg.h b/include/chunk_msg.h
index 25e1f9b..90272ca 100644
--- a/include/chunk_msg.h
+++ b/include/chunk_msg.h
@@ -20,6 +20,7 @@ enum chunksrv_ops {
 	CHO_PUT			= 3,
 	CHO_DEL			= 4,
 	CHO_LIST		= 5,
+	CHO_LOGIN		= 6,
 };
 
 enum chunk_errcode {
@@ -44,7 +45,6 @@ struct chunksrv_req {
 	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			sig[CHD_SIG_SZ];	/* HMAC signature */
 
 	/* variable-length key */
diff --git a/lib/chunkdc.c b/lib/chunkdc.c
index efbf77b..1597e91 100644
--- a/lib/chunkdc.c
+++ b/lib/chunkdc.c
@@ -49,7 +49,6 @@ static void req_init(struct st_client *stc, struct chunksrv_req *req)
 	memset(req, 0, sizeof(*req));
 	memcpy(req->magic, CHUNKD_MAGIC, CHD_MAGIC_SZ);
 	req->nonce = rand();
-	strcpy(req->user, stc->user);
 }
 
 static void req_set_key(struct chunksrv_req *req, const void *key,
@@ -138,6 +137,41 @@ void stc_free(struct st_client *stc)
 	free(stc);
 }
 
+static bool stc_login(struct st_client *stc)
+{
+	struct chunksrv_resp resp;
+	struct chunksrv_req *req = (struct chunksrv_req *) stc->req_buf;
+
+	if (stc->verbose)
+		fprintf(stderr, "libstc: LOGIN\n");
+
+	/* initialize request; username is sent as key/key_len */
+	req_init(stc, req);
+	req->op = CHO_LOGIN;
+	req_set_key(req, stc->user, strlen(stc->user) + 1);
+
+	/* sign request */
+	chreq_sign(req, stc->key, req->sig);
+
+	/* write request */
+	if (!net_write(stc, req, req_len(req)))
+		return false;
+
+	/* read response header */
+	if (!net_read(stc, &resp, sizeof(resp)))
+		return false;
+
+	/* check response code */
+	if (resp.resp_code != che_Success) {
+		if (stc->verbose)
+			fprintf(stderr, "LOGIN failed, resp code: %d\n",
+				resp.resp_code);
+		return false;
+	}
+
+	return true;
+}
+
 struct st_client *stc_new(const char *service_host, int port,
 			  const char *user, const char *secret_key,
 			  bool use_ssl)
@@ -147,6 +181,12 @@ struct st_client *stc_new(const char *service_host, int port,
 	int rc, fd = -1, on = 1;
 	char port_str[32];
 
+	if (!service_host || !*service_host ||
+	    port < 1 || port > 65535 ||
+	    !user || !*user ||
+	    !secret_key || !*secret_key)
+		return NULL;
+
 	sprintf(port_str, "%d", port);
 
 	memset(&hints, 0, sizeof(hints));
@@ -211,6 +251,9 @@ struct st_client *stc_new(const char *service_host, int port,
 			goto err_out_ssl;
 	}
 
+	if (!stc_login(stc))
+		goto err_out_ssl;
+
 	return stc;
 
 err_out_ssl:
diff --git a/server/chunkd.h b/server/chunkd.h
index e7e2115..d6b37c6 100644
--- a/server/chunkd.h
+++ b/server/chunkd.h
@@ -76,6 +76,8 @@ struct client {
 	char			addr_host[64];	/* ASCII version of inet addr */
 	int			fd;		/* socket */
 
+	char			user[CHD_USER_SZ + 1];
+
 	SSL			*ssl;
 	bool			read_want_write;
 	bool			write_want_read;
diff --git a/server/object.c b/server/object.c
index 5ca7a19..23b0aa9 100644
--- a/server/object.c
+++ b/server/object.c
@@ -30,7 +30,7 @@ bool object_del(struct client *cli)
 
 	resp_init_req(resp, &cli->creq);
 
-	rcb = fs_obj_delete(cli->creq.user, cli->key, cli->key_len, &err);
+	rcb = fs_obj_delete(cli->user, cli->key, cli->key_len, &err);
 	if (!rcb)
 		return cli_err(cli, err, true);
 
@@ -189,7 +189,7 @@ 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 *user = cli->user;
 	uint64_t content_len = le64_to_cpu(cli->creq.data_len);
 	enum chunk_errcode err;
 
@@ -286,7 +286,7 @@ 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, cli->key,
+	cli->in_obj = obj = fs_obj_open(cli->user, cli->key,
 					cli->key_len, &err);
 	if (!obj) {
 		free(get_resp);
diff --git a/server/server.c b/server/server.c
index 76c007f..2d9095f 100644
--- a/server/server.c
+++ b/server/server.c
@@ -728,7 +728,7 @@ static bool volume_list(struct client *cli)
 	bool rcb;
 	GList *res = NULL;
 
-	res = fs_list_objs(cli->creq.user);
+	res = fs_list_objs(cli->user);
 
 	s = g_markup_printf_escaped(
 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
@@ -785,7 +785,7 @@ static bool volume_list(struct client *cli)
 }
 
 static bool authcheck(const struct chunksrv_req *req, const void *key,
-		      size_t key_len)
+		      size_t key_len, const char *secret_key)
 {
 	char req_buf[sizeof(struct chunksrv_req) + CHD_KEY_SZ];
 	struct chunksrv_req *tmpreq = (struct chunksrv_req *) req_buf;
@@ -795,12 +795,39 @@ static bool authcheck(const struct chunksrv_req *req, const void *key,
 	memcpy((tmpreq + 1), key, key_len);
 	memset(tmpreq->sig, 0, sizeof(tmpreq->sig));
 
+	chreq_sign(tmpreq, secret_key, hmac);
+
+	return strcmp(req->sig, hmac) ? false : true;
+}
+
+static bool login_user(struct client *cli)
+{
+	struct chunksrv_req *req = &cli->creq;
+	enum chunk_errcode err;
+
+	/* validate username length */
+	if (cli->key_len < 1 || cli->key_len > CHD_USER_SZ) {
+		err = che_InvalidArgument;
+		cli->state = evt_dispose;
+		goto err_out;
+	}
+
+	memset(cli->user, 0, sizeof(cli->user));
+	memcpy(cli->user, cli->key, cli->key_len);
+
 	/* for lack of a better authentication scheme, we
 	 * supply the username as the secret key
 	 */
-	chreq_sign(tmpreq, req->user, hmac);
+	if (!authcheck(req, cli->key, cli->key_len, cli->user)) {
+		err = che_SignatureDoesNotMatch;
+		cli->state = evt_dispose;
+		goto err_out;
+	}
 
-	return strcmp(req->sig, hmac) ? false : true;
+	return cli_err(cli, che_Success, true);
+
+err_out:
+	return cli_err(cli, err, false);
 }
 
 static bool valid_req_hdr(const struct chunksrv_req *req)
@@ -810,10 +837,6 @@ static bool valid_req_hdr(const struct chunksrv_req *req)
 	if (memcmp(req->magic, CHUNKD_MAGIC, CHD_MAGIC_SZ))
 		return false;
 
-	len = strnlen(req->user, sizeof(req->user));
-	if (len < 1 || len == sizeof(req->user))
-		return false;
-
 	len = strnlen(req->sig, sizeof(req->sig));
 	if (len < 1 || len == sizeof(req->sig))
 		return false;
@@ -830,6 +853,7 @@ static const char *op2str(enum chunksrv_ops op)
 	case CHO_PUT:		return "CHO_PUT";
 	case CHO_DEL:		return "CHO_DEL";
 	case CHO_LIST:		return "CHO_LIST";
+	case CHO_LOGIN:		return "CHO_LOGIN";
 
 	default:
 		return "BUG/UNKNOWN!";
@@ -844,6 +868,7 @@ static bool cli_evt_exec_req(struct client *cli, unsigned int events)
 	struct chunksrv_req *req = &cli->creq;
 	bool rcb;
 	enum chunk_errcode err;
+	bool logged_in = (cli->user[0] != 0);
 
 	/* validate request header */
 	if (!valid_req_hdr(req)) {
@@ -851,27 +876,41 @@ static bool cli_evt_exec_req(struct client *cli, unsigned int events)
 		goto err_out;
 	}
 
+	if (debugging)
+		applog(LOG_DEBUG, "REQ(op %s, key %s (%u), user %s) "
+		       "seq %x len %lld login %s",
+		       op2str(req->op),
+		       cli->key,
+		       cli->key_len,
+		       cli->user,
+		       req->nonce,
+		       (long long) le64_to_cpu(req->data_len),
+		       logged_in ? "Y" : "N");
+
 	/* check authentication */
-	if (!authcheck(req, cli->key, cli->key_len)) {
+	/* for lack of a better authentication scheme, we
+	 * supply the username as the secret key
+	 */
+	if (logged_in &&
+	    !authcheck(req, cli->key, cli->key_len, cli->user)) {
 		err = che_SignatureDoesNotMatch;
 		goto err_out;
 	}
 
 	cli->state = evt_recycle;
 
-	if (debugging)
-		applog(LOG_DEBUG, "REQ(op %s, key %s (%u), user %s) seq %x len %lld",
-		       op2str(req->op),
-		       cli->key,
-		       cli->key_len,
-		       req->user,
-		       req->nonce,
-		       (long long) le64_to_cpu(req->data_len));
+	if (G_UNLIKELY((!logged_in) && (req->op != CHO_LOGIN))) {
+		cli->state = evt_dispose;
+		return true;
+	}
 
 	/*
 	 * operations on objects
 	 */
 	switch (req->op) {
+	case CHO_LOGIN:
+		rcb = login_user(cli);
+		break;
 	case CHO_NOP:
 		rcb = cli_err(cli, che_Success, true);
 		break;

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2009-11-10  8:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-10  8:00 [PATCH] chunkd: add LOGIN message, don't send username in each request Jeff Garzik

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.