Maemo: Do not store the password in the config file, ask the user for it on demand.
[strongswan.git] / src / frontends / maemo / src / strongswan-settings.c
1 /*
2 * Copyright (C) 2010 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <hildon-cp-plugin/hildon-cp-plugin-interface.h>
17 #include <gtk/gtk.h>
18 #include <hildon/hildon.h>
19 #include <hildon/hildon-file-chooser-dialog.h>
20
21 #include <string.h>
22
23 #include "strongswan-connections.h"
24
25 enum {
26 RESPONSE_NEW = 1,
27 RESPONSE_EDIT,
28 RESPONSE_DELETE
29 };
30
31 struct {
32 GtkWidget *dialog;
33 GtkWidget *list;
34 StrongswanConnections *conns;
35 } ListDialog = { 0, };
36
37 /**
38 * Callback to select a certificate
39 */
40 void select_cert(HildonButton *button, gpointer user_data)
41 {
42 GtkWidget *selector = hildon_file_chooser_dialog_new (GTK_WINDOW (user_data), GTK_FILE_CHOOSER_ACTION_OPEN);
43 gtk_widget_show_all (selector);
44 if (gtk_dialog_run (GTK_DIALOG (selector)) == GTK_RESPONSE_OK)
45 {
46 gchar *file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (selector));
47 hildon_button_set_value (button, file);
48 g_free(file);
49 }
50 gtk_widget_destroy (selector);
51 }
52
53 /**
54 * Shows a dialog to edit the given connection (or create a new one,
55 * if conn is NULL)
56 */
57 static void
58 edit_connection (gpointer *parent, StrongswanConnection *conn)
59 {
60 GtkWidget *dialog;
61 dialog = gtk_dialog_new_with_buttons (
62 conn ? "Edit Connection" : "New Connection",
63 GTK_WINDOW (parent),
64 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
65 GTK_STOCK_CANCEL,
66 GTK_RESPONSE_CANCEL,
67 GTK_STOCK_SAVE,
68 GTK_RESPONSE_OK,
69 NULL);
70 GtkWidget *vbox = GTK_DIALOG (dialog)->vbox;
71 GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
72
73 GtkWidget *name = hildon_entry_new (HILDON_SIZE_AUTO);
74 hildon_gtk_entry_set_placeholder_text (GTK_ENTRY (name), "Connection Name");
75 hildon_gtk_entry_set_input_mode (GTK_ENTRY (name),
76 HILDON_GTK_INPUT_MODE_AUTOCAP |
77 HILDON_GTK_INPUT_MODE_ALPHA |
78 HILDON_GTK_INPUT_MODE_NUMERIC);
79 GtkWidget *ncap = hildon_caption_new (group,
80 "Name",
81 name,
82 NULL,
83 HILDON_CAPTION_OPTIONAL);
84 gtk_box_pack_start (GTK_BOX (vbox), ncap, TRUE, TRUE, 0);
85
86 GtkWidget *host = hildon_entry_new (HILDON_SIZE_AUTO);
87 hildon_gtk_entry_set_placeholder_text (GTK_ENTRY (host), "Hostname / IP");
88 hildon_gtk_entry_set_input_mode (GTK_ENTRY (host),
89 HILDON_GTK_INPUT_MODE_FULL);
90 GtkWidget *hcap = hildon_caption_new (group,
91 "Host",
92 host,
93 NULL,
94 HILDON_CAPTION_OPTIONAL);
95 gtk_box_pack_start (GTK_BOX (vbox), hcap, TRUE, TRUE, 0);
96
97 GtkWidget *cert = hildon_button_new (HILDON_SIZE_FINGER_HEIGHT |
98 HILDON_SIZE_AUTO_WIDTH,
99 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
100 hildon_button_set_text (HILDON_BUTTON (cert),
101 "Host or CA Certificate",
102 "None");
103 hildon_button_set_alignment (HILDON_BUTTON (cert), 0, 0.5, 1, 1);
104 g_signal_connect (cert, "clicked", G_CALLBACK (select_cert), dialog);
105 GtkWidget *ccap = hildon_caption_new (group,
106 "Certificate",
107 cert,
108 NULL,
109 HILDON_CAPTION_OPTIONAL);
110 gtk_box_pack_start (GTK_BOX (vbox), ccap, TRUE, TRUE, 0);
111
112 GtkWidget *user = hildon_entry_new (HILDON_SIZE_AUTO);
113 hildon_gtk_entry_set_placeholder_text (GTK_ENTRY (user), "Username");
114 hildon_gtk_entry_set_input_mode (GTK_ENTRY (user),
115 HILDON_GTK_INPUT_MODE_FULL);
116 GtkWidget *ucap = hildon_caption_new (group,
117 "Username",
118 user,
119 NULL,
120 HILDON_CAPTION_OPTIONAL);
121 gtk_box_pack_start (GTK_BOX (vbox), ucap, TRUE, TRUE, 0);
122
123 if (conn)
124 {
125 gchar *c_name, *c_host, *c_cert, *c_user;
126 g_object_get (conn,
127 "name", &c_name,
128 "host", &c_host,
129 "cert", &c_cert,
130 "user", &c_user,
131 NULL);
132 gtk_entry_set_text (GTK_ENTRY (name), c_name);
133 gtk_entry_set_text (GTK_ENTRY (host), c_host);
134 hildon_button_set_value (HILDON_BUTTON (cert),
135 c_cert ? c_cert : "None");
136 gtk_entry_set_text (GTK_ENTRY (user), c_user);
137 g_free (c_name);
138 g_free (c_host);
139 g_free (c_cert);
140 g_free (c_user);
141 }
142
143 gtk_widget_show_all (dialog);
144
145 gint retval = gtk_dialog_run (GTK_DIALOG (dialog));
146 if (retval == GTK_RESPONSE_OK)
147 {
148 const gchar *c_name, *c_cert;
149 c_name = gtk_entry_get_text (GTK_ENTRY (name));
150 if (!conn)
151 {
152 conn = strongswan_connection_new (c_name);
153 }
154 c_cert = hildon_button_get_value (HILDON_BUTTON (cert));
155 c_cert = strcmp (c_cert, "None") ? c_cert : NULL;
156 g_object_set (conn,
157 "name", c_name,
158 "host", gtk_entry_get_text (GTK_ENTRY (host)),
159 "cert", c_cert,
160 "user", gtk_entry_get_text (GTK_ENTRY (user)),
161 NULL);
162 strongswan_connections_save_connection (ListDialog.conns, conn);
163 }
164 gtk_widget_destroy (dialog);
165 }
166
167 /**
168 * Creates a dialog showing a list of all connections
169 */
170 static void
171 create_list_dialog (gpointer *parent)
172 {
173 GtkWidget *dialog = gtk_dialog_new_with_buttons (
174 "strongSwan Connections",
175 GTK_WINDOW (parent),
176 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
177 GTK_STOCK_NEW,
178 RESPONSE_NEW,
179 GTK_STOCK_EDIT,
180 RESPONSE_EDIT,
181 GTK_STOCK_DELETE,
182 RESPONSE_DELETE,
183 GTK_STOCK_CLOSE,
184 GTK_RESPONSE_OK,
185 NULL);
186 ListDialog.dialog = dialog;
187 GtkWidget *vbox = GTK_DIALOG (dialog)->vbox;
188
189 ListDialog.conns = strongswan_connections_new ();
190
191 GtkTreeModel *model = strongswan_connections_get_model (ListDialog.conns);
192 ListDialog.list = gtk_tree_view_new_with_model (model);
193 g_object_unref (model);
194
195 GtkTreeSelection *selection;
196 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ListDialog.list));
197 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
198
199 GtkTreeViewColumn *column = gtk_tree_view_column_new ();
200 strongswan_connections_setup_column_renderers (ListDialog.conns,
201 GTK_CELL_LAYOUT (column));
202 gtk_tree_view_append_column (GTK_TREE_VIEW (ListDialog.list), column);
203
204 gtk_box_pack_start (GTK_BOX (vbox),
205 ListDialog.list,
206 TRUE,
207 TRUE,
208 HILDON_MARGIN_DEFAULT);
209 gtk_widget_show_all (dialog);
210 gtk_widget_hide (dialog);
211 }
212
213 /**
214 * Get the name fo the selected connection in the list (or NULL).
215 * The name has to be freed.
216 */
217 static gchar *
218 get_selected (void)
219 {
220 GtkTreeView *tree = GTK_TREE_VIEW(ListDialog.list);
221 GtkTreeSelection *selection;
222 GtkTreeModel *model;
223 GtkTreeIter iter;
224 gchar *name = NULL;
225
226 selection = gtk_tree_view_get_selection (tree);
227 model = gtk_tree_view_get_model (tree);
228 if (gtk_tree_selection_get_selected (selection, &model, &iter))
229 {
230 gtk_tree_model_get(model, &iter, 0, &name, -1);
231 }
232 return name;
233 }
234
235 /**
236 * main callback for control panel plugins
237 */
238 osso_return_t execute(osso_context_t *osso, gpointer data,
239 gboolean user_activated)
240 {
241 gint response;
242
243 create_list_dialog (data);
244
245 if (!user_activated)
246 {
247 /* load state */
248 }
249
250 do
251 {
252 gchar *selected;
253 response = gtk_dialog_run (GTK_DIALOG (ListDialog.dialog));
254 switch (response)
255 {
256 case RESPONSE_NEW:
257 {
258 edit_connection (data, NULL);
259 break;
260 }
261 case RESPONSE_EDIT:
262 {
263 StrongswanConnection *conn;
264 selected = get_selected ();
265 conn = strongswan_connections_get_connection (ListDialog.conns,
266 selected);
267 if (conn)
268 {
269 edit_connection (data, conn);
270 }
271 else
272 {
273 hildon_banner_show_information (NULL, NULL,
274 "Select a connection first");
275 }
276 g_free (selected);
277 break;
278 }
279 case RESPONSE_DELETE:
280 {
281 GtkWidget *confirm;
282 gint retval;
283 gchar *msg;
284 selected = get_selected ();
285 if (!selected)
286 {
287 hildon_banner_show_information (NULL, NULL,
288 "Select a connection first");
289 break;
290 }
291 msg = g_strdup_printf ("Delete connection?\n%s", selected);
292 confirm = hildon_note_new_confirmation (data, msg);
293 retval = gtk_dialog_run (GTK_DIALOG (confirm));
294 if (retval == GTK_RESPONSE_OK)
295 {
296 strongswan_connections_remove_connection (ListDialog.conns,
297 selected);
298 }
299 gtk_widget_destroy (confirm);
300 g_free (msg);
301 g_free (selected);
302 break;
303 }
304 default:
305 break;
306 }
307 }
308 while (response > 0);
309
310 gtk_widget_destroy (ListDialog.dialog);
311 g_object_unref (ListDialog.conns);
312 return OSSO_OK;
313 }
314
315 /**
316 * callback called in case state has to be saved
317 */
318 osso_return_t save_state(osso_context_t *osso, gpointer data)
319 {
320 /* save state */
321 return OSSO_OK;
322 }
323