- int sockfd, numbytes, i, interactive, received, ret;
- struct hostent *he;
- struct sockaddr_in their_addr;
- char *command = NULL;
- char buf[8192];
- char *auth_str;
- char *key_file, *config_file;
- long unsigned challenge_nr;
- char *line;
-
- get_options(argc, argv, &config_file, &key_file);
- if (args_info.loglevel_arg <= NOTICE)
- cmdline_parser_print_version();
- PARA_INFO_LOG(
- "current loglevel: %d\n"
- "using config_file: %s\n"
- "using key_file: %s\n"
- "connecting to %s:%d\n",
- args_info.loglevel_arg,
- config_file,
- key_file,
- args_info.hostname_arg,
- args_info.server_port_arg
- );
- interactive = args_info.inputs_num == 0? 1 : 0;
- if (interactive) {
- PARA_NOTICE_LOG("%s", "no command, entering interactive mode\n");
- signal(SIGINT, sigint_handler);
- } else {
- /* not interactive, concat args */
- for (i = 0; i < args_info.inputs_num; i++)
- append_str(&command, args_info.inputs[i]);
- }
-interactive_loop:
- crypt_function_recv = NULL;
- crypt_function_send = NULL;
- if (interactive) {
- int i = 0;
- char *p;
-
- rl_save_prompt();
- rl_message("\n");
- rl_kill_full_line(0, 0);
- rl_free_line_state();
- /* read a line via readline */
- line = rl_gets();
- if (!line)
- return 0;
- if (!line[0])
- goto interactive_loop;
- p = line;
- while (sscanf(p, "%200s%n", buf, &i) == 1) {
- append_str(&command, buf);
- p += i;
- }
- }
- /* get the host info */
- PARA_NOTICE_LOG("getting host info of %s\n",
- args_info.hostname_arg);
- if (!(he = get_host_info(args_info.hostname_arg)))
- exit(EXIT_FAILURE);
- /* get new socket */
- if ((sockfd = get_socket()) < 0)
- exit(EXIT_FAILURE);
- /* init their_addr */
- init_sockaddr(&their_addr, args_info.server_port_arg, he);
- /* Connect */
- PARA_NOTICE_LOG("connecting to %s...\n",
- args_info.hostname_arg);
- if (para_connect(sockfd, &their_addr) < 0)
- exit(EXIT_FAILURE);
- /* Receive Welcome message */
- if ((numbytes = recv_buffer(sockfd, buf, sizeof(buf))) < 0)
- exit(EXIT_FAILURE);
- /* send auth command */
- auth_str = make_message("auth %s%s", args_info.plain_given? "" : "rc4 ",
- args_info.user_arg);
- PARA_INFO_LOG("<-- %s--> %s\n", buf, auth_str);
- if (send_buffer(sockfd, auth_str) < 0)
- exit(EXIT_FAILURE);
- /* receive challenge number */
- if ((numbytes = recv_buffer(sockfd, buf, sizeof(buf))) < 0)
- exit(EXIT_FAILURE);
- if (numbytes != 64) {
- PARA_EMERG_LOG("did not receive valid challenge (got %i bytes)\n",
- numbytes);
- buf[numbytes] = '\0';
- PARA_ERROR_LOG("received the following instead: %s\n", buf);
- goto write_out;
- }
- PARA_INFO_LOG("<-- [challenge (%i bytes)]\n", numbytes);
- /* decrypt challenge number */
- ret = para_decrypt_challenge(key_file, &challenge_nr, (unsigned char *) buf,
- numbytes);
- if (ret < 0) {
- PARA_EMERG_LOG("decrypt error (%d). Bad secret key?\n", ret);
- exit(EXIT_FAILURE);
- }
- /* send decrypted challenge */
- PARA_INFO_LOG("--> %lu\n", challenge_nr);
- if (send_va_buffer(sockfd, "%s%lu", CHALLENGE_RESPONSE_MSG, challenge_nr) < 0)
- exit(EXIT_FAILURE);
- /* Wait for approval */
- PARA_NOTICE_LOG("%s", "waiting for approval from server\n");
- if ((numbytes = recv_buffer(sockfd, buf, sizeof(buf))) < 0)
- exit(EXIT_FAILURE);
- PARA_INFO_LOG("++++ server info ++++\n%s\n++++ end of server "
- "info ++++\n", buf);
- /* Check if server has sent "Proceed" message */
- if (!strstr(buf, PROCEED_MSG)) {
- PARA_EMERG_LOG("%s", "authentication failed\n");
- exit(EXIT_FAILURE);
- }
- if (numbytes >= PROCEED_MSG_LEN + 32) {
- PARA_INFO_LOG("%s", "decrypting session key\n");
- if (para_decrypt_buffer(key_file, rc4_buf,
- (unsigned char *)buf + PROCEED_MSG_LEN + 1,
- numbytes - PROCEED_MSG_LEN - 1) < 0) {
- PARA_EMERG_LOG("%s", "error receiving rc4 key\n");
- exit(EXIT_FAILURE);
- }
- RC4_set_key(&rc4_send_key, RC4_KEY_LEN, rc4_buf);
- RC4_set_key(&rc4_recv_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
- PARA_INFO_LOG("rc4 encrytion activated: %x:%x:%x:%x\n",
- rc4_buf[0], rc4_buf[1], rc4_buf[2], rc4_buf[3]);
- crypt_function_recv = rc4_recv;
- crypt_function_send = rc4_send;
- }
- /* send command */
- PARA_INFO_LOG("--> %s\n", command);
- if (send_buffer(sockfd, command) < 0)
- exit(EXIT_FAILURE);
- free(command);
- command = NULL;
- if (send_buffer(sockfd, EOC_MSG "\n") < 0)
- exit(EXIT_FAILURE);
- PARA_NOTICE_LOG("%s", "command sent.\n");
-write_out:
- received = 0;
- /* write server output to stdout */
- while ((numbytes = recv_bin_buffer(sockfd, buf, sizeof(buf))) > 0) {
- int ret;
-
- if (!received && strstr(buf, AWAITING_DATA_MSG)) {
- PARA_NOTICE_LOG("%s", "<-- awaiting data\n");
- PARA_NOTICE_LOG("%s", "--> sending stdin\n");
- while ((ret = read(STDIN_FILENO, buf,
- sizeof(buf))) > 0)
- send_bin_buffer(sockfd, buf, ret);
- PARA_NOTICE_LOG("%s", "closing connection\n");
- numbytes = 1;
- break;
+ init_random_seed_or_die();
+ sched.default_timeout.tv_sec = 1;
+
+ ret = client_parse_config(argc, argv, &ct, &client_loglevel);
+ if (ret < 0)
+ goto out;
+ if (ct->conf.complete_given)
+ print_completions();
+ if (ret == 0)
+ interactive_session(); /* does not return */
+
+ /*
+ * We add buffer tree nodes for stdin and stdout even though
+ * only one of them will be needed. This simplifies the code
+ * a bit wrt. to the buffer tree setup.
+ */
+ sit.btrn = btr_new_node(&(struct btr_node_description)
+ EMBRACE(.name = "stdin"));
+ ret = client_connect(ct, &sched, sit.btrn, NULL);
+ if (ret < 0)
+ goto out;
+ sot.btrn = btr_new_node(&(struct btr_node_description)
+ EMBRACE(.name = "stdout", .parent = ct->btrn[0]));
+ supervisor_task.task = task_register(&(struct task_info) {
+ .name = "supervisor",
+ .post_select = supervisor_post_select,
+ .context = &supervisor_task,
+ }, &sched);
+
+ ret = schedule(&sched);
+ if (ret >= 0) {
+ ret = task_status(ct->task);
+ if (ret < 0) {
+ switch (ret) {
+ /* these are not errors */
+ case -E_SERVER_CMD_SUCCESS:
+ case -E_EOF:
+ case -E_SERVER_EOF:
+ case -E_BTR_EOF:
+ ret = 0;
+ break;
+ default: ret = -E_SERVER_CMD_FAILURE;
+ }