1170530Ssam/* 2178354Ssam * Copyright (c) 2000-2002 Damien Miller. All rights reserved. 3170530Ssam * 4170530Ssam * Redistribution and use in source and binary forms, with or without 5170530Ssam * modification, are permitted provided that the following conditions 6170530Ssam * are met: 7170530Ssam * 1. Redistributions of source code must retain the above copyright 8170530Ssam * notice, this list of conditions and the following disclaimer. 9170530Ssam * 2. Redistributions in binary form must reproduce the above copyright 10170530Ssam * notice, this list of conditions and the following disclaimer in the 11170530Ssam * documentation and/or other materials provided with the distribution. 12170530Ssam * 13170530Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14170530Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15170530Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16170530Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17170530Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18170530Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19170530Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20170530Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21170530Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22170530Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23170530Ssam */ 24170530Ssam 25170530Ssam/* 26170530Ssam * This is a simple GNOME SSH passphrase grabber. To use it, set the 27170530Ssam * environment variable SSH_ASKPASS to point to the location of 28170530Ssam * gnome-ssh-askpass before calling "ssh-add < /dev/null". 29170530Ssam * 30170530Ssam * There is only two run-time options: if you set the environment variable 31170530Ssam * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab 32170530Ssam * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the 33170530Ssam * pointer will be grabbed too. These may have some benefit to security if 34170530Ssam * you don't trust your X server. We grab the keyboard always. 35170530Ssam */ 36178354Ssam 37170530Ssam/* 38170530Ssam * Compile with: 39170530Ssam * 40170530Ssam * cc `gnome-config --cflags gnome gnomeui` \ 41170530Ssam * gnome-ssh-askpass1.c -o gnome-ssh-askpass \ 42170530Ssam * `gnome-config --libs gnome gnomeui` 43170530Ssam * 44170530Ssam */ 45170530Ssam 46170530Ssam#include <stdlib.h> 47170530Ssam#include <stdio.h> 48170530Ssam#include <string.h> 49170530Ssam#include <gnome.h> 50178354Ssam#include <X11/Xlib.h> 51170530Ssam#include <gdk/gdkx.h> 52170530Ssam 53170530Ssamvoid 54170530Ssamreport_failed_grab (void) 55170530Ssam{ 56178354Ssam GtkWidget *err; 57178354Ssam 58178354Ssam err = gnome_message_box_new("Could not grab keyboard or mouse.\n" 59178354Ssam "A malicious client may be eavesdropping on your session.", 60178354Ssam GNOME_MESSAGE_BOX_ERROR, "EXIT", NULL); 61178354Ssam gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); 62178354Ssam gtk_object_set(GTK_OBJECT(err), "type", GTK_WINDOW_POPUP, NULL); 63178354Ssam 64178354Ssam gnome_dialog_run_and_close(GNOME_DIALOG(err)); 65178354Ssam} 66178354Ssam 67178354Ssamint 68178354Ssampassphrase_dialog(char *message) 69178354Ssam{ 70178354Ssam char *passphrase; 71178354Ssam char **messages; 72178354Ssam int result, i, grab_server, grab_pointer; 73170530Ssam GtkWidget *dialog, *entry, *label; 74170530Ssam 75170530Ssam grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); 76170530Ssam grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); 77170530Ssam 78170530Ssam dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK, 79170530Ssam GNOME_STOCK_BUTTON_CANCEL, NULL); 80170530Ssam 81173273Ssam messages = g_strsplit(message, "\\n", 0); 82173273Ssam if (messages) 83173273Ssam for(i = 0; messages[i]; i++) { 84173273Ssam label = gtk_label_new(messages[i]); 85173273Ssam gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), 86178354Ssam label, FALSE, FALSE, 0); 87178354Ssam } 88178354Ssam 89173273Ssam entry = gtk_entry_new(); 90178354Ssam gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), entry, FALSE, 91178354Ssam FALSE, 0); 92178354Ssam gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); 93178354Ssam gtk_widget_grab_focus(entry); 94178354Ssam 95178354Ssam /* Center window and prepare for grab */ 96178354Ssam gtk_object_set(GTK_OBJECT(dialog), "type", GTK_WINDOW_POPUP, NULL); 97178354Ssam gnome_dialog_set_default(GNOME_DIALOG(dialog), 0); 98178354Ssam gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); 99178354Ssam gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, TRUE); 100178354Ssam gnome_dialog_close_hides(GNOME_DIALOG(dialog), TRUE); 101178354Ssam gtk_container_set_border_width(GTK_CONTAINER(GNOME_DIALOG(dialog)->vbox), 102178354Ssam GNOME_PAD); 103170530Ssam gtk_widget_show_all(dialog); 104178354Ssam 105178354Ssam /* Grab focus */ 106170530Ssam if (grab_server) 107170530Ssam XGrabServer(GDK_DISPLAY()); 108170530Ssam if (grab_pointer && gdk_pointer_grab(dialog->window, TRUE, 0, 109170530Ssam NULL, NULL, GDK_CURRENT_TIME)) 110170530Ssam goto nograb; 111170530Ssam if (gdk_keyboard_grab(dialog->window, FALSE, GDK_CURRENT_TIME)) 112170530Ssam goto nograbkb; 113170530Ssam 114170530Ssam /* Make <enter> close dialog */ 115170530Ssam gnome_dialog_editable_enters(GNOME_DIALOG(dialog), GTK_EDITABLE(entry)); 116170530Ssam 117170530Ssam /* Run dialog */ 118170530Ssam result = gnome_dialog_run(GNOME_DIALOG(dialog)); 119170530Ssam 120170530Ssam /* Ungrab */ 121170530Ssam if (grab_server) 122170530Ssam XUngrabServer(GDK_DISPLAY()); 123178354Ssam if (grab_pointer) 124170530Ssam gdk_pointer_ungrab(GDK_CURRENT_TIME); 125170530Ssam gdk_keyboard_ungrab(GDK_CURRENT_TIME); 126170530Ssam gdk_flush(); 127170530Ssam 128173273Ssam /* Report passphrase if user selected OK */ 129173273Ssam passphrase = gtk_entry_get_text(GTK_ENTRY(entry)); 130178354Ssam if (result == 0) 131173273Ssam puts(passphrase); 132178354Ssam 133178354Ssam /* Zero passphrase in memory */ 134178354Ssam memset(passphrase, '\0', strlen(passphrase)); 135178354Ssam gtk_entry_set_text(GTK_ENTRY(entry), passphrase); 136173273Ssam 137178354Ssam gnome_dialog_close(GNOME_DIALOG(dialog)); 138178354Ssam return (result == 0 ? 0 : -1); 139178354Ssam 140178354Ssam /* 141178354Ssam * At least one grab failed - ungrab what we got, and report the 142178354Ssam * failure to the user. Note that XGrabServer() cannot fail. 143178354Ssam */ 144178354Ssam nograbkb: 145178354Ssam gdk_pointer_ungrab(GDK_CURRENT_TIME); 146178354Ssam nograb: 147178354Ssam if (grab_server) 148178354Ssam XUngrabServer(GDK_DISPLAY()); 149178354Ssam gnome_dialog_close(GNOME_DIALOG(dialog)); 150178354Ssam 151178354Ssam report_failed_grab(); 152178354Ssam return (-1); 153170530Ssam} 154173273Ssam 155173273Ssamint 156170530Ssammain(int argc, char **argv) 157170530Ssam{ 158178354Ssam char *message; 159178354Ssam int result; 160178354Ssam 161178354Ssam gnome_init("GNOME ssh-askpass", "0.1", argc, argv); 162178354Ssam 163173273Ssam if (argc == 2) 164178354Ssam message = argv[1]; 165178354Ssam else 166178354Ssam message = "Enter your OpenSSH passphrase:"; 167178354Ssam 168170530Ssam setvbuf(stdout, 0, _IONBF, 0); 169170530Ssam result = passphrase_dialog(message); 170178354Ssam 171178354Ssam return (result); 172178354Ssam} 173178354Ssam