summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
fa9e0ec)
This changes server and client to exchange the challenge response
as a sideband packet if both ends support sideband connections. The
SBD_CHALLENGE_RESPONSE designator is used for this purpose. On the
client side the changes are less intrusive due to an additional
cleanup of the state handling.
During connection setup the client's idea of the state of
the connection is monitored in the ->status variable of struct
client_task. If the client is in the CL_SENT_AUTH state, it receives
the challenge and sends the hash of the decrypted challenge back to the
server. Either operation may fail, and it seems cleaner to separate
the two. So this patch adds the new state CL_RECEIVED_CHALLENGE. The
clients enters this state once it decrypted the received challenge.
CL_RECEIVED_WELCOME,
/** Client sends the authentification request. */
CL_SENT_AUTH,
CL_RECEIVED_WELCOME,
/** Client sends the authentification request. */
CL_SENT_AUTH,
+ /** Server sends encrypted challenge. */
+ CL_RECEIVED_CHALLENGE,
/** Client solves the challenge and sends the result. */
CL_SENT_CH_RESPONSE,
/** Server accepts this authentication. */
/** Client solves the challenge and sends the result. */
CL_SENT_CH_RESPONSE,
/** Server accepts this authentication. */
bool use_sideband;
/** The sideband context, ignored if \a use_sideband is false. */
struct sb_context *sbc;
bool use_sideband;
/** The sideband context, ignored if \a use_sideband is false. */
struct sb_context *sbc;
+ /** The hash value of the decrypted challenge. */
+ unsigned char *challenge_hash;
/** The configuration (including the command). */
struct client_args_info conf;
/** The config file for client options. */
/** The configuration (including the command). */
struct client_args_info conf;
/** The config file for client options. */
free(ct->config_file);
free(ct->key_file);
client_cmdline_parser_free(&ct->conf);
free(ct->config_file);
free(ct->key_file);
client_cmdline_parser_free(&ct->conf);
+ free(ct->challenge_hash);
+ sb_free(ct->sbc);
case CL_RECEIVED_WELCOME:
case CL_RECEIVED_PROCEED:
case CL_RECEIVED_WELCOME:
case CL_RECEIVED_PROCEED:
+ case CL_RECEIVED_CHALLENGE:
para_fd_set(ct->scc.fd, &s->wfds, &s->max_fileno);
return;
para_fd_set(ct->scc.fd, &s->wfds, &s->max_fileno);
return;
/* decrypted challenge/session key buffer */
unsigned char crypt_buf[1024];
/* the SHA1 of the decrypted challenge */
/* decrypted challenge/session key buffer */
unsigned char crypt_buf[1024];
/* the SHA1 of the decrypted challenge */
- unsigned char challenge_hash[HASH_SIZE];
if (ct->use_sideband) {
struct sb_buffer sbb;
if (ct->use_sideband) {
struct sb_buffer sbb;
- hash_function((char *)crypt_buf, CHALLENGE_SIZE, challenge_hash);
+ ct->challenge_hash = para_malloc(HASH_SIZE);
+ hash_function((char *)crypt_buf, CHALLENGE_SIZE, ct->challenge_hash);
ct->scc.send = sc_new(crypt_buf + CHALLENGE_SIZE, SESSION_KEY_LEN);
ct->scc.recv = sc_new(crypt_buf + CHALLENGE_SIZE + SESSION_KEY_LEN,
SESSION_KEY_LEN);
ct->scc.send = sc_new(crypt_buf + CHALLENGE_SIZE, SESSION_KEY_LEN);
ct->scc.recv = sc_new(crypt_buf + CHALLENGE_SIZE + SESSION_KEY_LEN,
SESSION_KEY_LEN);
- hash_to_asc(challenge_hash, buf);
+ hash_to_asc(ct->challenge_hash, buf);
PARA_INFO_LOG("--> %s\n", buf);
PARA_INFO_LOG("--> %s\n", buf);
- ret = write_all(ct->scc.fd, (char *)challenge_hash, HASH_SIZE);
- if (ret < 0)
- goto out;
- ct->status = CL_SENT_CH_RESPONSE;
+ ct->status = CL_RECEIVED_CHALLENGE;
+ case CL_RECEIVED_CHALLENGE:
+ if (ct->use_sideband) {
+ ret = send_sb(ct, ct->challenge_hash, HASH_SIZE,
+ SBD_CHALLENGE_RESPONSE, false);
+ if (ret != 0)
+ ct->challenge_hash = NULL;
+ if (ret <= 0)
+ goto out;
+ } else {
+ ret = write_all(ct->scc.fd, (char *)ct->challenge_hash, HASH_SIZE);
+ if (ret < 0)
+ goto out;
+ }
+ ct->status = CL_SENT_CH_RESPONSE;
+ goto out;
case CL_SENT_CH_RESPONSE: /* read server response */
{
ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
case CL_SENT_CH_RESPONSE: /* read server response */
{
ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n",
CHALLENGE_SIZE, numbytes);
if (cc->use_sideband) {
PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n",
CHALLENGE_SIZE, numbytes);
if (cc->use_sideband) {
ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
buf = NULL;
if (ret < 0)
goto net_err;
ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
buf = NULL;
if (ret < 0)
goto net_err;
- buf = para_malloc(HANDSHAKE_BUFSIZE);
+ ret = recv_sb(&cc->scc, SBD_CHALLENGE_RESPONSE,
+ HANDSHAKE_BUFSIZE, &iov);
+ if (ret < 0)
+ goto net_err;
+ buf = iov.iov_base;
+ numbytes = iov.iov_len;
} else {
ret = write_all(fd, buf, numbytes);
if (ret < 0)
goto net_err;
} else {
ret = write_all(fd, buf, numbytes);
if (ret < 0)
goto net_err;
+ /* recv challenge response */
+ ret = recv_bin_buffer(fd, buf, HASH_SIZE);
+ if (ret < 0)
+ goto net_err;
+ numbytes = ret;
- /* recv challenge response */
- ret = recv_bin_buffer(fd, buf, HASH_SIZE);
- if (ret < 0)
- goto net_err;
- numbytes = ret;
- PARA_DEBUG_LOG("received %d bytes challenge response\n", ret);
+ PARA_DEBUG_LOG("received %zu bytes challenge response\n", numbytes);
ret = -E_BAD_USER;
if (!cc->u)
goto net_err;
ret = -E_BAD_USER;
if (!cc->u)
goto net_err;