40 #include <glib/gstdio.h> 41 #define LIBSSH_STATIC 1 42 #include <libssh/libssh.h> 46 #define REMMINA_SSH_TYPE_DSS 1 47 #define REMMINA_SSH_TYPE_RSA 2 49 static gboolean
remmina_get_keytype(
const gchar *private_key_file, gint *keytype, gboolean *encrypted)
53 gchar buf1[100], buf2[100];
55 if ((fp = g_fopen(private_key_file,
"r")) == NULL) {
58 if (!fgets(buf1,
sizeof(buf1), fp) || !fgets(buf2,
sizeof(buf2), fp)) {
64 if (strstr(buf1,
"BEGIN RSA"))
65 *keytype = REMMINA_SSH_TYPE_RSA;
66 else if (strstr(buf1,
"BEGIN DSA"))
67 *keytype = REMMINA_SSH_TYPE_DSS;
71 *encrypted = (strstr(buf2,
"ENCRYPTED") ? TRUE : FALSE);
79 "MIIBuwIBAAKBgQCXv9AzQXjxvXWC1qu3CdEqskX9YomTfyG865gb4D02ZwWuRU/9\n" 80 "C3I9/bEWLdaWgJYXIcFJsMCIkmWjjeSZyTmeoypI1iLifTHUxn3b7WNWi8AzKcVF\n" 81 "aBsBGiljsop9NiD1mEpA0G+nHHrhvTXz7pUvYrsrXcdMyM6rxqn77nbbnwIVALCi\n" 82 "xFdHZADw5KAVZI7r6QatEkqLAoGBAI4L1TQGFkq5xQ/nIIciW8setAAIyrcWdK/z\n" 83 "5/ZPeELdq70KDJxoLf81NL/8uIc4PoNyTRJjtT3R4f8Az1TsZWeh2+ReCEJxDWgG\n" 84 "fbk2YhRqoQTtXPFsI4qvzBWct42WonWqyyb1bPBHk+JmXFscJu5yFQ+JUVNsENpY\n" 85 "+Gkz3HqTAoGANlgcCuA4wrC+3Cic9CFkqiwO/Rn1vk8dvGuEQqFJ6f6LVfPfRTfa\n" 86 "QU7TGVLk2CzY4dasrwxJ1f6FsT8DHTNGnxELPKRuLstGrFY/PR7KeafeFZDf+fJ3\n" 87 "mbX5nxrld3wi5titTnX+8s4IKv29HJguPvOK/SI7cjzA+SqNfD7qEo8CFDIm1xRf\n" 88 "8xAPsSKs6yZ6j1FNklfu\n" 89 "-----END DSA PRIVATE KEY-----\n";
131 TRACE_CALL(__func__);
136 nx->
session_parameters = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
147 TRACE_CALL(__func__);
162 pthread_cancel(thread);
163 pthread_join(thread, NULL);
167 ssh_channel_close(nx->
channel);
196 TRACE_CALL(__func__);
201 err = ssh_get_error(nx->
session);
202 nx->
error = g_strdup_printf(fmt, err);
207 TRACE_CALL(__func__);
212 nx->
error = g_strdup_vprintf(fmt, args);
218 TRACE_CALL(__func__);
219 return (nx->
error != NULL);
225 TRACE_CALL(__func__);
231 TRACE_CALL(__func__);
240 TRACE_CALL(__func__);
246 TRACE_CALL(__func__);
252 TRACE_CALL(__func__);
258 TRACE_CALL(__func__);
259 struct timeval timeout;
269 ssh_channel_select(ch, NULL, NULL, &timeout);
272 while (is_stderr <= 1) {
273 len = ssh_channel_poll(nx->
channel, is_stderr);
274 if (len == SSH_ERROR) {
285 buffer = g_malloc(
sizeof(*buffer) * len);
286 len = ssh_channel_read(nx->
channel, buffer, len, is_stderr);
292 g_string_append_len(nx->
response, buffer, len);
300 TRACE_CALL(__func__);
315 for (i = 0; i < 7; i++) {
316 p2 = strchr(p1,
' ');
319 val = g_strndup(p1, (gint)(p2 - p1));
347 while (*p2 ==
' ' && p2 > p1)
349 val = g_strndup(p1, (gint)(p2 - p1 + 1));
356 TRACE_CALL(__func__);
365 s = g_ascii_strdown(line, -1);
369 nx->
version = g_strdup(
"3.3.0");
372 ptr = strchr(nx->
version,
' ');
376 ptr = strchr(nx->
version,
'-');
384 if (sscanf(line,
"NX> %i ", &status) < 1) {
398 ptr = strchr(line,
':');
408 TRACE_CALL(__func__);
418 if ((ptr = strchr(pos,
'\n')) == NULL)
421 len = ((gint)(ptr - pos)) + 1;
422 line = g_strndup(pos, len - 1);
425 if (l > 0 && line[l - 1] ==
'\r') {
436 TRACE_CALL(__func__);
451 }
else if (status >= 400 && status <= 599) {
479 if (sscanf(pos,
"NX> %i ", &status) < 1) {
492 TRACE_CALL(__func__);
509 TRACE_CALL(__func__);
515 TRACE_CALL(__func__);
519 va_start(args, cmdfmt);
520 cmd = g_strdup_vprintf(cmdfmt, args);
521 ssh_channel_write(nx->
channel, cmd, strlen(cmd));
524 ssh_set_fd_towrite(nx->
session);
525 ssh_channel_write(nx->
channel,
"\n", 1);
532 TRACE_CALL(__func__);
537 gchar *passphrase = NULL;
540 ssh_options_set(nx->
session, SSH_OPTIONS_HOST, server);
541 ssh_options_set(nx->
session, SSH_OPTIONS_PORT, &port);
542 ssh_options_set(nx->
session, SSH_OPTIONS_USER,
"nx");
544 if (private_key_file && private_key_file[0]) {
549 if (encrypted && !passphrase_func(&passphrase, userdata)) {
552 if ( ssh_pki_import_privkey_file(private_key_file, (passphrase ? passphrase :
""), NULL, NULL, &priv_key) != SSH_OK ) {
566 if (ssh_connect(nx->
session)) {
567 ssh_key_free(priv_key);
572 ret = ssh_userauth_publickey(nx->
session, NULL, priv_key);
574 ssh_key_free(priv_key);
576 if (ret != SSH_AUTH_SUCCESS) {
581 if ((nx->
channel = ssh_channel_new(nx->
session)) == NULL || ssh_channel_open_session(nx->
channel) != SSH_OK) {
585 if (ssh_channel_request_shell(nx->
channel) != SSH_OK) {
606 nx->
server = g_strdup(server);
613 TRACE_CALL(__func__);
623 if (response == 102) {
627 }
else if (response != 105) {
636 TRACE_CALL(__func__);
640 va_start(args, valuefmt);
641 value = g_strdup_vprintf(valuefmt, args);
648 TRACE_CALL(__func__);
653 cmd = g_string_new(cmd_type);
655 while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) {
656 g_string_append_printf(cmd,
" --%s=\"%s\"", key, value);
660 g_string_free(cmd, TRUE);
669 TRACE_CALL(__func__);
674 G_TYPE_STRING, G_TYPE_STRING);
685 TRACE_CALL(__func__);
686 gtk_tree_view_set_model(tree, GTK_TREE_MODEL(nx->
session_list));
691 TRACE_CALL(__func__);
694 return gtk_tree_model_get_iter_first(GTK_TREE_MODEL(nx->
session_list), iter);
699 TRACE_CALL(__func__);
702 return gtk_tree_model_iter_next(GTK_TREE_MODEL(nx->
session_list), iter);
708 TRACE_CALL(__func__);
711 gtk_tree_model_get(GTK_TREE_MODEL(nx->
session_list), iter, column, &val, -1);
717 TRACE_CALL(__func__);
718 gtk_list_store_set(nx->
session_list, iter, column, data, -1);
723 TRACE_CALL(__func__);
729 TRACE_CALL(__func__);
741 value = g_strdup_printf(
"%i", nx->
encryption);
748 TRACE_CALL(__func__);
755 TRACE_CALL(__func__);
762 TRACE_CALL(__func__);
769 TRACE_CALL(__func__);
775 TRACE_CALL(__func__);
778 ssize_t len = 0, lenw = 0;
780 struct timeval timeout;
781 ssh_channel channels[2];
782 ssh_channel channels_out[2];
786 gchar socketbuffer[10240];
787 gchar *socketbuffer_ptr = NULL;
788 gint socketbuffer_len = 0;
790 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
791 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
814 ret = ssh_select(channels, channels_out, sock + 1, &
set, &timeout);
817 if (ret == SSH_EINTR)
822 if (FD_ISSET(sock, &
set)) {
823 len = read(sock, buffer,
sizeof(buffer));
827 for (ptr = buffer, lenw = 0; len > 0; len -= lenw, ptr += lenw) {
828 ssh_set_fd_towrite(nx->
session);
829 lenw = ssh_channel_write(channels[0], (
char*)ptr, len);
841 if (channels_out[0] && socketbuffer_len <= 0) {
842 len = ssh_channel_read_nonblocking(channels_out[0], socketbuffer,
sizeof(socketbuffer), 0);
843 if (len == SSH_ERROR || len == SSH_EOF) {
846 }
else if (len > 0) {
847 socketbuffer_ptr = socketbuffer;
848 socketbuffer_len = len;
851 len = ssh_channel_read_nonblocking(channels_out[0], buffer,
sizeof(buffer), 1);
852 if (len == SSH_ERROR || len == SSH_EOF) {
859 if (nx->
running && socketbuffer_len > 0) {
860 for (lenw = 0; socketbuffer_len > 0; socketbuffer_len -= lenw, socketbuffer_ptr += lenw) {
861 lenw = write(sock, socketbuffer_ptr, socketbuffer_len);
862 if (lenw == -1 && errno == EAGAIN && nx->
running) {
883 TRACE_CALL(__func__);
887 struct sockaddr_in sin;
902 sock = socket(AF_INET, SOCK_STREAM, 0);
907 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt,
sizeof(sockopt));
909 sin.sin_family = AF_INET;
910 sin.sin_port = htons(port);
911 sin.sin_addr.s_addr = inet_addr(
"127.0.0.1");
913 if (bind(sock, (
struct sockaddr *)&sin,
sizeof(sin))) {
919 if (listen(sock, 1)) {
939 TRACE_CALL(__func__);
941 return g_strdup_printf(
"nx,session=%s,cookie=%s,id=%s,shmem=1,shpix=1,connect=127.0.0.1:%i",
945 return g_strdup_printf(
"nx,session=%s,cookie=%s,id=%s,shmem=1,shpix=1,connect=%s:%i",
953 TRACE_CALL(__func__);
956 GError *
error = NULL;
965 for (i = 0; envp[i]; i++) {
966 if (g_strcmp0(envp[i],
"DISPLAY") == 0) {
967 s = g_strdup_printf(
"DISPLAY=:%i", display);
969 s = g_strdup_printf(
"%s=%s", envp[i], g_getenv(envp[i]));
979 argv[argc++] = g_strdup(
"nxproxy");
980 argv[argc++] = g_strdup(
"-S");
984 ret = g_spawn_async(NULL, argv, envp, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &nx->
proxy_pid,
987 for (i = 0; i < argc; i++)
1004 TRACE_CALL(__func__);
gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file, RemminaNXPassphraseCallback passphrase_func, gpointer userdata)
void remmina_nx_session_set_log_callback(RemminaNXSession *nx, RemminaNXLogCallback log_callback)
void remmina_nx_session_set_localport(RemminaNXSession *nx, gint localport)
static gboolean remmina_nx_session_expect_status(RemminaNXSession *nx, gint status)
void remmina_nx_session_bye(RemminaNXSession *nx)
static gint remmina_nx_session_parse_line(RemminaNXSession *nx, const gchar *line, gchar **valueptr)
gboolean remmina_nx_session_attach(RemminaNXSession *nx)
gboolean remmina_nx_session_tunnel_open(RemminaNXSession *nx)
gboolean remmina_nx_session_start(RemminaNXSession *nx)
static gchar * remmina_nx_session_get_line(RemminaNXSession *nx)
void(* RemminaNXLogCallback)(const gchar *fmt,...)
static gboolean remmina_get_keytype(const gchar *private_key_file, gint *keytype, gboolean *encrypted)
gboolean remmina_nx_session_invoke_proxy(RemminaNXSession *nx, gint display, GChildWatchFunc exit_func, gpointer user_data)
const gchar * remmina_nx_session_get_error(RemminaNXSession *nx)
static gboolean remmina_nx_session_send_session_command(RemminaNXSession *nx, const gchar *cmd_type, gint response)
static gchar * remmina_nx_session_get_proxy_option(RemminaNXSession *nx)
static gint remmina_nx_session_expect_status2(RemminaNXSession *nx, gint status, gint status2)
RemminaNXSession * remmina_nx_session_new(void)
gboolean(* RemminaNXPassphraseCallback)(gchar **passphrase, gpointer userdata)
gboolean remmina_nx_session_has_error(RemminaNXSession *nx)
static void remmina_nx_session_parse_session_list_line(RemminaNXSession *nx, const gchar *line)
static void remmina_nx_session_add_common_parameters(RemminaNXSession *nx)
static const gchar nx_default_private_key[]
void remmina_nx_session_free(RemminaNXSession *nx)
static const gchar nx_hello_server_msg[]
void remmina_nx_session_set_encryption(RemminaNXSession *nx, gint encryption)
gboolean remmina_nx_session_list(RemminaNXSession *nx)
RemminaNXLogCallback log_callback
gboolean remmina_nx_session_iter_next(RemminaNXSession *nx, GtkTreeIter *iter)
GHashTable * session_parameters
gboolean remmina_nx_session_allow_start(RemminaNXSession *nx)
static void remmina_nx_session_send_command(RemminaNXSession *nx, const gchar *cmdfmt,...)
static gint remmina_nx_session_parse_response(RemminaNXSession *nx)
void remmina_nx_session_add_parameter(RemminaNXSession *nx, const gchar *name, const gchar *valuefmt,...)
gchar * remmina_nx_session_iter_get(RemminaNXSession *nx, GtkTreeIter *iter, gint column)
static gpointer remmina_nx_session_tunnel_main_thread(gpointer data)
static void remmina_nx_session_set_application_error(RemminaNXSession *nx, const gchar *fmt,...)
GtkListStore * session_list
void remmina_nx_session_iter_set(RemminaNXSession *nx, GtkTreeIter *iter, gint column, const gchar *data)
gboolean remmina_nx_session_terminate(RemminaNXSession *nx)
void remmina_nx_session_clear_error(RemminaNXSession *nx)
static void remmina_nx_session_set_error(RemminaNXSession *nx, const gchar *fmt)
gboolean remmina_nx_session_login(RemminaNXSession *nx, const gchar *username, const gchar *password)
void remmina_nx_session_set_tree_view(RemminaNXSession *nx, GtkTreeView *tree)
gboolean remmina_nx_session_iter_first(RemminaNXSession *nx, GtkTreeIter *iter)
static gboolean remmina_nx_session_get_response(RemminaNXSession *nx)
gboolean remmina_nx_session_restore(RemminaNXSession *nx)