+ PARA_INFO_LOG("status %d\n", p->status);
+ t->ret = 1;
+ if (p->fd < 0)
+ return;
+ if (!p->check_r && !p->check_w)
+ return;
+ if (p->check_r && !FD_ISSET(p->fd, &s->rfds))
+ return;
+ if (p->check_w && !FD_ISSET(p->fd, &s->wfds))
+ return;
+ switch (p->status) {
+ case CL_CONNECTED: /* receive welcome message */
+ t->ret = client_recv_buffer(p);
+ if (t->ret > 0)
+ p->status = CL_RECEIVED_WELCOME;
+ return;
+ case CL_RECEIVED_WELCOME: /* send auth command */
+ sprintf(p->buf, "auth %s%s", p->conf.plain_given?
+ "" : "rc4 ", p->user);
+ PARA_INFO_LOG("--> %s\n", p->buf);
+ t->ret = send_buffer(p->fd, p->buf);
+ if (t->ret >= 0)
+ p->status = CL_SENT_AUTH;
+ return;
+ case CL_SENT_AUTH: /* receive challenge number */
+ p->loaded = 0;
+ t->ret = client_recv_buffer(p);
+ if (t->ret < 0)
+ return;
+ if (t->ret != 64) {
+ t->ret = -E_INVALID_CHALLENGE;
+ PARA_ERROR_LOG("received the following: %s\n", p->buf);
+ return;
+ }
+ PARA_INFO_LOG("%s", "<-- [challenge]\n");
+ /* decrypt challenge number */
+ t->ret = para_decrypt_challenge(p->key_file, &p->challenge_nr,
+ (unsigned char *) p->buf, 64);
+ if (t->ret > 0)
+ p->status = CL_RECEIVED_CHALLENGE;
+ return;
+ case CL_RECEIVED_CHALLENGE: /* send decrypted challenge */
+ PARA_INFO_LOG("--> %lu\n", p->challenge_nr);
+ t->ret = send_va_buffer(p->fd, "%s%lu", CHALLENGE_RESPONSE_MSG,
+ p->challenge_nr);
+ if (t->ret > 0)
+ p->status = CL_SENT_CH_RESPONSE;
+ return;
+ case CL_SENT_CH_RESPONSE: /* read server response */
+ {
+ size_t bytes_received;
+ unsigned char rc4_buf[2 * RC4_KEY_LEN] = "";
+ p->loaded = 0;
+ t->ret = client_recv_buffer(p);
+ if (t->ret < 0)
+ return;
+ bytes_received = t->ret;
+ PARA_INFO_LOG("++++ server info ++++\n%s\n++++ end of server "
+ "info ++++\n", p->buf);
+ /* check if server has sent "Proceed" message */
+ t->ret = -E_CLIENT_AUTH;
+ if (!strstr(p->buf, PROCEED_MSG))
+ return;
+ t->ret = 1;
+ p->status = CL_RECEIVED_PROCEED;
+ if (bytes_received < PROCEED_MSG_LEN + 32)
+ return;
+ PARA_INFO_LOG("%s", "decrypting session key\n");
+ t->ret = para_decrypt_buffer(p->key_file, rc4_buf,
+ (unsigned char *)p->buf + PROCEED_MSG_LEN + 1,
+ bytes_received - PROCEED_MSG_LEN - 1);
+ if (t->ret < 0)
+ return;
+ RC4_set_key(&p->rc4_send_key, RC4_KEY_LEN, rc4_buf);
+ RC4_set_key(&p->rc4_recv_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
+ enable_crypt(p->fd, rc4_recv, rc4_send);
+ }
+ case CL_RECEIVED_PROCEED: /* concat args and send command */
+ {
+ int i;
+ char *command = NULL;
+ for (i = 0; i < p->conf.inputs_num; i++) {
+ char *tmp = command;
+ command = make_message("%s\n%s", command?
+ command : "", p->conf.inputs[i]);
+ free(tmp);
+ }
+ command = para_strcat(command, EOC_MSG "\n");
+ PARA_INFO_LOG("--> %s\n", command);
+ t->ret = send_buffer(p->fd, command);
+ free(command);
+ if (t->ret > 0)
+ p->status = CL_SENT_COMMAND;
+ return;
+ }
+ case CL_SENT_COMMAND:
+ p->loaded = 0;
+ t->ret = client_recv_buffer(p);
+ if (t->ret < 0)
+ return;
+ t->ret = -E_HANDSHAKE_COMPLETE;
+ if (strstr(p->buf, AWAITING_DATA_MSG))
+ p->status = CL_SENDING_STDIN;
+ else
+ p->status = CL_RECEIVING_SERVER_OUTPUT;
+ return;
+ case CL_SENDING_STDIN: /* FIXME: might block */
+ PARA_INFO_LOG("loaded: %d\n", *p->in_loaded);
+ t->ret = send_bin_buffer(p->fd, p->inbuf, *p->in_loaded);
+ if (t->ret <= 0) {
+ if (!t->ret)
+ t->ret = 1;
+ return;
+ }
+ *p->in_loaded = 0; /* FIXME: short writes */
+ return;
+ case CL_RECEIVING_SERVER_OUTPUT:
+ t->ret = client_recv_buffer(p);
+ return;
+ }
+
+}
+static int client_open(struct private_client_data *pcd)
+{
+ int ret;