summaryrefslogtreecommitdiff
path: root/src/passphrase.c
diff options
context:
space:
mode:
authorSimeon Simeonov2018-02-26 11:23:00 +0100
committerSimeon Simeonov2018-02-26 11:23:00 +0100
commit0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch)
treeaf916a30553c78ce9d4f2d8658656a175c5b6921 /src/passphrase.c
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'src/passphrase.c')
-rw-r--r--src/passphrase.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/passphrase.c b/src/passphrase.c
new file mode 100644
index 0000000..20447c1
--- /dev/null
+++ b/src/passphrase.c
@@ -0,0 +1,354 @@
1/* passphrase.c - GTK+ based passphrase callback
2 * Copyright (C) 2001 Werner Koch (dd9jn)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#if USE_GPGME
24
25#include <glib.h>
26#include <glib/gi18n.h>
27#include <gdk/gdktypes.h>
28#include <gdk/gdkkeysyms.h>
29#include <gdk/gdkdisplay.h>
30#ifdef GDK_WINDOWING_X11
31# include <gdk/gdkx.h>
32#endif /* GDK_WINDOWING_X11 */
33#include <gtk/gtkmain.h>
34#include <gtk/gtkwidget.h>
35#include <gtk/gtkwindow.h>
36#include <gtk/gtkvbox.h>
37#include <gtk/gtktable.h>
38#include <gtk/gtklabel.h>
39#include <gtk/gtkentry.h>
40#include <gtk/gtkhbbox.h>
41#include <gtk/gtkbutton.h>
42#include <gtk/gtksignal.h>
43#include <gtk/gtkstock.h>
44#include <string.h>
45#include <sys/types.h>
46#if HAVE_SYS_MMAN_H
47# include <sys/mman.h>
48#endif
49
50#ifdef G_OS_WIN32
51# include <windows.h>
52#endif
53
54#include "passphrase.h"
55#include "prefs_common.h"
56#include "manage_window.h"
57#include "utils.h"
58#include "gtkutils.h"
59
60static gboolean grab_all = FALSE;
61
62static gboolean pass_ack;
63static gchar *last_pass = NULL;
64
65static void passphrase_ok_cb(GtkWidget *widget, gpointer data);
66static void passphrase_cancel_cb(GtkWidget *widget, gpointer data);
67static gint passphrase_deleted(GtkWidget *widget, GdkEventAny *event,
68 gpointer data);
69static gboolean passphrase_key_pressed(GtkWidget *widget, GdkEventKey *event,
70 gpointer data);
71static gchar* passphrase_mbox(const gchar *uid_hint, const gchar *pass_hint,
72 gint prev_bad);
73
74static GtkWidget *create_description(const gchar *uid_hint,
75 const gchar *pass_hint, gint prev_bad);
76
77void
78gpgmegtk_set_passphrase_grab(gint yes)
79{
80 grab_all = yes;
81}
82
83static gchar*
84passphrase_mbox(const gchar *uid_hint, const gchar *pass_hint, gint prev_bad)
85{
86 gchar *the_passphrase = NULL;
87 GtkWidget *vbox;
88 GtkWidget *confirm_box;
89 GtkWidget *window;
90 GtkWidget *pass_entry;
91 GtkWidget *ok_button;
92 GtkWidget *cancel_button;
93
94 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
95 gtk_window_set_title(GTK_WINDOW(window), _("Passphrase"));
96 gtk_widget_set_size_request(window, 450, -1);
97 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
98 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
99 gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
100 g_signal_connect(G_OBJECT(window), "delete_event",
101 G_CALLBACK(passphrase_deleted), NULL);
102 g_signal_connect(G_OBJECT(window), "key_press_event",
103 G_CALLBACK(passphrase_key_pressed), NULL);
104 MANAGE_WINDOW_SIGNALS_CONNECT(window);
105 manage_window_set_transient(GTK_WINDOW(window));
106
107 vbox = gtk_vbox_new(FALSE, 8);
108 gtk_container_add(GTK_CONTAINER(window), vbox);
109 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
110
111 if (uid_hint || pass_hint) {
112 GtkWidget *label;
113 label = create_description (uid_hint, pass_hint, prev_bad);
114 gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
115 }
116
117 pass_entry = gtk_entry_new();
118 gtk_box_pack_start(GTK_BOX(vbox), pass_entry, FALSE, FALSE, 0);
119 gtk_entry_set_visibility(GTK_ENTRY(pass_entry), FALSE);
120 gtk_widget_grab_focus(pass_entry);
121
122 gtkut_stock_button_set_create(&confirm_box, &ok_button, GTK_STOCK_OK,
123 &cancel_button, GTK_STOCK_CANCEL,
124 NULL, NULL);
125 gtk_box_pack_end(GTK_BOX(vbox), confirm_box, FALSE, FALSE, 0);
126 gtk_widget_grab_default(ok_button);
127
128 g_signal_connect(G_OBJECT(ok_button), "clicked",
129 G_CALLBACK(passphrase_ok_cb), NULL);
130 g_signal_connect(G_OBJECT(pass_entry), "activate",
131 G_CALLBACK(passphrase_ok_cb), NULL);
132 g_signal_connect(G_OBJECT(cancel_button), "clicked",
133 G_CALLBACK(passphrase_cancel_cb), NULL);
134
135 gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER);
136 if (grab_all)
137 gtk_window_set_policy (GTK_WINDOW(window), FALSE, FALSE, TRUE);
138
139 gtk_widget_show_all(window);
140
141 if (grab_all) {
142 /* make sure that window is viewable
143 * FIXME: this is still not enough */
144 gtk_widget_show_now(window);
145 gdk_flush();
146#ifdef GDK_WINDOWING_X11
147 gdk_x11_display_grab(gdk_display_get_default());
148#endif /* GDK_WINDOWING_X11 */
149 if (gdk_pointer_grab(window->window, TRUE, 0,
150 window->window, NULL, GDK_CURRENT_TIME)) {
151#ifdef GDK_WINDOWING_X11
152 gdk_x11_display_ungrab(gdk_display_get_default());
153#endif /* GDK_WINDOWING_X11 */
154 g_warning("OOPS: Could not grab mouse\n");
155 gtk_widget_destroy(window);
156 return NULL;
157 }
158 if (gdk_keyboard_grab(window->window, FALSE, GDK_CURRENT_TIME)) {
159 gdk_display_pointer_ungrab(gdk_display_get_default(),
160 GDK_CURRENT_TIME);
161#ifdef GDK_WINDOWING_X11
162 gdk_x11_display_ungrab(gdk_display_get_default());
163#endif /* GDK_WINDOWING_X11 */
164 g_warning("OOPS: Could not grab keyboard\n");
165 gtk_widget_destroy(window);
166 return NULL;
167 }
168 }
169
170 gtk_main();
171
172 if (grab_all) {
173 gdk_display_keyboard_ungrab(gdk_display_get_default(),
174 GDK_CURRENT_TIME);
175 gdk_display_pointer_ungrab(gdk_display_get_default(), GDK_CURRENT_TIME);
176#ifdef GDK_WINDOWING_X11
177 gdk_x11_display_ungrab(gdk_display_get_default());
178#endif /* GDK_WINDOWING_X11 */
179 gdk_flush();
180 }
181
182 manage_window_focus_out(window, NULL, NULL);
183
184 if (pass_ack) {
185 const gchar *entry_text;
186 entry_text = gtk_entry_get_text(GTK_ENTRY(pass_entry));
187 the_passphrase = g_locale_from_utf8(entry_text, -1, NULL, NULL, NULL);
188 if (!the_passphrase)
189 the_passphrase = g_strdup(entry_text);
190 }
191 gtk_widget_destroy(window);
192
193 return the_passphrase;
194}
195
196
197static void
198passphrase_ok_cb(GtkWidget *widget, gpointer data)
199{
200 pass_ack = TRUE;
201 gtk_main_quit();
202}
203
204static void
205passphrase_cancel_cb(GtkWidget *widget, gpointer data)
206{
207 pass_ack = FALSE;
208 gtk_main_quit();
209}
210
211
212static gint
213passphrase_deleted(GtkWidget *widget, GdkEventAny *event, gpointer data)
214{
215 passphrase_cancel_cb(NULL, NULL);
216 return TRUE;
217}
218
219
220static gboolean
221passphrase_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
222{
223 if (event && event->keyval == GDK_Escape)
224 passphrase_cancel_cb(NULL, NULL);
225 return FALSE;
226}
227
228static gint
229linelen (const gchar *s)
230{
231 gint i;
232
233 for (i = 0; *s && *s != '\n'; s++, i++)
234 ;
235
236 return i;
237}
238
239static GtkWidget *
240create_description(const gchar *uid_hint, const gchar *pass_hint, gint prev_bad)
241{
242 const gchar *uid = NULL, *info = NULL;
243 gchar *buf;
244 GtkWidget *label;
245
246 if (!uid_hint)
247 uid = _("[no user id]");
248 else
249 uid = uid_hint;
250 if (!pass_hint)
251 info = "";
252 else
253 info = pass_hint;
254
255 buf = g_strdup_printf (_("%sPlease enter the passphrase for:\n\n"
256 " %.*s \n"
257 "(%.*s)\n"),
258 prev_bad ?
259 _("Bad passphrase! Try again...\n\n") : "",
260 linelen (uid), uid, linelen (info), info);
261
262 label = gtk_label_new (buf);
263 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
264 g_free (buf);
265
266 return label;
267}
268
269static int free_passphrase(gpointer _unused)
270{
271 if (last_pass != NULL) {
272#if HAVE_MLOCK
273 munlock(last_pass, strlen(last_pass));
274#endif
275 g_free(last_pass);
276 last_pass = NULL;
277 debug_print("%% passphrase removed\n");
278 }
279
280 return FALSE;
281}
282
283gpgme_error_t
284gpgmegtk_passphrase_cb(void *opaque, const char *uid_hint,
285 const char *passphrase_hint, int prev_bad, int fd)
286{
287 const char *pass;
288#if defined(G_OS_WIN32) && !defined(HAVE_GPGME_IO_WRITEN)
289 HANDLE hd = (HANDLE)fd;
290 DWORD n;
291#endif
292
293 if (prefs_common.store_passphrase && last_pass != NULL && !prev_bad) {
294#ifdef HAVE_GPGME_IO_WRITEN
295 gpgme_io_writen(fd, last_pass, strlen(last_pass));
296 gpgme_io_writen(fd, "\n", 1);
297#elif defined(G_OS_WIN32)
298 WriteFile(hd, last_pass, strlen(last_pass), &n, NULL);
299 WriteFile(hd, "\n", 1, &n, NULL);
300#else
301 write(fd, last_pass, strlen(last_pass));
302 write(fd, "\n", 1);
303#endif
304 return GPG_ERR_NO_ERROR;
305 }
306 gpgmegtk_set_passphrase_grab (prefs_common.passphrase_grab);
307 debug_print ("%% requesting passphrase for `%s':\n", uid_hint);
308 pass = passphrase_mbox (uid_hint, passphrase_hint, prev_bad);
309 gpgmegtk_free_passphrase();
310 if (!pass) {
311 debug_print ("%% cancel passphrase entry\n");
312#ifdef HAVE_GPGME_IO_WRITEN
313 gpgme_io_writen(fd, "\n", 1);
314#elif defined(G_OS_WIN32)
315 WriteFile(hd, "\n", 1, &n, NULL);
316 CloseHandle(hd); /* somehow it will block without this */
317#else
318 write(fd, "\n", 1);
319#endif
320 return GPG_ERR_CANCELED;
321 }
322 else {
323 if (prefs_common.store_passphrase) {
324 last_pass = g_strdup(pass);
325#if HAVE_MLOCK
326 if (mlock(last_pass, strlen(last_pass)) == -1)
327 debug_print("%% locking passphrase failed\n");
328#endif
329
330 if (prefs_common.store_passphrase_timeout > 0) {
331 g_timeout_add_full(G_PRIORITY_LOW, prefs_common.store_passphrase_timeout * 60 * 1000, free_passphrase, NULL, NULL);
332 }
333 }
334 debug_print ("%% sending passphrase\n");
335 }
336#ifdef HAVE_GPGME_IO_WRITEN
337 gpgme_io_writen(fd, pass, strlen(pass));
338 gpgme_io_writen(fd, "\n", 1);
339#elif defined(G_OS_WIN32)
340 WriteFile(hd, pass, strlen(pass), &n, NULL);
341 WriteFile(hd, "\n", 1, &n, NULL);
342#else
343 write(fd, pass, strlen(pass));
344 write(fd, "\n", 1);
345#endif
346 return GPG_ERR_NO_ERROR;
347}
348
349void gpgmegtk_free_passphrase()
350{
351 (void)free_passphrase(NULL); // could be inline
352}
353
354#endif /* USE_GPGME */