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. */
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. */
free(ct->config_file);
free(ct->key_file);
client_cmdline_parser_free(&ct->conf);
+ free(ct->challenge_hash);
+ sb_free(ct->sbc);
free(ct);
}
case CL_RECEIVED_WELCOME:
case CL_RECEIVED_PROCEED:
+ case CL_RECEIVED_CHALLENGE:
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 */
- unsigned char challenge_hash[HASH_SIZE];
if (ct->use_sideband) {
struct sb_buffer sbb;
if (ret < 0)
goto out;
}
- 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);
- hash_to_asc(challenge_hash, buf);
+ hash_to_asc(ct->challenge_hash, 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;
return;
}
+ 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);
PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n",
CHALLENGE_SIZE, numbytes);
if (cc->use_sideband) {
+ struct iovec iov;
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;
+ /* 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;