/** \file client_common.c Common functions of para_client and para_audiod. */
+#include <regex.h>
#include <sys/types.h>
#include <dirent.h>
#include <openssl/rc4.h>
#include "string.h"
#include "client.cmdline.h"
#include "client.h"
+#include "hash.h"
/**
* Close the connection to para_server and free all resources.
{
ssize_t ret;
- if (ct->status < CL_RECEIVED_PROCEED)
+ if (ct->status < CL_SENT_CH_RESPONSE)
ret = recv_buffer(ct->rc4c.fd, ct->buf + ct->loaded,
CLIENT_BUFSIZE - ct->loaded);
else
if (ret > 0)
ct->loaded += ret;
return ret;
-
}
/**
switch (ct->status) {
case CL_CONNECTED: /* receive welcome message */
t->error = client_recv_buffer(ct);
- if (t->error > 0)
- ct->status = CL_RECEIVED_WELCOME;
+ if (t->error < 0)
+ goto err;
+ ct->status = CL_RECEIVED_WELCOME;
return;
case CL_RECEIVED_WELCOME: /* send auth command */
- sprintf(ct->buf, "auth rc4 %s", ct->user);
+ sprintf(ct->buf, AUTH_REQUEST_MSG "%s", ct->user);
PARA_INFO_LOG("--> %s\n", ct->buf);
t->error = send_buffer(ct->rc4c.fd, ct->buf);
- if (t->error >= 0)
- ct->status = CL_SENT_AUTH;
+ if (t->error < 0)
+ goto err;
+ ct->status = CL_SENT_AUTH;
return;
- case CL_SENT_AUTH: /* receive challenge number */
+ case CL_SENT_AUTH: /* receive challenge and rc4 keys */
ct->loaded = 0;
t->error = client_recv_buffer(ct);
if (t->error < 0)
- return;
- if (t->error != 64) {
- t->error = -E_INVALID_CHALLENGE;
- PARA_ERROR_LOG("received the following: %s\n", ct->buf);
- return;
- }
- PARA_INFO_LOG("<-- [challenge]\n");
- /* decrypt challenge number */
- t->error = para_decrypt_challenge(ct->key_file, &ct->challenge_nr,
- (unsigned char *) ct->buf, 64);
- if (t->error > 0)
- ct->status = CL_RECEIVED_CHALLENGE;
+ goto err;
+ ct->loaded = t->error;
+ PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", ct->loaded);
+ ct->status = CL_RECEIVED_CHALLENGE;
return;
- case CL_RECEIVED_CHALLENGE: /* send decrypted challenge */
- PARA_INFO_LOG("--> %lu\n", ct->challenge_nr);
- t->error = send_va_buffer(ct->rc4c.fd, "%s%lu", CHALLENGE_RESPONSE_MSG,
- ct->challenge_nr);
- if (t->error > 0)
- ct->status = CL_SENT_CH_RESPONSE;
+ 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, ct->loaded);
+ if (t->error < 0)
+ goto err;
+ 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);
+ 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,
+ HASH_SIZE);
+ if (t->error < 0)
+ goto err;
+ ct->status = CL_SENT_CH_RESPONSE;
return;
+ }
case CL_SENT_CH_RESPONSE: /* read server response */
{
size_t bytes_received;
- unsigned char rc4_buf[2 * RC4_KEY_LEN] = "";
ct->loaded = 0;
t->error = client_recv_buffer(ct);
if (t->error < 0)
- return;
+ goto err;
bytes_received = t->error;
- PARA_DEBUG_LOG("++++ server info ++++\n%s\n++++ end of server "
- "info ++++\n", ct->buf);
- /* check if server has sent "Proceed" message and the rc4 keys */
+ /* check if server has sent "Proceed" message */
t->error = -E_CLIENT_AUTH;
- if (bytes_received < PROCEED_MSG_LEN + 2 * RC4_KEY_LEN)
- return;
+ if (bytes_received < PROCEED_MSG_LEN)
+ goto err;
if (!strstr(ct->buf, PROCEED_MSG))
- return;
- PARA_INFO_LOG("decrypting session key\n");
- t->error = para_decrypt_buffer(ct->key_file, rc4_buf,
- (unsigned char *)ct->buf + PROCEED_MSG_LEN + 1,
- bytes_received - PROCEED_MSG_LEN - 1);
- if (t->error < 0)
- return;
- RC4_set_key(&ct->rc4c.send_key, RC4_KEY_LEN, rc4_buf);
- RC4_set_key(&ct->rc4c.recv_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
+ goto err;
ct->status = CL_RECEIVED_PROCEED;
+ t->error = 0;
return;
}
case CL_RECEIVED_PROCEED: /* concat args and send command */
PARA_DEBUG_LOG("--> %s\n", command);
t->error = rc4_send_buffer(&ct->rc4c, command);
free(command);
- if (t->error > 0)
- ct->status = CL_SENT_COMMAND;
+ if (t->error < 0)
+ goto err;
+ ct->status = CL_SENT_COMMAND;
return;
}
case CL_SENT_COMMAND:
ct->loaded = 0;
t->error = client_recv_buffer(ct);
if (t->error < 0)
- return;
+ goto err;
if (strstr(ct->buf, AWAITING_DATA_MSG))
ct->status = CL_SENDING;
else
ct->status = CL_RECEIVING;
return;
- case CL_SENDING: /* FIXME: might block */
+ case CL_SENDING:
PARA_INFO_LOG("loaded: %zd\n", *ct->in_loaded);
- t->error = rc4_send_bin_buffer(&ct->rc4c, ct->inbuf, *ct->in_loaded);
+ t->error = rc4_send_bin_buffer(&ct->rc4c, ct->inbuf,
+ *ct->in_loaded);
if (t->error < 0)
- return;
+ goto err;
*ct->in_loaded = 0;
return;
case CL_RECEIVING:
t->error = client_recv_buffer(ct);
+ if (t->error < 0)
+ goto err;
return;
}
+err:
+ if (t->error != -E_SERVER_EOF)
+ PARA_ERROR_LOG("%s\n", para_strerror(-t->error));
}
/* connect to para_server and register the client task */