1 /* 2 * Copyright (c) 2000-2002 Damien Miller. All rights reserved. 3 * 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 */ 24 25 /* 26 * 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". 29 * 30 * There is only two run-time options: if you set the environment variable 31 * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab 32 * 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 34 * you don't trust your X server. We grab the keyboard always. 35 */ 36 37 /* 38 * Compile with: 39 * 40 * cc `gnome-config --cflags gnome gnomeui` \ 41 * gnome-ssh-askpass1.c -o gnome-ssh-askpass \ 42 * `gnome-config --libs gnome gnomeui` 43 * 44 */ 45 46 #include <stdlib.h> 47 #include <stdio.h> 48 #include <string.h> 49 #include <gnome.h> 50 #include <X11/Xlib.h> 51 #include <gdk/gdkx.h> 52 53 void 54 report_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 67 int 68 passphrase_dialog(char *message) 69 { 70 char *passphrase; 71 char **messages; 72 int result, i, grab_server, grab_pointer; 73 GtkWidget *dialog, *entry, *label; 74 75 grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); 76 grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); 77 78 dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK, 79 GNOME_STOCK_BUTTON_CANCEL, NULL); 80 81 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 } 88 89 entry = gtk_entry_new(); 90 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), entry, FALSE, 91 FALSE, 0); 92 gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); 93 gtk_widget_grab_focus(entry); 94 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); 101 gtk_container_set_border_width(GTK_CONTAINER(GNOME_DIALOG(dialog)->vbox), 102 GNOME_PAD); 103 gtk_widget_show_all(dialog); 104 105 /* Grab focus */ 106 if (grab_server) 107 XGrabServer(GDK_DISPLAY()); 108 if (grab_pointer && gdk_pointer_grab(dialog->window, TRUE, 0, 109 NULL, NULL, GDK_CURRENT_TIME)) 110 goto nograb; 111 if (gdk_keyboard_grab(dialog->window, FALSE, GDK_CURRENT_TIME)) 112 goto nograbkb; 113 114 /* Make <enter> close dialog */ 115 gnome_dialog_editable_enters(GNOME_DIALOG(dialog), GTK_EDITABLE(entry)); 116 117 /* Run dialog */ 118 result = gnome_dialog_run(GNOME_DIALOG(dialog)); 119 120 /* Ungrab */ 121 if (grab_server) 122 XUngrabServer(GDK_DISPLAY()); 123 if (grab_pointer) 124 gdk_pointer_ungrab(GDK_CURRENT_TIME); 125 gdk_keyboard_ungrab(GDK_CURRENT_TIME); 126 gdk_flush(); 127 128 /* Report passphrase if user selected OK */ 129 passphrase = gtk_entry_get_text(GTK_ENTRY(entry)); 130 if (result == 0) 131 puts(passphrase); 132 133 /* Zero passphrase in memory */ 134 memset(passphrase, '\0', strlen(passphrase)); 135 gtk_entry_set_text(GTK_ENTRY(entry), passphrase); 136 137 gnome_dialog_close(GNOME_DIALOG(dialog)); 138 return (result == 0 ? 0 : -1); 139 140 /* 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: 146 if (grab_server) 147 XUngrabServer(GDK_DISPLAY()); 148 gnome_dialog_close(GNOME_DIALOG(dialog)); 149 150 report_failed_grab(); 151 return (-1); 152 } 153 154 int 155 main(int argc, char **argv) 156 { 157 char *message; 158 int result; 159 160 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 167 setvbuf(stdout, 0, _IONBF, 0); 168 result = passphrase_dialog(message); 169 170 return (result); 171 } 172