~ubuntu-branches/ubuntu/hardy/network-manager-applet/hardy

« back to all changes in this revision

Viewing changes to src/vpn-password-dialog.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Mercatante
  • Date: 2007-06-15 12:46:22 UTC
  • Revision ID: james.westby@ubuntu.com-20070615124622-01cyrnf0uxxun4lz
Tags: upstream-0.6.5
ImportĀ upstreamĀ versionĀ 0.6.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
 
2
 *
 
3
 * Dan Williams <dcbw@redhat.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * (C) Copyright 2004 Red Hat, Inc.
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <gtk/gtk.h>
 
27
#include <glade/glade.h>
 
28
#include <glib.h>
 
29
#include <dbus/dbus.h>
 
30
#include <dbus/dbus-glib.h>
 
31
#include <glib/gi18n.h>
 
32
#include <unistd.h>
 
33
 
 
34
#include "applet.h"
 
35
#include "vpn-password-dialog.h"
 
36
#include "nm-utils.h"
 
37
 
 
38
 
 
39
typedef struct {
 
40
        GSList **passwords;
 
41
        int child_stdin;
 
42
        int num_newlines;
 
43
} IOUserData;
 
44
 
 
45
static void 
 
46
child_finished_cb (GPid pid, gint status, gpointer userdata)
 
47
{
 
48
        int *child_status = (gboolean *) userdata;
 
49
 
 
50
        *child_status = status;
 
51
}
 
52
 
 
53
static gboolean 
 
54
child_stdout_data_cb (GIOChannel *source, GIOCondition condition, gpointer userdata)
 
55
{
 
56
        char *str = NULL;
 
57
        IOUserData *io_user_data = (IOUserData *) userdata;
 
58
        GSList **passwords = (GSList **) io_user_data->passwords;
 
59
 
 
60
        if (! (condition & G_IO_IN))
 
61
                goto out;
 
62
 
 
63
        if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {
 
64
                int len;
 
65
 
 
66
                len = strlen (str);
 
67
                if (len == 1 && str[0] == '\n') {
 
68
 
 
69
                        /* on second line with a newline newline */
 
70
                        if (++io_user_data->num_newlines == 2) {
 
71
                                char buf[1];
 
72
                                /* terminate the child */
 
73
                                if (write (io_user_data->child_stdin, buf, sizeof (buf)) == -1)
 
74
                                        goto out;
 
75
                        }
 
76
                } else if (len > 0) {
 
77
                        /* remove terminating newline */
 
78
                        str[len - 1] = '\0';
 
79
                        *passwords = g_slist_append (*passwords, str);
 
80
                        str = NULL;
 
81
                }
 
82
        }
 
83
 
 
84
out:
 
85
        g_free (str);
 
86
 
 
87
        return TRUE;
 
88
}
 
89
 
 
90
GSList *
 
91
nma_vpn_request_password (NMApplet *applet, const char *name, const char *service, gboolean retry)
 
92
{
 
93
        const char       *argv[] = {NULL /*"/usr/libexec/nm-vpnc-auth-dialog"*/, 
 
94
                              "-n", NULL /*"davidznet42"*/, 
 
95
                              "-s", NULL /*"org.freedesktop.vpnc"*/, 
 
96
                              "-r",
 
97
                              NULL};
 
98
        GSList     *passwords = NULL;
 
99
        int         child_stdin;
 
100
        int         child_stdout;
 
101
        GPid        child_pid;
 
102
        int         child_status;
 
103
        GIOChannel *child_stdout_channel;
 
104
        guint       child_stdout_channel_eventid;
 
105
        GDir       *dir;
 
106
        char       *auth_dialog_binary;
 
107
        IOUserData io_user_data;
 
108
 
 
109
        auth_dialog_binary = NULL;
 
110
 
 
111
        /* find the auth-dialog binary */
 
112
        if ((dir = g_dir_open (VPN_NAME_FILES_DIR, 0, NULL)) != NULL) {
 
113
                const char *f;
 
114
 
 
115
                while (auth_dialog_binary == NULL && (f = g_dir_read_name (dir)) != NULL) {
 
116
                        char *path;
 
117
                        GKeyFile *keyfile;
 
118
 
 
119
                        if (!g_str_has_suffix (f, ".name"))
 
120
                                continue;
 
121
 
 
122
                        path = g_strdup_printf ("%s/%s", VPN_NAME_FILES_DIR, f);
 
123
 
 
124
                        keyfile = g_key_file_new ();
 
125
                        if (g_key_file_load_from_file (keyfile, path, 0, NULL)) {
 
126
                                char *thisservice;
 
127
 
 
128
                                if ((thisservice = g_key_file_get_string (keyfile, 
 
129
                                                                          "VPN Connection", 
 
130
                                                                          "service", NULL)) != NULL &&
 
131
                                    strcmp (thisservice, service) == 0) {
 
132
 
 
133
                                        auth_dialog_binary = g_key_file_get_string (keyfile, 
 
134
                                                                                    "GNOME", 
 
135
                                                                                    "auth-dialog", NULL);
 
136
                                }
 
137
 
 
138
                                g_free (thisservice);
 
139
                        }
 
140
                        g_key_file_free (keyfile);
 
141
                        g_free (path);
 
142
                }
 
143
                g_dir_close (dir);
 
144
        }
 
145
 
 
146
        if (auth_dialog_binary == NULL) {
 
147
                /* could find auth-dialog */
 
148
                GtkWidget *dialog;
 
149
 
 
150
                dialog = gtk_message_dialog_new (NULL,
 
151
                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
 
152
                                                 GTK_MESSAGE_ERROR,
 
153
                                                 GTK_BUTTONS_CLOSE,
 
154
                                                 _("Cannot start VPN connection '%s'"),
 
155
                                                 name);
 
156
                gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 
157
  _("Could not find the authentication dialog for VPN connection type '%s'. Contact your system administrator."),
 
158
                                                          service);
 
159
                gtk_window_present (GTK_WINDOW (dialog));
 
160
                g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
 
161
                goto out;
 
162
        }
 
