146
60
* @return returns true if the key is encrypted, false otherwise
149
pem_is_encrypted(const char *filename)
152
GIOChannel *pem_chan;
154
gboolean encrypted = FALSE;
156
pem_chan = g_io_channel_new_file (filename, "r", NULL);
158
if ( pem_chan == NULL ) {
163
while ( ! encrypted && (g_io_channel_read_line (pem_chan, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) ) {
164
if ( strstr (str, "Proc-Type: 4,ENCRYPTED") == str ) {
177
get_passwords (const char *vpn_name,
178
const char *vpn_service,
180
gboolean need_password,
181
gboolean need_certpass)
186
char *keyring_password;
187
char *keyring_certpass;
188
gboolean keyring_is_session;
189
GSList *keyring_result;
190
GnomeTwoPasswordDialogRemember remember;
191
int num_passwords = 0;
194
keyring_password = NULL;
195
keyring_certpass = NULL;
196
keyring_result = NULL;
198
g_return_val_if_fail (vpn_name != NULL, NULL);
200
/* Use the system user name, since the VPN might have a different user name */
202
if ((result = lookup_pass (vpn_name, vpn_service, &keyring_is_session)) != NULL) {
206
if ((keyring_result = lookup_pass (vpn_name, vpn_service, &keyring_is_session)) != NULL) {
207
keyring_password = g_strdup ((char *) keyring_result->data);
208
keyring_certpass = g_strdup ((char *) (g_slist_next (keyring_result))->data);
210
g_slist_foreach (keyring_result, (GFunc)g_free, NULL);
211
g_slist_free (keyring_result);
214
prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."), vpn_name);
215
dialog = gnome_two_password_dialog_new (_("Authenticate VPN"), prompt, NULL, NULL, FALSE);
218
gnome_two_password_dialog_set_show_username (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE);
219
gnome_two_password_dialog_set_show_userpass_buttons (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE);
220
gnome_two_password_dialog_set_show_domain (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE);
221
gnome_two_password_dialog_set_show_remember (GNOME_TWO_PASSWORD_DIALOG (dialog), TRUE);
223
if (need_password && need_certpass) {
224
gnome_two_password_dialog_set_show_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog),
226
gnome_two_password_dialog_set_password_secondary_label (GNOME_TWO_PASSWORD_DIALOG (dialog),
227
_("Certificate password:") );
229
/* if retrying, put in the passwords from the keyring */
230
if (keyring_password != NULL) {
231
gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog),
234
if (keyring_certpass != NULL) {
235
gnome_two_password_dialog_set_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog),
239
gnome_two_password_dialog_set_show_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog),
242
// defaults for label are ok
244
/* if retrying, put in the passwords from the keyring */
245
if (keyring_password != NULL) {
246
gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog),
250
} else if (need_certpass) {
251
gnome_two_password_dialog_set_password_primary_label (GNOME_TWO_PASSWORD_DIALOG (dialog),
252
_("Certificate password:") );
253
/* if retrying, put in the passwords from the keyring */
254
if (keyring_certpass != NULL) {
255
gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog),
261
/* use the same keyring storage options as from the items we put in the entry boxes */
262
remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_NOTHING;
263
if (keyring_result != NULL) {
264
if (keyring_is_session)
265
remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION;
267
remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER;
269
gnome_two_password_dialog_set_remember (GNOME_TWO_PASSWORD_DIALOG (dialog), remember);
271
gtk_widget_show (dialog);
273
if (gnome_two_password_dialog_run_and_block (GNOME_TWO_PASSWORD_DIALOG (dialog))) {
274
char *password = "unused";
275
char *certpass = "unused";
277
if (need_password && need_certpass) {
278
password = gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog));
279
certpass = gnome_two_password_dialog_get_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog));
282
password = gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog));
283
} else if (need_certpass) {
284
certpass = gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog));
288
result = g_slist_append (result, g_strdup (password));
289
result = g_slist_append (result, g_strdup (certpass));
291
switch (gnome_two_password_dialog_get_remember (GNOME_TWO_PASSWORD_DIALOG (dialog))) {
292
case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION:
293
save_vpn_password (vpn_name, vpn_service, "session", password, certpass);
295
case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER:
296
save_vpn_password (vpn_name, vpn_service, NULL, password, certpass);
303
g_free (keyring_password);
304
g_free (keyring_certpass);
306
gtk_widget_destroy (dialog);
63
pem_is_encrypted (const char *filename)
67
gboolean encrypted = FALSE;
69
pem_chan = g_io_channel_new_file (filename, "r", NULL);
73
while (g_io_channel_read_line (pem_chan, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
74
if (strncmp (str, PROC_TYPE_TAG, strlen (PROC_TYPE_TAG)) == 0) {
81
g_io_channel_shutdown (pem_chan, FALSE, NULL);
82
g_io_channel_unref (pem_chan);
88
clear_secrets (PasswordsInfo *info)
91
memset (info->password, 0, strlen (info->password));
92
g_free (info->password);
95
memset (info->certpass, 0, strlen (info->certpass));
96
g_free (info->certpass);
101
get_secrets (PasswordsInfo *info, gboolean retry)
103
GnomeTwoPasswordDialog *dialog;
104
gboolean is_session = TRUE;
106
gboolean success = FALSE, need_secret = FALSE;
108
g_return_val_if_fail (info->vpn_uuid != NULL, FALSE);
109
g_return_val_if_fail (info->vpn_name != NULL, FALSE);
111
if (info->need_password) {
112
info->password = keyring_helpers_lookup_secret (info->vpn_uuid, NM_OPENVPN_KEY_PASSWORD, &is_session);
117
if (info->need_certpass) {
118
info->certpass = keyring_helpers_lookup_secret (info->vpn_uuid, NM_OPENVPN_KEY_CERTPASS, &is_session);
123
/* Have all passwords and we're not supposed to ask the user again */
124
if (!need_secret && !retry)
127
prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."), info->vpn_name);
128
dialog = GNOME_TWO_PASSWORD_DIALOG (gnome_two_password_dialog_new (_("Authenticate VPN"), prompt, NULL, NULL, FALSE));
131
gnome_two_password_dialog_set_show_username (dialog, FALSE);
132
gnome_two_password_dialog_set_show_userpass_buttons (dialog, FALSE);
133
gnome_two_password_dialog_set_show_domain (dialog, FALSE);
134
gnome_two_password_dialog_set_show_remember (dialog, TRUE);
136
/* If nothing was found in the keyring, default to not remembering any secrets */
137
if (info->password || info->certpass) {
138
/* Otherwise set default remember based on which keyring the secrets were found in */
140
gnome_two_password_dialog_set_remember (dialog, GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION);
142
gnome_two_password_dialog_set_remember (dialog, GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER);
144
gnome_two_password_dialog_set_remember (dialog, GNOME_TWO_PASSWORD_DIALOG_REMEMBER_NOTHING);
146
/* pre-fill dialog with the password */
147
if (info->need_password && info->need_certpass) {
148
gnome_two_password_dialog_set_show_password_secondary (dialog, TRUE);
149
gnome_two_password_dialog_set_password_secondary_label (dialog, _("Certificate pass_word:") );
151
/* if retrying, put in the passwords from the keyring */
153
gnome_two_password_dialog_set_password (dialog, info->password);
155
gnome_two_password_dialog_set_password_secondary (dialog, info->certpass);
157
gnome_two_password_dialog_set_show_password_secondary (dialog, FALSE);
158
if (info->need_password) {
159
/* if retrying, put in the passwords from the keyring */
161
gnome_two_password_dialog_set_password (dialog, info->password);
162
} else if (info->need_certpass) {
163
gnome_two_password_dialog_set_password_primary_label (dialog, _("Certificate password:"));
164
/* if retrying, put in the passwords from the keyring */
166
gnome_two_password_dialog_set_password (dialog, info->certpass);
169
clear_secrets (info);
171
gtk_widget_show (GTK_WIDGET (dialog));
173
if (gnome_two_password_dialog_run_and_block (dialog)) {
174
gboolean save = FALSE;
175
char *keyring = NULL;
177
if (info->need_password)
178
info->password = g_strdup (gnome_two_password_dialog_get_password (dialog));
179
if (info->need_certpass) {
180
info->certpass = g_strdup (info->need_password ?
181
gnome_two_password_dialog_get_password_secondary (dialog) :
182
gnome_two_password_dialog_get_password (dialog));
185
switch (gnome_two_password_dialog_get_remember (dialog)) {
186
case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION:
189
case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER:
197
if (info->password) {
198
keyring_helpers_save_secret (info->vpn_uuid, info->vpn_name,
199
keyring, NM_OPENVPN_KEY_PASSWORD, info->password);
201
if (info->certpass) {
202
keyring_helpers_save_secret (info->vpn_uuid, info->vpn_name,
203
keyring, NM_OPENVPN_KEY_CERTPASS, info->certpass);
210
gtk_widget_destroy (GTK_WIDGET (dialog));
216
get_password_types (PasswordsInfo *info)
218
GConfClient *gconf_client = NULL;
223
char *connection_path = NULL;
224
gboolean success = FALSE;
225
char *connection_type;
227
/* FIXME: This whole thing sucks: we should not go around poking gconf
228
directly, but there's nothing that does it for us right now */
230
gconf_client = gconf_client_get_default ();
232
conf_list = gconf_client_all_dirs (gconf_client, "/system/networking/connections", NULL);
236
for (iter = conf_list; iter; iter = iter->next) {
237
const char *path = (const char *) iter->data;
239
key = g_strdup_printf ("%s/%s/%s",
241
NM_SETTING_CONNECTION_SETTING_NAME,
242
NM_SETTING_CONNECTION_TYPE);
243
str = gconf_client_get_string (gconf_client, key, NULL);
246
if (!str || strcmp (str, "vpn")) {
252
key = g_strdup_printf ("%s/%s/%s",
254
NM_SETTING_CONNECTION_SETTING_NAME,
255
NM_SETTING_CONNECTION_UUID);
256
str = gconf_client_get_string (gconf_client, key, NULL);
259
if (!str || strcmp (str, info->vpn_uuid)) {
265
/* Woo, found the connection */
266
connection_path = g_strdup (path);
270
g_slist_foreach (conf_list, (GFunc) g_free, NULL);
271
g_slist_free (conf_list);
273
if (!connection_path)
276
key = g_strdup_printf ("%s/%s/%s", connection_path,
277
NM_SETTING_VPN_SETTING_NAME,
278
NM_OPENVPN_KEY_CONNECTION_TYPE);
279
connection_type = gconf_client_get_string (gconf_client, key, NULL);
282
if ( !strcmp (connection_type, NM_OPENVPN_CONTYPE_TLS)
283
|| !strcmp (connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
286
if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS))
287
info->need_password = TRUE;
289
key = g_strdup_printf ("%s/%s/%s", connection_path, NM_SETTING_VPN_SETTING_NAME,
291
str = gconf_client_get_string (gconf_client, key, NULL);
293
info->need_certpass = pem_is_encrypted (str);
296
} else if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
298
} else if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_PASSWORD)) {
300
info->need_password = TRUE;
303
g_free (connection_type);
304
g_free (connection_path);
307
g_object_unref (gconf_client);
312
312
main (int argc, char *argv[])
314
GConfClient *gconf_client = NULL;
315
GConfValue *gconf_val = NULL;
316
gchar *gconf_key = NULL;
318
gboolean needs_password = FALSE;
319
gboolean needs_certpass = FALSE;
320
gboolean valid_conn = FALSE;
324
gchar *connection_type = NULL;
325
static gboolean retry = FALSE;
326
static gchar *vpn_name = NULL;
327
static gchar *vpn_service = NULL;
328
GError *error = NULL;
329
GOptionContext *context;
331
static GOptionEntry entries[] =
333
{ "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
334
{ "name", 'n', 0, G_OPTION_ARG_STRING, &vpn_name, "Name of VPN connection", NULL},
335
{ "service", 's', 0, G_OPTION_ARG_STRING, &vpn_service, "VPN service type", NULL},
340
bindtextdomain (GETTEXT_PACKAGE, NULL);
341
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
342
textdomain (GETTEXT_PACKAGE);
346
context = g_option_context_new ("- openvpn auth dialog");
347
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
348
g_option_context_add_group (context, gtk_get_option_group (TRUE));
349
g_option_context_parse (context, &argc, &argv, &error);
351
if (vpn_name == NULL || vpn_service == NULL) {
352
fprintf (stderr, "Have to supply both name and service\n");
356
if (strcmp (vpn_service, VPN_SERVICE) != 0) {
357
fprintf (stderr, "This dialog only works with the '%s' service\n", VPN_SERVICE);
361
gnome_program_init ("nm-openvpn-auth-dialog", VERSION, LIBGNOMEUI_MODULE,
363
GNOME_PARAM_NONE, GNOME_PARAM_NONE);
366
gconf_client = gconf_client_get_default();
367
escaped_name = gconf_escape_key (vpn_name, strlen (vpn_name));
368
gconf_key = g_strdup_printf ("%s/%s/vpn_data", GCONF_PATH_VPN_CONNECTIONS, escaped_name);
369
if ( !(gconf_val = gconf_client_get (gconf_client, gconf_key, NULL)) ||
370
!(gconf_val->type == GCONF_VALUE_LIST) ||
371
!(gconf_value_get_list_type (gconf_val) == GCONF_VALUE_STRING)) {
374
gconf_value_free (gconf_val);
382
for (i = gconf_value_get_list (gconf_val); i != NULL; i = g_slist_next (i)) {
383
const char *gkey = gconf_value_get_string ((GConfValue *)i->data);
384
const char *gval = NULL;
386
i = g_slist_next (i);
388
gval = gconf_value_get_string ((GConfValue *)i->data);
391
if ( gkey != NULL ) {
392
if ( strcmp (gkey, "connection-type") == 0 ) {
393
connection_type = g_strdup (gval);
394
if ( (strcmp (gval, "password") == 0) ||
395
(strcmp (gval, "x509userpass") == 0) ) {
396
needs_password = TRUE;
398
} else if ( strcmp (gkey, "key") == 0 ) {
399
key = g_strdup (gval);
403
gconf_value_free (gconf_val);
405
if ( (connection_type != NULL) && (key != NULL) ) {
406
if ( (strcmp (connection_type, "x509") == 0) ||
407
(strcmp (connection_type, "x509userpass") == 0) ) {
408
needs_certpass = pem_is_encrypted (key);
412
if ( needs_password || needs_certpass ) {
413
passwords = get_passwords (vpn_name, vpn_service, retry, needs_password, needs_certpass);
414
if (passwords == NULL)
417
/* dump the passwords to stdout */
418
for (i = passwords; i != NULL; i = g_slist_next (i)) {
419
char *password = (char *) i->data;
420
printf ("%s\n", password);
423
g_slist_foreach (passwords, (GFunc)g_free, NULL);
424
g_slist_free (passwords);
427
printf ("No password needed\nNo certpass needed\n");
431
/* for good measure, flush stdout since Kansas is going Bye-Bye */
434
/* wait for data on stdin */
435
bytes_read = fread (buf, sizeof (char), sizeof (buf), stdin);
438
g_object_unref (gconf_client);
439
g_option_context_free (context);
441
g_free (connection_type);
444
if ( ! valid_conn ) {
446
} else if ( needs_password ) {
447
return (passwords != NULL) ? 0 : 1;
315
gboolean retry = FALSE;
316
gchar *vpn_name = NULL;
317
gchar *vpn_uuid = NULL;
318
gchar *vpn_service = NULL;
321
GOptionContext *context;
322
GOptionEntry entries[] = {
323
{ "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
324
{ "uuid", 'u', 0, G_OPTION_ARG_STRING, &vpn_uuid, "UUID of VPN connection", NULL},
325
{ "name", 'n', 0, G_OPTION_ARG_STRING, &vpn_name, "Name of VPN connection", NULL},
326
{ "service", 's', 0, G_OPTION_ARG_STRING, &vpn_service, "VPN service type", NULL},
330
bindtextdomain (GETTEXT_PACKAGE, NULL);
331
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
332
textdomain (GETTEXT_PACKAGE);
334
gtk_init (&argc, &argv);
336
context = g_option_context_new ("- openvpn auth dialog");
337
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
338
g_option_context_parse (context, &argc, &argv, NULL);
339
g_option_context_free (context);
341
if (vpn_uuid == NULL || vpn_name == NULL || vpn_service == NULL) {
342
fprintf (stderr, "Have to supply ID, name, and service\n");
346
if (strcmp (vpn_service, NM_DBUS_SERVICE_OPENVPN) != 0) {
347
fprintf (stderr, "This dialog only works with the '%s' service\n", NM_DBUS_SERVICE_OPENVPN);
351
memset (&info, 0, sizeof (PasswordsInfo));
352
info.vpn_uuid = vpn_uuid;
353
info.vpn_name = vpn_name;
355
if (!get_password_types (&info)) {
356
fprintf (stderr, "Invalid connection");
360
if (!info.need_password && !info.need_certpass) {
361
printf ("%s\n%s\n\n\n", NM_OPENVPN_KEY_NOSECRET, "true");
365
if (get_secrets (&info, retry)) {
366
if (info.need_password)
367
printf ("%s\n%s\n", NM_OPENVPN_KEY_PASSWORD, info.password);
368
if (info.need_certpass)
369
printf ("%s\n%s\n", NM_OPENVPN_KEY_CERTPASS, info.certpass);
373
clear_secrets (&info);
375
/* for good measure, flush stdout since Kansas is going Bye-Bye */
378
/* wait for data on stdin */
379
ret = fread (buf, sizeof (char), sizeof (buf), stdin);