[prev in list] [next in list] [prev in thread] [next in thread]
List: hail-devel
Subject: [PATCH] chunkd: change net protocol to support arbitrary keys
From: Jeff Garzik <jeff () garzik ! org>
Date: 2009-11-05 5:10:25
Message-ID: 20091105051025.GA23171 () havoc ! gtf ! org
[Download RAW message or body]
Incompatible network protocol change just committed...
commit 6fb485cbffcf61d73b0cfe7effbf88c9e0b48377
Author: Jeff Garzik <jeff@garzik.org>
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@redhat.com>
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@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic