ct->scc.recv = NULL;
sc_free(ct->scc.send);
ct->scc.send = NULL;
- btr_free_node(ct->btrn);
- ct->btrn = NULL;
+ btr_remove_node(&ct->btrn);
}
/**
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;
return features;
}
+static int dispatch_sbb(struct client_task *ct, struct sb_buffer *sbb)
+{
+ int ret;
+ const char *designator[] = {SB_DESIGNATORS_ARRAY};
+
+ if (!sbb)
+ return 0;
+ if (sbb->band < NUM_SB_DESIGNATORS)
+ PARA_DEBUG_LOG("band: %s\n", designator[sbb->band]);
+
+ switch (sbb->band) {
+ case SBD_OUTPUT:
+ if (iov_valid(&sbb->iov))
+ btr_add_output(sbb->iov.iov_base, sbb->iov.iov_len,
+ ct->btrn);
+ ret = 1;
+ goto out;
+ case SBD_DEBUG_LOG:
+ case SBD_INFO_LOG:
+ case SBD_NOTICE_LOG:
+ case SBD_WARNING_LOG:
+ case SBD_ERROR_LOG:
+ case SBD_CRIT_LOG:
+ case SBD_EMERG_LOG:
+ if (iov_valid(&sbb->iov)) {
+ int ll = sbb->band - SBD_DEBUG_LOG;
+ para_log(ll, "remote: %s", (char *)sbb->iov.iov_base);
+ }
+ ret = 1;
+ goto deallocate;
+ case SBD_EXIT__SUCCESS:
+ ret = -E_SERVER_CMD_SUCCESS;
+ goto deallocate;
+ case SBD_EXIT__FAILURE:
+ ret = -E_SERVER_CMD_FAILURE;
+ goto deallocate;
+ default:
+ PARA_ERROR_LOG("invalid band %d\n", sbb->band);
+ ret = -E_BAD_BAND;
+ goto deallocate;
+ }
+deallocate:
+ free(sbb->iov.iov_base);
+out:
+ sbb->iov.iov_base = NULL;
+ return ret;
+}
+
static bool has_feature(const char *feature, struct client_task *ct)
{
return find_arg(feature, ct->features) >= 0? true : false;
}
+static int send_sb_command(struct client_task *ct)
+{
+ int i;
+ char *command, *p;
+ size_t len = 0;
+
+ if (ct->sbc)
+ return send_sb(ct, NULL, 0, 0, false);
+
+ for (i = 0; i < ct->conf.inputs_num; i++)
+ len += strlen(ct->conf.inputs[i]) + 1;
+ p = command = para_malloc(len);
+ for (i = 0; i < ct->conf.inputs_num; i++) {
+ strcpy(p, ct->conf.inputs[i]);
+ p += strlen(ct->conf.inputs[i]) + 1;
+ }
+ PARA_DEBUG_LOG("--> %s\n", command);
+ return send_sb(ct, command, len, SBD_COMMAND, false);
+}
+
/**
* The post select hook for client commands.
*
/* 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 */
{
+ if (ct->use_sideband) {
+ struct sb_buffer sbb;
+ ret = recv_sb(ct, &s->rfds, &sbb);
+ if (ret <= 0)
+ goto out;
+ free(sbb.iov.iov_base);
+ if (sbb.band != SBD_PROCEED)
+ ret = -E_BAD_BAND;
+ else
+ ct->status = CL_RECEIVED_PROCEED;
+ goto out;
+ }
ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
if (ret < 0 || n == 0)
goto out;
char *command = NULL;
if (!FD_ISSET(ct->scc.fd, &s->wfds))
return;
+ if (ct->use_sideband) {
+ ret = send_sb_command(ct);
+ if (ret <= 0)
+ goto out;
+ ct->status = CL_SENT_COMMAND;
+ return;
+ }
for (i = 0; i < ct->conf.inputs_num; i++) {
char *tmp = command;
command = make_message("%s\n%s", command?
case CL_SENT_COMMAND:
{
char *buf2;
+ if (ct->use_sideband) {
+ struct sb_buffer sbb;
+ ret = recv_sb(ct, &s->rfds, &sbb);
+ if (ret <= 0)
+ goto out;
+ if (sbb.band == SBD_AWAITING_DATA) {
+ ct->status = CL_SENDING;
+ free(sbb.iov.iov_base);
+ goto out;
+ }
+ ct->status = CL_RECEIVING;
+ ret = dispatch_sbb(ct, &sbb);
+ goto out;
+ }
/* can not use "buf" here because we need a malloced buffer */
buf2 = para_malloc(CLIENT_BUFSIZE);
ret = client_recv_buffer(ct, &s->rfds, buf2, CLIENT_BUFSIZE, &n);
*/
if (!FD_ISSET(ct->scc.fd, &s->rfds))
return;
+ if (ct->use_sideband) {
+ struct sb_buffer sbb;
+ ret = recv_sb(ct, &s->rfds, &sbb);
+ if (ret > 0)
+ ret = dispatch_sbb(ct, &sbb);
+ goto out;
+ }
buf2 = para_malloc(CLIENT_BUFSIZE);
ret = client_recv_buffer(ct, &s->rfds, buf2, CLIENT_BUFSIZE, &n);
if (n > 0) {
out:
t->error = ret;
if (ret < 0) {
- if (ret != -E_SERVER_EOF && ret != -E_BTR_EOF)
+ if (!ct->use_sideband && ret != -E_SERVER_EOF &&
+ ret != -E_BTR_EOF && ret != -E_EOF)
PARA_ERROR_LOG("%s\n", para_strerror(-t->error));
- btr_remove_node(btrn);
+ btr_remove_node(&ct->btrn);
}
}