static void change_host_key(void) { set_ssh_connect_res(SSH_OK); set_ssh_is_server_known_res(SSH_SERVER_KNOWN_CHANGED); wsh_ssh_session_t* session = g_slice_new0(wsh_ssh_session_t); session->hostname = remote; session->username = username; session->password = password; session->port = port; GError* err = NULL; wsh_ssh_host(session, &err); gint ret = wsh_verify_host_key(session, FALSE, FALSE, &err); g_assert(ret == WSH_SSH_NEED_ADD_HOST_KEY); g_assert(session->session == NULL); g_assert_error(err, WSH_SSH_ERROR, WSH_SSH_HOST_KEY_CHANGED_ERR); g_error_free(err); g_slice_free(wsh_ssh_session_t, session); }
static void fail_add_host_key(void) { set_ssh_connect_res(SSH_OK); set_ssh_is_server_known_res(SSH_SERVER_NOT_KNOWN); set_ssh_write_knownhost_res(SSH_ERROR); wsh_ssh_session_t* session = g_slice_new0(wsh_ssh_session_t); session->hostname = remote; session->username = username; session->password = password; session->port = port; GError *err = NULL; wsh_ssh_host(session, &err); gint ret = wsh_verify_host_key(session, TRUE, FALSE, &err); g_assert(ret == WSH_SSH_HOST_KEY_ERROR); g_assert(session->session == NULL); g_assert_error(err, WSH_SSH_ERROR, WSH_SSH_KNOWN_HOSTS_WRITE_ERR); g_error_free(err); g_slice_free(wsh_ssh_session_t, session); }
static void add_host_key(void) { set_ssh_connect_res(SSH_OK); set_ssh_is_server_known_res(SSH_SERVER_NOT_KNOWN); set_ssh_write_knownhost_res(SSH_OK); wsh_ssh_session_t* session = g_slice_new0(wsh_ssh_session_t); session->hostname = remote; session->username = username; session->password = password; session->port = port; GError *err = NULL; wsh_ssh_host(session, &err); gint ret = wsh_verify_host_key(session, TRUE, FALSE, &err); g_assert(ret == 0); g_assert(session->session != NULL); g_assert_no_error(err); g_free(session->session); g_slice_free(wsh_ssh_session_t, session); }
void wshc_try_ssh(wshc_host_info_t* host_info, const wshc_cmd_info_t* cmd_info) { g_assert(cmd_info != NULL); g_assert(host_info != NULL); GError* err = NULL; wsh_ssh_session_t session = { .hostname = host_info->hostname, .username = cmd_info->username, .password = cmd_info->password, .port = cmd_info->port, .session = NULL, .ssh_opts = cmd_info->ssh_opts, }; if (session.password == NULL) { session.auth_type = WSH_SSH_AUTH_PUBKEY; wshc_verbose_print(cmd_info->out, "Using public key authentication\n"); } else { session.auth_type = WSH_SSH_AUTH_PASSWORD; wshc_verbose_print(cmd_info->out, "Using password authentication\n"); } wshc_verbose_print(cmd_info->out, "Initiating connection to %s\n", host_info->hostname); if (wsh_ssh_host(&session, &err)) { wshc_add_failed_host(cmd_info->out, host_info->hostname, err->message); wshc_verbose_print(cmd_info->out, "Connection failed on %s: %s\n", host_info->hostname, err->message); g_error_free(err); err = NULL; return; } wshc_verbose_print(cmd_info->out, "Connection to %s successful\n", host_info->hostname); wshc_verbose_print(cmd_info->out, "Verifying host key for %s\n", host_info->hostname); if (wsh_verify_host_key(&session, FALSE, FALSE, &err)) { wshc_add_failed_host(cmd_info->out, host_info->hostname, err->message); wshc_verbose_print(cmd_info->out, "Host key verification for %s failed: %s\n", host_info->hostname, err->message); g_error_free(err); err = NULL; return; } wshc_verbose_print(cmd_info->out, "Host verification for %s successful\n", host_info->hostname); wshc_verbose_print(cmd_info->out, "Authenticating to %s\n", host_info->hostname); if (wsh_ssh_authenticate(&session, &err)) { wshc_add_failed_host(cmd_info->out, host_info->hostname, err->message); wshc_verbose_print(cmd_info->out, "Failed to authenticate to %s: %s\n", host_info->hostname, err->message); g_error_free(err); err = NULL; return; } wshc_verbose_print(cmd_info->out, "Authenticated to %s successfully\n", host_info->hostname); if (cmd_info->script) { wshc_verbose_print(cmd_info->out, "Initializing scp subsystem for %s\n", host_info->hostname); if (wsh_ssh_scp_init(&session, "~")) { wshc_add_failed_host(cmd_info->out, host_info->hostname, "Could not init scp"); wshc_verbose_print(cmd_info->out, "Failed to init scp on %s\n", host_info->hostname); return; } wshc_verbose_print(cmd_info->out, "Initialized scp subsystem on %s\n", host_info->hostname); wshc_verbose_print(cmd_info->out, "Transferring script %s to %s\n", cmd_info->script, host_info->hostname); if (wsh_ssh_scp_file(&session, cmd_info->script, TRUE, &err)) { wshc_add_failed_host(cmd_info->out, host_info->hostname, err->message); wshc_verbose_print(cmd_info->out, "Failed to transfer script %s to %s\n", cmd_info->script, host_info->hostname); g_error_free(err); err = NULL; } wshc_verbose_print(cmd_info->out, "Transferred script %s to %s successfully\n", cmd_info->script, host_info->hostname); wsh_ssh_scp_cleanup(&session); } wshc_verbose_print(cmd_info->out, "Execing wshd on %s\n", host_info->hostname); if (wsh_ssh_exec_wshd(&session, &err)) { wshc_add_failed_host(cmd_info->out, host_info->hostname, err->message); wshc_verbose_print(cmd_info->out, "Failed to exec wshd on %s: %s\n", host_info->hostname, err->message); g_error_free(err); err = NULL; return; } wshc_verbose_print(cmd_info->out, "Successfully launched wshd %s\n", host_info->hostname); wshc_verbose_print(cmd_info->out, "Sending command info to wshd on %s\n", host_info->hostname); if (wsh_ssh_send_cmd(&session, cmd_info->req, &err)) { wshc_verbose_print(cmd_info->out, "Failed to send command to %s: %s\n", host_info->hostname, err->message); wshc_add_failed_host(cmd_info->out, host_info->hostname, err->message); g_error_free(err); err = NULL; return; } wshc_verbose_print(cmd_info->out, "Successfully sent command info to wshd on %s\n", host_info->hostname); wshc_verbose_print(cmd_info->out, "Waiting for response from %s\n", host_info->hostname); if (wsh_ssh_recv_cmd_res(&session, host_info->res, &err)) { wshc_verbose_print(cmd_info->out, "Failed to receive a command from %s: %s\n", host_info->hostname, err->message); wshc_add_failed_host(cmd_info->out, host_info->hostname, err->message); g_error_free(err); err = NULL; return; } wshc_verbose_print(cmd_info->out, "Got response from %s\n", host_info->hostname); wsh_log_client_cmd_status(cmd_info->req->cmd_string, cmd_info->req->username, host_info->hostname, cmd_info->req->cwd, (*host_info->res)->exit_status); wshc_write_output(cmd_info->out, host_info->hostname, *host_info->res); wsh_free_unpacked_response(host_info->res); wsh_ssh_disconnect(&session); }
static gint scp_file(const wshc_scp_file_args* args) { GError *err = NULL; wsh_ssh_session_t session = { .session = NULL, .channel = NULL, .hostname = args->host, .username = args->user, .password = args->pass, .scp = NULL, .port = args->port, }; if (session.password == NULL) session.auth_type = WSH_SSH_AUTH_PUBKEY; else session.auth_type = WSH_SSH_AUTH_PASSWORD; if (wsh_ssh_host(&session, &err)) { g_printerr("%s\n", err->message); g_error_free(err); return EXIT_FAILURE; } if (wsh_verify_host_key(&session, FALSE, FALSE, &err)) { g_printerr("%s\n", err->message); g_error_free(err); return EXIT_FAILURE; } if (wsh_ssh_authenticate(&session, &err)) { g_printerr("%s\n", err->message); g_error_free(err); return EXIT_FAILURE; } if (wsh_ssh_scp_init(&session, args->location)) { g_printerr("Error initializing scp"); return EXIT_FAILURE; } for (gint i = 0; i < args->num_files; i++) { if (wsh_ssh_scp_file(&session, args->files[i], FALSE, &err)) { g_printerr("%s\n", err->message); g_error_free(err); err = NULL; } } wsh_ssh_scp_cleanup(&session); wsh_ssh_disconnect(&session); return EXIT_SUCCESS; } gint main(gint argc, gchar** argv) { GError* err = NULL; GOptionContext* context; gint ret = EXIT_SUCCESS; gchar** hosts = NULL; gsize num_hosts = 0; gchar* password = NULL; wsh_init_logger(WSH_LOGGER_CLIENT); wsh_ssh_init(); if (wsh_client_init(&err)) { g_printerr("%s", err->message); g_error_free(err); return EXIT_FAILURE; } context = g_option_context_new("[FILENAMES...] - scp file to multiple machines at once"); g_option_context_add_main_entries(context, entries, NULL); if (! g_option_context_parse(context, &argc, &argv, &err)) { g_printerr("Option parsing failed: %s\n", err->message); g_error_free(err); return EXIT_FAILURE; } if (argc == 1) { g_printerr("ERROR: Must provide a host and a file\n\n"); g_printerr("%s", g_option_context_get_help(context, FALSE, NULL)); g_option_context_free(context); return EXIT_FAILURE; } gchar* msg = NULL; if (! valid_arguments(&msg)) { g_printerr("%s\n", msg); g_free(msg); g_printerr("%s", g_option_context_get_help(context, FALSE, NULL)); g_option_context_free(context); return EXIT_FAILURE; } g_option_context_free(context); // We're done with option validation if (username == NULL) username = g_strdup(g_get_user_name()); if (ask_password) { if ((ret = wsh_client_lock_password_pages(&passwd_mem))) { g_printerr("%s\n", strerror(ret)); return ret; } password = ((gchar*)passwd_mem) + (WSH_MAX_PASSWORD_LEN * 0); if ((ret = wsh_client_getpass(password, WSH_MAX_PASSWORD_LEN, "SSH password: "******"%s\n", strerror(ret)); return ret; } if (! password) return EXIT_FAILURE; } if (!location) location = g_strdup("~"); if (file_arg) { if (wsh_exp_filename(&hosts, &num_hosts, file_arg, &err)) { g_printerr("%s\n", err->message); g_error_free(err); return EXIT_FAILURE; } } if (hosts_arg) { hosts = g_strsplit(hosts_arg, ",", 0); num_hosts = g_strv_length(hosts); } #ifdef WITH_RANGE if (range) { if (wsh_exp_range(&hosts, &num_hosts, range, &err)) { g_printerr("%s\n", err->message); g_error_free(err); return EXIT_FAILURE; } } #endif argv++; argc--; for (gint i = 1; i < argc; i++) { // scp will catch this, but I'd like to catch it before // we start even trying to scp files if (!g_file_test(argv[i], G_FILE_TEST_EXISTS)) { g_printerr("ERROR: %s doesn't exist\n", argv[i]); ret = EXIT_FAILURE; goto bad; } } if (threads <= 0) { wshc_scp_file_args args; args.port = port; args.user = username; args.pass = password; args.files = argv; args.num_files = argc; args.location = location; for (gsize i = 0; i < num_hosts; i++) { args.host = hosts[i]; scp_file(&args); } } else { GThreadPool* gtp; if ((gtp = g_thread_pool_new((GFunc)scp_file, NULL, threads, TRUE, &err)) == NULL) { g_printerr("%s\n", err->message); g_error_free(err); return EXIT_FAILURE; } wshc_scp_file_args args[num_hosts]; for (gsize i = 0; i < num_hosts; i++) { args[i].host = hosts[i]; args[i].port = port; args[i].user = username; args[i].pass = password; args[i].files = argv; args[i].num_files = argc; args[i].location = location; g_thread_pool_push(gtp, &args[i], NULL); } g_thread_pool_free(gtp, FALSE, TRUE); } if (password) { memset_s(password, WSH_MAX_PASSWORD_LEN, 0, strlen(password)); wsh_client_unlock_password_pages(passwd_mem); } bad: wsh_ssh_cleanup(); wsh_exit_logger(); if (password) g_free(password); password = NULL; if (range) g_free(range); range = NULL; if (hosts_arg) g_free(hosts_arg); g_free(username); username = NULL; return ret; }