ported NM plugin to upstream NetworkManager changes
[strongswan.git] / src / charon / plugins / nm / gnome / auth-dialog / main.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2004 Dan Williams
5 * Red Hat, Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * $Id$
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <string.h>
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27 #include <gnome-keyring.h>
28 #include <libgnomeui/libgnomeui.h>
29 #include <gconf/gconf-client.h>
30 #include <nm-vpn-plugin.h>
31 #include <nm-setting-vpn.h>
32 #include <nm-setting-connection.h>
33
34 #define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
35
36 /**
37 * lookup a password in the keyring
38 */
39 static char *lookup_password(char *name, char *service)
40 {
41 GList *list;
42 GList *iter;
43 char *pass = NULL;
44
45 if (gnome_keyring_find_network_password_sync(g_get_user_name(), NULL, name,
46 NULL, service, NULL, 0, &list) != GNOME_KEYRING_RESULT_OK)
47 {
48 return NULL;
49 }
50
51 for (iter = list; iter; iter = iter->next)
52 {
53 GnomeKeyringNetworkPasswordData *data = iter->data;
54
55 if (strcmp(data->object, "password") == 0 && data->password)
56 {
57 pass = g_strdup(data->password);
58 break;
59 }
60 }
61 gnome_keyring_network_password_list_free(list);
62 return pass;
63 }
64
65 /**
66 * get the connection type
67 */
68 static char* get_connection_type(char *uuid)
69 {
70 GConfClient *client = NULL;
71 GSList *list;
72 GSList *iter;
73 char *key, *str, *path, *found = NULL, *method = NULL;
74
75 client = gconf_client_get_default();
76
77 list = gconf_client_all_dirs(client, "/system/networking/connections", NULL);
78 g_return_val_if_fail(list, NULL);
79
80 for (iter = list; iter; iter = iter->next)
81 {
82 path = (char *) iter->data;
83
84 key = g_strdup_printf("%s/%s/%s", path,
85 NM_SETTING_CONNECTION_SETTING_NAME,
86 NM_SETTING_CONNECTION_UUID);
87 str = gconf_client_get_string(client, key, NULL);
88 g_free (key);
89
90 if (str && !strcmp(str, uuid))
91 {
92 found = g_strdup(path);
93 }
94 g_free (str);
95 if (found)
96 {
97 break;
98 }
99 }
100 g_slist_foreach(list, (GFunc)g_free, NULL);
101 g_slist_free(list);
102
103 if (found)
104 {
105 key = g_strdup_printf ("%s/%s/%s", found,
106 NM_SETTING_VPN_SETTING_NAME, "method");
107 method = gconf_client_get_string(client, key, NULL);
108 g_free(found);
109 g_free(key);
110 }
111 g_object_unref(client);
112 return method;
113 }
114
115 int main (int argc, char *argv[])
116 {
117 gboolean retry = FALSE;
118 gchar *name = NULL, *uuid = NULL, *service = NULL, *keyring = NULL, *pass;
119 GOptionContext *context;
120 GnomeProgram *program = NULL;
121 int exit_status = 1;
122 char buf, *agent, *type;
123 guint32 itemid;
124 GtkWidget *dialog;
125 GOptionEntry entries[] = {
126 { "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
127 { "uuid", 'u', 0, G_OPTION_ARG_STRING, &uuid, "UUID of VPN connection", NULL},
128 { "name", 'n', 0, G_OPTION_ARG_STRING, &name, "Name of VPN connection", NULL},
129 { "service", 's', 0, G_OPTION_ARG_STRING, &service, "VPN service type", NULL},
130 { NULL }
131 };
132
133 bindtextdomain(GETTEXT_PACKAGE, NULL);
134 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
135 textdomain(GETTEXT_PACKAGE);
136
137 context = g_option_context_new ("- strongswan auth dialog");
138 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
139
140 program = gnome_program_init ("nm-strongswan-auth-dialog", VERSION,
141 LIBGNOMEUI_MODULE,
142 argc, argv,
143 GNOME_PARAM_GOPTION_CONTEXT, context,
144 GNOME_PARAM_NONE);
145
146 if (uuid == NULL || name == NULL || service == NULL)
147 {
148 fprintf (stderr, "Have to supply UUID, name, and service\n");
149 g_object_unref (program);
150 return 1;
151 }
152
153 if (strcmp(service, NM_DBUS_SERVICE_STRONGSWAN) != 0)
154 {
155 fprintf(stderr, "This dialog only works with the '%s' service\n",
156 NM_DBUS_SERVICE_STRONGSWAN);
157 g_object_unref (program);
158 return 1;
159 }
160
161 type = get_connection_type(uuid);
162 if (!type)
163 {
164 fprintf(stderr, "Connection lookup failed\n");
165 g_object_unref (program);
166 return 1;
167 }
168 if (!strcmp(type, "eap") || !strcmp(type, "key"))
169 {
170 pass = lookup_password(name, service);
171 if (!pass || retry)
172 {
173 if (!strcmp(type, "eap"))
174 {
175 dialog = gnome_password_dialog_new(_("VPN password required"),
176 _("EAP password required to establish VPN connection:"),
177 NULL, NULL, TRUE);
178 }
179 else
180 {
181 dialog = gnome_password_dialog_new(_("VPN password required"),
182 _("Private key decryption password required to establish VPN connection:"),
183 NULL, NULL, TRUE);
184 }
185 gnome_password_dialog_set_show_remember(GNOME_PASSWORD_DIALOG(dialog), TRUE);
186 gnome_password_dialog_set_show_username(GNOME_PASSWORD_DIALOG(dialog), FALSE);
187 if (pass)
188 {
189 gnome_password_dialog_set_password(GNOME_PASSWORD_DIALOG(dialog), pass);
190 }
191 if (!gnome_password_dialog_run_and_block(GNOME_PASSWORD_DIALOG(dialog)))
192 {
193 g_object_unref (program);
194 return 1;
195 }
196
197 pass = gnome_password_dialog_get_password(GNOME_PASSWORD_DIALOG(dialog));
198 switch (gnome_password_dialog_get_remember(GNOME_PASSWORD_DIALOG(dialog)))
199 {
200 case GNOME_PASSWORD_DIALOG_REMEMBER_NOTHING:
201 break;
202 case GNOME_PASSWORD_DIALOG_REMEMBER_SESSION:
203 keyring = "session";
204 /* FALL */
205 case GNOME_PASSWORD_DIALOG_REMEMBER_FOREVER:
206 if (gnome_keyring_set_network_password_sync(keyring,
207 g_get_user_name(), NULL, name, "password", service, NULL, 0,
208 pass, &itemid) != GNOME_KEYRING_RESULT_OK)
209 {
210 g_warning ("storing password in keyring failed");
211 }
212 break;
213 }
214 }
215 printf("password\n%s\n", pass);
216 }
217 else
218 {
219 agent = getenv("SSH_AUTH_SOCK");
220 if (agent)
221 {
222 printf("agent\n%s\n", agent);
223 }
224 else
225 {
226 GtkWidget *dialog;
227
228 dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR,
229 GTK_BUTTONS_OK,
230 _("Configuration uses ssh-agent for authentication, "
231 "but ssh-agent is not running!"));
232 gtk_dialog_run (GTK_DIALOG (dialog));
233 gtk_widget_destroy (dialog);
234 return 1;
235 }
236 }
237 printf("\n\n");
238 /* flush output, wait for input */
239 fflush(stdout);
240 fread(&buf, 1, sizeof(buf), stdin);
241 g_object_unref(program);
242 return 0;
243 }
244