advanced-dialog.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
  2. /***************************************************************************
  3. *
  4. * Copyright (C) 2013 Dan Fruehauf, <malkodan@gmail.com>
  5. * Based on work by Dan Williams, <dcbw@redhat.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. **************************************************************************/
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #include <string.h>
  26. #include <sys/types.h>
  27. #include <stdlib.h>
  28. #include <sys/stat.h>
  29. #include <fcntl.h>
  30. #include <unistd.h>
  31. #include <errno.h>
  32. #include <glib/gi18n-lib.h>
  33. #include <nm-setting-connection.h>
  34. #include <nm-setting-8021x.h>
  35. #include "advanced-dialog.h"
  36. #include "nm-ssh.h"
  37. #include "src/nm-ssh-service.h"
  38. static const char *advanced_keys[] = {
  39. NM_SSH_KEY_PORT,
  40. NM_SSH_KEY_TUNNEL_MTU,
  41. NM_SSH_KEY_EXTRA_OPTS,
  42. NM_SSH_KEY_REMOTE_DEV,
  43. NM_SSH_KEY_TAP_DEV,
  44. NM_SSH_KEY_REMOTE_USERNAME,
  45. NM_SSH_KEY_NO_DEFAULT_ROUTE,
  46. NULL
  47. };
  48. static void
  49. copy_values (const char *key, const char *value, gpointer user_data)
  50. {
  51. GHashTable *hash = (GHashTable *) user_data;
  52. const char **i;
  53. for (i = &advanced_keys[0]; *i; i++) {
  54. if (strncmp (key, *i, strlen(key)))
  55. continue;
  56. g_hash_table_insert (hash, g_strdup (key), g_strdup (value));
  57. }
  58. }
  59. GHashTable *
  60. advanced_dialog_new_hash_from_connection (NMConnection *connection,
  61. GError **error)
  62. {
  63. GHashTable *hash;
  64. NMSettingVPN *s_vpn;
  65. hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
  66. s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
  67. nm_setting_vpn_foreach_data_item (s_vpn, copy_values, hash);
  68. return hash;
  69. }
  70. static void
  71. port_toggled_cb (GtkWidget *check, gpointer user_data)
  72. {
  73. GtkBuilder *builder = (GtkBuilder *) user_data;
  74. GtkWidget *widget;
  75. widget = GTK_WIDGET (gtk_builder_get_object (builder, "port_spinbutton"));
  76. gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)));
  77. }
  78. static void
  79. tunmtu_toggled_cb (GtkWidget *check, gpointer user_data)
  80. {
  81. GtkBuilder *builder = (GtkBuilder *) user_data;
  82. GtkWidget *widget;
  83. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_spinbutton"));
  84. gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)));
  85. }
  86. static void
  87. extra_opts_toggled_cb (GtkWidget *check, gpointer user_data)
  88. {
  89. GtkBuilder *builder = (GtkBuilder *) user_data;
  90. GtkWidget *widget;
  91. widget = GTK_WIDGET (gtk_builder_get_object (builder, "extra_opts_entry"));
  92. gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)));
  93. }
  94. static void
  95. remote_dev_toggled_cb (GtkWidget *check, gpointer user_data)
  96. {
  97. GtkBuilder *builder = (GtkBuilder *) user_data;
  98. GtkWidget *widget;
  99. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_dev_spinbutton"));
  100. gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)));
  101. }
  102. static void
  103. remote_username_toggled_cb (GtkWidget *check, gpointer user_data)
  104. {
  105. GtkBuilder *builder = (GtkBuilder *) user_data;
  106. GtkWidget *widget;
  107. /* Add a warning if not using root */
  108. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check) )) {
  109. GtkWidget *dialog;
  110. dialog = gtk_message_dialog_new(
  111. GTK_WINDOW (gtk_builder_get_object (builder, "ssh_advanced_dialog")),
  112. GTK_DIALOG_MODAL,
  113. GTK_MESSAGE_WARNING,
  114. GTK_BUTTONS_OK,
  115. _("You have chosen not to use 'root' as the remote username.\n\nPlease make sure the user you specify is allowed to open tun/tap devices on the remote host."));
  116. gtk_window_set_title(GTK_WINDOW(dialog), "Warning");
  117. gtk_dialog_run(GTK_DIALOG(dialog));
  118. gtk_widget_destroy(dialog);
  119. }
  120. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_username_entry"));
  121. gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)));
  122. }
  123. GtkWidget *
  124. advanced_dialog_new (GHashTable *hash)
  125. {
  126. GtkBuilder *builder;
  127. GtkWidget *dialog = NULL;
  128. char *ui_file = NULL;
  129. GtkWidget *widget;
  130. const char *value;
  131. GError *error = NULL;
  132. long int tmp;
  133. g_return_val_if_fail (hash != NULL, NULL);
  134. ui_file = g_strdup_printf ("%s/%s", UIDIR, "nm-ssh-dialog.ui");
  135. builder = gtk_builder_new ();
  136. gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
  137. if (!gtk_builder_add_from_file (builder, ui_file, &error)) {
  138. g_warning ("Couldn't load builder file: %s", error->message);
  139. g_error_free (error);
  140. g_object_unref (G_OBJECT (builder));
  141. goto out;
  142. }
  143. dialog = GTK_WIDGET (gtk_builder_get_object (builder, "ssh_advanced_dialog"));
  144. if (!dialog) {
  145. g_object_unref (G_OBJECT (builder));
  146. goto out;
  147. }
  148. gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
  149. g_object_set_data_full (G_OBJECT (dialog), "builder",
  150. builder, (GDestroyNotify) g_object_unref);
  151. widget = GTK_WIDGET (gtk_builder_get_object (builder, "port_checkbutton"));
  152. g_assert (widget);
  153. g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (port_toggled_cb), builder);
  154. value = g_hash_table_lookup (hash, NM_SSH_KEY_PORT);
  155. if (value && strlen (value)) {
  156. errno = 0;
  157. tmp = strtol (value, NULL, 10);
  158. if (errno == 0 && tmp > 0 && tmp < 65536) {
  159. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
  160. widget = GTK_WIDGET (gtk_builder_get_object (builder, "port_spinbutton"));
  161. gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget),
  162. (gdouble) tmp);
  163. }
  164. gtk_widget_set_sensitive (widget, TRUE);
  165. } else {
  166. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
  167. widget = GTK_WIDGET (gtk_builder_get_object (builder, "port_spinbutton"));
  168. gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) NM_SSH_DEFAULT_PORT);
  169. gtk_widget_set_sensitive (widget, FALSE);
  170. }
  171. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_checkbutton"));
  172. g_assert (widget);
  173. g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (tunmtu_toggled_cb), builder);
  174. value = g_hash_table_lookup (hash, NM_SSH_KEY_TUNNEL_MTU);
  175. if (value && strlen (value)) {
  176. errno = 0;
  177. tmp = strtol (value, NULL, 10);
  178. if (errno == 0 && tmp > 0 && tmp < 65536) {
  179. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
  180. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_spinbutton"));
  181. gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) tmp);
  182. gtk_widget_set_sensitive (widget, TRUE);
  183. }
  184. } else {
  185. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
  186. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_spinbutton"));
  187. gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) NM_SSH_DEFAULT_MTU);
  188. gtk_widget_set_sensitive (widget, FALSE);
  189. }
  190. widget = GTK_WIDGET (gtk_builder_get_object (builder, "extra_opts_checkbutton"));
  191. g_assert (widget);
  192. g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (extra_opts_toggled_cb), builder);
  193. value = g_hash_table_lookup (hash, NM_SSH_KEY_EXTRA_OPTS);
  194. if (value && strlen (value)) {
  195. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
  196. widget = GTK_WIDGET (gtk_builder_get_object (builder, "extra_opts_entry"));
  197. gtk_entry_set_text (GTK_ENTRY (widget), value);
  198. gtk_widget_set_sensitive (widget, TRUE);
  199. } else {
  200. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
  201. widget = GTK_WIDGET (gtk_builder_get_object (builder, "extra_opts_entry"));
  202. gtk_entry_set_text (GTK_ENTRY (widget), NM_SSH_DEFAULT_EXTRA_OPTS);
  203. gtk_widget_set_sensitive (widget, FALSE);
  204. }
  205. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_dev_checkbutton"));
  206. g_assert (widget);
  207. g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (remote_dev_toggled_cb), builder);
  208. value = g_hash_table_lookup (hash, NM_SSH_KEY_REMOTE_DEV);
  209. if (value && strlen (value)) {
  210. errno = 0;
  211. tmp = strtol (value, NULL, 10);
  212. if (errno == 0 && tmp >= 0 && tmp < 256) {
  213. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
  214. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_dev_spinbutton"));
  215. gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) tmp);
  216. }
  217. gtk_widget_set_sensitive (widget, TRUE);
  218. } else {
  219. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
  220. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_dev_spinbutton"));
  221. gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) NM_SSH_DEFAULT_REMOTE_DEV);
  222. gtk_widget_set_sensitive (widget, FALSE);
  223. }
  224. value = g_hash_table_lookup (hash, NM_SSH_KEY_TAP_DEV);
  225. if (value && IS_YES(value)) {
  226. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tap_checkbutton"));
  227. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
  228. }
  229. value = g_hash_table_lookup (hash, NM_SSH_KEY_NO_DEFAULT_ROUTE);
  230. if (value && IS_YES(value)) {
  231. widget = GTK_WIDGET (gtk_builder_get_object (builder, "no_default_route_checkbutton"));
  232. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
  233. }
  234. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_username_checkbutton"));
  235. g_assert (widget);
  236. g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (remote_username_toggled_cb), builder);
  237. value = g_hash_table_lookup (hash, NM_SSH_KEY_REMOTE_USERNAME);
  238. if (value && strlen (value)) {
  239. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
  240. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_username_entry"));
  241. gtk_entry_set_text (GTK_ENTRY (widget), value);
  242. gtk_widget_set_sensitive (widget, TRUE);
  243. } else {
  244. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
  245. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_username_entry"));
  246. gtk_entry_set_text (GTK_ENTRY (widget), NM_SSH_DEFAULT_REMOTE_USERNAME);
  247. gtk_widget_set_sensitive (widget, FALSE);
  248. }
  249. out:
  250. g_free (ui_file);
  251. return dialog;
  252. }
  253. GHashTable *
  254. advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error)
  255. {
  256. GHashTable *hash;
  257. GtkWidget *widget;
  258. GtkBuilder *builder;
  259. g_return_val_if_fail (dialog != NULL, NULL);
  260. if (error)
  261. g_return_val_if_fail (*error == NULL, NULL);
  262. builder = g_object_get_data (G_OBJECT (dialog), "builder");
  263. g_return_val_if_fail (builder != NULL, NULL);
  264. hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
  265. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_checkbutton"));
  266. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
  267. int tunmtu_size;
  268. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_spinbutton"));
  269. tunmtu_size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
  270. g_hash_table_insert (hash, g_strdup (NM_SSH_KEY_TUNNEL_MTU), g_strdup_printf ("%d", tunmtu_size));
  271. }
  272. widget = GTK_WIDGET (gtk_builder_get_object (builder, "port_checkbutton"));
  273. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
  274. int port;
  275. widget = GTK_WIDGET (gtk_builder_get_object (builder, "port_spinbutton"));
  276. port = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
  277. g_hash_table_insert (hash, g_strdup (NM_SSH_KEY_PORT), g_strdup_printf ("%d", port));
  278. }
  279. widget = GTK_WIDGET (gtk_builder_get_object (builder, "extra_opts_checkbutton"));
  280. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
  281. const gchar *extra_options;
  282. widget = GTK_WIDGET (gtk_builder_get_object (builder, "extra_opts_entry"));
  283. extra_options = gtk_entry_get_text (GTK_ENTRY (widget));
  284. g_hash_table_insert (hash, g_strdup (NM_SSH_KEY_EXTRA_OPTS), g_strdup(extra_options));
  285. }
  286. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_dev_checkbutton"));
  287. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
  288. int remote_dev;
  289. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_dev_spinbutton"));
  290. remote_dev = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
  291. g_hash_table_insert (hash, g_strdup (NM_SSH_KEY_REMOTE_DEV), g_strdup_printf ("%d", remote_dev));
  292. }
  293. widget = GTK_WIDGET (gtk_builder_get_object (builder, "tap_checkbutton"));
  294. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
  295. g_hash_table_insert (hash, g_strdup (NM_SSH_KEY_TAP_DEV), g_strdup (YES));
  296. widget = GTK_WIDGET (gtk_builder_get_object (builder, "no_default_route_checkbutton"));
  297. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
  298. g_hash_table_insert (hash, g_strdup (NM_SSH_KEY_NO_DEFAULT_ROUTE), g_strdup (YES));
  299. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_username_checkbutton"));
  300. if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
  301. const gchar *remote_username;
  302. widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_username_entry"));
  303. remote_username = gtk_entry_get_text (GTK_ENTRY (widget));
  304. g_hash_table_insert (hash, g_strdup (NM_SSH_KEY_REMOTE_USERNAME), g_strdup(remote_username));
  305. }
  306. return hash;
  307. }