client_post_select(): Defer decrypting of server challenge.
authorAndre Noll <maan@systemlinux.org>
Sun, 19 Jul 2009 01:10:34 +0000 (03:10 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 19 Jul 2009 01:10:34 +0000 (03:10 +0200)
The old code worked only by pure luck: We allocated the crypt buffer on the stack as
an ordinary automatic variable. This buffer was filled right after we received the challenge
from the server, but it was used in a _subsequent_ call to client_post_select(). There's
no guarantee that the content of the crypt buffer stays the same between these two calls.

So defer the decryption until the client status is CL_RECEIVED_CHALLENGE, i.e. until
the socket file descriptor is known to be ready for sending back the SHA1 of the decrypted
challenge.

client_common.c

index eb05358..108867b 100644 (file)
@@ -141,7 +141,6 @@ static ssize_t client_recv_buffer(struct client_task *ct)
 static void client_post_select(struct sched *s, struct task *t)
 {
        struct client_task *ct = container_of(t, struct client_task, task);
-       unsigned char crypt_buf[1024];
 
        t->error = 0;
        if (ct->rc4c.fd < 0)
@@ -172,23 +171,26 @@ static void client_post_select(struct sched *s, struct task *t)
                t->error = client_recv_buffer(ct);
                if (t->error < 0)
                        goto err;
-               PARA_INFO_LOG("<-- [challenge] (%d bytes)\n", t->error);
-               /* decrypt challenge/rc4 buffer  */
+               ct->loaded = t->error;
+               PARA_INFO_LOG("<-- [challenge] (%d bytes)\n", ct->loaded);
+               ct->status = CL_RECEIVED_CHALLENGE;
+               return;
+       case CL_RECEIVED_CHALLENGE:
+               {
+               /* decrypted challenge/rc4 buffer */
+               unsigned char crypt_buf[1024];
+               /* the SHA1 of the decrypted challenge */
+               unsigned char challenge_sha1[HASH_SIZE];
+
                t->error = para_decrypt_buffer(ct->key_file, crypt_buf,
-                       (unsigned char *)ct->buf, t->error);
+                       (unsigned char *)ct->buf, ct->loaded);
                if (t->error < 0)
                        goto err;
-               ct->status = CL_RECEIVED_CHALLENGE;
+               sha1_hash((char *)crypt_buf, CHALLENGE_SIZE, challenge_sha1);
                RC4_set_key(&ct->rc4c.send_key, RC4_KEY_LEN,
                        crypt_buf + CHALLENGE_SIZE);
                RC4_set_key(&ct->rc4c.recv_key, RC4_KEY_LEN,
                        crypt_buf + CHALLENGE_SIZE + RC4_KEY_LEN);
-               return;
-       case CL_RECEIVED_CHALLENGE:
-               {
-               unsigned char challenge_sha1[HASH_SIZE];
-               /* send sha1 of decrypted challenge */
-               sha1_hash((char *)crypt_buf, CHALLENGE_SIZE, challenge_sha1);
                hash_to_asc(challenge_sha1, ct->buf);
                PARA_INFO_LOG("--> %s\n", ct->buf);
                t->error = send_bin_buffer(ct->rc4c.fd, (char *)challenge_sha1,