163
 
 
164
        /* Fix up parameters with what we got */
 
165
        argv[0] = auth_dialog_binary;
 
166
        argv[2] = name;
 
167
        argv[4] = service;
 
168
        if (!retry)
 
169
                argv[5] = NULL;
 
170
 
 
171
        child_status = -1;
 
172
 
 
173
        if (!g_spawn_async_with_pipes (NULL,                       /* working_directory */
 
174
                                       (gchar **) argv,            /* argv */
 
175
                                       NULL,                       /* envp */
 
176
                                       G_SPAWN_DO_NOT_REAP_CHILD,  /* flags */
 
177
                                       NULL,                       /* child_setup */
 
178
                                       NULL,                       /* user_data */
 
179
                                       &child_pid,                 /* child_pid */
 
180
                                       &child_stdin,               /* standard_input */
 
181
                                       &child_stdout,              /* standard_output */
 
182
                                       NULL,                       /* standard_error */
 
183
                                       NULL)) {                    /* error */
 
184
                /* could not spawn */
 
185
                GtkWidget *dialog;
 
186
 
 
187
                dialog = gtk_message_dialog_new (NULL,
 
188
                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
 
189
                                                 GTK_MESSAGE_ERROR,
 
190
                                                 GTK_BUTTONS_CLOSE,
 
191
                                                 _("Cannot start VPN connection '%s'"),
 
192
                                                 name);
 
193
                gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 
194
  _("There was a problem launching the authentication dialog for VPN connection type '%s'. Contact your system administrator."),
 
195
                                                          service);
 
196
                gtk_window_present (GTK_WINDOW (dialog));
 
197
                g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
 
198
                goto out;
 
199
        }
 
200
 
 
201
        /* catch when child is reaped */
 
202
        g_child_watch_add (child_pid, child_finished_cb, (gpointer) &child_status);
 
203
 
 
204
        io_user_data.passwords = &passwords;
 
205
        io_user_data.child_stdin = child_stdin;
 
206
        io_user_data.num_newlines = 0;
 
207
 
 
208
        /* listen to what child has to say */
 
209
        child_stdout_channel = g_io_channel_unix_new (child_stdout);
 
210
        child_stdout_channel_eventid = g_io_add_watch (child_stdout_channel, G_IO_IN, child_stdout_data_cb, 
 
211
                                                       &io_user_data);
 
212
        g_io_channel_set_encoding (child_stdout_channel, NULL, NULL);
 
213
 
 
214
        /* recurse mainloop here until the child is finished (child_status is set in child_finished_cb) */
 
215
        while (child_status == -1) {
 
216
                g_main_context_iteration (NULL, TRUE);
 
217
        }
 
218
 
 
219
        g_spawn_close_pid (child_pid);
 
220
        g_source_remove (child_stdout_channel_eventid);
 
221
        g_io_channel_unref (child_stdout_channel);
 
222
 
 
223
        if (child_status != 0) {
 
224
                if (passwords != NULL) {
 
225
                        g_slist_foreach (passwords, (GFunc)g_free, NULL);
 
226
                        g_slist_free (passwords);
 
227
                        passwords = NULL;
 
228
                }
 
229
        }               
 
230
 
 
231
out:
 
232
        g_free (auth_dialog_binary);
 
233
 
 
234
        return passwords;
 
235
}