Just committed...


commit 8ee54c1631af713bc11426400a405d948ce71ffc
Author: Jeff Garzik <[email protected]>
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 <[email protected]>

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;
--
To unsubscribe from this list: send the line "unsubscribe hail-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to