blob: 4d51032d1d369afe1b17c9118b11b7911e5440f5 [file] [log] [blame]
Damien Millerd3dcfaf1999-11-09 13:52:33 +11001/*
Damien Miller6677d412002-01-25 00:59:25 +11002 * Copyright (c) 2000-2002 Damien Miller. All rights reserved.
Damien Millerb5e85a52001-02-16 11:18:58 +11003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
Damien Miller8b1c22b2000-03-15 12:13:01 +110024
25/*
Damien Millera8e06ce2003-11-21 23:48:55 +110026 * This is a simple GNOME SSH passphrase grabber. To use it, set the
27 * environment variable SSH_ASKPASS to point to the location of
28 * gnome-ssh-askpass before calling "ssh-add < /dev/null".
Damien Millerfaf2f642001-12-21 10:28:07 +110029 *
Damien Miller6677d412002-01-25 00:59:25 +110030 * There is only two run-time options: if you set the environment variable
Damien Miller414642b2002-01-25 00:46:04 +110031 * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab
Damien Millera8e06ce2003-11-21 23:48:55 +110032 * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the
33 * pointer will be grabbed too. These may have some benefit to security if
Damien Miller6677d412002-01-25 00:59:25 +110034 * you don't trust your X server. We grab the keyboard always.
Damien Millerfaf2f642001-12-21 10:28:07 +110035 */
36
37/*
Damien Millerb5e85a52001-02-16 11:18:58 +110038 * Compile with:
39 *
40 * cc `gnome-config --cflags gnome gnomeui` \
Damien Miller10f30852002-09-12 14:49:00 +100041 * gnome-ssh-askpass1.c -o gnome-ssh-askpass \
Damien Millerb5e85a52001-02-16 11:18:58 +110042 * `gnome-config --libs gnome gnomeui`
43 *
44 */
Damien Millerd3dcfaf1999-11-09 13:52:33 +110045
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49#include <gnome.h>
Damien Millerb9a692d1999-11-12 12:09:36 +110050#include <X11/Xlib.h>
51#include <gdk/gdkx.h>
Damien Millerd3dcfaf1999-11-09 13:52:33 +110052
Damien Miller5314ae72000-06-07 20:08:19 +100053void
54report_failed_grab (void)
55{
56 GtkWidget *err;
57
58 err = gnome_message_box_new("Could not grab keyboard or mouse.\n"
59 "A malicious client may be eavesdropping on your session.",
60 GNOME_MESSAGE_BOX_ERROR, "EXIT", NULL);
61 gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
62 gtk_object_set(GTK_OBJECT(err), "type", GTK_WINDOW_POPUP, NULL);
63
64 gnome_dialog_run_and_close(GNOME_DIALOG(err));
65}
66
Damien Miller10f30852002-09-12 14:49:00 +100067int
Damien Miller5314ae72000-06-07 20:08:19 +100068passphrase_dialog(char *message)
Damien Millerd3dcfaf1999-11-09 13:52:33 +110069{
70 char *passphrase;
Damien Millerb5e85a52001-02-16 11:18:58 +110071 char **messages;
Damien Miller6677d412002-01-25 00:59:25 +110072 int result, i, grab_server, grab_pointer;
Damien Millerd3dcfaf1999-11-09 13:52:33 +110073 GtkWidget *dialog, *entry, *label;
74
Damien Miller414642b2002-01-25 00:46:04 +110075 grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
Damien Miller6677d412002-01-25 00:59:25 +110076 grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL);
Damien Millerfaf2f642001-12-21 10:28:07 +110077
Damien Millerb5e85a52001-02-16 11:18:58 +110078 dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK,
79 GNOME_STOCK_BUTTON_CANCEL, NULL);
Damien Millerd3dcfaf1999-11-09 13:52:33 +110080
Damien Millerb5e85a52001-02-16 11:18:58 +110081 messages = g_strsplit(message, "\\n", 0);
82 if (messages)
83 for(i = 0; messages[i]; i++) {
84 label = gtk_label_new(messages[i]);
85 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox),
86 label, FALSE, FALSE, 0);
87 }
Damien Millerd3dcfaf1999-11-09 13:52:33 +110088
89 entry = gtk_entry_new();
Damien Millera8e06ce2003-11-21 23:48:55 +110090 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), entry, FALSE,
Damien Millerb5e85a52001-02-16 11:18:58 +110091 FALSE, 0);
Damien Millerd3dcfaf1999-11-09 13:52:33 +110092 gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
93 gtk_widget_grab_focus(entry);
Damien Millerb9a692d1999-11-12 12:09:36 +110094
95 /* Center window and prepare for grab */
96 gtk_object_set(GTK_OBJECT(dialog), "type", GTK_WINDOW_POPUP, NULL);
97 gnome_dialog_set_default(GNOME_DIALOG(dialog), 0);
98 gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
99 gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, TRUE);
100 gnome_dialog_close_hides(GNOME_DIALOG(dialog), TRUE);
Damien Millerb5e85a52001-02-16 11:18:58 +1100101 gtk_container_set_border_width(GTK_CONTAINER(GNOME_DIALOG(dialog)->vbox),
102 GNOME_PAD);
Damien Millerb9a692d1999-11-12 12:09:36 +1100103 gtk_widget_show_all(dialog);
104
105 /* Grab focus */
Damien Millerfaf2f642001-12-21 10:28:07 +1100106 if (grab_server)
107 XGrabServer(GDK_DISPLAY());
Damien Millera8e06ce2003-11-21 23:48:55 +1100108 if (grab_pointer && gdk_pointer_grab(dialog->window, TRUE, 0,
Damien Miller6677d412002-01-25 00:59:25 +1100109 NULL, NULL, GDK_CURRENT_TIME))
Damien Miller5314ae72000-06-07 20:08:19 +1000110 goto nograb;
111 if (gdk_keyboard_grab(dialog->window, FALSE, GDK_CURRENT_TIME))
112 goto nograbkb;
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100113
Damien Miller22218721999-11-22 12:51:42 +1100114 /* Make <enter> close dialog */
115 gnome_dialog_editable_enters(GNOME_DIALOG(dialog), GTK_EDITABLE(entry));
116
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100117 /* Run dialog */
118 result = gnome_dialog_run(GNOME_DIALOG(dialog));
Damien Miller5314ae72000-06-07 20:08:19 +1000119
Damien Millerb9a692d1999-11-12 12:09:36 +1100120 /* Ungrab */
Damien Millerfaf2f642001-12-21 10:28:07 +1100121 if (grab_server)
122 XUngrabServer(GDK_DISPLAY());
Damien Miller6677d412002-01-25 00:59:25 +1100123 if (grab_pointer)
124 gdk_pointer_ungrab(GDK_CURRENT_TIME);
Damien Millerb9a692d1999-11-12 12:09:36 +1100125 gdk_keyboard_ungrab(GDK_CURRENT_TIME);
126 gdk_flush();
127
Damien Miller5314ae72000-06-07 20:08:19 +1000128 /* Report passphrase if user selected OK */
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100129 passphrase = gtk_entry_get_text(GTK_ENTRY(entry));
Damien Miller5314ae72000-06-07 20:08:19 +1000130 if (result == 0)
131 puts(passphrase);
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100132
Damien Miller5314ae72000-06-07 20:08:19 +1000133 /* Zero passphrase in memory */
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100134 memset(passphrase, '\0', strlen(passphrase));
135 gtk_entry_set_text(GTK_ENTRY(entry), passphrase);
136
137 gnome_dialog_close(GNOME_DIALOG(dialog));
Damien Miller10f30852002-09-12 14:49:00 +1000138 return (result == 0 ? 0 : -1);
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100139
Damien Miller5314ae72000-06-07 20:08:19 +1000140 /* At least one grab failed - ungrab what we got, and report
141 the failure to the user. Note that XGrabServer() cannot
142 fail. */
143 nograbkb:
144 gdk_pointer_ungrab(GDK_CURRENT_TIME);
145 nograb:
Damien Millerfaf2f642001-12-21 10:28:07 +1100146 if (grab_server)
147 XUngrabServer(GDK_DISPLAY());
Damien Miller5314ae72000-06-07 20:08:19 +1000148 gnome_dialog_close(GNOME_DIALOG(dialog));
149
150 report_failed_grab();
Damien Miller10f30852002-09-12 14:49:00 +1000151 return (-1);
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100152}
153
Damien Miller5314ae72000-06-07 20:08:19 +1000154int
155main(int argc, char **argv)
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100156{
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100157 char *message;
Damien Miller10f30852002-09-12 14:49:00 +1000158 int result;
159
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100160 gnome_init("GNOME ssh-askpass", "0.1", argc, argv);
161
162 if (argc == 2)
163 message = argv[1];
164 else
165 message = "Enter your OpenSSH passphrase:";
166
Damien Miller5314ae72000-06-07 20:08:19 +1000167 setvbuf(stdout, 0, _IONBF, 0);
Damien Miller10f30852002-09-12 14:49:00 +1000168 result = passphrase_dialog(message);
169
170 return (result);
Damien Millerd3dcfaf1999-11-09 13:52:33 +1100171}