/* 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;
+ 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;
+ }
hash_function((char *)crypt_buf, CHALLENGE_SIZE, 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,
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);
}
return ret;
}
+#define HANDSHAKE_BUFSIZE 4096
+
/**
* Perform user authentication and execute a command.
*
__noreturn void handle_connect(int fd, const char *peername)
{
int ret;
- char buf[4096];
unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN];
unsigned char challenge_hash[HASH_SIZE];
- char *p, *command = NULL;
+ char *p, *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */;
size_t numbytes;
struct command_context cc_struct = {.peer = peername}, *cc = &cc_struct;
if (ret < 0)
goto net_err;
/* recv auth request line */
- ret = recv_buffer(fd, buf, sizeof(buf));
+ ret = recv_buffer(fd, buf, HANDSHAKE_BUFSIZE);
if (ret < 0)
goto net_err;
ret = parse_auth_request(buf, ret, &cc->u, &cc->use_sideband);
}
PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n",
CHALLENGE_SIZE, numbytes);
- ret = write_all(fd, buf, numbytes);
- if (ret < 0)
- goto net_err;
+ if (cc->use_sideband) {
+ ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
+ buf = NULL;
+ if (ret < 0)
+ goto net_err;
+ buf = para_malloc(HANDSHAKE_BUFSIZE);
+ } 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)
net_err:
PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
out:
+ free(buf);
free(command);
sc_free(cc->scc.recv);
sc_free(cc->scc.send);