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];
- ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
- if (ret < 0 || n == 0)
- goto out;
- PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n);
- ret = priv_decrypt(ct->key_file, crypt_buf,
- (unsigned char *)buf, n);
- if (ret < 0)
- goto out;
- hash_function((char *)crypt_buf, CHALLENGE_SIZE, challenge_hash);
+ if (ct->use_sideband) {
+ struct sb_buffer sbb;
+ ret = recv_sb(ct, &s->rfds, &sbb);
+ if (ret <= 0)
+ goto out;
+ if (sbb.band != SBD_CHALLENGE) {
+ ret = -E_BAD_BAND;
+ free(sbb.iov.iov_base);
+ goto out;
+ }
+ n = sbb.iov.iov_len;
+ PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n);
+ ret = priv_decrypt(ct->key_file, crypt_buf,
+ sbb.iov.iov_base, n);
+ free(sbb.iov.iov_base);
+ if (ret < 0)
+ goto out;
+ } else {
+ ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
+ if (ret < 0 || n == 0)
+ goto out;
+ PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n);
+ ret = priv_decrypt(ct->key_file, crypt_buf,
+ (unsigned char *)buf, n);
+ if (ret < 0)
+ goto out;
+ }
+ 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);
out:
t->error = ret;
if (ret < 0) {
- if (ret != -E_SERVER_EOF && ret != -E_BTR_EOF)
+ if (ret != -E_SERVER_EOF && ret != -E_BTR_EOF && ret != -E_EOF)
PARA_ERROR_LOG("%s\n", para_strerror(-t->error));
btr_remove_node(btrn);
}