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